import { MetadataMap, HttpError } from "@cognite/sdk-core"; import { CDF_VERSION } from "../constants"; import { version } from "../../package.json"; import { ClientLoginOptions, ApiKeyLogin, TokenLogin, isUsingSSL, bearerTokenString, getTokenWithCogniteClient, } from "./clientAuthUtils"; import HttpClientWithIntercept from "./httpClientWithIntercept"; export default class BaseWellsClient { private http: HttpClientWithIntercept; private metadata: MetadataMap; private projectName = ""; private hasBeenLoggedIn = false; constructor(options: ClientLoginOptions) { if (typeof options !== "object") { throw Error("`CogniteWellsClient` is missing parameter `options`"); } if (typeof options.appId !== "string") { throw Error("options.appId is required and must be of type string"); } const baseUrl = options.baseUrl || "https://greenfield.cognitedata.com"; this.http = new HttpClientWithIntercept(baseUrl); this.http.setDefaultHeader("X-CDP-APP", options.appId); this.http.setDefaultHeader("X-CDP-SDK", this.version); this.http.setDefaultHeader("cdf-version", CDF_VERSION); this.metadata = new MetadataMap(); } public get project() { return this.projectName; } /** * Login client with api-key * * @param options Login options * */ public loginWithApiKey = (options: ApiKeyLogin) => { if (this.hasBeenLoggedIn) { throw Error( "You cannot re-login with an already logged in Cognite client instance. Try to create a new Cognite Wells client instance instead." ); } if (typeof options !== "object") { throw Error("`loginWithApiKey` is missing parameter `options`"); } const { project, apiKey } = options; const keys: (keyof ApiKeyLogin)[] = ["project", "apiKey"]; for (const property of keys) { if (typeof options[property] !== "string") { throw Error( `options.${property} is required and must be of type string` ); } } this.projectName = project; this.httpClient.setDefaultHeader("api-key", apiKey); this.initAPIs(); this.hasBeenLoggedIn = true; }; public loginWithToken = async (options: TokenLogin) => { if (this.hasBeenLoggedIn) { throw Error( "You cannot re-login with an already logged in Cognite client instance. Try to create a new Cognite Wells client instance instead." ); } if (typeof options !== "object") { throw Error("`loginWithToken` is missing parameter `options`"); } const { project } = options; if (typeof project !== "string") { throw Error("options.project is required and must be of type string"); } this.projectName = project; if (!isUsingSSL()) { console.warn( "You should use SSL (https) when you login with Token since CDF only allows redirecting back to an HTTPS site" ); } const existingToken = options.accessToken; const tokenRefreshMethod = options.tokenRefreshCallback; const flow = options.authenticationFlow; // Aquire a token when logging in the first time const token = existingToken || (tokenRefreshMethod ? await tokenRefreshMethod() : undefined) || (flow ? await getTokenWithCogniteClient(flow!) : undefined); if (token) { this.httpClient.setDefaultHeader( "Authorization", bearerTokenString(token) ); } else throw new Error("Existing token or authentication flow must be passed."); this.initAPIs(); this.hasBeenLoggedIn = true; this.httpClient.setIfUsingLoginToken = true; this.httpClient.setReauthenticateMethod = tokenRefreshMethod ? tokenRefreshMethod : getTokenWithCogniteClient; if (flow) this.httpClient.setAuthFlow = flow; }; public get getBaseUrl() { return this.httpClient.getBaseUrl(); } public get isLoggedIn() { return this.hasBeenLoggedIn; } protected get version() { return `wells-js/${version}`; } protected initAPIs() { // will be overritten by subclasses } protected apiFactory = ( api: new ( relativePath: string, httpClient: HttpClientWithIntercept, map: MetadataMap ) => ApiType, relativePath: string ) => { return new api( `${this.http.getBaseUrl()}/${relativePath}`, this.httpClient, this.metadataMap ); }; protected get metadataMap() { return this.metadata; } protected get httpClient() { return this.http; } } export class ConfigureAPI { private _client?: HttpClientWithIntercept; protected project?: string; public set setHttpClient(httpClient: HttpClientWithIntercept) { this._client = httpClient; } protected get client(): HttpClientWithIntercept { if (this._client === undefined) { throw new Error("Client is not defined"); } return this._client; } public set setProject(project: string) { this.project = project; } protected getPath( targetRoute: string, cursor?: string, limit?: number ): string { if (this.project == undefined) { throw new HttpError(400, "The client project has not been set.", {}); } const baseUrl = this.client.getBaseUrl(); // URL constructor throws error if base url not included const path = new URL( `${baseUrl}/api/v1/projects/${this.project}/wdl${targetRoute}` ); if (cursor) { path.searchParams.append(`cursor`, `${cursor}`); } if (limit) { path.searchParams.append(`limit`, `${limit}`); } // we only need the route and params return path.toString().substring(baseUrl.length); } }