import { HttpOperationResponse } from "../httpOperationResponse" ; import * as utils from "../util/utils" ; import { WebResourceLike } from "../webResource" ; import { BaseRequestPolicy , RequestPolicy , RequestPolicyFactory , RequestPolicyOptionsLike , } from "./requestPolicy" ; export function rpRegistrationPolicy ( retryTimeout = 30 ) { return { create : ( nextPolicy , options ) => { return new RPRegistrationPolicy ( nextPolicy , options , retryTimeout ) ; } , } ; } export class RPRegistrationPolicy extends BaseRequestPolicy { constructor ( nextPolicy , options , readonly _retryTimeout = 30 ) { super ( nextPolicy , options ) ; } public sendRequest ( request ) { return this . _nextPolicy . sendRequest ( request . clone ( ) ) . then ( ( response ) => registerIfNeeded ( this , request , response ) ) ; } } function registerIfNeeded ( policy , request , response ) { if ( response . status === 409 ) { const rpName = checkRPNotRegisteredError ( response . bodyAsText as string ) ; if ( rpName ) { const urlPrefix = extractSubscriptionUrl ( request . url ) ; return ( registerRP ( policy , urlPrefix , rpName , request ) . catch ( ( ) => false ) . then ( ( registrationStatus ) => { if ( registrationStatus ) { request . headers . set ( "x-ms-client-request-id" , utils . generateUuid ( ) ) ; return policy . _nextPolicy . sendRequest ( request . clone ( ) ) ; } return response ; } ) ) ; } } return Promise . resolve ( response ) ; } param { WebResourceLike } originalRequest param { boolean } reuseUrlToo returns { object } function getRequestEssentials ( originalRequest , reuseUrlToo = false ) { const reqOptions = originalRequest . clone ( ) ; if ( reuseUrlToo ) { reqOptions . url = originalRequest . url ; } reqOptions . headers . set ( "x-ms-client-request-id" , utils . generateUuid ( ) ) ; reqOptions . headers . set ( "Content-Type" , "application/json; charset=utf-8" ) ; return reqOptions ; } param { string } body returns { string } function checkRPNotRegisteredError ( body ) { let result , responseBody ; if ( body ) { try { responseBody = JSON . parse ( body ) ; } catch ( err ) { } if ( responseBody && responseBody . error && responseBody . error . message && responseBody . error . code && responseBody . error . code === "MissingSubscriptionRegistration" ) { const matchRes = responseBody . error . message . match ( /.*'(.*)'/i ) ; if ( matchRes ) { result = matchRes . pop ( ) ; } } } return result ; } param { string } url returns { string } function extractSubscriptionUrl ( url ) { let result ; const matchRes = url . match ( /.*\/subscriptions\/[a-f0-9-]+\//gi ) ; if ( matchRes && matchRes [ 0 ] ) { result = matchRes [ 0 ] ; } else { throw new Error ( `Unable to extract subscriptionId from the given url - ${ url }.` ) ; } return result ; } param { RPRegistrationPolicy } policy param { string } urlPrefix param { string } provider param { WebResourceLike } originalRequest param { registrationCallback } callback function registerRP ( policy , urlPrefix , provider , originalRequest ) { const postUrl = `${ urlPrefix }providers/${ provider }/register?api-version=2016-02-01` ; const getUrl = `${ urlPrefix }providers/${ provider }?api-version=2016-02-01` ; const reqOptions = getRequestEssentials ( originalRequest ) ; reqOptions . method = "POST" ; reqOptions . url = postUrl ; return policy . _nextPolicy . sendRequest ( reqOptions ) . then ( ( response ) => { if ( response . status !== 200 ) { throw new Error ( `Autoregistration of ${ provider } failed. Please try registering manually.` ) ; } return getRegistrationStatus ( policy , getUrl , originalRequest ) ; } ) ; } param { RPRegistrationPolicy } policy param { string } url param { WebResourceLike } originalRequest returns { Promise < boolean > } function getRegistrationStatus ( policy , url , originalRequest ) { const reqOptions = getRequestEssentials ( originalRequest ) ; reqOptions . url = url ; reqOptions . method = "GET" ; return policy . _nextPolicy . sendRequest ( reqOptions ) . then ( ( res ) => { const obj = res . parsedBody as any ; if ( res . parsedBody && obj . registrationState && obj . registrationState === "Registered" ) { return true ; } else { return utils . delay ( policy . _retryTimeout * 1000 ) . then ( ( ) => getRegistrationStatus ( policy , url , originalRequest ) ) ; } } ) ; }