diff --git a/keyserver/src/user/identity.js b/keyserver/src/user/identity.js index 6de3e36b3..f337295bd 100644 --- a/keyserver/src/user/identity.js +++ b/keyserver/src/user/identity.js @@ -1,100 +1,128 @@ // @flow import type { QueryResults } from 'mysql'; import ashoat from 'lib/facts/ashoat.js'; import { getCommConfig } from 'lib/utils/comm-config.js'; import { ashoatKeyserverID } from 'lib/utils/validation-utils.js'; import type { UserCredentials } from './checks'; import { SQL, dbQuery } from '../database/database.js'; -const userIDMetadataKey = 'user_id'; -const accessTokenMetadataKey = 'access_token'; +const metadataKeys = Object.freeze({ + USER_ID: 'user_id', + ACCESS_TOKEN: 'access_token', +}); + +type MetadataKey = $Values; // This information is minted when registering with identity service // Naming should reflect the rust-bindings: userId -> user_id export type IdentityInfo = { +userId: string, +accessToken: string }; -async function fetchIdentityInfo(): Promise { - const versionQuery = SQL` +// This function should only be used to fetch string values from the metadata +// table +async function fetchMetadata( + keys: $ReadOnlyArray, +): Promise> { + const metadataQuery = SQL` SELECT name, data FROM metadata - WHERE name IN (${userIDMetadataKey}, ${accessTokenMetadataKey}) + WHERE name IN (${keys}) `; - const [result] = await dbQuery(versionQuery); - let userID, accessToken; + const [result] = await dbQuery(metadataQuery); + + const metadataMap = new Map(); + for (const row of result) { - if (row.name === userIDMetadataKey) { - userID = row.data; - } else if (row.name === accessTokenMetadataKey) { - accessToken = row.data; - } + metadataMap.set(row.name, row.data); } + return metadataMap; +} + +async function fetchIdentityInfo(): Promise { + const keys = [metadataKeys.USER_ID, metadataKeys.ACCESS_TOKEN]; + + const metadataMap = await fetchMetadata(keys); + + const userID = metadataMap.get(metadataKeys.USER_ID); + const accessToken = metadataMap.get(metadataKeys.ACCESS_TOKEN); + if (!userID || !accessToken) { return null; } + return { userId: userID, accessToken }; } let cachedKeyserverID: ?string; async function thisKeyserverID(): Promise { if (cachedKeyserverID) { return cachedKeyserverID; } const config = await getCommConfig({ folder: 'secrets', name: 'user_credentials', }); if (!config?.usingIdentityCredentials) { return ashoatKeyserverID; } const identityInfo = await fetchIdentityInfo(); cachedKeyserverID = identityInfo?.userId ?? ashoatKeyserverID; return cachedKeyserverID; } export type AdminData = { +username: string, +id: string, }; async function thisKeyserverAdmin(): Promise { const config = await getCommConfig({ folder: 'secrets', name: 'user_credentials', }); if (!config) { return { id: ashoat.id, username: ashoat.username, }; } const id = await thisKeyserverID(); return { id, username: config.username, }; } -function saveIdentityInfo(userInfo: IdentityInfo): Promise { +function saveMetadata( + metadataMap: Map, +): Promise { + const entries = [...metadataMap.entries()]; const updateQuery = SQL` REPLACE INTO metadata (name, data) - VALUES (${userIDMetadataKey}, ${userInfo.userId}), - (${accessTokenMetadataKey}, ${userInfo.accessToken}) + VALUES ${entries} `; return dbQuery(updateQuery); } +function saveIdentityInfo(userInfo: IdentityInfo): Promise { + const metadataMap = new Map(); + metadataMap.set(metadataKeys.USER_ID, userInfo.userId); + metadataMap.set(metadataKeys.ACCESS_TOKEN, userInfo.accessToken); + + return saveMetadata(metadataMap); +} + export { fetchIdentityInfo, thisKeyserverID, thisKeyserverAdmin, saveIdentityInfo, };