From 56678cbac0fc4a54c24df63f2a7e652ba0b76b1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Sun, 19 May 2019 15:08:16 +0900 Subject: [PATCH 1/9] Update README.md [AUTOGEN] (#4940) --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 363bb068b..28abc57f8 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md). noellabo CG Hekovic +Naoki Hirayama dansup Satsuki Yanagi @@ -161,6 +162,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md). noellabo CG Hekovic +Naoki Hirayama dansup @@ -173,7 +175,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
Takashi Shibuya
-**Last updated:** Mon, 13 May 2019 06:13:06 UTC +**Last updated:** Sun, 19 May 2019 02:37:06 UTC :four_leaf_clover: Copyright From e103904a0454d8a05cea60d984bc1ef1e2b9e652 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 19 May 2019 20:41:23 +0900 Subject: [PATCH 2/9] Resolve #4941 --- locales/ja-JP.yml | 9 +- migration/1558257926829-UserGroupInvite.ts | 25 +++++ .../app/common/views/components/messaging.vue | 5 +- .../common/views/pages/user-group-editor.vue | 12 ++- .../app/common/views/pages/user-groups.vue | 92 +++++++++++++++---- src/db/postgre.ts | 2 + src/models/entities/user-group-invite.ts | 42 +++++++++ src/models/entities/user-group-joining.ts | 1 + src/models/index.ts | 2 + src/models/repositories/user-group-invite.ts | 24 +++++ .../api/endpoints/i/user-group-invites.ts | 45 +++++++++ .../users/groups/invitations/accept.ts | 63 +++++++++++++ .../users/groups/invitations/reject.ts | 53 +++++++++++ .../users/groups/{push.ts => invite.ts} | 32 +++++-- .../api/endpoints/users/groups/joined.ts | 6 ++ 15 files changed, 379 insertions(+), 34 deletions(-) create mode 100644 migration/1558257926829-UserGroupInvite.ts create mode 100644 src/models/entities/user-group-invite.ts create mode 100644 src/models/repositories/user-group-invite.ts create mode 100644 src/server/api/endpoints/i/user-group-invites.ts create mode 100644 src/server/api/endpoints/users/groups/invitations/accept.ts create mode 100644 src/server/api/endpoints/users/groups/invitations/reject.ts rename src/server/api/endpoints/users/groups/{push.ts => invite.ts} (70%) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 529a63e6e..904737884 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -485,6 +485,7 @@ common/views/components/messaging.vue: group: "グループ" start-with-user: "ユーザーとトークを開始" start-with-group: "グループとトークを開始" + select-group: "グループを選択してください" common/views/components/messaging-room.vue: not-talked-user: "このユーザーとの会話はありません" @@ -764,7 +765,8 @@ common/views/components/user-group-editor.vue: remove-user: "このグループから削除" delete-are-you-sure: "グループ「$1」を削除しますか?" deleted: "削除しました" - add-user: "メンバーを追加" + invite: "招待" + invited: "招待を送信しました" common/views/components/user-lists.vue: user-lists: "リスト" @@ -775,6 +777,11 @@ common/views/components/user-groups.vue: user-groups: "グループ" create-group: "グループを作成" group-name: "グループ名" + owned-groups: "自分のグループ" + joined-groups: "参加しているグループ" + invites: "招待" + accept-invite: "参加" + reject-invite: "拒否" common/views/widgets/broadcast.vue: fetching: "確認中" diff --git a/migration/1558257926829-UserGroupInvite.ts b/migration/1558257926829-UserGroupInvite.ts new file mode 100644 index 000000000..a78e47922 --- /dev/null +++ b/migration/1558257926829-UserGroupInvite.ts @@ -0,0 +1,25 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class UserGroupInvite1558257926829 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE "user_group_invite" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "userGroupId" character varying(32) NOT NULL, CONSTRAINT "PK_3893884af0d3a5f4d01e7921a97" PRIMARY KEY ("id"))`); + await queryRunner.query(`CREATE INDEX "IDX_1039988afa3bf991185b277fe0" ON "user_group_invite" ("userId") `); + await queryRunner.query(`CREATE INDEX "IDX_e10924607d058004304611a436" ON "user_group_invite" ("userGroupId") `); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_78787741f9010886796f2320a4" ON "user_group_invite" ("userId", "userGroupId") `); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_d9ecaed8c6dc43f3592c229282" ON "user_group_joining" ("userId", "userGroupId") `); + await queryRunner.query(`ALTER TABLE "user_group_invite" ADD CONSTRAINT "FK_1039988afa3bf991185b277fe03" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "user_group_invite" ADD CONSTRAINT "FK_e10924607d058004304611a436a" FOREIGN KEY ("userGroupId") REFERENCES "user_group"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "user_group_invite" DROP CONSTRAINT "FK_e10924607d058004304611a436a"`); + await queryRunner.query(`ALTER TABLE "user_group_invite" DROP CONSTRAINT "FK_1039988afa3bf991185b277fe03"`); + await queryRunner.query(`DROP INDEX "IDX_d9ecaed8c6dc43f3592c229282"`); + await queryRunner.query(`DROP INDEX "IDX_78787741f9010886796f2320a4"`); + await queryRunner.query(`DROP INDEX "IDX_e10924607d058004304611a436"`); + await queryRunner.query(`DROP INDEX "IDX_1039988afa3bf991185b277fe0"`); + await queryRunner.query(`DROP TABLE "user_group_invite"`); + } + +} diff --git a/src/client/app/common/views/components/messaging.vue b/src/client/app/common/views/components/messaging.vue index 01d7a5a79..c7c70a4ce 100644 --- a/src/client/app/common/views/components/messaging.vue +++ b/src/client/app/common/views/components/messaging.vue @@ -217,12 +217,13 @@ export default Vue.extend({ this.navigate(user); }, async startGroup() { - const groups = await this.$root.api('users/groups/joined'); + const groups1 = await this.$root.api('users/groups/owned'); + const groups2 = await this.$root.api('users/groups/joined'); const { canceled, result: group } = await this.$root.dialog({ type: null, title: this.$t('select-group'), select: { - items: groups.map(group => ({ + items: groups1.concat(groups2).map(group => ({ value: group, text: group.name })) }, diff --git a/src/client/app/common/views/pages/user-group-editor.vue b/src/client/app/common/views/pages/user-group-editor.vue index fb9f1a677..ef79689ae 100644 --- a/src/client/app/common/views/pages/user-group-editor.vue +++ b/src/client/app/common/views/pages/user-group-editor.vue @@ -16,7 +16,7 @@
- {{ $t('add-user') }} + {{ $t('invite') }}
@@ -134,18 +134,22 @@ export default Vue.extend({ }); }, - async add() { + async invite() { + const t = this.$t('invited'); const { result: user } = await this.$root.dialog({ user: { local: true } }); if (user == null) return; - this.$root.api('users/groups/push', { + this.$root.api('users/groups/invite', { groupId: this.group.id, userId: user.id }).then(() => { - this.fetchUsers(); + this.$root.dialog({ + type: 'success', + text: t + }); }); } } diff --git a/src/client/app/common/views/pages/user-groups.vue b/src/client/app/common/views/pages/user-groups.vue index 336772799..2a89196e5 100644 --- a/src/client/app/common/views/pages/user-groups.vue +++ b/src/client/app/common/views/pages/user-groups.vue @@ -1,36 +1,70 @@ diff --git a/src/db/postgre.ts b/src/db/postgre.ts index 40b9ce151..fcec68602 100644 --- a/src/db/postgre.ts +++ b/src/db/postgre.ts @@ -26,6 +26,7 @@ import { UserList } from '../models/entities/user-list'; import { UserListJoining } from '../models/entities/user-list-joining'; import { UserGroup } from '../models/entities/user-group'; import { UserGroupJoining } from '../models/entities/user-group-joining'; +import { UserGroupInvite } from '../models/entities/user-group-invite'; import { Hashtag } from '../models/entities/hashtag'; import { NoteFavorite } from '../models/entities/note-favorite'; import { AbuseUserReport } from '../models/entities/abuse-user-report'; @@ -110,6 +111,7 @@ export function initDb(justBorrow = false, sync = false, log = false) { UserListJoining, UserGroup, UserGroupJoining, + UserGroupInvite, UserNotePining, Following, FollowRequest, diff --git a/src/models/entities/user-group-invite.ts b/src/models/entities/user-group-invite.ts new file mode 100644 index 000000000..2adf2c024 --- /dev/null +++ b/src/models/entities/user-group-invite.ts @@ -0,0 +1,42 @@ +import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; +import { User } from './user'; +import { UserGroup } from './user-group'; +import { id } from '../id'; + +@Entity() +@Index(['userId', 'userGroupId'], { unique: true }) +export class UserGroupInvite { + @PrimaryColumn(id()) + public id: string; + + @Column('timestamp with time zone', { + comment: 'The created date of the UserGroupInvite.' + }) + public createdAt: Date; + + @Index() + @Column({ + ...id(), + comment: 'The user ID.' + }) + public userId: User['id']; + + @ManyToOne(type => User, { + onDelete: 'CASCADE' + }) + @JoinColumn() + public user: User | null; + + @Index() + @Column({ + ...id(), + comment: 'The group ID.' + }) + public userGroupId: UserGroup['id']; + + @ManyToOne(type => UserGroup, { + onDelete: 'CASCADE' + }) + @JoinColumn() + public userGroup: UserGroup | null; +} diff --git a/src/models/entities/user-group-joining.ts b/src/models/entities/user-group-joining.ts index 17b534f42..e09c3230f 100644 --- a/src/models/entities/user-group-joining.ts +++ b/src/models/entities/user-group-joining.ts @@ -4,6 +4,7 @@ import { UserGroup } from './user-group'; import { id } from '../id'; @Entity() +@Index(['userId', 'userGroupId'], { unique: true }) export class UserGroupJoining { @PrimaryColumn(id()) public id: string; diff --git a/src/models/index.ts b/src/models/index.ts index c05d7febe..a60cd10ef 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -22,6 +22,7 @@ import { UserListRepository } from './repositories/user-list'; import { UserListJoining } from './entities/user-list-joining'; import { UserGroupRepository } from './repositories/user-group'; import { UserGroupJoining } from './entities/user-group-joining'; +import { UserGroupInviteRepository } from './repositories/user-group-invite'; import { FollowRequestRepository } from './repositories/follow-request'; import { MutingRepository } from './repositories/muting'; import { BlockingRepository } from './repositories/blocking'; @@ -56,6 +57,7 @@ export const UserLists = getCustomRepository(UserListRepository); export const UserListJoinings = getRepository(UserListJoining); export const UserGroups = getCustomRepository(UserGroupRepository); export const UserGroupJoinings = getRepository(UserGroupJoining); +export const UserGroupInvites = getCustomRepository(UserGroupInviteRepository); export const UserNotePinings = getRepository(UserNotePining); export const Followings = getCustomRepository(FollowingRepository); export const FollowRequests = getCustomRepository(FollowRequestRepository); diff --git a/src/models/repositories/user-group-invite.ts b/src/models/repositories/user-group-invite.ts new file mode 100644 index 000000000..1d4c2aa15 --- /dev/null +++ b/src/models/repositories/user-group-invite.ts @@ -0,0 +1,24 @@ +import { EntityRepository, Repository } from 'typeorm'; +import { UserGroupInvite } from '../entities/user-group-invite'; +import { UserGroups } from '..'; +import { ensure } from '../../prelude/ensure'; + +@EntityRepository(UserGroupInvite) +export class UserGroupInviteRepository extends Repository { + public async pack( + src: UserGroupInvite['id'] | UserGroupInvite, + ) { + const invite = typeof src === 'object' ? src : await this.findOne(src).then(ensure); + + return { + id: invite.id, + group: await UserGroups.pack(invite.userGroup || invite.userGroupId), + }; + } + + public packMany( + invites: any[], + ) { + return Promise.all(invites.map(x => this.pack(x))); + } +} diff --git a/src/server/api/endpoints/i/user-group-invites.ts b/src/server/api/endpoints/i/user-group-invites.ts new file mode 100644 index 000000000..9d07fa31a --- /dev/null +++ b/src/server/api/endpoints/i/user-group-invites.ts @@ -0,0 +1,45 @@ +import $ from 'cafy'; +import { ID } from '../../../../misc/cafy-id'; +import define from '../../define'; +import { UserGroupInvites } from '../../../../models'; +import { makePaginationQuery } from '../../common/make-pagination-query'; + +export const meta = { + desc: { + 'ja-JP': 'グループへの招待一覧を取得します。', + 'en-US': 'Get user group invitations.' + }, + + tags: ['account', 'groups'], + + requireCredential: true, + + kind: 'read:user-groups', + + params: { + limit: { + validator: $.optional.num.range(1, 100), + default: 10 + }, + + sinceId: { + validator: $.optional.type(ID), + }, + + untilId: { + validator: $.optional.type(ID), + }, + } +}; + +export default define(meta, async (ps, user) => { + const query = makePaginationQuery(UserGroupInvites.createQueryBuilder('invite'), ps.sinceId, ps.untilId) + .andWhere(`invite.userId = :meId`, { meId: user.id }) + .leftJoinAndSelect('invite.userGroup', 'user_group'); + + const invites = await query + .take(ps.limit!) + .getMany(); + + return await UserGroupInvites.packMany(invites); +}); diff --git a/src/server/api/endpoints/users/groups/invitations/accept.ts b/src/server/api/endpoints/users/groups/invitations/accept.ts new file mode 100644 index 000000000..33779dd34 --- /dev/null +++ b/src/server/api/endpoints/users/groups/invitations/accept.ts @@ -0,0 +1,63 @@ +import $ from 'cafy'; +import { ID } from '../../../../../../misc/cafy-id'; +import define from '../../../../define'; +import { ApiError } from '../../../../error'; +import { UserGroupJoinings, UserGroupInvites } from '../../../../../../models'; +import { genId } from '../../../../../../misc/gen-id'; +import { UserGroupJoining } from '../../../../../../models/entities/user-group-joining'; + +export const meta = { + desc: { + 'ja-JP': 'ユーザーグループへの招待を承認します。', + 'en-US': 'Accept invite of a user group.' + }, + + tags: ['groups', 'users'], + + requireCredential: true, + + kind: 'write:user-groups', + + params: { + inviteId: { + validator: $.type(ID), + desc: { + 'ja-JP': '招待ID', + 'en-US': 'The invite ID' + } + }, + }, + + errors: { + noSuchInvitation: { + message: 'No such invitation.', + code: 'NO_SUCH_INVITATION', + id: '98c11eca-c890-4f42-9806-c8c8303ebb5e' + }, + } +}; + +export default define(meta, async (ps, user) => { + // Fetch the invitation + const invite = await UserGroupInvites.findOne({ + id: ps.inviteId, + }); + + if (invite == null) { + throw new ApiError(meta.errors.noSuchInvitation); + } + + if (invite.userId !== user.id) { + throw new ApiError(meta.errors.noSuchInvitation); + } + + // Push the user + await UserGroupJoinings.save({ + id: genId(), + createdAt: new Date(), + userId: user.id, + userGroupId: invite.userGroupId + } as UserGroupJoining); + + UserGroupInvites.delete(invite.id); +}); diff --git a/src/server/api/endpoints/users/groups/invitations/reject.ts b/src/server/api/endpoints/users/groups/invitations/reject.ts new file mode 100644 index 000000000..e9e7bc8b4 --- /dev/null +++ b/src/server/api/endpoints/users/groups/invitations/reject.ts @@ -0,0 +1,53 @@ +import $ from 'cafy'; +import { ID } from '../../../../../../misc/cafy-id'; +import define from '../../../../define'; +import { ApiError } from '../../../../error'; +import { UserGroupInvites } from '../../../../../../models'; + +export const meta = { + desc: { + 'ja-JP': 'ユーザーグループへの招待を拒否します。', + 'en-US': 'Reject invite of a user group.' + }, + + tags: ['groups', 'users'], + + requireCredential: true, + + kind: 'write:user-groups', + + params: { + inviteId: { + validator: $.type(ID), + desc: { + 'ja-JP': '招待ID', + 'en-US': 'The invite ID' + } + }, + }, + + errors: { + noSuchInvitation: { + message: 'No such invitation.', + code: 'NO_SUCH_INVITATION', + id: 'ad7471d4-2cd9-44b4-ac68-e7136b4ce656' + }, + } +}; + +export default define(meta, async (ps, user) => { + // Fetch the invitation + const invite = await UserGroupInvites.findOne({ + id: ps.inviteId, + }); + + if (invite == null) { + throw new ApiError(meta.errors.noSuchInvitation); + } + + if (invite.userId !== user.id) { + throw new ApiError(meta.errors.noSuchInvitation); + } + + await UserGroupInvites.delete(invite.id); +}); diff --git a/src/server/api/endpoints/users/groups/push.ts b/src/server/api/endpoints/users/groups/invite.ts similarity index 70% rename from src/server/api/endpoints/users/groups/push.ts rename to src/server/api/endpoints/users/groups/invite.ts index 5371580db..503184a92 100644 --- a/src/server/api/endpoints/users/groups/push.ts +++ b/src/server/api/endpoints/users/groups/invite.ts @@ -3,14 +3,14 @@ import { ID } from '../../../../../misc/cafy-id'; import define from '../../../define'; import { ApiError } from '../../../error'; import { getUser } from '../../../common/getters'; -import { UserGroups, UserGroupJoinings } from '../../../../../models'; +import { UserGroups, UserGroupJoinings, UserGroupInvites } from '../../../../../models'; import { genId } from '../../../../../misc/gen-id'; -import { UserGroupJoining } from '../../../../../models/entities/user-group-joining'; +import { UserGroupInvite } from '../../../../../models/entities/user-group-invite'; export const meta = { desc: { - 'ja-JP': '指定したユーザーグループに指定したユーザーを追加します。', - 'en-US': 'Add a user to a user group.' + 'ja-JP': '指定したユーザーグループに指定したユーザーを招待します。', + 'en-US': 'Invite a user to a user group.' }, tags: ['groups', 'users'], @@ -50,6 +50,12 @@ export const meta = { message: 'That user has already been added to that group.', code: 'ALREADY_ADDED', id: '7e35c6a0-39b2-4488-aea6-6ee20bd5da2c' + }, + + alreadyInvited: { + message: 'That user has already been invited to that group.', + code: 'ALREADY_INVITED', + id: 'ee0f58b4-b529-4d13-b761-b9a3e69f97e6' } } }; @@ -71,20 +77,28 @@ export default define(meta, async (ps, me) => { throw e; }); - const exist = await UserGroupJoinings.findOne({ + const joining = await UserGroupJoinings.findOne({ userGroupId: userGroup.id, userId: user.id }); - if (exist) { + if (joining) { throw new ApiError(meta.errors.alreadyAdded); } - // Push the user - await UserGroupJoinings.save({ + const invite = await UserGroupInvites.findOne({ + userGroupId: userGroup.id, + userId: user.id + }); + + if (invite) { + throw new ApiError(meta.errors.alreadyInvited); + } + + await UserGroupInvites.save({ id: genId(), createdAt: new Date(), userId: user.id, userGroupId: userGroup.id - } as UserGroupJoining); + } as UserGroupInvite); }); diff --git a/src/server/api/endpoints/users/groups/joined.ts b/src/server/api/endpoints/users/groups/joined.ts index 14561fce0..853a2510d 100644 --- a/src/server/api/endpoints/users/groups/joined.ts +++ b/src/server/api/endpoints/users/groups/joined.ts @@ -1,6 +1,7 @@ import define from '../../../define'; import { UserGroups, UserGroupJoinings } from '../../../../../models'; import { types, bool } from '../../../../../misc/schema'; +import { Not, In } from 'typeorm'; export const meta = { desc: { @@ -25,8 +26,13 @@ export const meta = { }; export default define(meta, async (ps, me) => { + const ownedGroups = await UserGroups.find({ + userId: me.id, + }); + const joinings = await UserGroupJoinings.find({ userId: me.id, + userGroupId: Not(In(ownedGroups.map(x => x.id))) }); return await Promise.all(joinings.map(x => UserGroups.pack(x.userGroupId))); From 01fab09683db94bb79ae347060d76923f2617a6e Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 19 May 2019 20:43:33 +0900 Subject: [PATCH 3/9] Fix #4945 --- src/server/api/endpoints/users/groups/pull.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/server/api/endpoints/users/groups/pull.ts b/src/server/api/endpoints/users/groups/pull.ts index 5fc0c2fa5..3943560d7 100644 --- a/src/server/api/endpoints/users/groups/pull.ts +++ b/src/server/api/endpoints/users/groups/pull.ts @@ -42,7 +42,13 @@ export const meta = { message: 'No such user.', code: 'NO_SUCH_USER', id: '0b5cc374-3681-41da-861e-8bc1146f7a55' - } + }, + + isOwner: { + message: 'The user is the owner.', + code: 'IS_OWNER', + id: '1546eed5-4414-4dea-81c1-b0aec4f6d2af' + }, } }; @@ -63,6 +69,10 @@ export default define(meta, async (ps, me) => { throw e; }); + if (user.id === userGroup.userId) { + throw new ApiError(meta.errors.isOwner); + } + // Pull the user await UserGroupJoinings.delete({ userId: user.id }); }); From c2c2824e5016c26e4d445bc2c5d6042e760e9776 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 19 May 2019 20:47:41 +0900 Subject: [PATCH 4/9] Fix bug --- .../app/common/views/pages/follow-requests.vue | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/client/app/common/views/pages/follow-requests.vue b/src/client/app/common/views/pages/follow-requests.vue index 860efefd9..146d4b0c9 100644 --- a/src/client/app/common/views/pages/follow-requests.vue +++ b/src/client/app/common/views/pages/follow-requests.vue @@ -3,8 +3,8 @@
- -
+ +
@@ -56,13 +56,12 @@ export default Vue.extend({ From c610e5ed9ba300db9f95e901f83ffe59e19f109d Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 19 May 2019 20:48:10 +0900 Subject: [PATCH 5/9] Update note-favorite.ts --- src/models/repositories/note-favorite.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/models/repositories/note-favorite.ts b/src/models/repositories/note-favorite.ts index 5bc638410..b5875802f 100644 --- a/src/models/repositories/note-favorite.ts +++ b/src/models/repositories/note-favorite.ts @@ -13,6 +13,8 @@ export class NoteFavoriteRepository extends Repository { return { id: favorite.id, + createdAt: favorite.createdAt, + noteId: favorite.noteId, note: await Notes.pack(favorite.note || favorite.noteId, me), }; } From b9a6e551cdbc6f0583f26e5be4579883376a2794 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 19 May 2019 20:50:08 +0900 Subject: [PATCH 6/9] Add unique index --- migration/1558266512381-UserListJoining.ts | 13 +++++++++++++ src/models/entities/user-list-joining.ts | 1 + 2 files changed, 14 insertions(+) create mode 100644 migration/1558266512381-UserListJoining.ts diff --git a/migration/1558266512381-UserListJoining.ts b/migration/1558266512381-UserListJoining.ts new file mode 100644 index 000000000..f4a917045 --- /dev/null +++ b/migration/1558266512381-UserListJoining.ts @@ -0,0 +1,13 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class UserListJoining1558266512381 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_90f7da835e4c10aca6853621e1" ON "user_list_joining" ("userId", "userListId") `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_90f7da835e4c10aca6853621e1"`); + } + +} diff --git a/src/models/entities/user-list-joining.ts b/src/models/entities/user-list-joining.ts index 8af4efb6a..bb7dc40b9 100644 --- a/src/models/entities/user-list-joining.ts +++ b/src/models/entities/user-list-joining.ts @@ -4,6 +4,7 @@ import { UserList } from './user-list'; import { id } from '../id'; @Entity() +@Index(['userId', 'userListId'], { unique: true }) export class UserListJoining { @PrimaryColumn(id()) public id: string; From 45eeb74b830924aed337aa8131730588d71c41c1 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 19 May 2019 20:52:00 +0900 Subject: [PATCH 7/9] Fix #4948 --- src/models/repositories/messaging-message.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/repositories/messaging-message.ts b/src/models/repositories/messaging-message.ts index a64ed0732..6db2f4fa7 100644 --- a/src/models/repositories/messaging-message.ts +++ b/src/models/repositories/messaging-message.ts @@ -35,7 +35,7 @@ export class MessagingMessageRepository extends Repository { user: await Users.pack(message.user || message.userId, me), recipientId: message.recipientId, recipient: message.recipientId && opts.populateRecipient ? await Users.pack(message.recipient || message.recipientId, me) : undefined, - groupId: message.recipientId, + groupId: message.groupId, group: message.groupId && opts.populateGroup ? await UserGroups.pack(message.group || message.groupId) : undefined, fileId: message.fileId, file: message.fileId ? await DriveFiles.pack(message.fileId) : null, From c3fada264f27ae6fc6c73bd6b14d7b7cb4b2c1f5 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 19 May 2019 20:57:05 +0900 Subject: [PATCH 8/9] Fix #4938 --- src/server/api/common/read-messaging-message.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/api/common/read-messaging-message.ts b/src/server/api/common/read-messaging-message.ts index 544d89019..d18d8cd9d 100644 --- a/src/server/api/common/read-messaging-message.ts +++ b/src/server/api/common/read-messaging-message.ts @@ -42,7 +42,7 @@ export async function readUserMessagingMessage( publishMessagingStream(otherpartyId, userId, 'read', messageIds); publishMessagingIndexStream(userId, 'read', messageIds); - if (!Users.getHasUnreadMessagingMessage(userId)) { + if (!await Users.getHasUnreadMessagingMessage(userId)) { // 全ての(いままで未読だった)自分宛てのメッセージを(これで)読みましたよというイベントを発行 publishMainStream(userId, 'readAllMessagingMessages'); } @@ -96,7 +96,7 @@ export async function readGroupMessagingMessage( }); publishMessagingIndexStream(userId, 'read', reads); - if (!Users.getHasUnreadMessagingMessage(userId)) { + if (!await Users.getHasUnreadMessagingMessage(userId)) { // 全ての(いままで未読だった)自分宛てのメッセージを(これで)読みましたよというイベントを発行 publishMainStream(userId, 'readAllMessagingMessages'); } From d1d5e10b726dc2ecf197c64e433aebb33ca95f01 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 19 May 2019 21:02:17 +0900 Subject: [PATCH 9/9] 11.17.0 --- CHANGELOG.md | 14 ++++++++++++++ package.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c6143ab8..c1479b77a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,20 @@ mongodb: 8. master ブランチに戻す 9. enjoy +11.17.0 (2019/05/19) +-------------------- +### 注意 +このアップデートを適用した後、プロセスを起動(もしくは再起動)する前に[マイグレーション](#migration)の手順を実行してください + +### ✨Improvements +* ユーザーグループを招待制に + +### 🐛Fixes +* フォロー申請が表示されない問題を修正 +* トークの通知インジケーターが点灯し続ける問題を修正 +* 自分を自分のグループから削除できる問題を修正 +* 新しいタブでグループトークを開くことができない問題を修正 + 11.16.1 (2019/05/19) -------------------- ### 🐛Fixes diff --git a/package.json b/package.json index 5776c78f9..ff25d7756 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "11.16.1", + "version": "11.17.0", "codename": "daybreak", "repository": { "type": "git",