@sudobility/entity_service 1.0.7 → 1.0.9
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.
- package/dist/helpers/EntityHelper.js +25 -29
- package/dist/helpers/EntityHelper.js.map +1 -1
- package/dist/helpers/EntityMemberHelper.js +26 -30
- package/dist/helpers/EntityMemberHelper.js.map +1 -1
- package/dist/helpers/InvitationHelper.js +28 -32
- package/dist/helpers/InvitationHelper.js.map +1 -1
- package/dist/helpers/PermissionHelper.js +13 -17
- package/dist/helpers/PermissionHelper.js.map +1 -1
- package/dist/helpers/index.js +4 -11
- package/dist/helpers/index.js.map +1 -1
- package/dist/index.js +9 -38
- package/dist/index.js.map +1 -1
- package/dist/middleware/hono.js +18 -24
- package/dist/middleware/hono.js.map +1 -1
- package/dist/middleware/index.js +1 -8
- package/dist/middleware/index.js.map +1 -1
- package/dist/migrations/001_add_entities.d.ts +2 -0
- package/dist/migrations/001_add_entities.d.ts.map +1 -1
- package/dist/migrations/001_add_entities.js +6 -8
- package/dist/migrations/001_add_entities.js.map +1 -1
- package/dist/migrations/index.js +1 -6
- package/dist/migrations/index.js.map +1 -1
- package/dist/schema/entities.js +125 -135
- package/dist/schema/entities.js.map +1 -1
- package/dist/types/index.js +1 -8
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.js +1 -17
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/slug-generator.js +6 -14
- package/dist/utils/slug-generator.js.map +1 -1
- package/package.json +9 -16
- package/dist/helpers/EntityHelper.cjs +0 -253
- package/dist/helpers/EntityMemberHelper.cjs +0 -254
- package/dist/helpers/InvitationHelper.cjs +0 -256
- package/dist/helpers/PermissionHelper.cjs +0 -193
- package/dist/helpers/index.cjs +0 -15
- package/dist/index.cjs +0 -76
- package/dist/middleware/hono.cjs +0 -148
- package/dist/middleware/index.cjs +0 -12
- package/dist/migrations/001_add_entities.cjs +0 -330
- package/dist/migrations/index.cjs +0 -10
- package/dist/schema/entities.cjs +0 -311
- package/dist/types/index.cjs +0 -14
- package/dist/utils/index.cjs +0 -21
- package/dist/utils/slug-generator.cjs +0 -92
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* @fileoverview Entity Helper Class
|
|
4
3
|
* @description CRUD operations for entities (personal and organization workspaces)
|
|
5
4
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const types_1 = require("../types");
|
|
10
|
-
const utils_1 = require("../utils");
|
|
5
|
+
import { eq, and } from 'drizzle-orm';
|
|
6
|
+
import { EntityType, EntityRole, } from '../types';
|
|
7
|
+
import { generateEntitySlug, validateSlug, normalizeSlug } from '../utils';
|
|
11
8
|
/**
|
|
12
9
|
* Helper class for entity CRUD operations.
|
|
13
10
|
*/
|
|
14
|
-
class EntityHelper {
|
|
11
|
+
export class EntityHelper {
|
|
15
12
|
constructor(config) {
|
|
16
13
|
this.config = config;
|
|
17
14
|
}
|
|
@@ -22,13 +19,13 @@ class EntityHelper {
|
|
|
22
19
|
* @param email - Optional email for display name
|
|
23
20
|
*/
|
|
24
21
|
async createPersonalEntity(firebaseUid, email) {
|
|
25
|
-
const slug =
|
|
22
|
+
const slug = generateEntitySlug();
|
|
26
23
|
const displayName = email?.split('@')[0] ?? 'Personal';
|
|
27
24
|
const [entity] = await this.config.db
|
|
28
25
|
.insert(this.config.entitiesTable)
|
|
29
26
|
.values({
|
|
30
27
|
entity_slug: slug,
|
|
31
|
-
entity_type:
|
|
28
|
+
entity_type: EntityType.PERSONAL,
|
|
32
29
|
display_name: displayName,
|
|
33
30
|
})
|
|
34
31
|
.returning();
|
|
@@ -36,7 +33,7 @@ class EntityHelper {
|
|
|
36
33
|
await this.config.db.insert(this.config.membersTable).values({
|
|
37
34
|
entity_id: entity.id,
|
|
38
35
|
user_id: firebaseUid,
|
|
39
|
-
role:
|
|
36
|
+
role: EntityRole.ADMIN,
|
|
40
37
|
is_active: true,
|
|
41
38
|
});
|
|
42
39
|
return this.mapRecordToEntity(entity);
|
|
@@ -52,8 +49,8 @@ class EntityHelper {
|
|
|
52
49
|
const existing = await this.config.db
|
|
53
50
|
.select({ entity: this.config.entitiesTable })
|
|
54
51
|
.from(this.config.membersTable)
|
|
55
|
-
.innerJoin(this.config.entitiesTable,
|
|
56
|
-
.where(
|
|
52
|
+
.innerJoin(this.config.entitiesTable, eq(this.config.membersTable.entity_id, this.config.entitiesTable.id))
|
|
53
|
+
.where(and(eq(this.config.membersTable.user_id, firebaseUid), eq(this.config.membersTable.role, EntityRole.ADMIN), eq(this.config.membersTable.is_active, true), eq(this.config.entitiesTable.entity_type, EntityType.PERSONAL)))
|
|
57
54
|
.limit(1);
|
|
58
55
|
if (existing.length > 0) {
|
|
59
56
|
return this.mapRecordToEntity(existing[0].entity);
|
|
@@ -69,8 +66,8 @@ class EntityHelper {
|
|
|
69
66
|
// Determine slug
|
|
70
67
|
let slug;
|
|
71
68
|
if (request.entitySlug) {
|
|
72
|
-
slug =
|
|
73
|
-
if (!
|
|
69
|
+
slug = normalizeSlug(request.entitySlug);
|
|
70
|
+
if (!validateSlug(slug)) {
|
|
74
71
|
throw new Error('Invalid entity slug format');
|
|
75
72
|
}
|
|
76
73
|
// Check availability
|
|
@@ -85,7 +82,7 @@ class EntityHelper {
|
|
|
85
82
|
.insert(this.config.entitiesTable)
|
|
86
83
|
.values({
|
|
87
84
|
entity_slug: slug,
|
|
88
|
-
entity_type:
|
|
85
|
+
entity_type: EntityType.ORGANIZATION,
|
|
89
86
|
display_name: request.displayName,
|
|
90
87
|
description: request.description ?? null,
|
|
91
88
|
})
|
|
@@ -94,7 +91,7 @@ class EntityHelper {
|
|
|
94
91
|
await this.config.db.insert(this.config.membersTable).values({
|
|
95
92
|
entity_id: entity.id,
|
|
96
93
|
user_id: firebaseUid,
|
|
97
|
-
role:
|
|
94
|
+
role: EntityRole.OWNER,
|
|
98
95
|
is_active: true,
|
|
99
96
|
});
|
|
100
97
|
return this.mapRecordToEntity(entity);
|
|
@@ -106,7 +103,7 @@ class EntityHelper {
|
|
|
106
103
|
const results = await this.config.db
|
|
107
104
|
.select()
|
|
108
105
|
.from(this.config.entitiesTable)
|
|
109
|
-
.where(
|
|
106
|
+
.where(eq(this.config.entitiesTable.id, entityId))
|
|
110
107
|
.limit(1);
|
|
111
108
|
if (results.length === 0) {
|
|
112
109
|
return null;
|
|
@@ -120,7 +117,7 @@ class EntityHelper {
|
|
|
120
117
|
const results = await this.config.db
|
|
121
118
|
.select()
|
|
122
119
|
.from(this.config.entitiesTable)
|
|
123
|
-
.where(
|
|
120
|
+
.where(eq(this.config.entitiesTable.entity_slug, slug))
|
|
124
121
|
.limit(1);
|
|
125
122
|
if (results.length === 0) {
|
|
126
123
|
return null;
|
|
@@ -140,15 +137,15 @@ class EntityHelper {
|
|
|
140
137
|
role: this.config.membersTable.role,
|
|
141
138
|
})
|
|
142
139
|
.from(this.config.membersTable)
|
|
143
|
-
.innerJoin(this.config.entitiesTable,
|
|
144
|
-
.where(
|
|
140
|
+
.innerJoin(this.config.entitiesTable, eq(this.config.membersTable.entity_id, this.config.entitiesTable.id))
|
|
141
|
+
.where(and(eq(this.config.membersTable.user_id, firebaseUid), eq(this.config.membersTable.is_active, true)));
|
|
145
142
|
// If user has no entities, create a personal entity for them
|
|
146
143
|
if (results.length === 0) {
|
|
147
144
|
const personalEntity = await this.createPersonalEntity(firebaseUid, email);
|
|
148
145
|
return [
|
|
149
146
|
{
|
|
150
147
|
...personalEntity,
|
|
151
|
-
userRole:
|
|
148
|
+
userRole: EntityRole.OWNER,
|
|
152
149
|
},
|
|
153
150
|
];
|
|
154
151
|
}
|
|
@@ -174,8 +171,8 @@ class EntityHelper {
|
|
|
174
171
|
updates.avatar_url = request.avatarUrl;
|
|
175
172
|
}
|
|
176
173
|
if (request.entitySlug !== undefined) {
|
|
177
|
-
const slug =
|
|
178
|
-
if (!
|
|
174
|
+
const slug = normalizeSlug(request.entitySlug);
|
|
175
|
+
if (!validateSlug(slug)) {
|
|
179
176
|
throw new Error('Invalid entity slug format');
|
|
180
177
|
}
|
|
181
178
|
// Check if changing slug
|
|
@@ -190,7 +187,7 @@ class EntityHelper {
|
|
|
190
187
|
const [updated] = await this.config.db
|
|
191
188
|
.update(this.config.entitiesTable)
|
|
192
189
|
.set(updates)
|
|
193
|
-
.where(
|
|
190
|
+
.where(eq(this.config.entitiesTable.id, entityId))
|
|
194
191
|
.returning();
|
|
195
192
|
return this.mapRecordToEntity(updated);
|
|
196
193
|
}
|
|
@@ -203,12 +200,12 @@ class EntityHelper {
|
|
|
203
200
|
if (!entity) {
|
|
204
201
|
throw new Error('Entity not found');
|
|
205
202
|
}
|
|
206
|
-
if (entity.entityType ===
|
|
203
|
+
if (entity.entityType === EntityType.PERSONAL) {
|
|
207
204
|
throw new Error('Personal entities cannot be deleted');
|
|
208
205
|
}
|
|
209
206
|
await this.config.db
|
|
210
207
|
.delete(this.config.entitiesTable)
|
|
211
|
-
.where(
|
|
208
|
+
.where(eq(this.config.entitiesTable.id, entityId));
|
|
212
209
|
}
|
|
213
210
|
/**
|
|
214
211
|
* Check if a slug is available.
|
|
@@ -217,7 +214,7 @@ class EntityHelper {
|
|
|
217
214
|
const results = await this.config.db
|
|
218
215
|
.select({ id: this.config.entitiesTable.id })
|
|
219
216
|
.from(this.config.entitiesTable)
|
|
220
|
-
.where(
|
|
217
|
+
.where(eq(this.config.entitiesTable.entity_slug, slug))
|
|
221
218
|
.limit(1);
|
|
222
219
|
return results.length === 0;
|
|
223
220
|
}
|
|
@@ -226,7 +223,7 @@ class EntityHelper {
|
|
|
226
223
|
*/
|
|
227
224
|
async generateUniqueSlug() {
|
|
228
225
|
for (let attempts = 0; attempts < 10; attempts++) {
|
|
229
|
-
const slug =
|
|
226
|
+
const slug = generateEntitySlug();
|
|
230
227
|
if (await this.isSlugAvailable(slug)) {
|
|
231
228
|
return slug;
|
|
232
229
|
}
|
|
@@ -249,5 +246,4 @@ class EntityHelper {
|
|
|
249
246
|
};
|
|
250
247
|
}
|
|
251
248
|
}
|
|
252
|
-
exports.EntityHelper = EntityHelper;
|
|
253
249
|
//# sourceMappingURL=EntityHelper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityHelper.js","sourceRoot":"","sources":["../../src/helpers/EntityHelper.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EntityHelper.js","sourceRoot":"","sources":["../../src/helpers/EntityHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EACL,UAAU,EACV,UAAU,GAMX,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE3E;;GAEG;AACH,MAAM,OAAO,YAAY;IACvB,YAA6B,MAA0B;QAA1B,WAAM,GAAN,MAAM,CAAoB;IAAG,CAAC;IAE3D;;;;;OAKG;IACH,KAAK,CAAC,oBAAoB,CACxB,WAAmB,EACnB,KAAc;QAEd,MAAM,IAAI,GAAG,kBAAkB,EAAE,CAAC;QAClC,MAAM,WAAW,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC;QAEvD,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE;aAClC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;aACjC,MAAM,CAAC;YACN,WAAW,EAAE,IAAI;YACjB,WAAW,EAAE,UAAU,CAAC,QAAQ;YAChC,YAAY,EAAE,WAAW;SAC1B,CAAC;aACD,SAAS,EAAE,CAAC;QAEf,kEAAkE;QAClE,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC;YAC3D,SAAS,EAAE,MAAM,CAAC,EAAE;YACpB,OAAO,EAAE,WAAW;YACpB,IAAI,EAAE,UAAU,CAAC,KAAK;YACtB,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,yBAAyB,CAC7B,WAAmB,EACnB,KAAc;QAEd,yDAAyD;QACzD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE;aAClC,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;aAC7C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;aAC9B,SAAS,CACR,IAAI,CAAC,MAAM,CAAC,aAAa,EACzB,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CACrE;aACA,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,EACjD,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,EACnD,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,EAC5C,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,EAAE,UAAU,CAAC,QAAQ,CAAC,CAC/D,CACF;aACA,KAAK,CAAC,CAAC,CAAC,CAAC;QAEZ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,IAAI,CAAC,oBAAoB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IACvD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,wBAAwB,CAC5B,WAAmB,EACnB,OAA4B;QAE5B,iBAAiB;QACjB,IAAI,IAAY,CAAC;QACjB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YACzC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAChD,CAAC;YACD,qBAAqB;YACrB,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACzC,CAAC;QAED,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE;aAClC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;aACjC,MAAM,CAAC;YACN,WAAW,EAAE,IAAI;YACjB,WAAW,EAAE,UAAU,CAAC,YAAY;YACpC,YAAY,EAAE,OAAO,CAAC,WAAW;YACjC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI;SACzC,CAAC;aACD,SAAS,EAAE,CAAC;QAEf,uBAAuB;QACvB,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC;YAC3D,SAAS,EAAE,MAAM,CAAC,EAAE;YACpB,OAAO,EAAE,WAAW;YACpB,IAAI,EAAE,UAAU,CAAC,KAAK;YACtB,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,QAAgB;QAC9B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE;aACjC,MAAM,EAAE;aACR,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;aAC/B,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;aACjD,KAAK,CAAC,CAAC,CAAC,CAAC;QAEZ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,IAAY;QAChC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE;aACjC,MAAM,EAAE;aACR,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;aAC/B,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;aACtD,KAAK,CAAC,CAAC,CAAC,CAAC;QAEZ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,eAAe,CACnB,WAAmB,EACnB,KAAc;QAEd,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE;aACjC,MAAM,CAAC;YACN,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa;YACjC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI;SACpC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;aAC9B,SAAS,CACR,IAAI,CAAC,MAAM,CAAC,aAAa,EACzB,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CACrE;aACA,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,EACjD,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,CAC7C,CACF,CAAC;QAEJ,6DAA6D;QAC7D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YAC3E,OAAO;gBACL;oBACE,GAAG,cAAc;oBACjB,QAAQ,EAAE,UAAU,CAAC,KAAK;iBAC3B;aACF,CAAC;QACJ,CAAC;QAED,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;YACxC,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC;YACjC,QAAQ,EAAE,IAAkB;SAC7B,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CAChB,QAAgB,EAChB,OAA4B;QAE5B,MAAM,OAAO,GAAwB;YACnC,UAAU,EAAE,IAAI,IAAI,EAAE;SACvB,CAAC;QAEF,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACtC,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;QAC7C,CAAC;QAED,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACtC,OAAO,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QAC5C,CAAC;QAED,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACpC,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;QACzC,CAAC;QAED,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAC/C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAChD,CAAC;YACD,yBAAyB;YACzB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAChD,IAAI,QAAQ,IAAI,QAAQ,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;gBAC7C,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;oBACxC,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;gBAClD,CAAC;gBACD,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;YAC7B,CAAC;QACH,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE;aACnC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;aACjC,GAAG,CAAC,OAAO,CAAC;aACZ,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;aACjD,SAAS,EAAE,CAAC;QAEf,OAAO,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAAC,QAAgB;QACjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACtC,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,KAAK,UAAU,CAAC,QAAQ,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzD,CAAC;QAED,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE;aACjB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;aACjC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,IAAY;QAChC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE;aACjC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC;aAC5C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;aAC/B,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;aACtD,KAAK,CAAC,CAAC,CAAC,CAAC;QAEZ,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,kBAAkB;QAC9B,KAAK,IAAI,QAAQ,GAAG,CAAC,EAAE,QAAQ,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC;YACjD,MAAM,IAAI,GAAG,kBAAkB,EAAE,CAAC;YAClC,IAAI,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrC,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED;;OAEG;IACK,iBAAiB,CAAC,MAAW;QACnC,OAAO;YACL,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,UAAU,EAAE,MAAM,CAAC,WAAW;YAC9B,UAAU,EAAE,MAAM,CAAC,WAAyB;YAC5C,WAAW,EAAE,MAAM,CAAC,YAAY;YAChC,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,SAAS,EAAE,MAAM,CAAC,UAAU;YAC5B,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,WAAW,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACvE,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,WAAW,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACxE,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* @fileoverview Entity Member Helper Class
|
|
4
3
|
* @description Operations for managing entity members and their roles
|
|
5
4
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const drizzle_orm_1 = require("drizzle-orm");
|
|
9
|
-
const types_1 = require("../types");
|
|
5
|
+
import { eq, and } from 'drizzle-orm';
|
|
6
|
+
import { EntityRole, EntityType, } from '../types';
|
|
10
7
|
/**
|
|
11
8
|
* Helper class for entity member operations.
|
|
12
9
|
*/
|
|
13
|
-
class EntityMemberHelper {
|
|
10
|
+
export class EntityMemberHelper {
|
|
14
11
|
constructor(config) {
|
|
15
12
|
this.config = config;
|
|
16
13
|
}
|
|
@@ -20,13 +17,13 @@ class EntityMemberHelper {
|
|
|
20
17
|
*/
|
|
21
18
|
async getMembers(entityId, options) {
|
|
22
19
|
// Build conditions - default to active members only
|
|
23
|
-
const conditions = [
|
|
20
|
+
const conditions = [eq(this.config.membersTable.entity_id, entityId)];
|
|
24
21
|
if (options?.role) {
|
|
25
|
-
conditions.push(
|
|
22
|
+
conditions.push(eq(this.config.membersTable.role, options.role));
|
|
26
23
|
}
|
|
27
24
|
// Filter by is_active (default to true if not specified)
|
|
28
25
|
const isActive = options?.isActive ?? true;
|
|
29
|
-
conditions.push(
|
|
26
|
+
conditions.push(eq(this.config.membersTable.is_active, isActive));
|
|
30
27
|
let query = this.config.db
|
|
31
28
|
.select({
|
|
32
29
|
member: this.config.membersTable,
|
|
@@ -37,8 +34,8 @@ class EntityMemberHelper {
|
|
|
37
34
|
},
|
|
38
35
|
})
|
|
39
36
|
.from(this.config.membersTable)
|
|
40
|
-
.leftJoin(this.config.usersTable,
|
|
41
|
-
.where(
|
|
37
|
+
.leftJoin(this.config.usersTable, eq(this.config.membersTable.user_id, this.config.usersTable.firebase_uid))
|
|
38
|
+
.where(and(...conditions))
|
|
42
39
|
.$dynamic();
|
|
43
40
|
if (options?.limit) {
|
|
44
41
|
query = query.limit(options.limit);
|
|
@@ -55,11 +52,11 @@ class EntityMemberHelper {
|
|
|
55
52
|
*/
|
|
56
53
|
async getMember(entityId, userId, includeInactive = false) {
|
|
57
54
|
const conditions = [
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
eq(this.config.membersTable.entity_id, entityId),
|
|
56
|
+
eq(this.config.membersTable.user_id, userId),
|
|
60
57
|
];
|
|
61
58
|
if (!includeInactive) {
|
|
62
|
-
conditions.push(
|
|
59
|
+
conditions.push(eq(this.config.membersTable.is_active, true));
|
|
63
60
|
}
|
|
64
61
|
const results = await this.config.db
|
|
65
62
|
.select({
|
|
@@ -71,8 +68,8 @@ class EntityMemberHelper {
|
|
|
71
68
|
},
|
|
72
69
|
})
|
|
73
70
|
.from(this.config.membersTable)
|
|
74
|
-
.leftJoin(this.config.usersTable,
|
|
75
|
-
.where(
|
|
71
|
+
.leftJoin(this.config.usersTable, eq(this.config.membersTable.user_id, this.config.usersTable.firebase_uid))
|
|
72
|
+
.where(and(...conditions))
|
|
76
73
|
.limit(1);
|
|
77
74
|
if (results.length === 0) {
|
|
78
75
|
return null;
|
|
@@ -87,7 +84,7 @@ class EntityMemberHelper {
|
|
|
87
84
|
const results = await this.config.db
|
|
88
85
|
.select({ role: this.config.membersTable.role })
|
|
89
86
|
.from(this.config.membersTable)
|
|
90
|
-
.where(
|
|
87
|
+
.where(and(eq(this.config.membersTable.entity_id, entityId), eq(this.config.membersTable.user_id, userId), eq(this.config.membersTable.is_active, true)))
|
|
91
88
|
.limit(1);
|
|
92
89
|
if (results.length === 0) {
|
|
93
90
|
return null;
|
|
@@ -113,7 +110,7 @@ class EntityMemberHelper {
|
|
|
113
110
|
is_active: true,
|
|
114
111
|
updated_at: new Date(),
|
|
115
112
|
})
|
|
116
|
-
.where(
|
|
113
|
+
.where(and(eq(this.config.membersTable.entity_id, entityId), eq(this.config.membersTable.user_id, firebaseUid)))
|
|
117
114
|
.returning();
|
|
118
115
|
member = updated;
|
|
119
116
|
}
|
|
@@ -138,7 +135,7 @@ class EntityMemberHelper {
|
|
|
138
135
|
displayName: this.config.usersTable.display_name,
|
|
139
136
|
})
|
|
140
137
|
.from(this.config.usersTable)
|
|
141
|
-
.where(
|
|
138
|
+
.where(eq(this.config.usersTable.firebase_uid, firebaseUid))
|
|
142
139
|
.limit(1);
|
|
143
140
|
return this.mapRecordToMember(member, users[0] ?? null);
|
|
144
141
|
}
|
|
@@ -148,21 +145,21 @@ class EntityMemberHelper {
|
|
|
148
145
|
*/
|
|
149
146
|
async updateMemberRole(entityId, userId, role) {
|
|
150
147
|
// Cannot assign owner role via this method
|
|
151
|
-
if (role ===
|
|
148
|
+
if (role === EntityRole.OWNER) {
|
|
152
149
|
throw new Error('Cannot assign owner role. Use ownership transfer instead.');
|
|
153
150
|
}
|
|
154
151
|
// Check constraints for personal entities
|
|
155
152
|
const entity = await this.config.db
|
|
156
153
|
.select()
|
|
157
154
|
.from(this.config.entitiesTable)
|
|
158
|
-
.where(
|
|
155
|
+
.where(eq(this.config.entitiesTable.id, entityId))
|
|
159
156
|
.limit(1);
|
|
160
|
-
if (entity.length > 0 && entity[0].entity_type ===
|
|
157
|
+
if (entity.length > 0 && entity[0].entity_type === EntityType.PERSONAL) {
|
|
161
158
|
throw new Error('Cannot change roles in personal entities');
|
|
162
159
|
}
|
|
163
160
|
// Check if user is the owner - cannot change owner's role
|
|
164
161
|
const currentMember = await this.getMember(entityId, userId);
|
|
165
|
-
if (currentMember?.role ===
|
|
162
|
+
if (currentMember?.role === EntityRole.OWNER) {
|
|
166
163
|
throw new Error('Cannot change the owner\'s role');
|
|
167
164
|
}
|
|
168
165
|
const [updated] = await this.config.db
|
|
@@ -171,7 +168,7 @@ class EntityMemberHelper {
|
|
|
171
168
|
role,
|
|
172
169
|
updated_at: new Date(),
|
|
173
170
|
})
|
|
174
|
-
.where(
|
|
171
|
+
.where(and(eq(this.config.membersTable.entity_id, entityId), eq(this.config.membersTable.user_id, userId), eq(this.config.membersTable.is_active, true)))
|
|
175
172
|
.returning();
|
|
176
173
|
if (!updated) {
|
|
177
174
|
throw new Error('Member not found or inactive');
|
|
@@ -184,7 +181,7 @@ class EntityMemberHelper {
|
|
|
184
181
|
displayName: this.config.usersTable.display_name,
|
|
185
182
|
})
|
|
186
183
|
.from(this.config.usersTable)
|
|
187
|
-
.where(
|
|
184
|
+
.where(eq(this.config.usersTable.firebase_uid, userId))
|
|
188
185
|
.limit(1);
|
|
189
186
|
return this.mapRecordToMember(updated, users[0] ?? null);
|
|
190
187
|
}
|
|
@@ -197,9 +194,9 @@ class EntityMemberHelper {
|
|
|
197
194
|
const entity = await this.config.db
|
|
198
195
|
.select()
|
|
199
196
|
.from(this.config.entitiesTable)
|
|
200
|
-
.where(
|
|
197
|
+
.where(eq(this.config.entitiesTable.id, entityId))
|
|
201
198
|
.limit(1);
|
|
202
|
-
if (entity.length > 0 && entity[0].entity_type ===
|
|
199
|
+
if (entity.length > 0 && entity[0].entity_type === EntityType.PERSONAL) {
|
|
203
200
|
throw new Error('Cannot remove members from personal entities');
|
|
204
201
|
}
|
|
205
202
|
// Check if user is the owner - cannot remove owner
|
|
@@ -207,7 +204,7 @@ class EntityMemberHelper {
|
|
|
207
204
|
if (!member) {
|
|
208
205
|
throw new Error('Member not found');
|
|
209
206
|
}
|
|
210
|
-
if (member.role ===
|
|
207
|
+
if (member.role === EntityRole.OWNER) {
|
|
211
208
|
throw new Error('Cannot remove the entity owner');
|
|
212
209
|
}
|
|
213
210
|
// Soft delete - set is_active = false
|
|
@@ -217,7 +214,7 @@ class EntityMemberHelper {
|
|
|
217
214
|
is_active: false,
|
|
218
215
|
updated_at: new Date(),
|
|
219
216
|
})
|
|
220
|
-
.where(
|
|
217
|
+
.where(and(eq(this.config.membersTable.entity_id, entityId), eq(this.config.membersTable.user_id, userId)));
|
|
221
218
|
}
|
|
222
219
|
/**
|
|
223
220
|
* Check if a user is a member of an entity.
|
|
@@ -250,5 +247,4 @@ class EntityMemberHelper {
|
|
|
250
247
|
return member;
|
|
251
248
|
}
|
|
252
249
|
}
|
|
253
|
-
exports.EntityMemberHelper = EntityMemberHelper;
|
|
254
250
|
//# sourceMappingURL=EntityMemberHelper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityMemberHelper.js","sourceRoot":"","sources":["../../src/helpers/EntityMemberHelper.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EntityMemberHelper.js","sourceRoot":"","sources":["../../src/helpers/EntityMemberHelper.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* @fileoverview Entity Invitation Helper Class
|
|
4
3
|
* @description Operations for managing entity invitations
|
|
5
4
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const types_1 = require("../types");
|
|
10
|
-
const utils_1 = require("../utils");
|
|
5
|
+
import { eq, and, lt } from 'drizzle-orm';
|
|
6
|
+
import { InvitationStatus, } from '../types';
|
|
7
|
+
import { generateInvitationToken, calculateInvitationExpiry, } from '../utils';
|
|
11
8
|
/**
|
|
12
9
|
* Helper class for entity invitation operations.
|
|
13
10
|
*/
|
|
14
|
-
class InvitationHelper {
|
|
11
|
+
export class InvitationHelper {
|
|
15
12
|
constructor(config) {
|
|
16
13
|
this.config = config;
|
|
17
14
|
}
|
|
@@ -24,8 +21,8 @@ class InvitationHelper {
|
|
|
24
21
|
const existingMember = await this.config.db
|
|
25
22
|
.select()
|
|
26
23
|
.from(this.config.membersTable)
|
|
27
|
-
.innerJoin(this.config.usersTable,
|
|
28
|
-
.where(
|
|
24
|
+
.innerJoin(this.config.usersTable, eq(this.config.membersTable.user_id, this.config.usersTable.firebase_uid))
|
|
25
|
+
.where(and(eq(this.config.membersTable.entity_id, entityId), eq(this.config.usersTable.email, request.email), eq(this.config.membersTable.is_active, true)))
|
|
29
26
|
.limit(1);
|
|
30
27
|
if (existingMember.length > 0) {
|
|
31
28
|
throw new Error('User is already an active member of this entity');
|
|
@@ -34,20 +31,20 @@ class InvitationHelper {
|
|
|
34
31
|
const existingInvite = await this.config.db
|
|
35
32
|
.select()
|
|
36
33
|
.from(this.config.invitationsTable)
|
|
37
|
-
.where(
|
|
34
|
+
.where(and(eq(this.config.invitationsTable.entity_id, entityId), eq(this.config.invitationsTable.email, request.email), eq(this.config.invitationsTable.status, InvitationStatus.PENDING)))
|
|
38
35
|
.limit(1);
|
|
39
36
|
if (existingInvite.length > 0) {
|
|
40
37
|
throw new Error('An invitation is already pending for this email');
|
|
41
38
|
}
|
|
42
|
-
const token =
|
|
43
|
-
const expiresAt =
|
|
39
|
+
const token = generateInvitationToken();
|
|
40
|
+
const expiresAt = calculateInvitationExpiry();
|
|
44
41
|
const [invitation] = await this.config.db
|
|
45
42
|
.insert(this.config.invitationsTable)
|
|
46
43
|
.values({
|
|
47
44
|
entity_id: entityId,
|
|
48
45
|
email: request.email,
|
|
49
46
|
role: request.role,
|
|
50
|
-
status:
|
|
47
|
+
status: InvitationStatus.PENDING,
|
|
51
48
|
invited_by_user_id: invitedByUserId,
|
|
52
49
|
token,
|
|
53
50
|
expires_at: new Date(expiresAt),
|
|
@@ -62,7 +59,7 @@ class InvitationHelper {
|
|
|
62
59
|
const results = await this.config.db
|
|
63
60
|
.select()
|
|
64
61
|
.from(this.config.invitationsTable)
|
|
65
|
-
.where(
|
|
62
|
+
.where(eq(this.config.invitationsTable.token, token))
|
|
66
63
|
.limit(1);
|
|
67
64
|
if (results.length === 0) {
|
|
68
65
|
return null;
|
|
@@ -76,7 +73,7 @@ class InvitationHelper {
|
|
|
76
73
|
const results = await this.config.db
|
|
77
74
|
.select()
|
|
78
75
|
.from(this.config.invitationsTable)
|
|
79
|
-
.where(
|
|
76
|
+
.where(eq(this.config.invitationsTable.id, invitationId))
|
|
80
77
|
.limit(1);
|
|
81
78
|
if (results.length === 0) {
|
|
82
79
|
return null;
|
|
@@ -88,14 +85,14 @@ class InvitationHelper {
|
|
|
88
85
|
*/
|
|
89
86
|
async getEntityInvitations(entityId, options) {
|
|
90
87
|
// Build conditions
|
|
91
|
-
const conditions = [
|
|
88
|
+
const conditions = [eq(this.config.invitationsTable.entity_id, entityId)];
|
|
92
89
|
if (options?.status) {
|
|
93
|
-
conditions.push(
|
|
90
|
+
conditions.push(eq(this.config.invitationsTable.status, options.status));
|
|
94
91
|
}
|
|
95
92
|
let query = this.config.db
|
|
96
93
|
.select()
|
|
97
94
|
.from(this.config.invitationsTable)
|
|
98
|
-
.where(
|
|
95
|
+
.where(and(...conditions))
|
|
99
96
|
.$dynamic();
|
|
100
97
|
if (options?.limit) {
|
|
101
98
|
query = query.limit(options.limit);
|
|
@@ -116,8 +113,8 @@ class InvitationHelper {
|
|
|
116
113
|
entity: this.config.entitiesTable,
|
|
117
114
|
})
|
|
118
115
|
.from(this.config.invitationsTable)
|
|
119
|
-
.innerJoin(this.config.entitiesTable,
|
|
120
|
-
.where(
|
|
116
|
+
.innerJoin(this.config.entitiesTable, eq(this.config.invitationsTable.entity_id, this.config.entitiesTable.id))
|
|
117
|
+
.where(and(eq(this.config.invitationsTable.email, email), eq(this.config.invitationsTable.status, InvitationStatus.PENDING)));
|
|
121
118
|
return results.map(({ invitation, entity }) => ({
|
|
122
119
|
...this.mapRecordToInvitation(invitation),
|
|
123
120
|
entity: {
|
|
@@ -142,7 +139,7 @@ class InvitationHelper {
|
|
|
142
139
|
if (!invitation) {
|
|
143
140
|
throw new Error('Invitation not found');
|
|
144
141
|
}
|
|
145
|
-
if (invitation.status !==
|
|
142
|
+
if (invitation.status !== InvitationStatus.PENDING) {
|
|
146
143
|
throw new Error('Invitation is no longer pending');
|
|
147
144
|
}
|
|
148
145
|
if (new Date(invitation.expiresAt) < new Date()) {
|
|
@@ -150,10 +147,10 @@ class InvitationHelper {
|
|
|
150
147
|
await this.config.db
|
|
151
148
|
.update(this.config.invitationsTable)
|
|
152
149
|
.set({
|
|
153
|
-
status:
|
|
150
|
+
status: InvitationStatus.EXPIRED,
|
|
154
151
|
updated_at: new Date(),
|
|
155
152
|
})
|
|
156
|
-
.where(
|
|
153
|
+
.where(eq(this.config.invitationsTable.id, invitation.id));
|
|
157
154
|
throw new Error('Invitation has expired');
|
|
158
155
|
}
|
|
159
156
|
// Add user as member with active status
|
|
@@ -167,11 +164,11 @@ class InvitationHelper {
|
|
|
167
164
|
await this.config.db
|
|
168
165
|
.update(this.config.invitationsTable)
|
|
169
166
|
.set({
|
|
170
|
-
status:
|
|
167
|
+
status: InvitationStatus.ACCEPTED,
|
|
171
168
|
accepted_at: new Date(),
|
|
172
169
|
updated_at: new Date(),
|
|
173
170
|
})
|
|
174
|
-
.where(
|
|
171
|
+
.where(eq(this.config.invitationsTable.id, invitation.id));
|
|
175
172
|
}
|
|
176
173
|
/**
|
|
177
174
|
* Decline an invitation.
|
|
@@ -181,16 +178,16 @@ class InvitationHelper {
|
|
|
181
178
|
if (!invitation) {
|
|
182
179
|
throw new Error('Invitation not found');
|
|
183
180
|
}
|
|
184
|
-
if (invitation.status !==
|
|
181
|
+
if (invitation.status !== InvitationStatus.PENDING) {
|
|
185
182
|
throw new Error('Invitation is no longer pending');
|
|
186
183
|
}
|
|
187
184
|
await this.config.db
|
|
188
185
|
.update(this.config.invitationsTable)
|
|
189
186
|
.set({
|
|
190
|
-
status:
|
|
187
|
+
status: InvitationStatus.DECLINED,
|
|
191
188
|
updated_at: new Date(),
|
|
192
189
|
})
|
|
193
|
-
.where(
|
|
190
|
+
.where(eq(this.config.invitationsTable.id, invitation.id));
|
|
194
191
|
}
|
|
195
192
|
/**
|
|
196
193
|
* Cancel an invitation (by entity admin).
|
|
@@ -198,7 +195,7 @@ class InvitationHelper {
|
|
|
198
195
|
async cancelInvitation(invitationId) {
|
|
199
196
|
await this.config.db
|
|
200
197
|
.delete(this.config.invitationsTable)
|
|
201
|
-
.where(
|
|
198
|
+
.where(eq(this.config.invitationsTable.id, invitationId));
|
|
202
199
|
}
|
|
203
200
|
/**
|
|
204
201
|
* Process pending invitations for a new user.
|
|
@@ -226,10 +223,10 @@ class InvitationHelper {
|
|
|
226
223
|
const result = await this.config.db
|
|
227
224
|
.update(this.config.invitationsTable)
|
|
228
225
|
.set({
|
|
229
|
-
status:
|
|
226
|
+
status: InvitationStatus.EXPIRED,
|
|
230
227
|
updated_at: new Date(),
|
|
231
228
|
})
|
|
232
|
-
.where(
|
|
229
|
+
.where(and(eq(this.config.invitationsTable.status, InvitationStatus.PENDING), lt(this.config.invitationsTable.expires_at, new Date())))
|
|
233
230
|
.returning();
|
|
234
231
|
return result.length;
|
|
235
232
|
}
|
|
@@ -252,5 +249,4 @@ class InvitationHelper {
|
|
|
252
249
|
};
|
|
253
250
|
}
|
|
254
251
|
}
|
|
255
|
-
exports.InvitationHelper = InvitationHelper;
|
|
256
252
|
//# sourceMappingURL=InvitationHelper.js.map
|