• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vocdoni / saas-backend / 16598104829

29 Jul 2025 01:51PM UTC coverage: 58.021% (+0.1%) from 57.876%
16598104829

push

github

emmdim
api: Adds tests for publish group census endoint

1 of 1 new or added line in 1 file covered. (100.0%)

123 existing lines in 6 files now uncovered.

5306 of 9145 relevant lines covered (58.02%)

27.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.03
/api/organization_groups.go
1
package api
2

3
import (
4
        "encoding/json"
5
        "net/http"
6
        "strconv"
7

8
        "github.com/go-chi/chi/v5"
9
        "github.com/vocdoni/saas-backend/api/apicommon"
10
        "github.com/vocdoni/saas-backend/db"
11
        "github.com/vocdoni/saas-backend/errors"
12
)
13

14
// organizationMemberGroupsHandler godoc
15
//
16
//        @Summary                Get organization member groups
17
//        @Description        Get the list of groups and their info of the organization
18
//        @Description        Does not return the members of the groups, only the groups themselves.
19
//        @Description        Needs admin or manager role
20
//        @Tags                        organizations
21
//        @Accept                        json
22
//        @Produce                json
23
//        @Security                BearerAuth
24
//        @Param                        address                path                string        true        "Organization address"
25
//        @Param                        page                query                integer        false        "Page number (default: 1)"
26
//        @Param                        pageSize        query                integer        false        "Number of items per page (default: 10)"
27
//        @Success                200                        {object}        apicommon.OrganizationMemberGroupsResponse
28
//        @Failure                400                        {object}        errors.Error        "Invalid input data"
29
//        @Failure                401                        {object}        errors.Error        "Unauthorized"
30
//        @Failure                404                        {object}        errors.Error        "Organization not found"
31
//        @Failure                500                        {object}        errors.Error        "Internal server error"
32
//        @Router                        /organizations/{address}/groups [get]
33
func (a *API) organizationMemberGroupsHandler(w http.ResponseWriter, r *http.Request) {
5✔
34
        // get the user from the request context
5✔
35
        user, ok := apicommon.UserFromContext(r.Context())
5✔
36
        if !ok {
5✔
37
                errors.ErrUnauthorized.Write(w)
×
38
                return
×
39
        }
×
40
        // get the organization info from the request context
41
        org, _, ok := a.organizationFromRequest(r)
5✔
42
        if !ok {
6✔
43
                errors.ErrNoOrganizationProvided.Write(w)
1✔
44
                return
1✔
45
        }
1✔
46
        if !user.HasRoleFor(org.Address, db.AdminRole) && !user.HasRoleFor(org.Address, db.ManagerRole) {
5✔
47
                // if the user is not admin or manager of the organization, return an error
1✔
48
                errors.ErrUnauthorized.Withf("user is not admin of organization").Write(w)
1✔
49
                return
1✔
50
        }
1✔
51

52
        // Parse pagination parameters from query string
53
        page := 1      // Default page number
3✔
54
        pageSize := 10 // Default page size
3✔
55

3✔
56
        if pageStr := r.URL.Query().Get("page"); pageStr != "" {
3✔
57
                if pageVal, err := strconv.Atoi(pageStr); err == nil && pageVal > 0 {
×
58
                        page = pageVal
×
59
                }
×
60
        }
61

62
        if pageSizeStr := r.URL.Query().Get("pageSize"); pageSizeStr != "" {
3✔
63
                if pageSizeVal, err := strconv.Atoi(pageSizeStr); err == nil && pageSizeVal > 0 {
×
64
                        pageSize = pageSizeVal
×
65
                }
×
66
        }
67

68
        // send the organization back to the user
69
        pages, groups, err := a.db.OrganizationMemberGroups(org.Address, page, pageSize)
3✔
70
        if err != nil {
3✔
71
                errors.ErrGenericInternalServerError.Withf("could not get organization members: %v", err).Write(w)
×
72
                return
×
73
        }
×
74
        memberGroups := apicommon.OrganizationMemberGroupsResponse{
3✔
75
                TotalPages:  pages,
3✔
76
                CurrentPage: page,
3✔
77
                Groups:      make([]*apicommon.OrganizationMemberGroupInfo, 0, len(groups)),
3✔
78
        }
3✔
79
        for _, group := range groups {
9✔
80
                memberGroups.Groups = append(memberGroups.Groups, &apicommon.OrganizationMemberGroupInfo{
6✔
81
                        ID:           group.ID.Hex(),
6✔
82
                        Title:        group.Title,
6✔
83
                        Description:  group.Description,
6✔
84
                        CreatedAt:    group.CreatedAt,
6✔
85
                        UpdatedAt:    group.UpdatedAt,
6✔
86
                        CensusIDs:    group.CensusIDs,
6✔
87
                        MembersCount: len(group.MemberIDs),
6✔
88
                })
6✔
89
        }
6✔
90
        apicommon.HTTPWriteJSON(w, memberGroups)
3✔
91
}
92

93
// organizationMemberGroupHandler godoc
94
//
95
//        @Summary                Get the information of an organization member group
96
//        @Description        Get the information of an organization member group by its ID
97
//        @Description        Needs admin or manager role
98
//        @Tags                        organizations
99
//        @Accept                        json
100
//        @Produce                json
101
//        @Security                BearerAuth
102
//        @Param                        address        path                string        true        "Organization address"
103
//        @Param                        groupID        path                string        true        "Group ID"
104
//        @Success                200                {object}        apicommon.OrganizationMemberGroupInfo
105
//        @Failure                400                {object}        errors.Error        "Invalid input data"
106
//        @Failure                401                {object}        errors.Error        "Unauthorized"
107
//        @Failure                404                {object}        errors.Error        "Organization or group not found"
108
//        @Failure                500                {object}        errors.Error        "Internal server error"
109
//        @Router                        /organizations/{address}/groups/{groupID} [get]
110
func (a *API) organizationMemberGroupHandler(w http.ResponseWriter, r *http.Request) {
6✔
111
        // get the group ID from the request path
6✔
112
        groupID := chi.URLParam(r, "groupID")
6✔
113
        if groupID == "" {
6✔
114
                errors.ErrInvalidData.Withf("group ID is required").Write(w)
×
115
                return
×
116
        }
×
117
        // get the user from the request context
118
        user, ok := apicommon.UserFromContext(r.Context())
6✔
119
        if !ok {
6✔
120
                errors.ErrUnauthorized.Write(w)
×
121
                return
×
122
        }
×
123
        // get the organization info from the request context
124
        org, _, ok := a.organizationFromRequest(r)
6✔
125
        if !ok {
6✔
126
                errors.ErrNoOrganizationProvided.Write(w)
×
127
                return
×
128
        }
×
129
        if !user.HasRoleFor(org.Address, db.AdminRole) && !user.HasRoleFor(org.Address, db.ManagerRole) {
6✔
130
                // if the user is not admin or manager of the organization, return an error
×
131
                errors.ErrUnauthorized.Withf("user is not admin of organization").Write(w)
×
132
                return
×
133
        }
×
134

135
        group, err := a.db.OrganizationMemberGroup(groupID, org.Address)
6✔
136
        if err != nil {
8✔
137
                if err == db.ErrNotFound {
3✔
138
                        errors.ErrInvalidData.Withf("group not found").Write(w)
1✔
139
                        return
1✔
140
                }
1✔
141
                errors.ErrGenericInternalServerError.Withf("could not get organization member group: %v", err).Write(w)
1✔
142
                return
1✔
143
        }
144
        apicommon.HTTPWriteJSON(w, &apicommon.OrganizationMemberGroupInfo{
4✔
145
                ID:          group.ID.Hex(),
4✔
146
                Title:       group.Title,
4✔
147
                Description: group.Description,
4✔
148
                MemberIDs:   group.MemberIDs,
4✔
149
                CensusIDs:   group.CensusIDs,
4✔
150
                CreatedAt:   group.CreatedAt,
4✔
151
                UpdatedAt:   group.UpdatedAt,
4✔
152
        })
4✔
153
}
154

155
// createOrganizationMemberGroupHandler godoc
156
//
157
//        @Summary                Create an organization member group
158
//        @Description        Create an organization member group with the given members
159
//        @Description        Needs admin or manager role
160
//        @Tags                        organizations
161
//        @Accept                        json
162
//        @Produce                json
163
//        @Security                BearerAuth
164
//        @Param                        address        path                string                                                                                        true        "Organization address"
165
//        @Param                        group        body                apicommon.CreateOrganizationMemberGroupRequest        true        "Group info to create"
166
//        @Success                200                {object}        apicommon.OrganizationMemberGroupInfo
167
//        @Failure                400                {object}        errors.Error        "Invalid input data"
168
//        @Failure                401                {object}        errors.Error        "Unauthorized"
169
//        @Failure                404                {object}        errors.Error        "Organization not found"
170
//        @Failure                500                {object}        errors.Error        "Internal server error"
171
//        @Router                        /organizations/{address}/groups [post]
172
func (a *API) createOrganizationMemberGroupHandler(w http.ResponseWriter, r *http.Request) {
9✔
173
        // get the user from the request context
9✔
174
        user, ok := apicommon.UserFromContext(r.Context())
9✔
175
        if !ok {
9✔
176
                errors.ErrUnauthorized.Write(w)
×
177
                return
×
178
        }
×
179
        // get the organization info from the request context
180
        org, _, ok := a.organizationFromRequest(r)
9✔
181
        if !ok {
10✔
182
                errors.ErrNoOrganizationProvided.Write(w)
1✔
183
                return
1✔
184
        }
1✔
185
        if !user.HasRoleFor(org.Address, db.AdminRole) && !user.HasRoleFor(org.Address, db.ManagerRole) {
9✔
186
                // if the user is not admin or manager of the organization, return an error
1✔
187
                errors.ErrUnauthorized.Withf("user is not admin of organization").Write(w)
1✔
188
                return
1✔
189
        }
1✔
190

191
        var toCreate apicommon.CreateOrganizationMemberGroupRequest
7✔
192
        if err := json.NewDecoder(r.Body).Decode(&toCreate); err != nil {
7✔
193
                errors.ErrMalformedBody.Write(w)
×
194
                return
×
195
        }
×
196

197
        newMemberGroup := &db.OrganizationMemberGroup{
7✔
198
                Title:       toCreate.Title,
7✔
199
                Description: toCreate.Description,
7✔
200
                MemberIDs:   toCreate.MemberIDs,
7✔
201
                OrgAddress:  org.Address,
7✔
202
        }
7✔
203

7✔
204
        groupID, err := a.db.CreateOrganizationMemberGroup(newMemberGroup)
7✔
205
        if err != nil {
8✔
206
                if err == db.ErrNotFound {
1✔
207
                        errors.ErrInvalidData.Withf("organization not found").Write(w)
×
208
                        return
×
209
                }
×
210
                errors.ErrGenericInternalServerError.Withf("could not create organization member group: %v", err).Write(w)
1✔
211
                return
1✔
212
        }
213
        apicommon.HTTPWriteJSON(w, &apicommon.OrganizationMemberGroupInfo{
6✔
214
                ID: groupID,
6✔
215
        })
6✔
216
}
217

218
// updateOrganizationMemberGroupHandler godoc
219
//
220
//        @Summary                Update an organization member group
221
//        @Description        Update an organization member group changing the info, and adding or removing members
222
//        @Description        Needs admin or manager role
223
//        @Tags                        organizations
224
//        @Accept                        json
225
//        @Produce                json
226
//        @Security                BearerAuth
227
//        @Param                        address        path                string                                                                                        true        "Organization address"
228
//        @Param                        groupID        path                string                                                                                        true        "Group ID"
229
//        @Param                        group        body                apicommon.UpdateOrganizationMemberGroupsRequest        true        "Group info to update"
230
//        @Success                200                {string}        string                                                                                        "OK"
231
//        @Failure                400                {object}        errors.Error                                                                        "Invalid input data"
232
//        @Failure                401                {object}        errors.Error                                                                        "Unauthorized"
233
//        @Failure                404                {object}        errors.Error                                                                        "Organization or group not found"
234
//        @Failure                500                {object}        errors.Error                                                                        "Internal server error"
235
//        @Router                        /organizations/{address}/groups/{groupID} [put]
236
func (a *API) updateOrganizationMemberGroupHandler(w http.ResponseWriter, r *http.Request) {
5✔
237
        // get the group ID from the request path
5✔
238
        groupID := chi.URLParam(r, "groupID")
5✔
239
        if groupID == "" {
5✔
240
                errors.ErrInvalidData.Withf("group ID is required").Write(w)
×
241
                return
×
242
        }
×
243
        // get the user from the request context
244
        user, ok := apicommon.UserFromContext(r.Context())
5✔
245
        if !ok {
5✔
246
                errors.ErrUnauthorized.Write(w)
×
247
                return
×
248
        }
×
249
        // get the organization info from the request context
250
        org, _, ok := a.organizationFromRequest(r)
5✔
251
        if !ok {
5✔
252
                errors.ErrNoOrganizationProvided.Write(w)
×
253
                return
×
254
        }
×
255
        if !user.HasRoleFor(org.Address, db.AdminRole) && !user.HasRoleFor(org.Address, db.ManagerRole) {
6✔
256
                // if the user is not admin or manager of the organization, return an error
1✔
257
                errors.ErrUnauthorized.Withf("user is not admin of organization").Write(w)
1✔
258
                return
1✔
259
        }
1✔
260

261
        var toUpdate apicommon.UpdateOrganizationMemberGroupsRequest
4✔
262
        if err := json.NewDecoder(r.Body).Decode(&toUpdate); err != nil {
4✔
263
                errors.ErrMalformedBody.Write(w)
×
264
                return
×
265
        }
×
266

267
        err := a.db.UpdateOrganizationMemberGroup(
4✔
268
                groupID,
4✔
269
                org.Address,
4✔
270
                toUpdate.Title,
4✔
271
                toUpdate.Description,
4✔
272
                toUpdate.AddMembers,
4✔
273
                toUpdate.RemoveMembers,
4✔
274
        )
4✔
275
        if err != nil {
5✔
276
                if err == db.ErrNotFound {
1✔
277
                        errors.ErrInvalidData.Withf("group not found").Write(w)
×
278
                        return
×
279
                }
×
280
                errors.ErrGenericInternalServerError.Withf("could not update organization member group: %v", err).Write(w)
1✔
281
                return
1✔
282
        }
283
        apicommon.HTTPWriteOK(w)
3✔
284
}
285

286
// deleteOrganizationMemberGroupHandler godoc
287
//
288
//        @Summary                Delete an organization member group
289
//        @Description        Delete an organization member group by its ID
290
//        @Tags                        organizations
291
//        @Accept                        json
292
//        @Produce                json
293
//        @Security                BearerAuth
294
//        @Param                        address        path                string                        true        "Organization address"
295
//        @Param                        groupID        path                string                        true        "Group ID"
296
//        @Success                200                {string}        string                        "OK"
297
//        @Failure                400                {object}        errors.Error        "Invalid input data"
298
//        @Failure                401                {object}        errors.Error        "Unauthorized"
299
//        @Failure                404                {object}        errors.Error        "Organization or group not found"
300
//        @Failure                500                {object}        errors.Error        "Internal server error"
301
//        @Router                        /organizations/{address}/groups/{groupID} [delete]
302
func (a *API) deleteOrganizationMemberGroupHandler(w http.ResponseWriter, r *http.Request) {
5✔
303
        // get the member ID from the request path
5✔
304
        groupID := chi.URLParam(r, "groupID")
5✔
305
        if groupID == "" {
5✔
306
                errors.ErrInvalidData.Withf("group ID is required").Write(w)
×
307
                return
×
308
        }
×
309
        // get the user from the request context
310
        user, ok := apicommon.UserFromContext(r.Context())
5✔
311
        if !ok {
5✔
312
                errors.ErrUnauthorized.Write(w)
×
313
                return
×
314
        }
×
315
        // get the organization info from the request context
316
        org, _, ok := a.organizationFromRequest(r)
5✔
317
        if !ok {
5✔
318
                errors.ErrNoOrganizationProvided.Write(w)
×
319
                return
×
320
        }
×
321
        if !user.HasRoleFor(org.Address, db.AdminRole) && !user.HasRoleFor(org.Address, db.ManagerRole) {
6✔
322
                // if the user is not admin or manager of the organization, return an error
1✔
323
                errors.ErrUnauthorized.Withf("user is not admin of organization").Write(w)
1✔
324
                return
1✔
325
        }
1✔
326
        if err := a.db.DeleteOrganizationMemberGroup(groupID, org.Address); err != nil {
5✔
327
                if err == db.ErrNotFound {
1✔
328
                        errors.ErrInvalidData.Withf("group not found").Write(w)
×
329
                        return
×
330
                }
×
331
                errors.ErrGenericInternalServerError.Withf("could not delete organization member group: %v", err).Write(w)
1✔
332
                return
1✔
333
        }
334
        apicommon.HTTPWriteOK(w)
3✔
335
}
336

337
// listOrganizationMemberGroupsHandler godoc
338
//
339
//        @Summary                Get the list of members with details of an organization member group
340
//        @Description        Get the list of members with details of an organization member group
341
//        @Description        Needs admin or manager role
342
//        @Tags                        organizations
343
//        @Accept                        json
344
//        @Produce                json
345
//        @Security                BearerAuth
346
//        @Param                        address                path                string        true        "Organization address"
347
//        @Param                        groupID                path                string        true        "Group ID"
348
//        @Param                        page                query                int                false        "Page number for pagination"
349
//        @Param                        pageSize        query                int                false        "Number of items per page"
350
//        @Success                200                        {object}        apicommon.ListOrganizationMemberGroupResponse
351
//        @Failure                400                        {object}        errors.Error        "Invalid input data"
352
//        @Failure                401                        {object}        errors.Error        "Unauthorized"
353
//        @Failure                404                        {object}        errors.Error        "Organization or group not found"
354
//        @Failure                500                        {object}        errors.Error        "Internal server error"
355
//        @Router                        /organizations/{address}/groups/{groupID}/members [get]
356
func (a *API) listOrganizationMemberGroupsHandler(w http.ResponseWriter, r *http.Request) {
4✔
357
        // get the group ID from the request path
4✔
358
        groupID := chi.URLParam(r, "groupID")
4✔
359
        if groupID == "" {
4✔
360
                errors.ErrInvalidData.Withf("group ID is required").Write(w)
×
361
                return
×
362
        }
×
363
        // get the user from the request context
364
        user, ok := apicommon.UserFromContext(r.Context())
4✔
365
        if !ok {
4✔
366
                errors.ErrUnauthorized.Write(w)
×
367
                return
×
368
        }
×
369
        // get the organization info from the request context
370
        org, _, ok := a.organizationFromRequest(r)
4✔
371
        if !ok {
4✔
372
                errors.ErrNoOrganizationProvided.Write(w)
×
373
                return
×
374
        }
×
375
        if !user.HasRoleFor(org.Address, db.AdminRole) && !user.HasRoleFor(org.Address, db.ManagerRole) {
5✔
376
                // if the user is not admin or manager of the organization, return an error
1✔
377
                errors.ErrUnauthorized.Withf("user is not admin of organization").Write(w)
1✔
378
                return
1✔
379
        }
1✔
380

381
        // Parse pagination parameters from query string
382
        page := 1      // Default page number
3✔
383
        pageSize := 10 // Default page size
3✔
384

3✔
385
        if pageStr := r.URL.Query().Get("page"); pageStr != "" {
4✔
386
                if pageVal, err := strconv.Atoi(pageStr); err == nil && pageVal > 0 {
2✔
387
                        page = pageVal
1✔
388
                }
1✔
389
        }
390

391
        if pageSizeStr := r.URL.Query().Get("pageSize"); pageSizeStr != "" {
4✔
392
                if pageSizeVal, err := strconv.Atoi(pageSizeStr); err == nil && pageSizeVal > 0 {
2✔
393
                        pageSize = pageSizeVal
1✔
394
                }
1✔
395
        }
396

397
        totalPages, members, err := a.db.ListOrganizationMemberGroup(groupID, org.Address, int64(page), int64(pageSize))
3✔
398
        if err != nil {
4✔
399
                if err == db.ErrNotFound {
1✔
400
                        errors.ErrInvalidData.Withf("group not found").Write(w)
×
401
                        return
×
402
                }
×
403
                errors.ErrGenericInternalServerError.Withf("could not get organization member group members: %v", err).Write(w)
1✔
404
                return
1✔
405
        }
406
        if totalPages == 0 {
2✔
407
                // If no members are found, return an empty response
×
408
                apicommon.HTTPWriteJSON(w, &apicommon.ListOrganizationMemberGroupResponse{
×
409
                        TotalPages:  totalPages,
×
410
                        CurrentPage: 0,
×
411
                        Members:     []apicommon.OrgMember{},
×
412
                })
×
413
        }
×
414
        // convert the members to the response format
415
        membersResponse := make([]apicommon.OrgMember, 0, len(members))
2✔
416
        for _, m := range members {
6✔
417
                membersResponse = append(membersResponse, apicommon.OrgMemberFromDb(*m))
4✔
418
        }
4✔
419

420
        apicommon.HTTPWriteJSON(w, &apicommon.ListOrganizationMemberGroupResponse{
2✔
421
                TotalPages:  totalPages,
2✔
422
                CurrentPage: page,
2✔
423
                Members:     membersResponse,
2✔
424
        })
2✔
425
}
426

427
// organizationMemberGroupValidateHandler godoc
428
//
429
//        @Summary                Validate organization group members data
430
//        @Description        Checks the AuthFields for duplicates or empty fields and the TwoFaFields for empty ones.
431
//        @Tags                        organizations
432
//        @Accept                        json
433
//        @Produce                json
434
//        @Security                BearerAuth
435
//        @Param                        address        path                string                                                                        true        "Organization address"
436
//        @Param                        groupID        path                string                                                                        true        "Group ID"
437
//        @Param                        members        body                apicommon.ValidateMemberGroupRequest        true        "Members validation request"
438
//        @Success                200                {string}        string                                                                        "OK"
439
//        @Failure                400                {object}        errors.Error                                                        "Invalid input data"
440
//        @Failure                401                {object}        errors.Error                                                        "Unauthorized"
441
//        @Failure                404                {object}        errors.Error                                                        "Organization or group not found"
442
//        @Failure                500                {object}        errors.Error                                                        "Internal server error"
443
//
444
//        @Router                        /organizations/{address}/groups/{groupID}/validate [post]
445
func (a *API) organizationMemberGroupValidateHandler(w http.ResponseWriter, r *http.Request) {
8✔
446
        // get the group ID from the request path
8✔
447
        groupID := chi.URLParam(r, "groupID")
8✔
448
        if groupID == "" {
8✔
UNCOV
449
                errors.ErrInvalidData.Withf("group ID is required").Write(w)
×
UNCOV
450
                return
×
UNCOV
451
        }
×
452
        // get the user from the request context
453
        user, ok := apicommon.UserFromContext(r.Context())
8✔
454
        if !ok {
8✔
UNCOV
455
                errors.ErrUnauthorized.Write(w)
×
UNCOV
456
                return
×
UNCOV
457
        }
×
458
        // get the organization info from the request context
459
        org, _, ok := a.organizationFromRequest(r)
8✔
460
        if !ok {
8✔
UNCOV
461
                errors.ErrNoOrganizationProvided.Write(w)
×
UNCOV
462
                return
×
UNCOV
463
        }
×
464
        if !user.HasRoleFor(org.Address, db.AdminRole) && !user.HasRoleFor(org.Address, db.ManagerRole) {
9✔
465
                // if the user is not admin or manager of the organization, return an error
1✔
466
                errors.ErrUnauthorized.Withf("user is not admin of organization").Write(w)
1✔
467
                return
1✔
468
        }
1✔
469

470
        var membersRequest apicommon.ValidateMemberGroupRequest
7✔
471
        if err := json.NewDecoder(r.Body).Decode(&membersRequest); err != nil {
7✔
UNCOV
472
                errors.ErrMalformedBody.Write(w)
×
UNCOV
473
                return
×
UNCOV
474
        }
×
475

476
        if len(membersRequest.AuthFields) == 0 && len(membersRequest.TwoFaFields) == 0 {
8✔
477
                errors.ErrInvalidData.Withf("missing both AuthFields and TwoFaFields").Write(w)
1✔
478
                return
1✔
479
        }
1✔
480

481
        // check the org members to veriy tha the OrgMemberAuthFields can be used for authentication
482
        aggregationResults, err := a.db.CheckGroupMembersFields(
6✔
483
                org.Address,
6✔
484
                groupID,
6✔
485
                membersRequest.AuthFields,
6✔
486
                membersRequest.TwoFaFields,
6✔
487
        )
6✔
488
        if err != nil {
7✔
489
                errors.ErrGenericInternalServerError.WithErr(err).Write(w)
1✔
490
                return
1✔
491
        }
1✔
492
        if len(aggregationResults.Duplicates) > 0 || len(aggregationResults.MissingData) > 0 {
8✔
493
                // if there are incorrect members, return an error with the IDs of the incorrect members
3✔
494
                errors.ErrInvalidData.WithData(aggregationResults).Write(w)
3✔
495
                return
3✔
496
        }
3✔
497

498
        apicommon.HTTPWriteOK(w)
2✔
499
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc