diff --git a/keyserver/src/creators/account-creator.js b/keyserver/src/creators/account-creator.js --- a/keyserver/src/creators/account-creator.js +++ b/keyserver/src/creators/account-creator.js @@ -193,4 +193,144 @@ }; } -export default createAccount; +async function createSIWEAccount( + viewer: Viewer, + request: RegisterRequest, +): Promise { + if (request.password.trim() === '') { + throw new ServerError('empty_password'); + } + const usernameRegex = hasMinCodeVersion(viewer.platformDetails, 69) + ? validUsernameRegex + : oldValidUsernameRegex; + if (request.username.search(usernameRegex) === -1) { + throw new ServerError('invalid_username'); + } + + const usernameQuery = SQL` + SELECT COUNT(id) AS count + FROM users + WHERE LCASE(username) = LCASE(${request.username}) + `; + const promises = [dbQuery(usernameQuery)]; + const { calendarQuery } = request; + if (calendarQuery) { + promises.push(verifyCalendarQueryThreadIDs(calendarQuery)); + } + + const [[usernameResult]] = await Promise.all(promises); + if (reservedUsernamesSet.has(request.username.toLowerCase())) { + if (hasMinCodeVersion(viewer.platformDetails, 120)) { + throw new ServerError('username_reserved'); + } else { + throw new ServerError('username_taken'); + } + } + if (usernameResult[0].count !== 0) { + throw new ServerError('username_taken'); + } + + const hash = bcrypt.hashSync(request.password); + const time = Date.now(); + const deviceToken = request.deviceTokenUpdateRequest + ? request.deviceTokenUpdateRequest.deviceToken + : viewer.deviceToken; + const [id] = await createIDs('users', 1); + const newUserRow = [id, request.username, hash, time]; + const newUserQuery = SQL` + INSERT INTO users(id, username, hash, creation_time) + VALUES ${[newUserRow]} + `; + const [userViewerData] = await Promise.all([ + createNewUserCookie(id, { + platformDetails: request.platformDetails, + deviceToken, + }), + deleteCookie(viewer.cookieID), + dbQuery(newUserQuery), + ]); + viewer.setNewCookie(userViewerData); + + if (calendarQuery) { + await setNewSession(viewer, calendarQuery, 0); + } + + await Promise.all([ + updateThread( + createScriptViewer(ashoat.id), + { + threadID: genesis.id, + changes: { newMemberIDs: [id] }, + }, + { forceAddMembers: true, silenceMessages: true, ignorePermissions: true }, + ), + viewerAcknowledgmentUpdater(viewer, policyTypes.tosAndPrivacyPolicy), + ]); + + const [privateThreadResult, ashoatThreadResult] = await Promise.all([ + createPrivateThread(viewer, request.username), + createThread( + viewer, + { + type: threadTypes.PERSONAL, + initialMemberIDs: [ashoat.id], + }, + { forceAddMembers: true }, + ), + ]); + const ashoatThreadID = ashoatThreadResult.newThreadInfo + ? ashoatThreadResult.newThreadInfo.id + : ashoatThreadResult.newThreadID; + const privateThreadID = privateThreadResult.newThreadInfo + ? privateThreadResult.newThreadInfo.id + : privateThreadResult.newThreadID; + invariant( + ashoatThreadID && privateThreadID, + 'createThread should return either newThreadInfo or newThreadID', + ); + + let messageTime = Date.now(); + const ashoatMessageDatas = ashoatMessages.map(message => ({ + type: messageTypes.TEXT, + threadID: ashoatThreadID, + creatorID: ashoat.id, + time: messageTime++, + text: message, + })); + const privateMessageDatas = privateMessages.map(message => ({ + type: messageTypes.TEXT, + threadID: privateThreadID, + creatorID: commbot.userID, + time: messageTime++, + text: message, + })); + const messageDatas = [...ashoatMessageDatas, ...privateMessageDatas]; + const [ + messageInfos, + threadsResult, + userInfos, + currentUserInfo, + ] = await Promise.all([ + createMessages(viewer, messageDatas), + fetchThreadInfos(viewer), + fetchKnownUserInfos(viewer), + fetchLoggedInUserInfo(viewer), + ]); + const rawMessageInfos = [ + ...ashoatThreadResult.newMessageInfos, + ...privateThreadResult.newMessageInfos, + ...messageInfos, + ]; + + return { + id, + rawMessageInfos, + currentUserInfo, + cookieChange: { + threadInfos: threadsResult.threadInfos, + userInfos: values(userInfos), + }, + }; +} + +export { createAccount, createSIWEAccount }; diff --git a/keyserver/src/responders/user-responders.js b/keyserver/src/responders/user-responders.js --- a/keyserver/src/responders/user-responders.js +++ b/keyserver/src/responders/user-responders.js @@ -44,7 +44,7 @@ tOldValidUsername, } from 'lib/utils/validation-utils'; -import createAccount from '../creators/account-creator'; +import { createAccount } from '../creators/account-creator'; import { dbQuery, SQL } from '../database/database'; import { deleteAccount } from '../deleters/account-deleters'; import { deleteCookie } from '../deleters/cookie-deleters';