import { AbstractClient } from './AbstractClient.js';
const AUTH_API_ENDPOINT = 'api/v2/auth/token/generate';
/**
* # Client examples
*
* Authenticate against a Graphistry server using a username and password, and manage communications with it.
*
* Different authentication modes may be desirable depending on the type of Graphistry server.
*
*
*
* ---
*
*
*
* @example **Authenticate against Graphistry Hub for a personal account**
* ```javascript
* import { Client } from '@graphistry/node-api';
* const client = new Client('my_username', 'my_password');
* ```
*
*
*
* @example **Authenticate against an org in Graphistry Hub**
* ```javascript
* import { Client } from '@graphistry/node-api';
* const client = new Client('my_username', 'my_password', 'my_org');
* ```
*
*
*
* @example **Authenticate against a private Graphistry server**
* ```javascript
* import { Client } from '@graphistry/node-api';
* const client = new Client('my_username', 'my_password', '', 'http', 'my-ec2.aws.com:8080');
* ```
*
*
*
* @example **Upload via internal IP but publish urls via a public domain**
* ```javascript
* import { Client } from '@graphistry/node-api';
* const client = new Client(
* 'my_username', 'my_password', '',
* 'http', '10.20.0.1:8080',
* 'https://www.my-site.com'
* );
* ```
*
*
*
* @example **Upload through the local docker network but publish urls via a public domain**
* ```javascript
* import { Client } from '@graphistry/node-api';
* const client = new Client(
* 'my_username', 'my_password', '',
* 'http', 'nginx',
* 'https://www.my-site.com'
* );
* ```
*
*
*
* @example **Create a client with an externally-provided JWT token**
* ```javascript
* import { Client } from '@graphistry/node-api';
* const client = new Client();
* client.setToken('Bearer 123abc');
* ```
*/
export class Client extends AbstractClient {
public readonly username: string;
private _password: string;
/**
*
* See examples at top of file
*
* @param username The username to authenticate with.
* @param password The password to authenticate with.
* @param org The organization to use (optional)
* @param protocol The protocol to use for the server during uploads: 'http' or 'https'.
* @param host The hostname of the server during uploads: defaults to 'hub.graphistry.com'
* @param clientProtocolHostname Base path to use inside the browser and when sharing public URLs: defaults to '{protocol}://{host}'
* @param fetch The fetch implementation to use
* @param version The version of the client library
* @param agent The agent name to use when communicating with the server
*/
constructor (
username: string, password: string, org?: string,
protocol = 'https', host = 'hub.graphistry.com',
clientProtocolHostname?: string,
fetch?: any, // eslint-disable-line @typescript-eslint/no-explicit-any
version?: string,
agent = '@graphistry/js-upload-api',
) {
super(org, protocol, host, clientProtocolHostname, fetch, version, agent);
this.username = username;
this._password = password;
if (this.isServerConfigured()) {
this._getAuthTokenPromise = this.getAuthToken();
}
}
public isServerConfigured() {
return (this.username || '') !== '' && (this._password || '') !== '' && (this.host || '') !== '';
}
public checkStale(username: string, password: string, protocol: string, host: string, clientProtocolHostname?: string) {
// username changed
if (this.username !== username) {
return true;
}
// password changed
if (this._password !== password) {
return true;
}
// protocol changed
if (this.protocol !== protocol) {
return true;
}
// host changed
if (this.host !== host) {
return true;
}
// clientProtocolHostname changed
if (this.clientProtocolHostname !== clientProtocolHostname) {
return true;
}
return false;
}
/**
* Get the authentication token for the current user.
* By default, reuses current token if available.
*
* @param force If true, forces a new token to be generated; defaults to false
*
* @returns The authentication token
*
*/
protected async getAuthToken(force = false) {
if (!force && this.authTokenValid()) {
return this._token || ''; // workaround ts not recognizing that _token is set
}
//Throw exception if invalid username or password
if (!this.isServerConfigured()) {
throw new Error('Invalid username or password');
}
if (!force && this._getAuthTokenPromise) {
// reusing outstanding auth promise
return await this._getAuthTokenPromise;
}
let response = await this.postToApi(
AUTH_API_ENDPOINT,
{
username: this.username,
password: this._password,
...(this.org ? {org_name: this.org} : {}),
},
this.getBaseHeaders(),
);
response = await response.json();
const tok : string = response.token;
this._token = tok;
if (!this.authTokenValid()) {
console.error('auth token failure', {response, username: this.username, host: this.host});
throw new Error({'error': 'Auth token failure', ...(response||{})});
}
return tok;
}
/**
*
* @param username
* @param password
* @param org
* @param protocol
* @param host
* @returns Promise for the authentication token
*
* Helper to fetch a token for a given user
*
*/
public async fetchToken(
username: string, password: string, org?: string, protocol = 'https', host = 'hub.graphistry.com'
): Promise {
let response = await this.postToApi(
AUTH_API_ENDPOINT,
{
username: username,
password: password,
...(org ? {org_name: org} : {}),
},
this.getBaseHeaders(),
`${protocol}://${host}/`
);
response = await response.json();
return response.token;
}
}