diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2020-01-30 04:37:25 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-01-30 04:37:25 +0900 |
| commit | f6154dc0af1a0d65819e87240f4385f9573095cb (patch) | |
| tree | 699a5ca07d6727b7f8497d4769f25d6d62f94b5a /src/server/api/common | |
| parent | Add Event activity-type support (#5785) (diff) | |
| download | sharkey-f6154dc0af1a0d65819e87240f4385f9573095cb.tar.gz sharkey-f6154dc0af1a0d65819e87240f4385f9573095cb.tar.bz2 sharkey-f6154dc0af1a0d65819e87240f4385f9573095cb.zip | |
v12 (#5712)
Co-authored-by: MeiMei <30769358+mei23@users.noreply.github.com>
Co-authored-by: Satsuki Yanagi <17376330+u1-liquid@users.noreply.github.com>
Diffstat (limited to 'src/server/api/common')
| -rw-r--r-- | src/server/api/common/read-notification.ts | 18 | ||||
| -rw-r--r-- | src/server/api/common/signin.ts | 5 | ||||
| -rw-r--r-- | src/server/api/common/signup.ts | 104 |
3 files changed, 111 insertions, 16 deletions
diff --git a/src/server/api/common/read-notification.ts b/src/server/api/common/read-notification.ts index c8d43ba286..f686446c5c 100644 --- a/src/server/api/common/read-notification.ts +++ b/src/server/api/common/read-notification.ts @@ -1,8 +1,8 @@ import { publishMainStream } from '../../../services/stream'; import { User } from '../../../models/entities/user'; import { Notification } from '../../../models/entities/notification'; -import { Mutings, Notifications } from '../../../models'; -import { In, Not } from 'typeorm'; +import { Notifications, Users } from '../../../models'; +import { In } from 'typeorm'; /** * Mark notifications as read @@ -11,11 +11,6 @@ export async function readNotification( userId: User['id'], notificationIds: Notification['id'][] ) { - const mute = await Mutings.find({ - muterId: userId - }); - const mutedUserIds = mute.map(m => m.muteeId); - // Update documents await Notifications.update({ id: In(notificationIds), @@ -24,14 +19,7 @@ export async function readNotification( isRead: true }); - // Calc count of my unread notifications - const count = await Notifications.count({ - notifieeId: userId, - ...(mutedUserIds.length > 0 ? { notifierId: Not(In(mutedUserIds)) } : {}), - isRead: false - }); - - if (count === 0) { + if (!await Users.getHasUnreadNotification(userId)) { // 全ての(いままで未読だった)通知を(これで)読みましたよというイベントを発行 publishMainStream(userId, 'readAllNotifications'); } diff --git a/src/server/api/common/signin.ts b/src/server/api/common/signin.ts index 66f89182d2..aa2786f8fc 100644 --- a/src/server/api/common/signin.ts +++ b/src/server/api/common/signin.ts @@ -24,7 +24,10 @@ export default function(ctx: Koa.Context, user: ILocalUser, redirect = false) { ctx.redirect(config.url); } else { - ctx.body = { i: user.token }; + ctx.body = { + id: user.id, + i: user.token + }; ctx.status = 200; } diff --git a/src/server/api/common/signup.ts b/src/server/api/common/signup.ts new file mode 100644 index 0000000000..f0eb27e5e4 --- /dev/null +++ b/src/server/api/common/signup.ts @@ -0,0 +1,104 @@ +import * as bcrypt from 'bcryptjs'; +import { generateKeyPair } from 'crypto'; +import generateUserToken from './generate-native-user-token'; +import { User } from '../../../models/entities/user'; +import { Users, UsedUsernames } from '../../../models'; +import { UserProfile } from '../../../models/entities/user-profile'; +import { getConnection } from 'typeorm'; +import { genId } from '../../../misc/gen-id'; +import { toPunyNullable } from '../../../misc/convert-host'; +import { UserKeypair } from '../../../models/entities/user-keypair'; +import { usersChart } from '../../../services/chart'; +import { UsedUsername } from '../../../models/entities/used-username'; + +export async function signup(username: User['username'], password: UserProfile['password'], host: string | null = null) { + // Validate username + if (!Users.validateLocalUsername.ok(username)) { + throw new Error('INVALID_USERNAME'); + } + + // Validate password + if (!Users.validatePassword.ok(password)) { + throw new Error('INVALID_PASSWORD'); + } + + const usersCount = await Users.count({}); + + // Generate hash of password + const salt = await bcrypt.genSalt(8); + const hash = await bcrypt.hash(password, salt); + + // Generate secret + const secret = generateUserToken(); + + // Check username duplication + if (await Users.findOne({ usernameLower: username.toLowerCase(), host: null })) { + throw new Error('DUPLICATED_USERNAME'); + } + + // Check deleted username duplication + if (await UsedUsernames.findOne({ username: username.toLowerCase() })) { + throw new Error('USED_USERNAME'); + } + + const keyPair = await new Promise<string[]>((res, rej) => + generateKeyPair('rsa', { + modulusLength: 4096, + publicKeyEncoding: { + type: 'spki', + format: 'pem' + }, + privateKeyEncoding: { + type: 'pkcs8', + format: 'pem', + cipher: undefined, + passphrase: undefined + } + } as any, (err, publicKey, privateKey) => + err ? rej(err) : res([publicKey, privateKey]) + )); + + let account!: User; + + // Start transaction + await getConnection().transaction(async transactionalEntityManager => { + const exist = await transactionalEntityManager.findOne(User, { + usernameLower: username.toLowerCase(), + host: null + }); + + if (exist) throw new Error(' the username is already used'); + + account = await transactionalEntityManager.save(new User({ + id: genId(), + createdAt: new Date(), + username: username, + usernameLower: username.toLowerCase(), + host: toPunyNullable(host), + token: secret, + isAdmin: usersCount === 0, + })); + + await transactionalEntityManager.save(new UserKeypair({ + publicKey: keyPair[0], + privateKey: keyPair[1], + userId: account.id + })); + + await transactionalEntityManager.save(new UserProfile({ + userId: account.id, + autoAcceptFollowed: true, + autoWatch: false, + password: hash, + })); + + await transactionalEntityManager.save(new UsedUsername({ + createdAt: new Date(), + username: username.toLowerCase(), + })); + }); + + usersChart.update(account, true); + + return { account, secret }; +} |