diff --git a/packages/identity-service/src/authMiddleware.js b/packages/identity-service/src/authMiddleware.js index c4bfff3b547..f01418851c3 100644 --- a/packages/identity-service/src/authMiddleware.js +++ b/packages/identity-service/src/authMiddleware.js @@ -11,6 +11,68 @@ const models = require('./models') const audiusLibsWrapper = require('./audiusLibsInstance') const { encodeHashId, decodeHashId } = require('./utils/hashIds') +const SDK_USER_LOOKUP_TIMEOUT_MS = 3000 + +const withTimeout = (promise, ms, message) => { + let timeoutId + const timeout = new Promise((_resolve, reject) => { + timeoutId = setTimeout(() => reject(new Error(message)), ms) + }) + + return Promise.race([ + promise, + timeout + ]).finally(() => clearTimeout(timeoutId)) +} + +const getUserAccountForWallet = async ({ + req, + walletAddress, + encodedDataMessage, + signature +}) => { + const audiusSdk = req.app.get('audiusSdk') + const usersApi = audiusSdk?.users ?? audiusSdk?.full?.users + + if (!usersApi) { + throw new Error('Audius SDK users API is unavailable') + } + + return withTimeout( + usersApi.getUserAccount({ + wallet: walletAddress, + encodedDataMessage, + encodedDataSignature: signature + }), + SDK_USER_LOOKUP_TIMEOUT_MS, + 'audiusSdk.users.getUserAccount timed out' + ) +} + +const backfillUserFromAccount = async ({ + req, + user, + walletAddress, + encodedDataMessage, + signature +}) => { + const res = await getUserAccountForWallet({ + req, + walletAddress, + encodedDataMessage, + signature + }) + const accountUser = res.data.user + const userId = decodeHashId(accountUser.id) + const handle = accountUser.handle + + return user.update({ + blockchainUserId: userId, + handle, + isGuest: !handle + }) +} + /** * Queries for whether the wallet address has privilege to act as actingUserId * @param {number} managerWalletAddress @@ -114,18 +176,12 @@ async function authMiddleware(req, res, next) { // ensuring that the user.handle always represents the latest state on chain if (!user.blockchainUserId || !user.handle) { try { - const res = await req.app.get('audiusSdk').full.users.getUserAccount({ - wallet: walletAddress, + user = await backfillUserFromAccount({ + req, + user, + walletAddress, encodedDataMessage, - encodedDataSignature: signature - }) - const discprovUser = res.data.user - const userId = decodeHashId(discprovUser.id) - const handle = discprovUser.handle - user = await user.update({ - blockchainUserId: userId, - handle, - isGuest: !handle + signature }) } catch (e) { req.logger.error(e, 'Failed to update blockchainUserId/handle') @@ -181,18 +237,12 @@ const parameterizedAuthMiddleware = ({ shouldRespondBadRequest }) => { if (!user.blockchainUserId || !user.handle) { try { - const res = await req.app.get('audiusSdk').full.users.getUserAccount({ - wallet: walletAddress, + user = await backfillUserFromAccount({ + req, + user, + walletAddress, encodedDataMessage, - encodedDataSignature: signature - }) - const discprovUser = res.data.user - const userId = decodeHashId(discprovUser.id) - const handle = discprovUser.handle - user = await user.update({ - blockchainUserId: userId, - handle, - isGuest: !handle + signature }) } catch (e) { req.logger.error(e, 'Failed to update blockchainUserId/handle') diff --git a/packages/identity-service/src/routes/idSignals.js b/packages/identity-service/src/routes/idSignals.js index a0adca05bfe..ad5994db924 100644 --- a/packages/identity-service/src/routes/idSignals.js +++ b/packages/identity-service/src/routes/idSignals.js @@ -79,6 +79,13 @@ module.exports = function (app) { handleResponse(async (req) => { const { blockchainUserId, handle } = req.user + if (!handle) { + req.logger.warn( + `idSignals | record_ip | Skipping IP record for user with id ${blockchainUserId} because handle is missing` + ) + return successResponse() + } + try { const userIP = getIP(req) req.logger.info( diff --git a/packages/web/src/pages/sign-up-page/pages/LoadingAccountPage.tsx b/packages/web/src/pages/sign-up-page/pages/LoadingAccountPage.tsx index d59b27b3bb2..722847a344b 100644 --- a/packages/web/src/pages/sign-up-page/pages/LoadingAccountPage.tsx +++ b/packages/web/src/pages/sign-up-page/pages/LoadingAccountPage.tsx @@ -1,5 +1,9 @@ import { useEffect } from 'react' +import { + selectIsAccountComplete, + useCurrentAccountUser +} from '@audius/common/api' import { route } from '@audius/common/utils' import { Flex } from '@audius/harmony' import { useSelector } from 'react-redux' @@ -26,10 +30,15 @@ export const LoadingAccountPage = () => { const isFastReferral = useFastReferral() const accountReady = useSelector(getAccountReady) const accountCreationStatus = useSelector(getStatus) + const { data: hasCompleteAccount = false } = useCurrentAccountUser({ + select: selectIsAccountComplete + }) const isAccountReady = isFastReferral - ? accountReady - : accountReady || accountCreationStatus === EditingStatus.SUCCESS + ? accountReady || hasCompleteAccount + : accountReady || + hasCompleteAccount || + accountCreationStatus === EditingStatus.SUCCESS useEffect(() => { if (isAccountReady) {