From 1c5291f8185651c231903129ee7c1cee263f9f03 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Mar 2023 10:20:03 +0900 Subject: feat: 時限ロール (#10145) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 時限ロール * クライアントから期限を確認できるように * リファクタとか * fix test * fix test * fix test * clean up --- .../src/server/api/endpoints/admin/roles/assign.ts | 29 +++++++--------------- .../server/api/endpoints/admin/roles/unassign.ts | 22 ++-------------- .../src/server/api/endpoints/admin/roles/users.ts | 6 +++++ 3 files changed, 17 insertions(+), 40 deletions(-) (limited to 'packages/backend/src/server/api/endpoints/admin') diff --git a/packages/backend/src/server/api/endpoints/admin/roles/assign.ts b/packages/backend/src/server/api/endpoints/admin/roles/assign.ts index 7bfb2f6625..b80aaba122 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/assign.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/assign.ts @@ -1,10 +1,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/index.js'; +import type { RolesRepository, UsersRepository } from '@/models/index.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; -import { IdService } from '@/core/IdService.js'; -import { GlobalEventService } from '@/core/GlobalEventService.js'; import { RoleService } from '@/core/RoleService.js'; export const meta = { @@ -39,6 +37,10 @@ export const paramDef = { properties: { roleId: { type: 'string', format: 'misskey:id' }, userId: { type: 'string', format: 'misskey:id' }, + expiresAt: { + type: 'integer', + nullable: true, + }, }, required: [ 'roleId', @@ -56,12 +58,7 @@ export default class extends Endpoint { @Inject(DI.rolesRepository) private rolesRepository: RolesRepository, - @Inject(DI.roleAssignmentsRepository) - private roleAssignmentsRepository: RoleAssignmentsRepository, - - private globalEventService: GlobalEventService, private roleService: RoleService, - private idService: IdService, ) { super(meta, paramDef, async (ps, me) => { const role = await this.rolesRepository.findOneBy({ id: ps.roleId }); @@ -78,19 +75,11 @@ export default class extends Endpoint { throw new ApiError(meta.errors.noSuchUser); } - const date = new Date(); - const created = await this.roleAssignmentsRepository.insert({ - id: this.idService.genId(), - createdAt: date, - roleId: role.id, - userId: user.id, - }).then(x => this.roleAssignmentsRepository.findOneByOrFail(x.identifiers[0])); + if (ps.expiresAt && ps.expiresAt <= Date.now()) { + return; + } - this.rolesRepository.update(ps.roleId, { - lastUsedAt: new Date(), - }); - - this.globalEventService.publishInternalEvent('userRoleAssigned', created); + await this.roleService.assign(user.id, role.id, ps.expiresAt ? new Date(ps.expiresAt) : null); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts b/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts index 141cc5ee89..45c4f76943 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/unassign.ts @@ -1,10 +1,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/index.js'; +import type { RolesRepository, UsersRepository } from '@/models/index.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; -import { IdService } from '@/core/IdService.js'; -import { GlobalEventService } from '@/core/GlobalEventService.js'; import { RoleService } from '@/core/RoleService.js'; export const meta = { @@ -62,12 +60,7 @@ export default class extends Endpoint { @Inject(DI.rolesRepository) private rolesRepository: RolesRepository, - @Inject(DI.roleAssignmentsRepository) - private roleAssignmentsRepository: RoleAssignmentsRepository, - - private globalEventService: GlobalEventService, private roleService: RoleService, - private idService: IdService, ) { super(meta, paramDef, async (ps, me) => { const role = await this.rolesRepository.findOneBy({ id: ps.roleId }); @@ -84,18 +77,7 @@ export default class extends Endpoint { throw new ApiError(meta.errors.noSuchUser); } - const roleAssignment = await this.roleAssignmentsRepository.findOneBy({ userId: user.id, roleId: role.id }); - if (roleAssignment == null) { - throw new ApiError(meta.errors.notAssigned); - } - - await this.roleAssignmentsRepository.delete(roleAssignment.id); - - this.rolesRepository.update(ps.roleId, { - lastUsedAt: new Date(), - }); - - this.globalEventService.publishInternalEvent('userRoleUnassigned', roleAssignment); + await this.roleService.unassign(user.id, role.id); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/roles/users.ts b/packages/backend/src/server/api/endpoints/admin/roles/users.ts index bb016a8425..ec1e86fec9 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/users.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/users.ts @@ -1,4 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; +import { Brackets } from 'typeorm'; import type { RoleAssignmentsRepository, RolesRepository } from '@/models/index.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; @@ -56,6 +57,10 @@ export default class extends Endpoint { const query = this.queryService.makePaginationQuery(this.roleAssignmentsRepository.createQueryBuilder('assign'), ps.sinceId, ps.untilId) .andWhere('assign.roleId = :roleId', { roleId: role.id }) + .andWhere(new Brackets(qb => { qb + .where('assign.expiresAt IS NOT NULL') + .orWhere('assign.expiresAt > :now', { now: new Date() }); + })) .innerJoinAndSelect('assign.user', 'user'); const assigns = await query @@ -65,6 +70,7 @@ export default class extends Endpoint { return await Promise.all(assigns.map(async assign => ({ id: assign.id, user: await this.userEntityService.pack(assign.user!, me, { detail: true }), + expiresAt: assign.expiresAt, }))); }); } -- cgit v1.2.3-freya From 9e5278d2760a66c3d8fadadbe45ccf2f09da1130 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Mar 2023 12:02:37 +0900 Subject: fix of #10145 --- packages/backend/src/core/entities/RoleEntityService.ts | 2 +- packages/backend/src/server/api/endpoints/admin/roles/users.ts | 2 +- packages/backend/src/server/api/endpoints/roles/users.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'packages/backend/src/server/api/endpoints/admin') diff --git a/packages/backend/src/core/entities/RoleEntityService.ts b/packages/backend/src/core/entities/RoleEntityService.ts index 4208e03a8c..2f1d51fa1a 100644 --- a/packages/backend/src/core/entities/RoleEntityService.ts +++ b/packages/backend/src/core/entities/RoleEntityService.ts @@ -32,7 +32,7 @@ export class RoleEntityService { const assignedCount = await this.roleAssignmentsRepository.createQueryBuilder('assign') .where('assign.roleId = :roleId', { roleId: role.id }) .andWhere(new Brackets(qb => { qb - .where('assign.expiresAt IS NOT NULL') + .where('assign.expiresAt IS NULL') .orWhere('assign.expiresAt > :now', { now: new Date() }); })) .getCount(); diff --git a/packages/backend/src/server/api/endpoints/admin/roles/users.ts b/packages/backend/src/server/api/endpoints/admin/roles/users.ts index ec1e86fec9..930d3fee40 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/users.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/users.ts @@ -58,7 +58,7 @@ export default class extends Endpoint { const query = this.queryService.makePaginationQuery(this.roleAssignmentsRepository.createQueryBuilder('assign'), ps.sinceId, ps.untilId) .andWhere('assign.roleId = :roleId', { roleId: role.id }) .andWhere(new Brackets(qb => { qb - .where('assign.expiresAt IS NOT NULL') + .where('assign.expiresAt IS NULL') .orWhere('assign.expiresAt > :now', { now: new Date() }); })) .innerJoinAndSelect('assign.user', 'user'); diff --git a/packages/backend/src/server/api/endpoints/roles/users.ts b/packages/backend/src/server/api/endpoints/roles/users.ts index 2a8684e6d7..607dc24206 100644 --- a/packages/backend/src/server/api/endpoints/roles/users.ts +++ b/packages/backend/src/server/api/endpoints/roles/users.ts @@ -58,7 +58,7 @@ export default class extends Endpoint { const query = this.queryService.makePaginationQuery(this.roleAssignmentsRepository.createQueryBuilder('assign'), ps.sinceId, ps.untilId) .andWhere('assign.roleId = :roleId', { roleId: role.id }) .andWhere(new Brackets(qb => { qb - .where('assign.expiresAt IS NOT NULL') + .where('assign.expiresAt IS NULL') .orWhere('assign.expiresAt > :now', { now: new Date() }); })) .innerJoinAndSelect('assign.user', 'user'); -- cgit v1.2.3-freya From d0bbeeee526543b48e3143231fabaa0c0e10e0c4 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Mar 2023 14:22:53 +0900 Subject: :art: --- .../src/server/api/endpoints/admin/roles/users.ts | 1 + packages/frontend/src/pages/admin/roles.role.vue | 65 ++++++++++----- packages/frontend/src/pages/my-lists/list.vue | 96 ++++++++++------------ 3 files changed, 90 insertions(+), 72 deletions(-) (limited to 'packages/backend/src/server/api/endpoints/admin') diff --git a/packages/backend/src/server/api/endpoints/admin/roles/users.ts b/packages/backend/src/server/api/endpoints/admin/roles/users.ts index 930d3fee40..35edca5460 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/users.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/users.ts @@ -69,6 +69,7 @@ export default class extends Endpoint { return await Promise.all(assigns.map(async assign => ({ id: assign.id, + createdAt: assign.createdAt, user: await this.userEntityService.pack(assign.user!, me, { detail: true }), expiresAt: assign.expiresAt, }))); diff --git a/packages/frontend/src/pages/admin/roles.role.vue b/packages/frontend/src/pages/admin/roles.role.vue index 7951086bf1..c5792f649c 100644 --- a/packages/frontend/src/pages/admin/roles.role.vue +++ b/packages/frontend/src/pages/admin/roles.role.vue @@ -30,12 +30,19 @@ @@ -77,6 +84,8 @@ const usersPagination = { })), }; +let expandedItems = $ref([]); + const role = reactive(await os.api('admin/roles/show', { roleId: props.id, })); @@ -129,7 +138,7 @@ async function assign() { : null; await os.apiWithDialog('admin/roles/assign', { roleId: role.id, userId: user.id, expiresAt }); - role.users.push(user); + //role.users.push(user); } async function unassign(user, ev) { @@ -139,16 +148,17 @@ async function unassign(user, ev) { danger: true, action: async () => { await os.apiWithDialog('admin/roles/unassign', { roleId: role.id, userId: user.id }); - role.users = role.users.filter(u => u.id !== user.id); + //role.users = role.users.filter(u => u.id !== user.id); }, }], ev.currentTarget ?? ev.target); } -async function showExpireInfo(assignment) { - os.alert({ - type: 'info', - text: assignment.expiresAt.toLocaleString(), - }); +async function toggleItem(item) { + if (expandedItems.includes(item.id)) { + expandedItems = expandedItems.filter(x => x !== item.id); + } else { + expandedItems.push(item.id); + } } const headerActions = $computed(() => []); @@ -162,24 +172,41 @@ definePageMetadata(computed(() => ({ diff --git a/packages/frontend/src/pages/my-lists/list.vue b/packages/frontend/src/pages/my-lists/list.vue index f47b4bf90f..a6a3974d0c 100644 --- a/packages/frontend/src/pages/my-lists/list.vue +++ b/packages/frontend/src/pages/my-lists/list.vue @@ -2,13 +2,13 @@ -
+
-
+
{{ i18n.ts.addUser }} {{ i18n.ts.rename }} - {{ i18n.ts.delete }} + {{ i18n.ts.delete }}
@@ -16,18 +16,12 @@
{{ i18n.ts.members }}
-
-
-
- -
- - -
-
- -
-
+
+
+ + + +
@@ -44,6 +38,8 @@ import * as os from '@/os'; import { mainRouter } from '@/router'; import { definePageMetadata } from '@/scripts/page-metadata'; import { i18n } from '@/i18n'; +import { userPage } from '@/filters/user'; +import MkUserCardMini from '@/components/MkUserCardMini.vue'; const props = defineProps<{ listId: string; @@ -76,13 +72,20 @@ function addUser() { }); } -function removeUser(user) { - os.api('users/lists/pull', { - listId: list.id, - userId: user.id, - }).then(() => { - users = users.filter(x => x.id !== user.id); - }); +async function removeUser(user, ev) { + os.popupMenu([{ + text: i18n.ts.remove, + icon: 'ti ti-x', + danger: true, + action: async () => { + os.api('users/lists/pull', { + listId: list.id, + userId: user.id, + }).then(() => { + users = users.filter(x => x.id !== user.id); + }); + }, + }], ev.currentTarget ?? ev.target); } async function renameList() { @@ -126,37 +129,24 @@ definePageMetadata(computed(() => list ? { } : null)); - -- cgit v1.2.3-freya