UNPKG

@sitecore/sc-contenthub-webclient-sdk

Version:

Sitecore Content Hub WebClient SDK.

272 lines 14.2 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.InternalClient = void 0; /* eslint-disable @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-assignment */ const axios_1 = __importDefault(require("axios")); const ta_json_1 = require("ta-json"); const oauth_client_credentials_grant_1 = __importDefault(require("../authentication/oauth-client-credentials-grant")); const oauth_password_grant_1 = __importDefault(require("../authentication/oauth-password-grant")); const oauth_refreshtoken_grant_1 = __importDefault(require("../authentication/oauth-refreshtoken-grant")); const token_info_1 = require("../authentication/token-info"); const authentication_error_1 = require("../errors/authentication-error"); const invalid_operation_error_1 = require("../errors/invalid-operation-error"); const guard_1 = __importDefault(require("../guard")); const http_method_1 = require("../http-method"); const response_message_1 = require("./response-message"); class InternalClient { /** * Indicates if we should authenticate with OAuth. */ get shouldAuthenticateWithOAuth() { return !!(this._passwordGrant || this._refreshTokenGrant || this._clientCredentialsGrant); } constructor(baseUri, oauthGrant) { this._passwordGrant = null; this._refreshTokenGrant = null; this._clientCredentialsGrant = null; this._requestHeaders = {}; guard_1.default.notNullOrUndefined(baseUri); guard_1.default.notNull(oauthGrant); const baseUrl = typeof baseUri === "string" ? baseUri : baseUri.href(); guard_1.default.stringNotNullOrEmpty(baseUrl); const createClientParameters = { baseURL: baseUrl, withCredentials: true, }; // This setting should be added to the .env file for connecting to a server using a self signed certificate if (typeof process !== "undefined" && process != null) { if (process.env.IGNORE_HTTPS_ERRORS === "true") { // Esbuild doesn't like importing node modules when building for browsers. // That is why we use require to load the node modules for node environments. const https = require("https"); createClientParameters.httpsAgent = new https.Agent({ rejectUnauthorized: false, }); } } this._client = axios_1.default.create(createClientParameters); if (oauthGrant instanceof oauth_password_grant_1.default) { this._passwordGrant = oauthGrant; } else if (oauthGrant instanceof oauth_refreshtoken_grant_1.default) { this._refreshTokenGrant = oauthGrant; } else if (oauthGrant instanceof oauth_client_credentials_grant_1.default) { this._clientCredentialsGrant = oauthGrant; } if (this.shouldAuthenticateWithOAuth) { const createRefreshTokenResponseInterceptor = () => { const responseInterceptor = this._client.interceptors.response.use((response) => response, (error) => { // Reject promise if usual error if (error.status !== 401) { return Promise.reject(error); } // When response code is 401, try to refresh the token. // Eject the interceptor so it doesn't loop in case the token refresh causes the 401 response. this._client.interceptors.response.eject(responseInterceptor); return this._client .request({ url: "/oauth/token", method: "POST", transformRequest: [ function (data, headers) { headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"; return Object.keys(data) .reduce((d, k) => { d.push(`${k}=${encodeURIComponent(data[k])}`); return d; }, []) .join("&"); }, ], data: ta_json_1.TaJson.serialize(this._refreshTokenGrant), }) .then(response => { const tokenInfo = ta_json_1.TaJson.deserialize(response.data, token_info_1.TokenInfo); this._accessToken = tokenInfo.accessToken; this._refreshTokenGrant.refreshToken = tokenInfo.refreshToken; error.response.config.headers["Authorization"] = "Bearer " + tokenInfo.accessToken; return (0, axios_1.default)(error.response.config); }) .catch(error => { this._isAuthenticated = false; throw error; }) .finally(createRefreshTokenResponseInterceptor); }); }; createRefreshTokenResponseInterceptor.bind(this); createRefreshTokenResponseInterceptor(); } else { // No OAuthGrant specified, so we must be in the browser. this._client.defaults.withCredentials = true; // Send the cookies with the requests. this._isAuthenticated = true; // Let's assume we're already authenticated } } authenticateAsync() { return __awaiter(this, void 0, void 0, function* () { if (this._isAuthenticated || !this.shouldAuthenticateWithOAuth) { return true; } if (this._accessToken) { return true; } const grant = this._passwordGrant || this._clientCredentialsGrant; if (!grant) { throw new invalid_operation_error_1.InvalidOperationError("Can not authenticate - Missing OAuth grant."); } return yield this._client .request({ url: "/oauth/token", method: "POST", transformRequest: [ function (data, headers) { headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"; return Object.keys(data) .reduce((d, k) => { d.push(`${k}=${encodeURIComponent(data[k])}`); return d; }, []) .join("&"); }, ], data: ta_json_1.TaJson.serialize(grant), }) .then(response => { const tokenInfo = ta_json_1.TaJson.deserialize(response.data, token_info_1.TokenInfo); this._accessToken = tokenInfo.accessToken; this._refreshTokenGrant = new oauth_refreshtoken_grant_1.default(grant.clientId, grant.clientSecret, tokenInfo.refreshToken); this._client.interceptors.request.use(config => { config.headers["Authorization"] = `Bearer ${this._accessToken}`; return config; }, error => { return Promise.reject(error); }); this._isAuthenticated = true; return true; }) .catch(error => { this._isAuthenticated = false; throw new authentication_error_1.AuthenticationError("Authentication failed.", error); }); }); } setRequestHeaders(headers) { guard_1.default.notNullOrUndefined(headers); this._requestHeaders = headers; } /** * Sets the provided error handler as an interceptor for the responses. * @param onError - the callback that should be called on error. */ setResponseErrorHandler(onError) { if (this.shouldAuthenticateWithOAuth) { throw new invalid_operation_error_1.InvalidOperationError("Unable to set response error handler when authenticating via OAuth."); } this._client.interceptors.response.use(response => response, error => onError(error)); } send_onFulfilled(requestMsg) { return (response) => { return response_message_1.ResponseMessage.build(response.status, response.headers, { requestMessage: Object.freeze(requestMsg), content: response.data, statusText: response.statusText, }); }; } send_onRejected(error) { if (error.response) { return response_message_1.ResponseMessage.build(error.response.status, error.response.headers, { statusText: error.response.statusText, content: error.response.data, }); } else if (error.request) { return response_message_1.ResponseMessage.build(error.request.status, {}, { statusText: error.request.statusText, content: error.request.data }); } else { throw error; } } sendAsync(requestGenerator, cancelCallback) { return __awaiter(this, void 0, void 0, function* () { if (!this._isAuthenticated) { throw new invalid_operation_error_1.InvalidOperationError("Client is not authenticated. Authenticate first."); } guard_1.default.notNullOrUndefined(requestGenerator); const requestMsg = requestGenerator(); guard_1.default.notNullOrUndefined(requestMsg.requestUri); const requestUrl = typeof requestMsg.requestUri === "string" ? requestMsg.requestUri : requestMsg.requestUri.href(); guard_1.default.stringNotNullOrEmpty(requestUrl); const requestConfig = {}; requestConfig.headers = Object.assign(Object.assign({}, this._requestHeaders), requestMsg.requestHeaders); if (cancelCallback) { requestConfig.cancelToken = new axios_1.default.CancelToken(cancelCallback); } let result = response_message_1.ResponseMessage.build(0); // Not a valid status code, but we'll know it failed. switch (requestMsg.method) { case http_method_1.HttpMethod.DELETE: result = yield this._client .delete(requestUrl, requestConfig) .then(this.send_onFulfilled(requestMsg), error => this.send_onRejected(error)); break; case http_method_1.HttpMethod.GET: result = yield this._client .get(requestUrl, requestConfig) .then(this.send_onFulfilled(requestMsg), error => this.send_onRejected(error)); break; case http_method_1.HttpMethod.HEAD: result = yield this._client .head(requestUrl, requestConfig) .then(this.send_onFulfilled(requestMsg), error => this.send_onRejected(error)); break; case http_method_1.HttpMethod.OPTIONS: requestConfig.method = "OPTIONS"; requestConfig.url = requestUrl; result = yield this._client .request(requestConfig) .then(this.send_onFulfilled(requestMsg), error => this.send_onRejected(error)); break; case http_method_1.HttpMethod.PATCH: result = yield this._client .patch(requestUrl, typeof requestMsg.content === "string" ? requestMsg.content : ta_json_1.TaJson.serialize(requestMsg.content), requestConfig) .then(this.send_onFulfilled(requestMsg), error => this.send_onRejected(error)); break; case http_method_1.HttpMethod.POST: result = yield this._client .post(requestUrl, typeof requestMsg.content === "string" ? requestMsg.content : ta_json_1.TaJson.serialize(requestMsg.content), requestConfig) .then(this.send_onFulfilled(requestMsg), error => this.send_onRejected(error)); break; case http_method_1.HttpMethod.PUT: result = yield this._client .put(requestUrl, typeof requestMsg.content === "string" ? requestMsg.content : ta_json_1.TaJson.serialize(requestMsg.content), requestConfig) .then(this.send_onFulfilled(requestMsg), error => this.send_onRejected(error)); break; default: throw "Method not supported."; } return result; }); } } exports.InternalClient = InternalClient; //# sourceMappingURL=internal-client.js.map