summaryrefslogtreecommitdiff
path: root/src/server/api/common
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2020-01-30 04:37:25 +0900
committerGitHub <noreply@github.com>2020-01-30 04:37:25 +0900
commitf6154dc0af1a0d65819e87240f4385f9573095cb (patch)
tree699a5ca07d6727b7f8497d4769f25d6d62f94b5a /src/server/api/common
parentAdd Event activity-type support (#5785) (diff)
downloadsharkey-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.ts18
-rw-r--r--src/server/api/common/signin.ts5
-rw-r--r--src/server/api/common/signup.ts104
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 };
+}