This repository has no description
1package notella
2
3import (
4 "context"
5 "fmt"
6
7 "git.inpt.fr/churros/notella/db"
8 ll "github.com/gwennlbh/label-logger-go"
9)
10
11// AllUsers returns all the users in the database that have at least one notification subscription
12func AllUsers() ([]string, error) {
13 users, err := prisma.User.FindMany(
14 db.User.NotificationSubscriptions.Some(
15 db.NotificationSubscription.Endpoint.Not(""),
16 ),
17 ).Select(
18 db.User.ID.Field(),
19 ).Exec(context.Background())
20
21 if err != nil {
22 return []string{}, fmt.Errorf("while getting all users: %w", err)
23 }
24
25 ids := make([]string, len(users))
26 for i, user := range users {
27 ids[i] = user.ID
28 }
29
30 return ids, nil
31}
32
33// Receivers determines which users to send the notification to
34func Receivers(message Message) ([]string, error) {
35 ll.Debug("Determining receivers for message %s on %s", message.Event, message.ChurrosObjectId)
36 switch message.Event {
37 case EventNewPost:
38 return receiversForPost(message)
39 case EventBookingPaid:
40 return receiversForBookingPaid(message)
41 case EventContributionPaid:
42 return receiversForContributionPaid(message)
43 case EventGodchildAccepted, EventGodchildRejected:
44 return receiversForGodchildResponse(message)
45 case EventGodchildRequest:
46 return receiversForGodchildRequest(message)
47 case EventShotgunOpensSoon:
48 return receiversForShotgunOpens(message)
49 case EventShotgunClosesSoon:
50 return receiversForShotgunCloses(message)
51 case EventLoginStuck, EventPendingSignup:
52 return receiversForUserCandidate(message)
53 case EventTest:
54 return []string{}, fmt.Errorf("test event is for subscriptions, not users")
55 }
56
57 // For other events, assume the message churros object id is the user id
58 if message.ChurrosObjectId != "" {
59 _, err := prisma.User.FindUnique(
60 db.User.ID.Equals(message.ChurrosObjectId),
61 ).Exec(context.Background())
62 if err == nil {
63 return []string{message.ChurrosObjectId}, nil
64 }
65 }
66
67 return []string{}, nil
68}
69
70func receiversForPost(message Message) (userIds []string, err error) {
71 post, err := prisma.Article.FindUnique(
72 db.Article.ID.Equals(message.ChurrosObjectId),
73 ).With(
74 db.Article.Group.Fetch().With(
75 db.Group.Members.Fetch().Select(
76 db.GroupMember.MemberID.Field(),
77 ),
78 db.Group.StudentAssociation.Fetch().With(
79 db.StudentAssociation.School.Fetch().With(
80 db.School.Majors.Fetch().With(
81 db.Major.Students.Fetch().Select(
82 db.User.ID.Field(),
83 ),
84 ),
85 ),
86 ),
87 ),
88 ).Exec(context.Background())
89
90 if err != nil {
91 return []string{}, fmt.Errorf("while getting the post %q: %w", message.Id, err)
92 }
93
94 switch post.Visibility {
95 case db.VisibilityPrivate, db.VisibilityUnlisted:
96 return []string{}, nil
97 case db.VisibilityPublic:
98 return AllUsers()
99 case db.VisibilitySchoolRestricted:
100 for _, major := range post.Group().StudentAssociation().School().Majors() {
101 for _, student := range major.Students() {
102 userIds = append(userIds, student.ID)
103 }
104 }
105 return
106 case db.VisibilityGroupRestricted:
107 for _, member := range post.Group().Members() {
108 userIds = append(userIds, member.MemberID)
109 }
110 return
111 }
112
113 return userIds, fmt.Errorf("unknown post visibility %q", post.Visibility)
114}
115
116func receiversForBookingPaid(message Message) (userIds []string, err error) {
117 booking, err := prisma.Registration.FindUnique(
118 db.Registration.ID.Equals(message.ChurrosObjectId),
119 ).Exec(context.Background())
120
121 if err != nil {
122 err = fmt.Errorf("while getting booking: %w", err)
123 return
124 }
125
126 authorId, ok := booking.AuthorID()
127 if ok {
128 userIds = append(userIds, authorId)
129 }
130
131 beneficiaryId, ok := booking.InternalBeneficiaryID()
132 if ok {
133 userIds = append(userIds, beneficiaryId)
134 }
135
136 return
137}
138
139func receiversForContributionPaid(message Message) (userIds []string, err error) {
140 contribution, err := prisma.Contribution.FindUnique(
141 db.Contribution.ID.Equals(message.ChurrosObjectId),
142 ).Exec(context.Background())
143
144 if err != nil {
145 err = fmt.Errorf("while getting contribution: %w", err)
146 return
147 }
148
149 return []string{contribution.UserID}, nil
150}
151
152func receiversForGodchildResponse(message Message) (userIds []string, err error) {
153 godchildRequest, err := prisma.GodparentRequest.FindUnique(
154 db.GodparentRequest.ID.Equals(message.ChurrosObjectId),
155 ).Exec(context.Background())
156
157 if err != nil {
158 err = fmt.Errorf("while getting godchild request: %w", err)
159 return
160 }
161
162 return []string{godchildRequest.GodchildID}, nil
163}
164
165func receiversForGodchildRequest(message Message) (userIds []string, err error) {
166 godchildRequest, err := prisma.GodparentRequest.FindUnique(
167 db.GodparentRequest.ID.Equals(message.ChurrosObjectId),
168 ).Exec(context.Background())
169
170 if err != nil {
171 err = fmt.Errorf("while getting godchild request: %w", err)
172 return
173 }
174
175 return []string{godchildRequest.GodparentID}, nil
176}
177
178func receiversForShotgunOpens(message Message) (userIds []string, err error) {
179 shotgun, err := prisma.Event.FindUnique(
180 db.Event.ID.Equals(message.ChurrosObjectId),
181 ).With(
182 db.Event.Group.Fetch().With(
183 db.Group.Members.Fetch().Select(
184 db.GroupMember.MemberID.Field(),
185 ),
186 db.Group.StudentAssociation.Fetch().With(
187 db.StudentAssociation.School.Fetch().With(
188 db.School.Majors.Fetch().With(
189 db.Major.Students.Fetch().Select(
190 db.User.ID.Field(),
191 ),
192 ),
193 ),
194 ),
195 ),
196 ).Exec(context.Background())
197
198 userIds = make([]string, 0)
199
200 switch shotgun.Visibility {
201 case db.VisibilityPublic:
202 return AllUsers()
203 case db.VisibilitySchoolRestricted:
204 for _, major := range shotgun.Group().StudentAssociation().School().Majors() {
205 for _, student := range major.Students() {
206 userIds = append(userIds, student.ID)
207 }
208 }
209 return
210 case db.VisibilityGroupRestricted:
211 for _, member := range shotgun.Group().Members() {
212 userIds = append(userIds, member.MemberID)
213 }
214 return
215 }
216
217 return
218}
219
220func receiversForShotgunCloses(message Message) (userIds []string, err error) {
221 shotgun, err := prisma.Event.FindUnique(
222 db.Event.ID.Equals(message.ChurrosObjectId),
223 ).With(
224 db.Event.Group.Fetch().With(
225 db.Group.Members.Fetch().Select(
226 db.GroupMember.MemberID.Field(),
227 ),
228 db.Group.StudentAssociation.Fetch().With(
229 db.StudentAssociation.School.Fetch().With(
230 db.School.Majors.Fetch().With(
231 db.Major.Students.Fetch().Select(
232 db.User.ID.Field(),
233 ),
234 ),
235 ),
236 ),
237 ),
238 db.Event.Tickets.Fetch().With(
239 db.Ticket.Registrations.Fetch().Select(
240 db.Registration.AuthorID.Field(),
241 db.Registration.InternalBeneficiaryID.Field(),
242 ),
243 ),
244 ).Exec(context.Background())
245
246 switch shotgun.Visibility {
247 case db.VisibilityPublic:
248 return AllUsers()
249 case db.VisibilitySchoolRestricted:
250 for _, major := range shotgun.Group().StudentAssociation().School().Majors() {
251 for _, student := range major.Students() {
252 userIds = append(userIds, student.ID)
253 }
254 }
255 return
256 case db.VisibilityGroupRestricted:
257 for _, member := range shotgun.Group().Members() {
258 userIds = append(userIds, member.MemberID)
259 }
260 return
261 }
262
263 // Remove users that are booked to the event
264
265 usersToRemove := make([]string, 0)
266
267 for _, ticket := range shotgun.Tickets() {
268 for _, registration := range ticket.Registrations() {
269 authorId, ok := registration.AuthorID()
270 if ok {
271 usersToRemove = append(usersToRemove, authorId)
272 }
273
274 beneficiaryId, ok := registration.InternalBeneficiaryID()
275 if ok {
276 usersToRemove = append(usersToRemove, beneficiaryId)
277 }
278 }
279 }
280
281 for _, user := range usersToRemove {
282 for i, id := range userIds {
283 if id == user {
284 userIds = append(userIds[:i], userIds[i+1:]...)
285 break
286 }
287 }
288 }
289
290 return
291}
292
293func receiversForUserCandidate(message Message) (userIds []string, err error) {
294 // Find school of the user candidate or user
295 school, err := prisma.School.FindFirst(
296 db.School.Majors.Some(
297 db.Major.Or(
298 db.Major.Students.Some(db.User.ID.Equals(message.ChurrosObjectId)),
299 db.Major.UserCandidates.Some(db.UserCandidate.ID.Equals(message.ChurrosObjectId)),
300 ),
301 ),
302 ).Exec(context.Background())
303
304 if err != nil {
305 return []string{}, fmt.Errorf("while getting school of user or usercandidate %s: %w", message.ChurrosObjectId, err)
306 }
307
308 systemAdmins, err := prisma.User.FindMany(
309 db.User.Admin.Equals(true),
310 ).Select(
311 db.User.ID.Field(),
312 ).Exec(context.Background())
313
314 if err != nil {
315 return []string{}, fmt.Errorf("while getting system admins: %w", err)
316 }
317
318 // If external account, send to system admins
319 if school == nil {
320 for _, admin := range systemAdmins {
321 userIds = append(userIds, admin.ID)
322 }
323 return
324 }
325
326 // If user or candidate has a school, get student association admins for that school
327 studentAssociationAdmins, err := prisma.User.FindMany(
328 db.User.AdminOfStudentAssociations.Some(
329 db.StudentAssociation.SchoolID.Equals(school.ID),
330 ),
331 ).Select(
332 db.User.ID.Field(),
333 ).Exec(context.Background())
334
335 if err != nil {
336 return []string{}, fmt.Errorf("while getting student association admins for %+v: %w", school, err)
337 }
338
339 for _, admin := range studentAssociationAdmins {
340 userIds = append(userIds, admin.ID)
341 }
342
343 return
344}