@boxyhq/saml-jackson 1.1.6 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/controller/error.d.ts +5 -0
  2. package/dist/controller/error.js +6 -1
  3. package/dist/controller/utils.d.ts +13 -0
  4. package/dist/controller/utils.js +27 -1
  5. package/dist/db/mem.js +7 -3
  6. package/dist/directory-sync/Base.d.ts +15 -0
  7. package/dist/directory-sync/Base.js +39 -0
  8. package/dist/directory-sync/DirectoryConfig.d.ts +43 -0
  9. package/dist/directory-sync/DirectoryConfig.js +186 -0
  10. package/dist/directory-sync/DirectoryGroups.d.ts +26 -0
  11. package/dist/directory-sync/DirectoryGroups.js +254 -0
  12. package/dist/directory-sync/DirectoryUsers.d.ts +22 -0
  13. package/dist/directory-sync/DirectoryUsers.js +175 -0
  14. package/dist/directory-sync/Groups.d.ts +47 -0
  15. package/dist/directory-sync/Groups.js +195 -0
  16. package/dist/directory-sync/Users.d.ts +47 -0
  17. package/dist/directory-sync/Users.js +135 -0
  18. package/dist/directory-sync/WebhookEventsLogger.d.ts +13 -0
  19. package/dist/directory-sync/WebhookEventsLogger.js +57 -0
  20. package/dist/directory-sync/events.d.ts +7 -0
  21. package/dist/directory-sync/events.js +53 -0
  22. package/dist/directory-sync/index.d.ts +6 -0
  23. package/dist/directory-sync/index.js +42 -0
  24. package/dist/directory-sync/request.d.ts +7 -0
  25. package/dist/directory-sync/request.js +30 -0
  26. package/dist/directory-sync/transform.d.ts +7 -0
  27. package/dist/directory-sync/transform.js +26 -0
  28. package/dist/directory-sync/utils.d.ts +39 -0
  29. package/dist/directory-sync/utils.js +140 -0
  30. package/dist/index.d.ts +2 -1
  31. package/dist/index.js +7 -3
  32. package/dist/typings.d.ts +275 -7
  33. package/dist/typings.js +9 -0
  34. package/package.json +3 -1
@@ -0,0 +1,254 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.DirectoryGroups = void 0;
13
+ const utils_1 = require("./utils");
14
+ const events_1 = require("./events");
15
+ class DirectoryGroups {
16
+ constructor({ directories, users, groups, }) {
17
+ this.directories = directories;
18
+ this.users = users;
19
+ this.groups = groups;
20
+ }
21
+ create(directory, body) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ const { displayName, members } = body;
24
+ const { data: group } = yield this.groups.create({
25
+ name: displayName,
26
+ raw: body,
27
+ });
28
+ yield (0, events_1.sendEvent)('group.created', { directory, group }, this.callback);
29
+ return {
30
+ status: 201,
31
+ data: {
32
+ schemas: ['urn:ietf:params:scim:schemas:core:2.0:Group'],
33
+ id: group === null || group === void 0 ? void 0 : group.id,
34
+ displayName: group === null || group === void 0 ? void 0 : group.name,
35
+ members: members !== null && members !== void 0 ? members : [],
36
+ },
37
+ };
38
+ });
39
+ }
40
+ get(group) {
41
+ return __awaiter(this, void 0, void 0, function* () {
42
+ return {
43
+ status: 200,
44
+ data: {
45
+ schemas: ['urn:ietf:params:scim:schemas:core:2.0:Group'],
46
+ id: group.id,
47
+ displayName: group.name,
48
+ members: (0, utils_1.toGroupMembers)(yield this.groups.getAllUsers(group.id)),
49
+ },
50
+ };
51
+ });
52
+ }
53
+ delete(directory, group) {
54
+ return __awaiter(this, void 0, void 0, function* () {
55
+ yield this.groups.removeAllUsers(group.id);
56
+ yield this.groups.delete(group.id);
57
+ yield (0, events_1.sendEvent)('group.deleted', { directory, group }, this.callback);
58
+ return {
59
+ status: 200,
60
+ data: {},
61
+ };
62
+ });
63
+ }
64
+ getAll(queryParams) {
65
+ return __awaiter(this, void 0, void 0, function* () {
66
+ const { filter } = queryParams;
67
+ let groups = [];
68
+ if (filter) {
69
+ // Filter by group displayName
70
+ // filter: displayName eq "Developer"
71
+ const { data } = yield this.groups.search(filter.split('eq ')[1].replace(/['"]+/g, ''));
72
+ groups = data;
73
+ }
74
+ else {
75
+ // Fetch all the existing group
76
+ const { data } = yield this.groups.list({ pageOffset: undefined, pageLimit: undefined });
77
+ groups = data;
78
+ }
79
+ return {
80
+ status: 200,
81
+ data: {
82
+ schemas: ['urn:ietf:params:scim:api:messages:2.0:ListResponse'],
83
+ totalResults: groups ? groups.length : 0,
84
+ itemsPerPage: groups ? groups.length : 0,
85
+ startIndex: 1,
86
+ Resources: groups ? groups.map((group) => group.raw) : [],
87
+ },
88
+ };
89
+ });
90
+ }
91
+ // Update group displayName
92
+ updateDisplayName(directory, group, body) {
93
+ return __awaiter(this, void 0, void 0, function* () {
94
+ const { displayName } = body;
95
+ const { data: updatedGroup, error } = yield this.groups.update(group.id, {
96
+ name: displayName,
97
+ raw: Object.assign(Object.assign({}, group.raw), body),
98
+ });
99
+ if (error || !updatedGroup) {
100
+ throw error;
101
+ }
102
+ yield (0, events_1.sendEvent)('group.updated', { directory, group: updatedGroup }, this.callback);
103
+ return updatedGroup;
104
+ });
105
+ }
106
+ patch(directory, group, body) {
107
+ return __awaiter(this, void 0, void 0, function* () {
108
+ const { Operations } = body;
109
+ const operation = (0, utils_1.parseGroupOperations)(Operations);
110
+ // Add group members
111
+ if (operation.action === 'addGroupMember') {
112
+ yield this.addGroupMembers(directory, group, operation.members);
113
+ }
114
+ // Remove group members
115
+ if (operation.action === 'removeGroupMember') {
116
+ yield this.removeGroupMembers(directory, group, operation.members);
117
+ }
118
+ // Update group name
119
+ if (operation.action === 'updateGroupName') {
120
+ yield this.updateDisplayName(directory, group, {
121
+ displayName: operation.displayName,
122
+ });
123
+ }
124
+ const { data: updatedGroup } = yield this.groups.get(group.id);
125
+ return {
126
+ status: 200,
127
+ data: {
128
+ schemas: ['urn:ietf:params:scim:schemas:core:2.0:Group'],
129
+ id: updatedGroup === null || updatedGroup === void 0 ? void 0 : updatedGroup.id,
130
+ displayName: updatedGroup === null || updatedGroup === void 0 ? void 0 : updatedGroup.name,
131
+ members: (0, utils_1.toGroupMembers)(yield this.groups.getAllUsers(group.id)),
132
+ },
133
+ };
134
+ });
135
+ }
136
+ update(directory, group, body) {
137
+ return __awaiter(this, void 0, void 0, function* () {
138
+ const { displayName, members } = body;
139
+ // Update group name
140
+ const updatedGroup = yield this.updateDisplayName(directory, group, {
141
+ displayName,
142
+ });
143
+ // Update group members
144
+ if (members) {
145
+ yield this.addOrRemoveGroupMembers(directory, group, members);
146
+ }
147
+ return {
148
+ status: 200,
149
+ data: {
150
+ schemas: ['urn:ietf:params:scim:schemas:core:2.0:Group'],
151
+ id: group.id,
152
+ displayName: updatedGroup.name,
153
+ members: (0, utils_1.toGroupMembers)(yield this.groups.getAllUsers(group.id)),
154
+ },
155
+ };
156
+ });
157
+ }
158
+ addGroupMembers(directory, group, members, sendWebhookEvent = true) {
159
+ return __awaiter(this, void 0, void 0, function* () {
160
+ if (members === undefined || (members && members.length === 0)) {
161
+ return;
162
+ }
163
+ for (const member of members) {
164
+ if (yield this.groups.isUserInGroup(group.id, member.value)) {
165
+ continue;
166
+ }
167
+ yield this.groups.addUserToGroup(group.id, member.value);
168
+ const { data: user } = yield this.users.get(member.value);
169
+ if (sendWebhookEvent && user) {
170
+ yield (0, events_1.sendEvent)('group.user_added', { directory, group, user }, this.callback);
171
+ }
172
+ }
173
+ });
174
+ }
175
+ removeGroupMembers(directory, group, members, sendWebhookEvent = true) {
176
+ return __awaiter(this, void 0, void 0, function* () {
177
+ if (members.length === 0) {
178
+ return;
179
+ }
180
+ for (const member of members) {
181
+ yield this.groups.removeUserFromGroup(group.id, member.value);
182
+ const { data: user } = yield this.users.get(member.value);
183
+ // User may not exist in the directory, so we need to check if the user exists
184
+ if (sendWebhookEvent && user) {
185
+ yield (0, events_1.sendEvent)('group.user_removed', { directory, group, user }, this.callback);
186
+ }
187
+ }
188
+ });
189
+ }
190
+ // Add or remove users from a group
191
+ addOrRemoveGroupMembers(directory, group, members) {
192
+ return __awaiter(this, void 0, void 0, function* () {
193
+ const users = (0, utils_1.toGroupMembers)(yield this.groups.getAllUsers(group.id));
194
+ const usersToAdd = members.filter((member) => !users.some((user) => user.value === member.value));
195
+ const usersToRemove = users
196
+ .filter((user) => !members.some((member) => member.value === user.value))
197
+ .map((user) => ({ value: user.value }));
198
+ yield this.addGroupMembers(directory, group, usersToAdd, false);
199
+ yield this.removeGroupMembers(directory, group, usersToRemove, false);
200
+ });
201
+ }
202
+ respondWithError(error) {
203
+ return {
204
+ status: error ? error.code : 500,
205
+ data: null,
206
+ };
207
+ }
208
+ // Handle the request from the Identity Provider and route it to the appropriate method
209
+ handleRequest(request, callback) {
210
+ return __awaiter(this, void 0, void 0, function* () {
211
+ const { body, query, resourceId: groupId, directoryId, apiSecret } = request;
212
+ const method = request.method.toUpperCase();
213
+ // Get the directory
214
+ const { data: directory, error } = yield this.directories.get(directoryId);
215
+ if (error || !directory) {
216
+ return this.respondWithError(error);
217
+ }
218
+ // Validate the request
219
+ if (directory.scim.secret != apiSecret) {
220
+ return this.respondWithError({ code: 401, message: 'Unauthorized' });
221
+ }
222
+ this.callback = callback;
223
+ this.users.setTenantAndProduct(directory.tenant, directory.product);
224
+ this.groups.setTenantAndProduct(directory.tenant, directory.product);
225
+ // Get the group
226
+ const { data: group } = groupId ? yield this.groups.get(groupId) : { data: null };
227
+ if (group) {
228
+ switch (method) {
229
+ case 'GET':
230
+ return yield this.get(group);
231
+ case 'PUT':
232
+ return yield this.update(directory, group, body);
233
+ case 'PATCH':
234
+ return yield this.patch(directory, group, body);
235
+ case 'DELETE':
236
+ return yield this.delete(directory, group);
237
+ }
238
+ }
239
+ switch (method) {
240
+ case 'POST':
241
+ return yield this.create(directory, body);
242
+ case 'GET':
243
+ return yield this.getAll({
244
+ filter: query.filter,
245
+ });
246
+ }
247
+ return {
248
+ status: 404,
249
+ data: {},
250
+ };
251
+ });
252
+ }
253
+ }
254
+ exports.DirectoryGroups = DirectoryGroups;
@@ -0,0 +1,22 @@
1
+ import type { DirectoryConfig, Directory, DirectorySyncResponse, DirectorySyncRequest, User, Users, IDirectoryUsers, EventCallback } from '../typings';
2
+ export declare class DirectoryUsers implements IDirectoryUsers {
3
+ private directories;
4
+ private users;
5
+ private callback;
6
+ constructor({ directories, users }: {
7
+ directories: DirectoryConfig;
8
+ users: Users;
9
+ });
10
+ create(directory: Directory, body: any): Promise<DirectorySyncResponse>;
11
+ get(user: User): Promise<DirectorySyncResponse>;
12
+ update(directory: Directory, user: User, body: any): Promise<DirectorySyncResponse>;
13
+ patch(directory: Directory, user: User, body: any): Promise<DirectorySyncResponse>;
14
+ delete(directory: Directory, user: User): Promise<DirectorySyncResponse>;
15
+ getAll(queryParams: {
16
+ count: number;
17
+ startIndex: number;
18
+ filter?: string;
19
+ }): Promise<DirectorySyncResponse>;
20
+ private respondWithError;
21
+ handleRequest(request: DirectorySyncRequest, callback?: EventCallback): Promise<DirectorySyncResponse>;
22
+ }
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.DirectoryUsers = void 0;
13
+ const utils_1 = require("./utils");
14
+ const events_1 = require("./events");
15
+ class DirectoryUsers {
16
+ constructor({ directories, users }) {
17
+ this.directories = directories;
18
+ this.users = users;
19
+ }
20
+ create(directory, body) {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ const { name, emails } = body;
23
+ const { data: user } = yield this.users.create({
24
+ first_name: name && 'givenName' in name ? name.givenName : '',
25
+ last_name: name && 'familyName' in name ? name.familyName : '',
26
+ email: emails[0].value,
27
+ active: true,
28
+ raw: body,
29
+ });
30
+ yield (0, events_1.sendEvent)('user.created', { directory, user }, this.callback);
31
+ return {
32
+ status: 201,
33
+ data: user === null || user === void 0 ? void 0 : user.raw,
34
+ };
35
+ });
36
+ }
37
+ get(user) {
38
+ return __awaiter(this, void 0, void 0, function* () {
39
+ return {
40
+ status: 200,
41
+ data: user.raw,
42
+ };
43
+ });
44
+ }
45
+ update(directory, user, body) {
46
+ return __awaiter(this, void 0, void 0, function* () {
47
+ const { name, emails, active } = body;
48
+ const { data: updatedUser } = yield this.users.update(user.id, {
49
+ first_name: name.givenName,
50
+ last_name: name.familyName,
51
+ email: emails[0].value,
52
+ active,
53
+ raw: body,
54
+ });
55
+ yield (0, events_1.sendEvent)('user.updated', { directory, user: updatedUser }, this.callback);
56
+ return {
57
+ status: 200,
58
+ data: updatedUser === null || updatedUser === void 0 ? void 0 : updatedUser.raw,
59
+ };
60
+ });
61
+ }
62
+ patch(directory, user, body) {
63
+ return __awaiter(this, void 0, void 0, function* () {
64
+ const { Operations } = body;
65
+ const operation = (0, utils_1.parseUserOperations)(Operations);
66
+ if (operation.action === 'updateUser') {
67
+ const { data: updatedUser } = yield this.users.update(user.id, Object.assign(Object.assign(Object.assign({}, user), operation.attributes), { raw: Object.assign(Object.assign({}, user.raw), operation.raw) }));
68
+ yield (0, events_1.sendEvent)('user.updated', { directory, user: updatedUser }, this.callback);
69
+ return {
70
+ status: 200,
71
+ data: updatedUser === null || updatedUser === void 0 ? void 0 : updatedUser.raw,
72
+ };
73
+ }
74
+ return {
75
+ status: 200,
76
+ data: null,
77
+ };
78
+ });
79
+ }
80
+ delete(directory, user) {
81
+ return __awaiter(this, void 0, void 0, function* () {
82
+ yield this.users.delete(user.id);
83
+ yield (0, events_1.sendEvent)('user.deleted', { directory, user }, this.callback);
84
+ return {
85
+ status: 200,
86
+ data: user.raw,
87
+ };
88
+ });
89
+ }
90
+ getAll(queryParams) {
91
+ return __awaiter(this, void 0, void 0, function* () {
92
+ const { startIndex, filter, count } = queryParams;
93
+ let users = [];
94
+ let totalResults = 0;
95
+ if (filter) {
96
+ // Search users by userName
97
+ // filter: userName eq "john@example.com"
98
+ const { data } = yield this.users.search(filter.split('eq ')[1].replace(/['"]+/g, ''));
99
+ users = data;
100
+ totalResults = users ? users.length : 0;
101
+ }
102
+ else {
103
+ // Fetch all the existing Users (Paginated)
104
+ // At this moment, we don't have method to count the database records.
105
+ const { data: allUsers } = yield this.users.list({});
106
+ const { data } = yield this.users.list({ pageOffset: startIndex - 1, pageLimit: count });
107
+ users = data;
108
+ totalResults = allUsers ? allUsers.length : 0;
109
+ }
110
+ return {
111
+ status: 200,
112
+ data: {
113
+ schemas: ['urn:ietf:params:scim:api:messages:2.0:ListResponse'],
114
+ startIndex: startIndex ? startIndex : 1,
115
+ totalResults: totalResults ? totalResults : 0,
116
+ itemsPerPage: count ? count : 0,
117
+ Resources: users ? users.map((user) => user.raw) : [],
118
+ },
119
+ };
120
+ });
121
+ }
122
+ respondWithError(error) {
123
+ return {
124
+ status: error ? error.code : 500,
125
+ data: null,
126
+ };
127
+ }
128
+ // Handle the request from the Identity Provider and route it to the appropriate method
129
+ handleRequest(request, callback) {
130
+ return __awaiter(this, void 0, void 0, function* () {
131
+ const { body, query, resourceId: userId, directoryId, apiSecret } = request;
132
+ const method = request.method.toUpperCase();
133
+ // Get the directory
134
+ const { data: directory, error } = yield this.directories.get(directoryId);
135
+ if (error || !directory) {
136
+ return this.respondWithError(error);
137
+ }
138
+ // Validate the request
139
+ if (directory.scim.secret != apiSecret) {
140
+ return this.respondWithError({ code: 401, message: 'Unauthorized' });
141
+ }
142
+ this.callback = callback;
143
+ this.users.setTenantAndProduct(directory.tenant, directory.product);
144
+ // Get the user
145
+ const { data: user } = userId ? yield this.users.get(userId) : { data: null };
146
+ if (user) {
147
+ switch (method) {
148
+ case 'GET':
149
+ return yield this.get(user);
150
+ case 'PATCH':
151
+ return yield this.patch(directory, user, body);
152
+ case 'PUT':
153
+ return yield this.update(directory, user, body);
154
+ case 'DELETE':
155
+ return yield this.delete(directory, user);
156
+ }
157
+ }
158
+ switch (method) {
159
+ case 'POST':
160
+ return yield this.create(directory, body);
161
+ case 'GET':
162
+ return yield this.getAll({
163
+ count: query.count,
164
+ startIndex: query.startIndex,
165
+ filter: query.filter,
166
+ });
167
+ }
168
+ return {
169
+ status: 404,
170
+ data: {},
171
+ };
172
+ });
173
+ }
174
+ }
175
+ exports.DirectoryUsers = DirectoryUsers;
@@ -0,0 +1,47 @@
1
+ import type { Group, DatabaseStore, ApiError } from '../typings';
2
+ import { Base } from './Base';
3
+ export declare class Groups extends Base {
4
+ constructor({ db }: {
5
+ db: DatabaseStore;
6
+ });
7
+ create(param: {
8
+ name: string;
9
+ raw: any;
10
+ }): Promise<{
11
+ data: Group | null;
12
+ error: ApiError | null;
13
+ }>;
14
+ get(id: string): Promise<{
15
+ data: Group | null;
16
+ error: ApiError | null;
17
+ }>;
18
+ update(id: string, param: {
19
+ name: string;
20
+ raw: any;
21
+ }): Promise<{
22
+ data: Group | null;
23
+ error: ApiError | null;
24
+ }>;
25
+ delete(id: string): Promise<{
26
+ data: null;
27
+ error: ApiError | null;
28
+ }>;
29
+ getAllUsers(groupId: string): Promise<{
30
+ user_id: string;
31
+ }[]>;
32
+ addUserToGroup(groupId: string, userId: string): Promise<void>;
33
+ removeUserFromGroup(groupId: string, userId: string): Promise<void>;
34
+ removeAllUsers(groupId: string): Promise<void>;
35
+ isUserInGroup(groupId: string, userId: string): Promise<boolean>;
36
+ search(displayName: string): Promise<{
37
+ data: Group[] | null;
38
+ error: ApiError | null;
39
+ }>;
40
+ list({ pageOffset, pageLimit, }: {
41
+ pageOffset?: number;
42
+ pageLimit?: number;
43
+ }): Promise<{
44
+ data: Group[] | null;
45
+ error: ApiError | null;
46
+ }>;
47
+ }
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.Groups = void 0;
36
+ const dbutils = __importStar(require("../db/utils"));
37
+ const error_1 = require("../controller/error");
38
+ const Base_1 = require("./Base");
39
+ class Groups extends Base_1.Base {
40
+ constructor({ db }) {
41
+ super({ db });
42
+ }
43
+ // Create a new group
44
+ create(param) {
45
+ return __awaiter(this, void 0, void 0, function* () {
46
+ try {
47
+ const { name, raw } = param;
48
+ const id = this.createId();
49
+ raw['id'] = id;
50
+ const group = {
51
+ id,
52
+ name,
53
+ raw,
54
+ };
55
+ yield this.store('groups').put(id, group, {
56
+ name: 'displayName',
57
+ value: name,
58
+ });
59
+ return { data: group, error: null };
60
+ }
61
+ catch (err) {
62
+ return (0, error_1.apiError)(err);
63
+ }
64
+ });
65
+ }
66
+ // Get a group by id
67
+ get(id) {
68
+ return __awaiter(this, void 0, void 0, function* () {
69
+ try {
70
+ const group = yield this.store('groups').get(id);
71
+ if (!group) {
72
+ throw new error_1.JacksonError(`Group with id ${id} not found.`, 404);
73
+ }
74
+ return { data: group, error: null };
75
+ }
76
+ catch (err) {
77
+ return (0, error_1.apiError)(err);
78
+ }
79
+ });
80
+ }
81
+ // Update the group data
82
+ update(id, param) {
83
+ return __awaiter(this, void 0, void 0, function* () {
84
+ try {
85
+ const { name, raw } = param;
86
+ const group = {
87
+ id,
88
+ name,
89
+ raw,
90
+ };
91
+ yield this.store('groups').put(id, group);
92
+ return { data: group, error: null };
93
+ }
94
+ catch (err) {
95
+ return (0, error_1.apiError)(err);
96
+ }
97
+ });
98
+ }
99
+ // Delete a group by id
100
+ delete(id) {
101
+ return __awaiter(this, void 0, void 0, function* () {
102
+ try {
103
+ const { data, error } = yield this.get(id);
104
+ if (error || !data) {
105
+ throw error;
106
+ }
107
+ yield this.store('groups').delete(id);
108
+ return { data: null, error: null };
109
+ }
110
+ catch (err) {
111
+ return (0, error_1.apiError)(err);
112
+ }
113
+ });
114
+ }
115
+ // Get all users in a group
116
+ getAllUsers(groupId) {
117
+ return __awaiter(this, void 0, void 0, function* () {
118
+ const users = yield this.store('members').getByIndex({
119
+ name: 'groupId',
120
+ value: groupId,
121
+ });
122
+ if (users.length === 0) {
123
+ return [];
124
+ }
125
+ return users;
126
+ });
127
+ }
128
+ // Add a user to a group
129
+ addUserToGroup(groupId, userId) {
130
+ return __awaiter(this, void 0, void 0, function* () {
131
+ const id = dbutils.keyDigest(dbutils.keyFromParts(groupId, userId));
132
+ yield this.store('members').put(id, {
133
+ group_id: groupId,
134
+ user_id: userId,
135
+ }, {
136
+ name: 'groupId',
137
+ value: groupId,
138
+ });
139
+ });
140
+ }
141
+ // Remove a user from a group
142
+ removeUserFromGroup(groupId, userId) {
143
+ return __awaiter(this, void 0, void 0, function* () {
144
+ const id = dbutils.keyDigest(dbutils.keyFromParts(groupId, userId));
145
+ yield this.store('members').delete(id);
146
+ });
147
+ }
148
+ // Remove all users from a group
149
+ removeAllUsers(groupId) {
150
+ return __awaiter(this, void 0, void 0, function* () {
151
+ const users = yield this.getAllUsers(groupId);
152
+ if (users.length === 0) {
153
+ return;
154
+ }
155
+ for (const user of users) {
156
+ yield this.removeUserFromGroup(groupId, user.user_id);
157
+ }
158
+ });
159
+ }
160
+ // Check if a user is a member of a group
161
+ isUserInGroup(groupId, userId) {
162
+ return __awaiter(this, void 0, void 0, function* () {
163
+ const id = dbutils.keyDigest(dbutils.keyFromParts(groupId, userId));
164
+ return !!(yield this.store('members').get(id));
165
+ });
166
+ }
167
+ // Search groups by displayName
168
+ search(displayName) {
169
+ return __awaiter(this, void 0, void 0, function* () {
170
+ try {
171
+ const groups = (yield this.store('groups').getByIndex({
172
+ name: 'displayName',
173
+ value: displayName,
174
+ }));
175
+ return { data: groups, error: null };
176
+ }
177
+ catch (err) {
178
+ return (0, error_1.apiError)(err);
179
+ }
180
+ });
181
+ }
182
+ // Get all groups in a directory
183
+ list({ pageOffset, pageLimit, }) {
184
+ return __awaiter(this, void 0, void 0, function* () {
185
+ try {
186
+ const groups = (yield this.store('groups').getAll(pageOffset, pageLimit));
187
+ return { data: groups, error: null };
188
+ }
189
+ catch (err) {
190
+ return (0, error_1.apiError)(err);
191
+ }
192
+ });
193
+ }
194
+ }
195
+ exports.Groups = Groups;