Changeset View
Changeset View
Standalone View
Standalone View
keyserver/src/creators/account-creator.js
// @flow | // @flow | ||||
import invariant from 'invariant'; | import invariant from 'invariant'; | ||||
import { getRustAPI } from 'rust-node-addon'; | |||||
import bcrypt from 'twin-bcrypt'; | import bcrypt from 'twin-bcrypt'; | ||||
import ashoat from 'lib/facts/ashoat.js'; | import ashoat from 'lib/facts/ashoat.js'; | ||||
import bots from 'lib/facts/bots.js'; | import bots from 'lib/facts/bots.js'; | ||||
import genesis from 'lib/facts/genesis.js'; | import genesis from 'lib/facts/genesis.js'; | ||||
import { policyTypes } from 'lib/facts/policies.js'; | import { policyTypes } from 'lib/facts/policies.js'; | ||||
import { | import { | ||||
validUsernameRegex, | validUsernameRegex, | ||||
oldValidUsernameRegex, | oldValidUsernameRegex, | ||||
} from 'lib/shared/account-utils.js'; | } from 'lib/shared/account-utils.js'; | ||||
import { hasMinCodeVersion } from 'lib/shared/version-utils.js'; | import { hasMinCodeVersion } from 'lib/shared/version-utils.js'; | ||||
import type { | import type { | ||||
RegisterResponse, | RegisterResponse, | ||||
RegisterRequest, | RegisterRequest, | ||||
} from 'lib/types/account-types.js'; | } from 'lib/types/account-types.js'; | ||||
import type { SignedIdentityKeysBlob } from 'lib/types/crypto-types.js'; | import type { | ||||
SignedIdentityKeysBlob, | |||||
IdentityKeysBlob, | |||||
} from 'lib/types/crypto-types.js'; | |||||
import type { | import type { | ||||
PlatformDetails, | PlatformDetails, | ||||
DeviceTokenUpdateRequest, | DeviceTokenUpdateRequest, | ||||
} from 'lib/types/device-types.js'; | } from 'lib/types/device-types.js'; | ||||
import type { CalendarQuery } from 'lib/types/entry-types.js'; | import type { CalendarQuery } from 'lib/types/entry-types.js'; | ||||
import { messageTypes } from 'lib/types/message-types.js'; | import { messageTypes } from 'lib/types/message-types.js'; | ||||
import type { SIWESocialProof } from 'lib/types/siwe-types.js'; | import type { SIWESocialProof } from 'lib/types/siwe-types.js'; | ||||
import { threadTypes } from 'lib/types/thread-types.js'; | import { threadTypes } from 'lib/types/thread-types.js'; | ||||
Show All 12 Lines | |||||
import { dbQuery, SQL } from '../database/database.js'; | import { dbQuery, SQL } from '../database/database.js'; | ||||
import { deleteCookie } from '../deleters/cookie-deleters.js'; | import { deleteCookie } from '../deleters/cookie-deleters.js'; | ||||
import { fetchThreadInfos } from '../fetchers/thread-fetchers.js'; | import { fetchThreadInfos } from '../fetchers/thread-fetchers.js'; | ||||
import { | import { | ||||
fetchLoggedInUserInfo, | fetchLoggedInUserInfo, | ||||
fetchKnownUserInfos, | fetchKnownUserInfos, | ||||
} from '../fetchers/user-fetchers.js'; | } from '../fetchers/user-fetchers.js'; | ||||
import { verifyCalendarQueryThreadIDs } from '../responders/entry-responders.js'; | import { verifyCalendarQueryThreadIDs } from '../responders/entry-responders.js'; | ||||
import { handleAsyncPromise } from '../responders/handlers.js'; | |||||
import { createNewUserCookie, setNewSession } from '../session/cookies.js'; | import { createNewUserCookie, setNewSession } from '../session/cookies.js'; | ||||
import { createScriptViewer } from '../session/scripts.js'; | import { createScriptViewer } from '../session/scripts.js'; | ||||
import type { Viewer } from '../session/viewer.js'; | import type { Viewer } from '../session/viewer.js'; | ||||
import { updateThread } from '../updaters/thread-updaters.js'; | import { updateThread } from '../updaters/thread-updaters.js'; | ||||
import { viewerAcknowledgmentUpdater } from '../updaters/viewer-acknowledgment-updater.js'; | import { viewerAcknowledgmentUpdater } from '../updaters/viewer-acknowledgment-updater.js'; | ||||
const { commbot } = bots; | const { commbot } = bots; | ||||
Show All 20 Lines | ): Promise<RegisterResponse> { | ||||
} | } | ||||
const usernameQuery = SQL` | const usernameQuery = SQL` | ||||
SELECT COUNT(id) AS count | SELECT COUNT(id) AS count | ||||
FROM users | FROM users | ||||
WHERE LCASE(username) = LCASE(${request.username}) | WHERE LCASE(username) = LCASE(${request.username}) | ||||
`; | `; | ||||
const promises = [dbQuery(usernameQuery)]; | const promises = [dbQuery(usernameQuery)]; | ||||
const { calendarQuery } = request; | const { calendarQuery, signedIdentityKeysBlob } = request; | ||||
if (calendarQuery) { | if (calendarQuery) { | ||||
promises.push(verifyCalendarQueryThreadIDs(calendarQuery)); | promises.push(verifyCalendarQueryThreadIDs(calendarQuery)); | ||||
} | } | ||||
const [[usernameResult]] = await Promise.all(promises); | const [[usernameResult]] = await Promise.all(promises); | ||||
if ( | if ( | ||||
reservedUsernamesSet.has(request.username.toLowerCase()) || | reservedUsernamesSet.has(request.username.toLowerCase()) || | ||||
isValidEthereumAddress(request.username.toLowerCase()) | isValidEthereumAddress(request.username.toLowerCase()) | ||||
Show All 15 Lines | const deviceToken = request.deviceTokenUpdateRequest | ||||
: viewer.deviceToken; | : viewer.deviceToken; | ||||
const [id] = await createIDs('users', 1); | const [id] = await createIDs('users', 1); | ||||
const newUserRow = [id, request.username, hash, time]; | const newUserRow = [id, request.username, hash, time]; | ||||
const newUserQuery = SQL` | const newUserQuery = SQL` | ||||
INSERT INTO users(id, username, hash, creation_time) | INSERT INTO users(id, username, hash, creation_time) | ||||
VALUES ${[newUserRow]} | VALUES ${[newUserRow]} | ||||
`; | `; | ||||
const [userViewerData] = await Promise.all([ | const [userViewerData, rustAPI] = await Promise.all([ | ||||
createNewUserCookie(id, { | createNewUserCookie(id, { | ||||
platformDetails: request.platformDetails, | platformDetails: request.platformDetails, | ||||
deviceToken, | deviceToken, | ||||
signedIdentityKeysBlob: request.signedIdentityKeysBlob, | signedIdentityKeysBlob, | ||||
}), | }), | ||||
getRustAPI(), | |||||
ashoat: @jon's approach in D6944 is actually probably better... I should've suggested that. Basically… | |||||
deleteCookie(viewer.cookieID), | deleteCookie(viewer.cookieID), | ||||
dbQuery(newUserQuery), | dbQuery(newUserQuery), | ||||
]); | ]); | ||||
viewer.setNewCookie(userViewerData); | viewer.setNewCookie(userViewerData); | ||||
if (calendarQuery) { | if (calendarQuery) { | ||||
await setNewSession(viewer, calendarQuery, 0); | await setNewSession(viewer, calendarQuery, 0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | await Promise.all([ | ||||
fetchLoggedInUserInfo(viewer), | fetchLoggedInUserInfo(viewer), | ||||
]); | ]); | ||||
const rawMessageInfos = [ | const rawMessageInfos = [ | ||||
...ashoatThreadResult.newMessageInfos, | ...ashoatThreadResult.newMessageInfos, | ||||
...privateThreadResult.newMessageInfos, | ...privateThreadResult.newMessageInfos, | ||||
...messageInfos, | ...messageInfos, | ||||
]; | ]; | ||||
if (signedIdentityKeysBlob) { | |||||
const identityKeys: IdentityKeysBlob = JSON.parse( | |||||
signedIdentityKeysBlob.payload, | |||||
); | |||||
handleAsyncPromise( | |||||
rustAPI.registerUser( | |||||
id, | |||||
identityKeys.primaryIdentityPublicKeys.ed25519, | |||||
request.username, | |||||
request.password, | |||||
signedIdentityKeysBlob, | |||||
), | |||||
); | |||||
} | |||||
return { | return { | ||||
id, | id, | ||||
rawMessageInfos, | rawMessageInfos, | ||||
currentUserInfo, | currentUserInfo, | ||||
cookieChange: { | cookieChange: { | ||||
threadInfos: threadsResult.threadInfos, | threadInfos: threadsResult.threadInfos, | ||||
userInfos: values(userInfos), | userInfos: values(userInfos), | ||||
}, | }, | ||||
▲ Show 20 Lines • Show All 99 Lines • Show Last 20 Lines |
@jon's approach in D6944 is actually probably better... I should've suggested that. Basically we don't need to wait on getRustAPI() at all since we're wrapping the call with handleAsyncPromise. So instead we can construct a promise that composes getRustAPI() with the later call