@sitecore/sc-contenthub-webclient-sdk
Version:
Sitecore Content Hub WebClient SDK.
272 lines • 14.2 kB
JavaScript
"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