From a38517dbb70f0c4d2ccaaf267a31222121d69a9f Mon Sep 17 00:00:00 2001 From: Igor Zynov Date: Fri, 25 Jul 2025 17:00:46 +0400 Subject: [PATCH 1/3] feat(notification): add `viewAll` method to mark multiple notifications as viewed --- .../list/methods/notification.json | 19 +++++++++++++ .../permissions/list/models/notification.json | 24 ++++++++++++++++ .../notification/src/methods/index.ts | 2 ++ .../src/methods/notice/view-all.ts | 25 +++++++++++++++++ .../notification/src/services/notice/index.ts | 28 +++++++++++++++++++ 5 files changed, 98 insertions(+) create mode 100644 microservices/notification/src/methods/notice/view-all.ts diff --git a/microservices/authorization/migrations/permissions/list/methods/notification.json b/microservices/authorization/migrations/permissions/list/methods/notification.json index 05f53c35..41be5587 100644 --- a/microservices/authorization/migrations/permissions/list/methods/notification.json +++ b/microservices/authorization/migrations/permissions/list/methods/notification.json @@ -232,6 +232,25 @@ "modelOut": "notification.HideAllOutput", "methodFilters": [] }, + { + "microservice": "notification", + "method": "notice.view-all", + "description": "Notifications multiple set as viewed", + "allowGroup": [ + "user" + ], + "denyGroup": [], + "createdAt": "2025-07-24T12:00:00.000Z", + "modelOut": "notification.ViewAllOutput", + "methodFilters": [ + { + "filterTitle": "By userId", + "operator": "and", + "roleAlias": "guest", + "createdAt": "2022-03-15T06:18:07.204Z" + } + ] + }, { "microservice": "notification", "method": "task.count", diff --git a/microservices/authorization/migrations/permissions/list/models/notification.json b/microservices/authorization/migrations/permissions/list/models/notification.json index fbbd23a3..4e6c9f21 100644 --- a/microservices/authorization/migrations/permissions/list/models/notification.json +++ b/microservices/authorization/migrations/permissions/list/models/notification.json @@ -520,6 +520,30 @@ }, "createdAt": "2023-09-20T18:49:48.824Z" }, + { + "microservice": "notification", + "alias": "notification.ViewAllOutput", + "title": "View All Output", + "schema": { + "status": { + "in": { + "admin": "allow" + }, + "out": { + "user": "allow" + } + }, + "affected": { + "in": { + "admin": "allow" + }, + "out": { + "user": "allow" + } + } + }, + "createdAt": "2025-07-24T12:00:00.000Z" + }, { "microservice": "notification", "alias": "notification.Task", diff --git a/microservices/notification/src/methods/index.ts b/microservices/notification/src/methods/index.ts index 368655fb..5a76f598 100644 --- a/microservices/notification/src/methods/index.ts +++ b/microservices/notification/src/methods/index.ts @@ -8,6 +8,7 @@ import FcmTokenSave from '@methods/fcm-token/save'; import CrudMessage from '@methods/messages/crud'; import CrudNotice from '@methods/notice/crud'; import { hideAll as NoticeHideAll } from '@methods/notice/hide-all'; +import { viewAll as NoticeViewAll } from '@methods/notice/view-all'; import PhoneSend from '@methods/phone/send'; import PushSend from '@methods/push/send'; import CrudTask from '@methods/task/crud'; @@ -21,6 +22,7 @@ export default (ms: Microservice): void => { notice: { ...CrudNotice, 'hide-all': NoticeHideAll, + 'view-all': NoticeViewAll, }, task: CrudTask, }; diff --git a/microservices/notification/src/methods/notice/view-all.ts b/microservices/notification/src/methods/notice/view-all.ts new file mode 100644 index 00000000..2a141ef0 --- /dev/null +++ b/microservices/notification/src/methods/notice/view-all.ts @@ -0,0 +1,25 @@ +import { Endpoint, IsUndefinable } from '@lomray/microservice-helpers'; +import { IsBoolean, IsNumber } from 'class-validator'; +import Notice from '@services/notice'; + +class ViewAllOutput { + @IsBoolean() + status: boolean; + + @IsNumber() + @IsUndefinable() + affected?: number; +} + +/** + * View all user's notifications + */ +const viewAll = Endpoint.custom( + () => ({ + output: ViewAllOutput, + description: 'Notifications multiple view', + }), + ({ payload }) => Notice.init().viewAll(payload?.authentication?.userId as string), +); + +export { viewAll, ViewAllOutput }; diff --git a/microservices/notification/src/services/notice/index.ts b/microservices/notification/src/services/notice/index.ts index 24032527..6cc00fac 100644 --- a/microservices/notification/src/services/notice/index.ts +++ b/microservices/notification/src/services/notice/index.ts @@ -1,6 +1,7 @@ import { EntityManager, getManager } from 'typeorm'; import NoticeEntity from '@entities/notice'; import type { HideAllOutput } from '@methods/notice/hide-all'; +import type { ViewAllOutput } from '@methods/notice/view-all'; /** * Notice service @@ -51,6 +52,33 @@ class Notice { affected, }; } + + /** + * View all user's notifications + */ + public async viewAll(userId?: string): Promise { + if (!userId) { + return { + status: false, + }; + } + + const repository = this.manager.getRepository(NoticeEntity); + const { affected } = await repository.update( + { + userId, + isViewed: false, + }, + { + isViewed: true, + }, + ); + + return { + status: true, + affected, + }; + } } export default Notice; From bf8578c20b6c2cdd556e80aa667744d67593495a Mon Sep 17 00:00:00 2001 From: Igor Zynov Date: Fri, 25 Jul 2025 17:57:19 +0400 Subject: [PATCH 2/3] feat(notification): add `ViewAllInput` model and update `viewAll` method to use typed input --- .../permissions/list/methods/notification.json | 10 ++-------- .../permissions/list/models/notification.json | 16 ++++++++++++++++ .../notification/src/methods/notice/view-all.ts | 12 +++++++++--- .../notification/src/services/notice/index.ts | 4 ++-- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/microservices/authorization/migrations/permissions/list/methods/notification.json b/microservices/authorization/migrations/permissions/list/methods/notification.json index 41be5587..901343c5 100644 --- a/microservices/authorization/migrations/permissions/list/methods/notification.json +++ b/microservices/authorization/migrations/permissions/list/methods/notification.json @@ -241,15 +241,9 @@ ], "denyGroup": [], "createdAt": "2025-07-24T12:00:00.000Z", + "modelIn": "notification.ViewAllInput", "modelOut": "notification.ViewAllOutput", - "methodFilters": [ - { - "filterTitle": "By userId", - "operator": "and", - "roleAlias": "guest", - "createdAt": "2022-03-15T06:18:07.204Z" - } - ] + "methodFilters": [] }, { "microservice": "notification", diff --git a/microservices/authorization/migrations/permissions/list/models/notification.json b/microservices/authorization/migrations/permissions/list/models/notification.json index 4e6c9f21..dc5e26e3 100644 --- a/microservices/authorization/migrations/permissions/list/models/notification.json +++ b/microservices/authorization/migrations/permissions/list/models/notification.json @@ -520,6 +520,22 @@ }, "createdAt": "2023-09-20T18:49:48.824Z" }, + { + "microservice": "notification", + "alias": "notification.ViewAllInput", + "title": "View All Input", + "schema": { + "userId": { + "in": { + "user": "allow" + }, + "out": { + "user": "allow" + } + } + }, + "createdAt": "2025-07-24T12:00:00.000Z" + }, { "microservice": "notification", "alias": "notification.ViewAllOutput", diff --git a/microservices/notification/src/methods/notice/view-all.ts b/microservices/notification/src/methods/notice/view-all.ts index 2a141ef0..1c458e0b 100644 --- a/microservices/notification/src/methods/notice/view-all.ts +++ b/microservices/notification/src/methods/notice/view-all.ts @@ -1,7 +1,12 @@ import { Endpoint, IsUndefinable } from '@lomray/microservice-helpers'; -import { IsBoolean, IsNumber } from 'class-validator'; +import { IsBoolean, IsNumber, IsString } from 'class-validator'; import Notice from '@services/notice'; +class ViewAllInput { + @IsString() + userId: string; +} + class ViewAllOutput { @IsBoolean() status: boolean; @@ -16,10 +21,11 @@ class ViewAllOutput { */ const viewAll = Endpoint.custom( () => ({ + input: ViewAllInput, output: ViewAllOutput, description: 'Notifications multiple view', }), - ({ payload }) => Notice.init().viewAll(payload?.authentication?.userId as string), + ({ userId }) => Notice.init().viewAll(userId), ); -export { viewAll, ViewAllOutput }; +export { viewAll, ViewAllOutput, ViewAllInput }; diff --git a/microservices/notification/src/services/notice/index.ts b/microservices/notification/src/services/notice/index.ts index 6cc00fac..d9ac51be 100644 --- a/microservices/notification/src/services/notice/index.ts +++ b/microservices/notification/src/services/notice/index.ts @@ -1,7 +1,7 @@ import { EntityManager, getManager } from 'typeorm'; import NoticeEntity from '@entities/notice'; import type { HideAllOutput } from '@methods/notice/hide-all'; -import type { ViewAllOutput } from '@methods/notice/view-all'; +import type { ViewAllInput, ViewAllOutput } from '@methods/notice/view-all'; /** * Notice service @@ -56,7 +56,7 @@ class Notice { /** * View all user's notifications */ - public async viewAll(userId?: string): Promise { + public async viewAll(userId?: ViewAllInput['userId']): Promise { if (!userId) { return { status: false, From 0327aeb2dba06f31e6c1f9a6947317d480211a10 Mon Sep 17 00:00:00 2001 From: Igor Zynov Date: Fri, 25 Jul 2025 18:29:04 +0400 Subject: [PATCH 3/3] feat(notification): update permission schema to include `admin` and conditional access for `user` --- .../migrations/permissions/list/models/notification.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/microservices/authorization/migrations/permissions/list/models/notification.json b/microservices/authorization/migrations/permissions/list/models/notification.json index dc5e26e3..e70e943d 100644 --- a/microservices/authorization/migrations/permissions/list/models/notification.json +++ b/microservices/authorization/migrations/permissions/list/models/notification.json @@ -527,7 +527,10 @@ "schema": { "userId": { "in": { - "user": "allow" + "admin": "allow", + "user": { + "condition": "Fields: user owner" + } }, "out": { "user": "allow"