diff --git a/keyserver/src/fetchers/user-fetchers.js b/keyserver/src/fetchers/user-fetchers.js --- a/keyserver/src/fetchers/user-fetchers.js +++ b/keyserver/src/fetchers/user-fetchers.js @@ -1,5 +1,7 @@ // @flow +import invariant from 'invariant'; + import { hasMinCodeVersion } from 'lib/shared/version-utils.js'; import type { AvatarDBContent, ClientAvatar } from 'lib/types/avatar-types.js'; import { @@ -21,6 +23,7 @@ } from 'lib/types/user-types.js'; import { ServerError } from 'lib/utils/errors.js'; +import { getUploadURL } from './upload-fetchers.js'; import { dbQuery, SQL } from '../database/database.js'; import type { Viewer } from '../session/viewer.js'; @@ -32,9 +35,12 @@ } const query = SQL` - SELECT id, username, avatar - FROM users - WHERE id IN (${userIDs}) + SELECT u.id, u.username, u.avatar, + up.id AS upload_id, up.secret AS upload_secret + FROM users u + LEFT JOIN uploads up + ON up.container = u.id + WHERE u.id IN (${userIDs}) `; const [result] = await dbQuery(query); @@ -43,9 +49,25 @@ const id = row.id.toString(); const avatar: ?AvatarDBContent = row.avatar ? JSON.parse(row.avatar) : null; - // TODO: Handle construction of `ClientImageAvatar` when `type === 'image'` - const clientAvatar: ?ClientAvatar = - avatar && avatar.type !== 'image' ? avatar : null; + let clientAvatar: ?ClientAvatar; + if (avatar && avatar.type !== 'image') { + clientAvatar = avatar; + } else if ( + avatar && + avatar.type === 'image' && + row.upload_id && + row.upload_secret + ) { + const uploadID = row.upload_id.toString(); + invariant( + uploadID === avatar.uploadID, + 'uploadID of upload should match uploadID of image avatar', + ); + clientAvatar = { + type: 'image', + uri: getUploadURL(uploadID, row.upload_secret), + }; + } userInfos[id] = clientAvatar ? { @@ -84,7 +106,8 @@ const query = SQL` SELECT ru.user1, ru.user2, u.username, u.avatar, ru.status AS undirected_status, - rd1.status AS user1_directed_status, rd2.status AS user2_directed_status + rd1.status AS user1_directed_status, rd2.status AS user2_directed_status, + up.id AS upload_id, up.secret AS upload_secret FROM relationships_undirected ru LEFT JOIN relationships_directed rd1 ON rd1.user1 = ru.user1 AND rd1.user2 = ru.user2 @@ -92,6 +115,9 @@ ON rd2.user1 = ru.user2 AND rd2.user2 = ru.user1 LEFT JOIN users u ON u.id != ${viewer.userID} AND (u.id = ru.user1 OR u.id = ru.user2) + LEFT JOIN uploads up + ON up.container != ${viewer.userID} + AND (up.container = ru.user1 OR up.container = ru.user2) `; if (userIDs) { query.append(SQL` @@ -104,12 +130,15 @@ `); } query.append(SQL` - UNION SELECT id AS user1, NULL AS user2, username, avatar, + UNION SELECT u.id AS user1, NULL AS user2, u.username, u.avatar, CAST(NULL AS UNSIGNED) AS undirected_status, CAST(NULL AS UNSIGNED) AS user1_directed_status, - CAST(NULL AS UNSIGNED) AS user2_directed_status - FROM users - WHERE id = ${viewer.userID} + CAST(NULL AS UNSIGNED) AS user2_directed_status, + up.id AS upload_id, up.secret AS upload_secret + FROM users u + LEFT JOIN uploads up + ON up.container = u.id + WHERE u.id = ${viewer.userID} `); const [result] = await dbQuery(query); @@ -121,9 +150,25 @@ const avatar: ?AvatarDBContent = row.avatar ? JSON.parse(row.avatar) : null; - // TODO: Handle construction of `ClientImageAvatar` when `type === 'image'` - const clientAvatar: ?ClientAvatar = - avatar && avatar.type !== 'image' ? avatar : null; + let clientAvatar: ?ClientAvatar; + if (avatar && avatar.type !== 'image') { + clientAvatar = avatar; + } else if ( + avatar && + avatar.type === 'image' && + row.upload_id && + row.upload_secret + ) { + const uploadID = row.upload_id.toString(); + invariant( + uploadID === avatar.uploadID, + 'uploadID of upload should match uploadID of image avatar', + ); + clientAvatar = { + type: 'image', + uri: getUploadURL(uploadID, row.upload_secret), + }; + } const userInfo = clientAvatar ? { @@ -229,9 +274,12 @@ viewer: Viewer, ): Promise { const userQuery = SQL` - SELECT id, username, avatar - FROM users - WHERE id = ${viewer.userID} + SELECT u.id, u.username, u.avatar, + up.id AS upload_id, up.secret AS upload_secret + FROM users u + LEFT JOIN uploads up + ON up.container = u.id + WHERE u.id = ${viewer.userID} `; const settingsQuery = SQL` @@ -257,7 +305,7 @@ } const id = userRow.id.toString(); - const { username, avatar } = userRow; + const { username, upload_id, upload_secret } = userRow; if (stillExpectsEmailFields) { return { @@ -273,8 +321,27 @@ username, }; + const avatar: ?AvatarDBContent = userRow.avatar + ? JSON.parse(userRow.avatar) + : null; + + let clientAvatar: ?ClientAvatar; + if (avatar && avatar.type !== 'image') { + clientAvatar = avatar; + } else if (avatar && avatar.type === 'image' && upload_id && upload_secret) { + const uploadID = upload_id.toString(); + invariant( + uploadID === avatar.uploadID, + 'uploadID of upload should match uploadID of image avatar', + ); + clientAvatar = { + type: 'image', + uri: getUploadURL(uploadID, upload_secret), + }; + } + if (avatar) { - loggedInUserInfo = { ...loggedInUserInfo, avatar: JSON.parse(avatar) }; + loggedInUserInfo = { ...loggedInUserInfo, avatar: clientAvatar }; } const featureGateSettings = !hasMinCodeVersion(viewer.platformDetails, 1000);