@@ -4,154 +4,122 @@ import type { NotificationId, OrganizationMemberId } from "@hazel/schema"
44import { Context , Effect , Layer , Option } from "effect"
55import { isAdminOrOwner } from "../lib/policy-utils"
66
7- export class NotificationPolicy extends Context . Service < NotificationPolicy > ( ) (
8- "NotificationPolicy/Policy" ,
9- {
10- make : Effect . gen ( function * ( ) {
11- const policyEntity = "Notification" as const
12-
13- const notificationRepo = yield * NotificationRepo
14- const organizationMemberRepo = yield * OrganizationMemberRepo
15-
16- const canCreate = ( _memberId : OrganizationMemberId ) =>
17- ErrorUtils . refailUnauthorized (
7+ export class NotificationPolicy extends Context . Service < NotificationPolicy > ( ) ( "NotificationPolicy/Policy" , {
8+ make : Effect . gen ( function * ( ) {
9+ const policyEntity = "Notification" as const
10+
11+ const notificationRepo = yield * NotificationRepo
12+ const organizationMemberRepo = yield * OrganizationMemberRepo
13+
14+ const canCreate = ( _memberId : OrganizationMemberId ) =>
15+ ErrorUtils . refailUnauthorized (
16+ policyEntity ,
17+ "create" ,
18+ ) (
19+ policy (
1820 policyEntity ,
1921 "create" ,
20- ) (
22+ Effect . fn ( `${ policyEntity } .create` ) ( function * ( _actor ) {
23+ return yield * Effect . succeed ( true )
24+ } ) ,
25+ ) ,
26+ )
27+
28+ const canView = ( id : NotificationId ) =>
29+ ErrorUtils . refailUnauthorized (
30+ policyEntity ,
31+ "view" ,
32+ ) (
33+ notificationRepo . with ( id , ( notification ) =>
2134 policy (
2235 policyEntity ,
23- "create" ,
24- Effect . fn ( `${ policyEntity } .create` ) ( function * ( _actor ) {
25- return yield * Effect . succeed ( true )
36+ "view" ,
37+ Effect . fn ( `${ policyEntity } .view` ) ( function * ( actor ) {
38+ const member = yield * organizationMemberRepo . findById ( notification . memberId )
39+
40+ if ( Option . isSome ( member ) && member . value . userId === actor . id ) {
41+ return yield * Effect . succeed ( true )
42+ }
43+
44+ return yield * Effect . succeed ( false )
2645 } ) ,
2746 ) ,
28- )
29-
30- const canView = ( id : NotificationId ) =>
31- ErrorUtils . refailUnauthorized (
32- policyEntity ,
33- "view" ,
34- ) (
35- notificationRepo . with ( id , ( notification ) =>
47+ ) ,
48+ )
49+
50+ const canUpdate = ( id : NotificationId ) =>
51+ ErrorUtils . refailUnauthorized (
52+ policyEntity ,
53+ "update" ,
54+ ) (
55+ notificationRepo . with ( id , ( notification ) =>
56+ organizationMemberRepo . with ( notification . memberId , ( member ) =>
3657 policy (
3758 policyEntity ,
38- "view" ,
39- Effect . fn ( `${ policyEntity } .view` ) ( function * ( actor ) {
40- const member = yield * organizationMemberRepo . findById ( notification . memberId )
41-
42- if ( Option . isSome ( member ) && member . value . userId === actor . id ) {
59+ "update" ,
60+ Effect . fn ( `${ policyEntity } .update` ) ( function * ( actor ) {
61+ if ( member . userId === actor . id ) {
4362 return yield * Effect . succeed ( true )
4463 }
4564
65+ const actorMember = yield * organizationMemberRepo . findByOrgAndUser (
66+ member . organizationId ,
67+ actor . id ,
68+ )
69+
70+ if ( Option . isSome ( actorMember ) ) {
71+ return yield * Effect . succeed ( isAdminOrOwner ( actorMember . value . role ) )
72+ }
73+
4674 return yield * Effect . succeed ( false )
4775 } ) ,
4876 ) ,
4977 ) ,
50- )
78+ ) ,
79+ )
80+
81+ const canDelete = ( id : NotificationId ) =>
82+ ErrorUtils . refailUnauthorized (
83+ policyEntity ,
84+ "delete" ,
85+ ) (
86+ notificationRepo . with ( id , ( notification ) =>
87+ organizationMemberRepo . with ( notification . memberId , ( member ) =>
88+ policy (
89+ policyEntity ,
90+ "delete" ,
91+ Effect . fn ( `${ policyEntity } .delete` ) ( function * ( actor ) {
92+ if ( member . userId === actor . id ) {
93+ return yield * Effect . succeed ( true )
94+ }
5195
52- const canUpdate = ( id : NotificationId ) =>
53- ErrorUtils . refailUnauthorized (
54- policyEntity ,
55- "update" ,
56- ) (
57- notificationRepo . with ( id , ( notification ) =>
58- organizationMemberRepo . with ( notification . memberId , ( member ) =>
59- policy (
60- policyEntity ,
61- "update" ,
62- Effect . fn ( `${ policyEntity } .update` ) ( function * ( actor ) {
63- if ( member . userId === actor . id ) {
64- return yield * Effect . succeed ( true )
65- }
66-
67- const actorMember = yield * organizationMemberRepo . findByOrgAndUser (
68- member . organizationId ,
69- actor . id ,
70- )
71-
72- if ( Option . isSome ( actorMember ) ) {
73- return yield * Effect . succeed ( isAdminOrOwner ( actorMember . value . role ) )
74- }
75-
76- return yield * Effect . succeed ( false )
77- } ) ,
78- ) ,
79- ) ,
80- ) ,
81- )
96+ const actorMember = yield * organizationMemberRepo . findByOrgAndUser (
97+ member . organizationId ,
98+ actor . id ,
99+ )
82100
83- const canDelete = ( id : NotificationId ) =>
84- ErrorUtils . refailUnauthorized (
85- policyEntity ,
86- "delete" ,
87- ) (
88- notificationRepo . with ( id , ( notification ) =>
89- organizationMemberRepo . with ( notification . memberId , ( member ) =>
90- policy (
91- policyEntity ,
92- "delete" ,
93- Effect . fn ( `${ policyEntity } .delete` ) ( function * ( actor ) {
94- if ( member . userId === actor . id ) {
95- return yield * Effect . succeed ( true )
96- }
97-
98- const actorMember = yield * organizationMemberRepo . findByOrgAndUser (
99- member . organizationId ,
100- actor . id ,
101- )
102-
103- if ( Option . isSome ( actorMember ) ) {
104- return yield * Effect . succeed ( isAdminOrOwner ( actorMember . value . role ) )
105- }
106-
107- return yield * Effect . succeed ( false )
108- } ) ,
109- ) ,
110- ) ,
111- ) ,
112- )
101+ if ( Option . isSome ( actorMember ) ) {
102+ return yield * Effect . succeed ( isAdminOrOwner ( actorMember . value . role ) )
103+ }
113104
114- const canMarkAsRead = ( id : NotificationId ) =>
115- ErrorUtils . refailUnauthorized (
116- policyEntity ,
117- "markAsRead" ,
118- ) (
119- notificationRepo . with ( id , ( notification ) =>
120- organizationMemberRepo . with ( notification . memberId , ( member ) =>
121- policy (
122- policyEntity ,
123- "markAsRead" ,
124- Effect . fn ( `${ policyEntity } .markAsRead` ) ( function * ( actor ) {
125- if ( member . userId === actor . id ) {
126- return yield * Effect . succeed ( true )
127- }
128-
129- const actorMember = yield * organizationMemberRepo . findByOrgAndUser (
130- member . organizationId ,
131- actor . id ,
132- )
133-
134- if ( Option . isSome ( actorMember ) ) {
135- return yield * Effect . succeed ( isAdminOrOwner ( actorMember . value . role ) )
136- }
137-
138- return yield * Effect . succeed ( false )
139- } ) ,
140- ) ,
105+ return yield * Effect . succeed ( false )
106+ } ) ,
141107 ) ,
142108 ) ,
143- )
144-
145- const canMarkAllAsRead = ( memberId : OrganizationMemberId ) =>
146- ErrorUtils . refailUnauthorized (
147- policyEntity ,
148- "markAllAsRead" ,
149- ) (
150- organizationMemberRepo . with ( memberId , ( member ) =>
109+ ) ,
110+ )
111+
112+ const canMarkAsRead = ( id : NotificationId ) =>
113+ ErrorUtils . refailUnauthorized (
114+ policyEntity ,
115+ "markAsRead" ,
116+ ) (
117+ notificationRepo . with ( id , ( notification ) =>
118+ organizationMemberRepo . with ( notification . memberId , ( member ) =>
151119 policy (
152120 policyEntity ,
153- "markAllAsRead " ,
154- Effect . fn ( `${ policyEntity } .markAllAsRead ` ) ( function * ( actor ) {
121+ "markAsRead " ,
122+ Effect . fn ( `${ policyEntity } .markAsRead ` ) ( function * ( actor ) {
155123 if ( member . userId === actor . id ) {
156124 return yield * Effect . succeed ( true )
157125 }
@@ -162,22 +130,50 @@ export class NotificationPolicy extends Context.Service<NotificationPolicy>()(
162130 )
163131
164132 if ( Option . isSome ( actorMember ) ) {
165- return yield * Effect . succeed (
166- actorMember . value . role === "admin" ||
167- actorMember . value . role === "owner" ,
168- )
133+ return yield * Effect . succeed ( isAdminOrOwner ( actorMember . value . role ) )
169134 }
170135
171136 return yield * Effect . succeed ( false )
172137 } ) ,
173138 ) ,
174139 ) ,
175- )
140+ ) ,
141+ )
142+
143+ const canMarkAllAsRead = ( memberId : OrganizationMemberId ) =>
144+ ErrorUtils . refailUnauthorized (
145+ policyEntity ,
146+ "markAllAsRead" ,
147+ ) (
148+ organizationMemberRepo . with ( memberId , ( member ) =>
149+ policy (
150+ policyEntity ,
151+ "markAllAsRead" ,
152+ Effect . fn ( `${ policyEntity } .markAllAsRead` ) ( function * ( actor ) {
153+ if ( member . userId === actor . id ) {
154+ return yield * Effect . succeed ( true )
155+ }
156+
157+ const actorMember = yield * organizationMemberRepo . findByOrgAndUser (
158+ member . organizationId ,
159+ actor . id ,
160+ )
161+
162+ if ( Option . isSome ( actorMember ) ) {
163+ return yield * Effect . succeed (
164+ actorMember . value . role === "admin" || actorMember . value . role === "owner" ,
165+ )
166+ }
167+
168+ return yield * Effect . succeed ( false )
169+ } ) ,
170+ ) ,
171+ ) ,
172+ )
176173
177- return { canCreate, canView, canUpdate, canDelete, canMarkAsRead, canMarkAllAsRead } as const
178- } ) ,
179- } ,
180- ) {
174+ return { canCreate, canView, canUpdate, canDelete, canMarkAsRead, canMarkAllAsRead } as const
175+ } ) ,
176+ } ) {
181177 static readonly layer = Layer . effect ( this , this . make ) . pipe (
182178 Layer . provide ( NotificationRepo . layer ) ,
183179 Layer . provide ( OrganizationMemberRepo . layer ) ,
0 commit comments