UNPKG

box-ui-elements-mlh

Version:
150 lines (134 loc) 5.84 kB
/** * @flow * @file An example of a token managing service * @author Box */ import { TYPED_ID_FOLDER_PREFIX, TYPED_ID_FILE_PREFIX } from '../constants'; import type { Token, TokenLiteral } from '../common/types/core'; const error = new Error( 'Bad id or auth token. ID should be typed id like file_123 or folder_123! Token should be a string or function.', ); class TokenService { /** * Function to fetch a single token. The user supplied token can either * itself be a simple token or instead be a function that returns a promise. * This promise then resolves to either a string/null/undefined token or * a read/write token pair. * * @private * @param {string} id - box item typed id * @param {string} tokenOrTokenFunction - Optional token or token function * @return {Promise} that resolves to a token */ static async getToken(id: string, tokenOrTokenFunction: Token): Promise<?string> { // Make sure we are getting typed ids // Tokens should either be null or undefined or string or functions // Anything else is not supported and throw error if ( (tokenOrTokenFunction !== null && tokenOrTokenFunction !== undefined && typeof tokenOrTokenFunction !== 'string' && typeof tokenOrTokenFunction !== 'function') || (!id.startsWith(TYPED_ID_FOLDER_PREFIX) && !id.startsWith(TYPED_ID_FILE_PREFIX)) ) { throw error; } // Token is a simple string or null or undefined if (!tokenOrTokenFunction || typeof tokenOrTokenFunction === 'string') { return tokenOrTokenFunction; } // Token is a function which returns a promise. // Promise on resolution returns a string/null/undefined token or token pair. const token = await tokenOrTokenFunction(id); if (!token || typeof token === 'string' || (typeof token === 'object' && (token.read || token.write))) { return token; } throw error; } /** * Gets a string read token. * Defaults to a simple token string. * * @public * @param {string} id - box item typed id * @param {Token} tokenOrTokenFunction - Optional token or token function * @return {Promise} that resolves to a token */ static async getReadToken(id: string, tokenOrTokenFunction: Token): Promise<?string> { const token: TokenLiteral = await TokenService.getToken(id, tokenOrTokenFunction); if (token && typeof token === 'object') { return token.read; } return token; } /** * Gets read tokens. * * @public * @param {string|string[]} id - box item typed id(s) * @param {Token} tokenOrTokenFunction - Token to use or token generation function * @return {Promise} Promise that resolves with id to token map */ static async getReadTokens(id: string | string[], tokenOrTokenFunction: Token): Promise<Object> { const ids: string[] = Array.isArray(id) ? id : [id]; const promises: Promise<?string>[] = ids.map((typedId: string) => TokenService.getReadToken(typedId, tokenOrTokenFunction), ); const tokens: (?string)[] = await Promise.all(promises); const tokenMap = {}; tokens.forEach((token, index) => { tokenMap[ids[index]] = token; }); return Promise.resolve(tokenMap); } /** * Gets a string write token. * Defaults to either the read token or a simple token string. * * @public * @param {string} id - box item typed id * @param {string} tokenOrTokenFunction - Optional token or token function * @return {Promise} that resolves to a token */ static async getWriteToken(id: string, tokenOrTokenFunction: Token): Promise<?string> { const token: TokenLiteral = await TokenService.getToken(id, tokenOrTokenFunction); if (token && typeof token === 'object') { return token.write || token.read; } return token; } /** * Function to fetch and cache multiple tokens. The user supplied token can either * itself be a simple token or instead be a function that returns a promise. * This promise then resolves signifying requested tokens were cached. * * This function however does not return tokens as it is expected to only be used * by the token generator to cache all tokens that may be needed in the future. * * @public * @param {Array<string>} idd - box item typed ids * @param {string} tokenOrTokenFunction - Optional token or token function * @return {Promise<TokenMap>} that resolves to a token map */ static async cacheTokens(ids: Array<string>, tokenOrTokenFunction: Token): Promise<void> { // Make sure we are getting typed ids // Tokens should either be null or undefined or string or functions // Anything else is not supported and throw error if ( (tokenOrTokenFunction !== null && tokenOrTokenFunction !== undefined && typeof tokenOrTokenFunction !== 'string' && typeof tokenOrTokenFunction !== 'function') || !ids.every(itemId => itemId.startsWith(TYPED_ID_FOLDER_PREFIX) || itemId.startsWith(TYPED_ID_FILE_PREFIX)) ) { throw error; } // Only need to fetch and cache multiple tokens when the user supplied token was a // token function. This function should internally cache the tokens for future use. if (typeof tokenOrTokenFunction === 'function') { await tokenOrTokenFunction(ids); } return Promise.resolve(); } } export default TokenService;