grm-shared-library 1.1.246 → 1.1.248

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 (32) hide show
  1. package/dist/cjs/kafka/dtos/user/guardians-changed-payload.dto.js +66 -0
  2. package/dist/cjs/kafka/dtos/user/guardians-changed-payload.dto.js.map +1 -0
  3. package/dist/cjs/kafka/index.js +1 -0
  4. package/dist/cjs/kafka/index.js.map +1 -1
  5. package/dist/cjs/kafka/topics.js +4 -0
  6. package/dist/cjs/kafka/topics.js.map +1 -1
  7. package/dist/cjs/modules/user/dtos/guardian-identifier.dto.js +2 -2
  8. package/dist/cjs/modules/user/dtos/guardian-identifier.dto.js.map +1 -1
  9. package/dist/cjs/modules/user/index.js +1 -0
  10. package/dist/cjs/modules/user/index.js.map +1 -1
  11. package/dist/cjs/modules/user/utils/app-account.util.js +90 -0
  12. package/dist/cjs/modules/user/utils/app-account.util.js.map +1 -0
  13. package/dist/esm/kafka/dtos/user/guardians-changed-payload.dto.js +62 -0
  14. package/dist/esm/kafka/dtos/user/guardians-changed-payload.dto.js.map +1 -0
  15. package/dist/esm/kafka/index.js +1 -0
  16. package/dist/esm/kafka/index.js.map +1 -1
  17. package/dist/esm/kafka/topics.js +4 -0
  18. package/dist/esm/kafka/topics.js.map +1 -1
  19. package/dist/esm/modules/user/dtos/guardian-identifier.dto.js +2 -2
  20. package/dist/esm/modules/user/dtos/guardian-identifier.dto.js.map +1 -1
  21. package/dist/esm/modules/user/index.js +1 -0
  22. package/dist/esm/modules/user/index.js.map +1 -1
  23. package/dist/esm/modules/user/utils/app-account.util.js +83 -0
  24. package/dist/esm/modules/user/utils/app-account.util.js.map +1 -0
  25. package/dist/types/kafka/dtos/user/guardians-changed-payload.dto.d.ts +32 -0
  26. package/dist/types/kafka/index.d.ts +1 -0
  27. package/dist/types/kafka/topics.d.ts +1 -0
  28. package/dist/types/modules/user/index.d.ts +1 -0
  29. package/dist/types/modules/user/interfaces/account-analytics.d.ts +184 -8
  30. package/dist/types/modules/user/interfaces/guardian.d.ts +7 -0
  31. package/dist/types/modules/user/utils/app-account.util.d.ts +59 -0
  32. package/package.json +72 -72
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.GuardiansChangedPayloadDto = exports.GuardiansChangedReason = void 0;
13
+ const class_validator_1 = require("class-validator");
14
+ /** What changed about somebody's guardians - for logs and analytics; every reason means "refresh". */
15
+ var GuardiansChangedReason;
16
+ (function (GuardiansChangedReason) {
17
+ /** A guardian was added. */
18
+ GuardiansChangedReason["ADDED"] = "ADDED";
19
+ /** A guardian was removed by the person they guard. */
20
+ GuardiansChangedReason["REMOVED"] = "REMOVED";
21
+ /** Another guardian became the primary one. */
22
+ GuardiansChangedReason["PRIMARY_CHANGED"] = "PRIMARY_CHANGED";
23
+ /** A guardian on the list by phone number proved that number in the same organization's app, and is now an app guardian. */
24
+ GuardiansChangedReason["PROMOTED"] = "PROMOTED";
25
+ /** An app guardian's account was deleted; they stay on the list by phone number. */
26
+ GuardiansChangedReason["DEMOTED"] = "DEMOTED";
27
+ /** A guardian stopped looking after one of their dependents. */
28
+ GuardiansChangedReason["DEPENDENT_REMOVED"] = "DEPENDENT_REMOVED";
29
+ })(GuardiansChangedReason || (exports.GuardiansChangedReason = GuardiansChangedReason = {}));
30
+ /**
31
+ * Payload of `KAFKA_TOPICS.GUARDIANS_CHANGED`: somebody's guardian list changed,
32
+ * and these people's apps should read their guardians and dependents again.
33
+ *
34
+ * Ids only - no names, numbers or relationships. The apps read the lists through
35
+ * the guardian API, which applies its own access rules.
36
+ */
37
+ class GuardiansChangedPayloadDto {
38
+ }
39
+ exports.GuardiansChangedPayloadDto = GuardiansChangedPayloadDto;
40
+ __decorate([
41
+ (0, class_validator_1.IsInt)(),
42
+ (0, class_validator_1.IsPositive)(),
43
+ __metadata("design:type", Number)
44
+ ], GuardiansChangedPayloadDto.prototype, "organizationId", void 0);
45
+ __decorate([
46
+ (0, class_validator_1.IsInt)(),
47
+ (0, class_validator_1.IsPositive)(),
48
+ __metadata("design:type", Number)
49
+ ], GuardiansChangedPayloadDto.prototype, "dependentId", void 0);
50
+ __decorate([
51
+ (0, class_validator_1.IsArray)(),
52
+ (0, class_validator_1.ArrayMinSize)(1),
53
+ (0, class_validator_1.ArrayMaxSize)(100),
54
+ (0, class_validator_1.IsInt)({ each: true }),
55
+ (0, class_validator_1.IsPositive)({ each: true }),
56
+ __metadata("design:type", Array)
57
+ ], GuardiansChangedPayloadDto.prototype, "userIds", void 0);
58
+ __decorate([
59
+ (0, class_validator_1.IsEnum)(GuardiansChangedReason),
60
+ __metadata("design:type", String)
61
+ ], GuardiansChangedPayloadDto.prototype, "reason", void 0);
62
+ __decorate([
63
+ (0, class_validator_1.IsISO8601)(),
64
+ __metadata("design:type", String)
65
+ ], GuardiansChangedPayloadDto.prototype, "occurredAt", void 0);
66
+ //# sourceMappingURL=guardians-changed-payload.dto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guardians-changed-payload.dto.js","sourceRoot":"","sources":["../../../../../src/kafka/dtos/user/guardians-changed-payload.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAA4G;AAE5G,sGAAsG;AACtG,IAAY,sBAaX;AAbD,WAAY,sBAAsB;IAC9B,4BAA4B;IAC5B,yCAAe,CAAA;IACf,uDAAuD;IACvD,6CAAmB,CAAA;IACnB,+CAA+C;IAC/C,6DAAmC,CAAA;IACnC,4HAA4H;IAC5H,+CAAqB,CAAA;IACrB,oFAAoF;IACpF,6CAAmB,CAAA;IACnB,gEAAgE;IAChE,iEAAuC,CAAA;AAC3C,CAAC,EAbW,sBAAsB,sCAAtB,sBAAsB,QAajC;AAED;;;;;;GAMG;AACH,MAAa,0BAA0B;CAwBtC;AAxBD,gEAwBC;AApBG;IAFC,IAAA,uBAAK,GAAE;IACP,IAAA,4BAAU,GAAE;;kEACW;AAKxB;IAFC,IAAA,uBAAK,GAAE;IACP,IAAA,4BAAU,GAAE;;+DACQ;AAQrB;IALC,IAAA,yBAAO,GAAE;IACT,IAAA,8BAAY,EAAC,CAAC,CAAC;IACf,IAAA,8BAAY,EAAC,GAAG,CAAC;IACjB,IAAA,uBAAK,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACrB,IAAA,4BAAU,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;;2DACR;AAGnB;IADC,IAAA,wBAAM,EAAC,sBAAsB,CAAC;;0DACC;AAGhC;IADC,IAAA,2BAAS,GAAE;;8DACQ"}
@@ -24,4 +24,5 @@ __exportStar(require("./dtos/otp/create-otp-payload.dto"), exports);
24
24
  __exportStar(require("./dtos/otp/otp-payload.dto"), exports);
25
25
  __exportStar(require("./dtos/password/password-reset-payload.dto"), exports);
26
26
  __exportStar(require("./dtos/account-deletion/account-deletion-request-payload.dto"), exports);
27
+ __exportStar(require("./dtos/user/guardians-changed-payload.dto"), exports);
27
28
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/kafka/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,mDAAiC;AACjC,8EAA4D;AAC5D,uEAAqD;AACrD,iFAA+D;AAC/D,0EAAwD;AACxD,oEAAkD;AAClD,6DAA2C;AAC3C,6EAA2D;AAC3D,+FAA6E"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/kafka/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,mDAAiC;AACjC,8EAA4D;AAC5D,uEAAqD;AACrD,iFAA+D;AAC/D,0EAAwD;AACxD,oEAAkD;AAClD,6DAA2C;AAC3C,6EAA2D;AAC3D,+FAA6E;AAC7E,4EAA0D"}
@@ -12,6 +12,10 @@ exports.KAFKA_TOPICS = {
12
12
  USER_CREATED: 'user.created',
13
13
  USER_UPDATED: 'user.updated',
14
14
  USER_DELETED: 'user.deleted',
15
+ // Somebody's guardians or dependents changed (producer: clarion-authentication;
16
+ // payload GuardiansChangedPayloadDto; consumer: clarion-notification, which
17
+ // sends each affected person a silent push so their app refreshes). Ids only.
18
+ GUARDIANS_CHANGED: 'user.guardians.changed.v1',
15
19
  // Org. ORG_CREATED is published by clarion-organization after commit
16
20
  // (payload OrganizationCreatedEvent); clarion-incident provisions the Safety
17
21
  // Alerts category from it.
@@ -1 +1 @@
1
- {"version":3,"file":"topics.js","sourceRoot":"","sources":["../../../src/kafka/topics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"topics.js","sourceRoot":"","sources":["../../../src/kafka/topics.ts"],"names":[],"mappings":"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"}
@@ -17,7 +17,7 @@ class GuardianIdentifierDto {
17
17
  exports.GuardianIdentifierDto = GuardianIdentifierDto;
18
18
  __decorate([
19
19
  (0, swagger_1.ApiProperty)({
20
- description: 'Phone number for external guardian',
20
+ description: 'Phone number of an external guardian (older apps). Prefer relationshipId, which names either kind.',
21
21
  example: '+1234567890',
22
22
  required: false,
23
23
  type: 'string'
@@ -28,7 +28,7 @@ __decorate([
28
28
  ], GuardianIdentifierDto.prototype, "phoneNumber", void 0);
29
29
  __decorate([
30
30
  (0, swagger_1.ApiProperty)({
31
- description: 'Relationship ID for system guardian',
31
+ description: 'The guardian entry id - `id` of an app-user guardian relation or of an external guardian (since grm-shared-library 1.1.248)',
32
32
  example: 789,
33
33
  required: false,
34
34
  type: 'number'
@@ -1 +1 @@
1
- {"version":3,"file":"guardian-identifier.dto.js","sourceRoot":"","sources":["../../../../../src/modules/user/dtos/guardian-identifier.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAC9C,qDAA6E;AAE7E,MAAa,qBAAqB;CAoBjC;AApBD,sDAoBC;AAXG;IARC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,oCAAoC;QACjD,OAAO,EAAE,aAAa;QACtB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,QAAQ;KACjB,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;0DACQ;AAUrB;IARC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,qCAAqC;QAClD,OAAO,EAAE,GAAG;QACZ,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,QAAQ;KACjB,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;6DACW"}
1
+ {"version":3,"file":"guardian-identifier.dto.js","sourceRoot":"","sources":["../../../../../src/modules/user/dtos/guardian-identifier.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAC9C,qDAA6E;AAE7E,MAAa,qBAAqB;CAoBjC;AApBD,sDAoBC;AAXG;IARC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,oGAAoG;QACjH,OAAO,EAAE,aAAa;QACtB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,QAAQ;KACjB,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;0DACQ;AAUrB;IARC,IAAA,qBAAW,EAAC;QACT,WAAW,EAAE,6HAA6H;QAC1I,OAAO,EAAE,GAAG;QACZ,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,QAAQ;KACjB,CAAC;IACD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;6DACW"}
@@ -32,4 +32,5 @@ __exportStar(require("./interfaces/guardian"), exports);
32
32
  __exportStar(require("./interfaces/guardian-relation"), exports);
33
33
  __exportStar(require("./interfaces/guardians-response"), exports);
34
34
  __exportStar(require("./interfaces/account-analytics"), exports);
35
+ __exportStar(require("./utils/app-account.util"), exports);
35
36
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/user/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC;AACvC,yDAAuC;AACvC,sDAAoC;AACpC,iEAA+C;AAC/C,sEAAoD;AACpD,6EAA2D;AAC3D,+EAA6D;AAC7D,yEAAuD;AAEvD,2DAAyC;AACzC,qEAAmD;AACnD,wEAAsD;AAEtD,oDAAkC;AAClC,4DAA0C;AAC1C,4DAA0C;AAC1C,wDAAsC;AACtC,iEAA+C;AAC/C,kEAAgD;AAChD,iEAA+C"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/user/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC;AACvC,yDAAuC;AACvC,sDAAoC;AACpC,iEAA+C;AAC/C,sEAAoD;AACpD,6EAA2D;AAC3D,+EAA6D;AAC7D,yEAAuD;AAEvD,2DAAyC;AACzC,qEAAmD;AACnD,wEAAsD;AAEtD,oDAAkC;AAClC,4DAA0C;AAC1C,4DAA0C;AAC1C,wDAAsC;AACtC,iEAA+C;AAC/C,kEAAgD;AAChD,iEAA+C;AAE/C,2DAAyC"}
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.APP_ACCOUNT_ERROR_CODES = exports.APP_ACCOUNT_ROLE = void 0;
4
+ exports.isAppAccount = isAppAccount;
5
+ exports.hasAppRole = hasAppRole;
6
+ exports.parseAppOrganizations = parseAppOrganizations;
7
+ exports.isAccountFromAnotherApp = isAccountFromAnotherApp;
8
+ const role_enum_1 = require("../../role/enums/role.enum");
9
+ /**
10
+ * App accounts and staff accounts.
11
+ *
12
+ * Each brand's mobile app (G4S Kenya, GeoSHIELD, SGA Security, ...) is its own
13
+ * product for one organization's customers, so an account made in one app is an
14
+ * account with that organization only. Signing in to another brand's app means
15
+ * registering with that brand. One person may therefore hold several app
16
+ * accounts - one per organization - with the same phone number and e-mail.
17
+ *
18
+ * Staff (Super-Admin, organization and control-centre staff, responders,
19
+ * corporate-client admins) keep one platform-wide account each: their e-mail and
20
+ * phone number stay unique across the whole platform.
21
+ *
22
+ * An APP ACCOUNT is one whose only role is Mobile-User. That is the same rule the
23
+ * database's unique indexes use (`roles = '{Mobile-User}'`), so code and schema
24
+ * can never disagree about which kind an account is. An account holding
25
+ * Mobile-User beside a staff role is a staff account that also uses an app.
26
+ */
27
+ exports.APP_ACCOUNT_ROLE = role_enum_1.Roles.MOBILE_USER;
28
+ /** An account whose only role is Mobile-User: unique within its organization, not platform-wide. */
29
+ function isAppAccount(roles) {
30
+ return Array.isArray(roles) && roles.length === 1 && roles[0] === exports.APP_ACCOUNT_ROLE;
31
+ }
32
+ /** Holds the Mobile-User role, alone or beside staff roles: someone who can use a brand's app. */
33
+ function hasAppRole(roles) {
34
+ return Array.isArray(roles) && roles.includes(exports.APP_ACCOUNT_ROLE);
35
+ }
36
+ /**
37
+ * Parses `APP_ORGANIZATIONS`. Blank means "none configured". A malformed entry
38
+ * throws: a typo here would let an app sign people in to the wrong organization,
39
+ * so it must stop the service at boot rather than be skipped.
40
+ */
41
+ function parseAppOrganizations(raw) {
42
+ const map = new Map();
43
+ for (const entry of String(raw !== null && raw !== void 0 ? raw : '').split(',')) {
44
+ const trimmed = entry.trim();
45
+ if (!trimmed)
46
+ continue;
47
+ const match = /^([A-Za-z0-9_-]+)\s*:\s*(\d+)$/.exec(trimmed);
48
+ if (!match)
49
+ throw new Error(`APP_ORGANIZATIONS: "${trimmed}" is not <appId>:<organizationId>`);
50
+ const [, appId, id] = match;
51
+ const organizationId = Number(id);
52
+ if (!Number.isSafeInteger(organizationId) || organizationId <= 0) {
53
+ throw new Error(`APP_ORGANIZATIONS: "${trimmed}" names no valid organization`);
54
+ }
55
+ const existing = map.get(appId);
56
+ if (existing !== undefined && existing !== organizationId) {
57
+ throw new Error(`APP_ORGANIZATIONS: ${appId} is given two organizations (${existing} and ${organizationId})`);
58
+ }
59
+ map.set(appId, organizationId);
60
+ }
61
+ return map;
62
+ }
63
+ /**
64
+ * Whether a signed-in account is being used from another organization's app: the
65
+ * request names an app (`X-App-Id`) that belongs to organization A, and the account
66
+ * is an app user of organization B.
67
+ *
68
+ * Unknown here means "not a mismatch": no app named, an app with no configured
69
+ * organization, or an account that is staff only. Those keep working as before.
70
+ */
71
+ function isAccountFromAnotherApp(appOrganizations, appId, account) {
72
+ if (!appId)
73
+ return false;
74
+ const expected = appOrganizations.get(appId);
75
+ if (expected === undefined)
76
+ return false;
77
+ if (!hasAppRole(account.roles))
78
+ return false;
79
+ return Number(account.organizationId) !== expected;
80
+ }
81
+ /** Error codes a client can act on, for the account rules above. */
82
+ exports.APP_ACCOUNT_ERROR_CODES = {
83
+ /** A token or session belongs to another organization's app: sign out and sign in again here. */
84
+ APP_ACCOUNT_MISMATCH: 'APP_ACCOUNT_MISMATCH',
85
+ /** A sign-in names an app and an organization that do not belong together. */
86
+ APP_ORGANIZATION_MISMATCH: 'APP_ORGANIZATION_MISMATCH',
87
+ /** An older app asked for "the" account of a number that has accounts with several organizations. */
88
+ ACCOUNT_AMBIGUOUS: 'ACCOUNT_AMBIGUOUS',
89
+ };
90
+ //# sourceMappingURL=app-account.util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-account.util.js","sourceRoot":"","sources":["../../../../../src/modules/user/utils/app-account.util.ts"],"names":[],"mappings":";;;AAuBA,oCAEC;AAGD,gCAEC;AAeD,sDAmBC;AAUD,0DAUC;AApFD,0DAAmD;AAEnD;;;;;;;;;;;;;;;;;GAiBG;AACU,QAAA,gBAAgB,GAAG,iBAAK,CAAC,WAAW,CAAC;AAElD,oGAAoG;AACpG,SAAgB,YAAY,CAAC,KAA2C;IACpE,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,wBAAgB,CAAC;AACvF,CAAC;AAED,kGAAkG;AAClG,SAAgB,UAAU,CAAC,KAA2C;IAClE,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,wBAAgB,CAAC,CAAC;AACpE,CAAC;AAUD;;;;GAIG;AACH,SAAgB,qBAAqB,CAAC,GAA8B;IAChE,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,GAAG,aAAH,GAAG,cAAH,GAAG,GAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,MAAM,KAAK,GAAG,gCAAgC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7D,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,OAAO,mCAAmC,CAAC,CAAC;QAC/F,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC;QAC5B,MAAM,cAAc,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,IAAI,cAAc,IAAI,CAAC,EAAE,CAAC;YAC/D,MAAM,IAAI,KAAK,CAAC,uBAAuB,OAAO,+BAA+B,CAAC,CAAC;QACnF,CAAC;QACD,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,gCAAgC,QAAQ,QAAQ,cAAc,GAAG,CAAC,CAAC;QAClH,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,uBAAuB,CACnC,gBAAkC,EAClC,KAAgC,EAChC,OAAsF;IAEtF,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC7C,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACzC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,OAAO,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,QAAQ,CAAC;AACvD,CAAC;AAED,oEAAoE;AACvD,QAAA,uBAAuB,GAAG;IACnC,iGAAiG;IACjG,oBAAoB,EAAE,sBAAsB;IAC5C,8EAA8E;IAC9E,yBAAyB,EAAE,2BAA2B;IACtD,qGAAqG;IACrG,iBAAiB,EAAE,mBAAmB;CAChC,CAAC"}
@@ -0,0 +1,62 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { ArrayMaxSize, ArrayMinSize, IsArray, IsEnum, IsInt, IsISO8601, IsPositive } from "class-validator";
11
+ /** What changed about somebody's guardians - for logs and analytics; every reason means "refresh". */
12
+ export var GuardiansChangedReason;
13
+ (function (GuardiansChangedReason) {
14
+ /** A guardian was added. */
15
+ GuardiansChangedReason["ADDED"] = "ADDED";
16
+ /** A guardian was removed by the person they guard. */
17
+ GuardiansChangedReason["REMOVED"] = "REMOVED";
18
+ /** Another guardian became the primary one. */
19
+ GuardiansChangedReason["PRIMARY_CHANGED"] = "PRIMARY_CHANGED";
20
+ /** A guardian on the list by phone number proved that number in the same organization's app, and is now an app guardian. */
21
+ GuardiansChangedReason["PROMOTED"] = "PROMOTED";
22
+ /** An app guardian's account was deleted; they stay on the list by phone number. */
23
+ GuardiansChangedReason["DEMOTED"] = "DEMOTED";
24
+ /** A guardian stopped looking after one of their dependents. */
25
+ GuardiansChangedReason["DEPENDENT_REMOVED"] = "DEPENDENT_REMOVED";
26
+ })(GuardiansChangedReason || (GuardiansChangedReason = {}));
27
+ /**
28
+ * Payload of `KAFKA_TOPICS.GUARDIANS_CHANGED`: somebody's guardian list changed,
29
+ * and these people's apps should read their guardians and dependents again.
30
+ *
31
+ * Ids only - no names, numbers or relationships. The apps read the lists through
32
+ * the guardian API, which applies its own access rules.
33
+ */
34
+ export class GuardiansChangedPayloadDto {
35
+ }
36
+ __decorate([
37
+ IsInt(),
38
+ IsPositive(),
39
+ __metadata("design:type", Number)
40
+ ], GuardiansChangedPayloadDto.prototype, "organizationId", void 0);
41
+ __decorate([
42
+ IsInt(),
43
+ IsPositive(),
44
+ __metadata("design:type", Number)
45
+ ], GuardiansChangedPayloadDto.prototype, "dependentId", void 0);
46
+ __decorate([
47
+ IsArray(),
48
+ ArrayMinSize(1),
49
+ ArrayMaxSize(100),
50
+ IsInt({ each: true }),
51
+ IsPositive({ each: true }),
52
+ __metadata("design:type", Array)
53
+ ], GuardiansChangedPayloadDto.prototype, "userIds", void 0);
54
+ __decorate([
55
+ IsEnum(GuardiansChangedReason),
56
+ __metadata("design:type", String)
57
+ ], GuardiansChangedPayloadDto.prototype, "reason", void 0);
58
+ __decorate([
59
+ IsISO8601(),
60
+ __metadata("design:type", String)
61
+ ], GuardiansChangedPayloadDto.prototype, "occurredAt", void 0);
62
+ //# sourceMappingURL=guardians-changed-payload.dto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guardians-changed-payload.dto.js","sourceRoot":"","sources":["../../../../../src/kafka/dtos/user/guardians-changed-payload.dto.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE5G,sGAAsG;AACtG,MAAM,CAAN,IAAY,sBAaX;AAbD,WAAY,sBAAsB;IAC9B,4BAA4B;IAC5B,yCAAe,CAAA;IACf,uDAAuD;IACvD,6CAAmB,CAAA;IACnB,+CAA+C;IAC/C,6DAAmC,CAAA;IACnC,4HAA4H;IAC5H,+CAAqB,CAAA;IACrB,oFAAoF;IACpF,6CAAmB,CAAA;IACnB,gEAAgE;IAChE,iEAAuC,CAAA;AAC3C,CAAC,EAbW,sBAAsB,KAAtB,sBAAsB,QAajC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,0BAA0B;CAwBtC;AApBG;IAFC,KAAK,EAAE;IACP,UAAU,EAAE;;kEACW;AAKxB;IAFC,KAAK,EAAE;IACP,UAAU,EAAE;;+DACQ;AAQrB;IALC,OAAO,EAAE;IACT,YAAY,CAAC,CAAC,CAAC;IACf,YAAY,CAAC,GAAG,CAAC;IACjB,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;;2DACR;AAGnB;IADC,MAAM,CAAC,sBAAsB,CAAC;;0DACC;AAGhC;IADC,SAAS,EAAE;;8DACQ"}
@@ -8,4 +8,5 @@ export * from './dtos/otp/create-otp-payload.dto';
8
8
  export * from './dtos/otp/otp-payload.dto';
9
9
  export * from './dtos/password/password-reset-payload.dto';
10
10
  export * from './dtos/account-deletion/account-deletion-request-payload.dto';
11
+ export * from './dtos/user/guardians-changed-payload.dto';
11
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/kafka/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,cAAc,6CAA6C,CAAC;AAC5D,cAAc,sCAAsC,CAAC;AACrD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,yCAAyC,CAAC;AACxD,cAAc,mCAAmC,CAAC;AAClD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,8DAA8D,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/kafka/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,cAAc,6CAA6C,CAAC;AAC5D,cAAc,sCAAsC,CAAC;AACrD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,yCAAyC,CAAC;AACxD,cAAc,mCAAmC,CAAC;AAClD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,8DAA8D,CAAC;AAC7E,cAAc,2CAA2C,CAAC"}
@@ -9,6 +9,10 @@ export const KAFKA_TOPICS = {
9
9
  USER_CREATED: 'user.created',
10
10
  USER_UPDATED: 'user.updated',
11
11
  USER_DELETED: 'user.deleted',
12
+ // Somebody's guardians or dependents changed (producer: clarion-authentication;
13
+ // payload GuardiansChangedPayloadDto; consumer: clarion-notification, which
14
+ // sends each affected person a silent push so their app refreshes). Ids only.
15
+ GUARDIANS_CHANGED: 'user.guardians.changed.v1',
12
16
  // Org. ORG_CREATED is published by clarion-organization after commit
13
17
  // (payload OrganizationCreatedEvent); clarion-incident provisions the Safety
14
18
  // Alerts category from it.
@@ -1 +1 @@
1
- {"version":3,"file":"topics.js","sourceRoot":"","sources":["../../../src/kafka/topics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"topics.js","sourceRoot":"","sources":["../../../src/kafka/topics.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG;IACxB,OAAO;IACP,eAAe,EAAE,iBAAiB;IAClC,cAAc,EAAE,gBAAgB;IAChC,eAAe,EAAE,iBAAiB;IAClC,6BAA6B,EAAE,+BAA+B;IAC9D,6BAA6B,EAAE,+BAA+B;IAC9D,OAAO;IACP,YAAY,EAAE,cAAc;IAC5B,YAAY,EAAE,cAAc;IAC5B,YAAY,EAAE,cAAc;IAC5B,gFAAgF;IAChF,4EAA4E;IAC5E,8EAA8E;IAC9E,iBAAiB,EAAE,2BAA2B;IAC9C,qEAAqE;IACrE,6EAA6E;IAC7E,2BAA2B;IAC3B,WAAW,EAAE,aAAa;IAC1B,WAAW,EAAE,aAAa;IAC1B,WAAW,EAAE,aAAa;IAC1B,MAAM;IACN,YAAY,EAAE,eAAe;IAC7B,aAAa,EAAE,eAAe;IAC9B,WAAW;IACX,cAAc,EAAE,gBAAgB;IAChC,WAAW;IACX,gBAAgB,EAAE,kBAAkB;IACpC,gBAAgB,EAAE,kBAAkB;IACpC,uBAAuB,EAAE,yBAAyB;IAClD,sBAAsB,EAAE,wBAAwB;IAChD,yBAAyB,EAAE,2BAA2B;IACtD,wBAAwB,EAAE,0BAA0B;IACpD,0BAA0B,EAAE,4BAA4B;IACxD,sBAAsB,EAAE,wBAAwB;IAChD,iBAAiB,EAAE,mBAAmB;IACtC,2BAA2B,EAAE,6BAA6B;IAC1D,yCAAyC,EAAE,2CAA2C;IACtF,4EAA4E;IAC5E,6EAA6E;IAC7E,6EAA6E;IAC7E,6EAA6E;IAC7E,uCAAuC,EAAE,4CAA4C;IACrF,8CAA8C,EAAE,mDAAmD;IACnG,sDAAsD,EAClD,2DAA2D;IAC/D,qEAAqE;IACrE,+BAA+B;IAC/B,0CAA0C,EAAE,4DAA4D;IACxG,OAAO;IACP,oBAAoB,EAAE,sBAAsB;IAC5C,yBAAyB,EAAE,2BAA2B;IACtD,qBAAqB,EAAE,uBAAuB;IAC9C,OAAO;IACP,YAAY,EAAE,cAAc;IAC5B,UAAU,EAAE,YAAY;IACxB,WAAW,EAAE,aAAa;IAC1B,OAAO;IACP,iBAAiB,EAAE,mBAAmB;IACtC,oBAAoB,EAAE,sBAAsB;IAC5C,WAAW;IACX,qBAAqB,EAAE,uBAAuB;IAC9C,uBAAuB,EAAE,yBAAyB;IAClD,qBAAqB,EAAE,uBAAuB;IAC9C,sBAAsB,EAAE,wBAAwB;IAChD,qBAAqB,EAAE,uBAAuB;IAC9C,mBAAmB,EAAE,qBAAqB;IAC1C,qBAAqB,EAAE,uBAAuB;IAC9C,oBAAoB,EAAE,sBAAsB;IAC5C,wBAAwB,EAAE,0BAA0B;IACpD,wBAAwB,EAAE,0BAA0B;IACpD,wBAAwB,EAAE,0BAA0B;IACpD,iEAAiE;IACjE,iBAAiB,EAAE,oCAAoC;IACvD,eAAe,EAAE,kCAAkC;IACnD,wBAAwB,EAAE,6BAA6B;IACvD,wBAAwB,EAAE,6BAA6B;IACvD,wBAAwB,EAAE,6BAA6B;IACvD,wEAAwE;IACxE,+DAA+D;IAC/D,yBAAyB,EAAE,uCAAuC;IAClE,yBAAyB,EAAE,uCAAuC;IAClE,yBAAyB,EAAE,uCAAuC;IAClE,wCAAwC,EACpC,sDAAsD;IAC1D,gCAAgC,EAAE,8CAA8C;IAChF,iFAAiF;IACjF,wBAAwB,EAAE,6BAA6B;IACvD,+BAA+B,EAAE,oCAAoC;IACrE,iFAAiF;IACjF,2EAA2E;IAC3E,4EAA4E;IAC5E,2EAA2E;IAC3E,iEAAiE;IACjE,sBAAsB,EAAE,2BAA2B;IACnD,sBAAsB,EAAE,2BAA2B;IACnD,uBAAuB,EAAE,4BAA4B;IACrD,6BAA6B,EAAE,kCAAkC;IACjE,+BAA+B,EAAE,oCAAoC;IACrE,8BAA8B,EAAE,mCAAmC;IACnE,+BAA+B,EAAE,oCAAoC;IACrE,4BAA4B,EAAE,iCAAiC;IAC/D,uBAAuB,EAAE,4BAA4B;IACrD,qBAAqB,EAAE,0BAA0B;IACjD,uBAAuB,EAAE,4BAA4B;IACrD,0BAA0B,EAAE,+BAA+B;IAC3D,2BAA2B,EAAE,gCAAgC;IAC7D,wBAAwB,EAAE,6BAA6B;IACvD,wBAAwB,EAAE,6BAA6B;IACvD,yBAAyB,EAAE,8BAA8B;IACzD,0BAA0B,EAAE,+BAA+B;IAC3D,oCAAoC,EAAE,yCAAyC;IAC/E,iCAAiC,EAAE,sCAAsC;IACzE,4BAA4B,EAAE,iCAAiC;IAC/D,+BAA+B,EAAE,oCAAoC;IACrE,wEAAwE;IACxE,8EAA8E;IAC9E,mDAAmD;IACnD,oBAAoB,EAAE,yBAAyB;IAC/C,sBAAsB,EAAE,2BAA2B;IACnD,kBAAkB,EAAE,uBAAuB;IAC3C,0BAA0B,EAAE,+BAA+B;IAC3D,+EAA+E;IAC/E,8DAA8D;IAC9D,iBAAiB,EAAE,6BAA6B;IAChD,4BAA4B,EAAE,wCAAwC;IACtE,mBAAmB,EAAE,+BAA+B;IACpD,uBAAuB,EAAE,mCAAmC;IAC5D,eAAe,EAAE,2BAA2B;IAC5C,2EAA2E;IAC3E,uEAAuE;IACvE,6EAA6E;IAC7E,+BAA+B;IAC/B,qCAAqC,EAAE,0CAA0C;IACjF,oBAAoB,EAAE,yBAAyB;IAC/C,8BAA8B,EAAE,mCAAmC;IACnE,0EAA0E;IAC1E,0EAA0E;IAC1E,yCAAyC,EAAE,8CAA8C;IACzF,sCAAsC,EAAE,wDAAwD;CACnG,CAAC"}
@@ -13,7 +13,7 @@ export class GuardianIdentifierDto {
13
13
  }
14
14
  __decorate([
15
15
  ApiProperty({
16
- description: 'Phone number for external guardian',
16
+ description: 'Phone number of an external guardian (older apps). Prefer relationshipId, which names either kind.',
17
17
  example: '+1234567890',
18
18
  required: false,
19
19
  type: 'string'
@@ -24,7 +24,7 @@ __decorate([
24
24
  ], GuardianIdentifierDto.prototype, "phoneNumber", void 0);
25
25
  __decorate([
26
26
  ApiProperty({
27
- description: 'Relationship ID for system guardian',
27
+ description: 'The guardian entry id - `id` of an app-user guardian relation or of an external guardian (since grm-shared-library 1.1.248)',
28
28
  example: 789,
29
29
  required: false,
30
30
  type: 'number'
@@ -1 +1 @@
1
- {"version":3,"file":"guardian-identifier.dto.js","sourceRoot":"","sources":["../../../../../src/modules/user/dtos/guardian-identifier.dto.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAc,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7E,MAAM,OAAO,qBAAqB;CAoBjC;AAXG;IARC,WAAW,CAAC;QACT,WAAW,EAAE,oCAAoC;QACjD,OAAO,EAAE,aAAa;QACtB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,QAAQ;KACjB,CAAC;IACD,QAAQ,EAAE;IACV,UAAU,EAAE;;0DACQ;AAUrB;IARC,WAAW,CAAC;QACT,WAAW,EAAE,qCAAqC;QAClD,OAAO,EAAE,GAAG;QACZ,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,QAAQ;KACjB,CAAC;IACD,QAAQ,EAAE;IACV,UAAU,EAAE;;6DACW"}
1
+ {"version":3,"file":"guardian-identifier.dto.js","sourceRoot":"","sources":["../../../../../src/modules/user/dtos/guardian-identifier.dto.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAc,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7E,MAAM,OAAO,qBAAqB;CAoBjC;AAXG;IARC,WAAW,CAAC;QACT,WAAW,EAAE,oGAAoG;QACjH,OAAO,EAAE,aAAa;QACtB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,QAAQ;KACjB,CAAC;IACD,QAAQ,EAAE;IACV,UAAU,EAAE;;0DACQ;AAUrB;IARC,WAAW,CAAC;QACT,WAAW,EAAE,6HAA6H;QAC1I,OAAO,EAAE,GAAG;QACZ,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,QAAQ;KACjB,CAAC;IACD,QAAQ,EAAE;IACV,UAAU,EAAE;;6DACW"}
@@ -16,4 +16,5 @@ export * from './interfaces/guardian';
16
16
  export * from './interfaces/guardian-relation';
17
17
  export * from './interfaces/guardians-response';
18
18
  export * from './interfaces/account-analytics';
19
+ export * from './utils/app-account.util';
19
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/user/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qCAAqC,CAAC;AACpD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,8CAA8C,CAAC;AAC7D,cAAc,wCAAwC,CAAC;AAEvD,cAAc,0BAA0B,CAAC;AACzC,cAAc,oCAAoC,CAAC;AACnD,cAAc,uCAAuC,CAAC;AAEtD,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/user/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qCAAqC,CAAC;AACpD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,8CAA8C,CAAC;AAC7D,cAAc,wCAAwC,CAAC;AAEvD,cAAc,0BAA0B,CAAC;AACzC,cAAc,oCAAoC,CAAC;AACnD,cAAc,uCAAuC,CAAC;AAEtD,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAE/C,cAAc,0BAA0B,CAAC"}
@@ -0,0 +1,83 @@
1
+ import { Roles } from '../../role/enums/role.enum';
2
+ /**
3
+ * App accounts and staff accounts.
4
+ *
5
+ * Each brand's mobile app (G4S Kenya, GeoSHIELD, SGA Security, ...) is its own
6
+ * product for one organization's customers, so an account made in one app is an
7
+ * account with that organization only. Signing in to another brand's app means
8
+ * registering with that brand. One person may therefore hold several app
9
+ * accounts - one per organization - with the same phone number and e-mail.
10
+ *
11
+ * Staff (Super-Admin, organization and control-centre staff, responders,
12
+ * corporate-client admins) keep one platform-wide account each: their e-mail and
13
+ * phone number stay unique across the whole platform.
14
+ *
15
+ * An APP ACCOUNT is one whose only role is Mobile-User. That is the same rule the
16
+ * database's unique indexes use (`roles = '{Mobile-User}'`), so code and schema
17
+ * can never disagree about which kind an account is. An account holding
18
+ * Mobile-User beside a staff role is a staff account that also uses an app.
19
+ */
20
+ export const APP_ACCOUNT_ROLE = Roles.MOBILE_USER;
21
+ /** An account whose only role is Mobile-User: unique within its organization, not platform-wide. */
22
+ export function isAppAccount(roles) {
23
+ return Array.isArray(roles) && roles.length === 1 && roles[0] === APP_ACCOUNT_ROLE;
24
+ }
25
+ /** Holds the Mobile-User role, alone or beside staff roles: someone who can use a brand's app. */
26
+ export function hasAppRole(roles) {
27
+ return Array.isArray(roles) && roles.includes(APP_ACCOUNT_ROLE);
28
+ }
29
+ /**
30
+ * Parses `APP_ORGANIZATIONS`. Blank means "none configured". A malformed entry
31
+ * throws: a typo here would let an app sign people in to the wrong organization,
32
+ * so it must stop the service at boot rather than be skipped.
33
+ */
34
+ export function parseAppOrganizations(raw) {
35
+ const map = new Map();
36
+ for (const entry of String(raw !== null && raw !== void 0 ? raw : '').split(',')) {
37
+ const trimmed = entry.trim();
38
+ if (!trimmed)
39
+ continue;
40
+ const match = /^([A-Za-z0-9_-]+)\s*:\s*(\d+)$/.exec(trimmed);
41
+ if (!match)
42
+ throw new Error(`APP_ORGANIZATIONS: "${trimmed}" is not <appId>:<organizationId>`);
43
+ const [, appId, id] = match;
44
+ const organizationId = Number(id);
45
+ if (!Number.isSafeInteger(organizationId) || organizationId <= 0) {
46
+ throw new Error(`APP_ORGANIZATIONS: "${trimmed}" names no valid organization`);
47
+ }
48
+ const existing = map.get(appId);
49
+ if (existing !== undefined && existing !== organizationId) {
50
+ throw new Error(`APP_ORGANIZATIONS: ${appId} is given two organizations (${existing} and ${organizationId})`);
51
+ }
52
+ map.set(appId, organizationId);
53
+ }
54
+ return map;
55
+ }
56
+ /**
57
+ * Whether a signed-in account is being used from another organization's app: the
58
+ * request names an app (`X-App-Id`) that belongs to organization A, and the account
59
+ * is an app user of organization B.
60
+ *
61
+ * Unknown here means "not a mismatch": no app named, an app with no configured
62
+ * organization, or an account that is staff only. Those keep working as before.
63
+ */
64
+ export function isAccountFromAnotherApp(appOrganizations, appId, account) {
65
+ if (!appId)
66
+ return false;
67
+ const expected = appOrganizations.get(appId);
68
+ if (expected === undefined)
69
+ return false;
70
+ if (!hasAppRole(account.roles))
71
+ return false;
72
+ return Number(account.organizationId) !== expected;
73
+ }
74
+ /** Error codes a client can act on, for the account rules above. */
75
+ export const APP_ACCOUNT_ERROR_CODES = {
76
+ /** A token or session belongs to another organization's app: sign out and sign in again here. */
77
+ APP_ACCOUNT_MISMATCH: 'APP_ACCOUNT_MISMATCH',
78
+ /** A sign-in names an app and an organization that do not belong together. */
79
+ APP_ORGANIZATION_MISMATCH: 'APP_ORGANIZATION_MISMATCH',
80
+ /** An older app asked for "the" account of a number that has accounts with several organizations. */
81
+ ACCOUNT_AMBIGUOUS: 'ACCOUNT_AMBIGUOUS',
82
+ };
83
+ //# sourceMappingURL=app-account.util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-account.util.js","sourceRoot":"","sources":["../../../../../src/modules/user/utils/app-account.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAEnD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC,WAAW,CAAC;AAElD,oGAAoG;AACpG,MAAM,UAAU,YAAY,CAAC,KAA2C;IACpE,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,gBAAgB,CAAC;AACvF,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,UAAU,CAAC,KAA2C;IAClE,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AACpE,CAAC;AAUD;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAA8B;IAChE,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,GAAG,aAAH,GAAG,cAAH,GAAG,GAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,MAAM,KAAK,GAAG,gCAAgC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7D,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,OAAO,mCAAmC,CAAC,CAAC;QAC/F,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC;QAC5B,MAAM,cAAc,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,IAAI,cAAc,IAAI,CAAC,EAAE,CAAC;YAC/D,MAAM,IAAI,KAAK,CAAC,uBAAuB,OAAO,+BAA+B,CAAC,CAAC;QACnF,CAAC;QACD,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,gCAAgC,QAAQ,QAAQ,cAAc,GAAG,CAAC,CAAC;QAClH,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CACnC,gBAAkC,EAClC,KAAgC,EAChC,OAAsF;IAEtF,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC7C,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACzC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,OAAO,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,QAAQ,CAAC;AACvD,CAAC;AAED,oEAAoE;AACpE,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACnC,iGAAiG;IACjG,oBAAoB,EAAE,sBAAsB;IAC5C,8EAA8E;IAC9E,yBAAyB,EAAE,2BAA2B;IACtD,qGAAqG;IACrG,iBAAiB,EAAE,mBAAmB;CAChC,CAAC"}
@@ -0,0 +1,32 @@
1
+ /** What changed about somebody's guardians - for logs and analytics; every reason means "refresh". */
2
+ export declare enum GuardiansChangedReason {
3
+ /** A guardian was added. */
4
+ ADDED = "ADDED",
5
+ /** A guardian was removed by the person they guard. */
6
+ REMOVED = "REMOVED",
7
+ /** Another guardian became the primary one. */
8
+ PRIMARY_CHANGED = "PRIMARY_CHANGED",
9
+ /** A guardian on the list by phone number proved that number in the same organization's app, and is now an app guardian. */
10
+ PROMOTED = "PROMOTED",
11
+ /** An app guardian's account was deleted; they stay on the list by phone number. */
12
+ DEMOTED = "DEMOTED",
13
+ /** A guardian stopped looking after one of their dependents. */
14
+ DEPENDENT_REMOVED = "DEPENDENT_REMOVED"
15
+ }
16
+ /**
17
+ * Payload of `KAFKA_TOPICS.GUARDIANS_CHANGED`: somebody's guardian list changed,
18
+ * and these people's apps should read their guardians and dependents again.
19
+ *
20
+ * Ids only - no names, numbers or relationships. The apps read the lists through
21
+ * the guardian API, which applies its own access rules.
22
+ */
23
+ export declare class GuardiansChangedPayloadDto {
24
+ /** The organization whose app the people use. Pushes go only to devices of this organization. */
25
+ organizationId: number;
26
+ /** Whose guardian list changed. */
27
+ dependentId: number;
28
+ /** Every app user whose guardians or dependents changed: the dependent and any app guardian involved. */
29
+ userIds: number[];
30
+ reason: GuardiansChangedReason;
31
+ occurredAt: string;
32
+ }
@@ -8,3 +8,4 @@ export * from './dtos/otp/create-otp-payload.dto';
8
8
  export * from './dtos/otp/otp-payload.dto';
9
9
  export * from './dtos/password/password-reset-payload.dto';
10
10
  export * from './dtos/account-deletion/account-deletion-request-payload.dto';
11
+ export * from './dtos/user/guardians-changed-payload.dto';
@@ -7,6 +7,7 @@ export declare const KAFKA_TOPICS: {
7
7
  USER_CREATED: string;
8
8
  USER_UPDATED: string;
9
9
  USER_DELETED: string;
10
+ GUARDIANS_CHANGED: string;
10
11
  ORG_CREATED: string;
11
12
  ORG_UPDATED: string;
12
13
  ORG_DELETED: string;
@@ -16,3 +16,4 @@ export * from './interfaces/guardian';
16
16
  export * from './interfaces/guardian-relation';
17
17
  export * from './interfaces/guardians-response';
18
18
  export * from './interfaces/account-analytics';
19
+ export * from './utils/app-account.util';
@@ -61,7 +61,7 @@ export interface AccountAnalyticsKindRow {
61
61
  /** Of the accounts created in the period, how far each got - as they stand now. */
62
62
  export interface AccountAnalyticsFunnel {
63
63
  created: number;
64
- /** Confirmed their phone or e-mail with a one-time code. */
64
+ /** Proved their phone or e-mail: a sign-in code, Google or Apple (the older app: its one-time code). */
65
65
  verified: number;
66
66
  acceptedTerms: number;
67
67
  /** Signed in at least once. */
@@ -84,7 +84,7 @@ export interface AccountAnalyticsAccounts {
84
84
  /** Active accounts that were created in an earlier period. */
85
85
  returning: number;
86
86
  funnel: AccountAnalyticsFunnel;
87
- /** Now: never confirmed their phone or e-mail with a one-time code. */
87
+ /** Now: never proved their phone or e-mail (see `AccountAnalyticsFunnel.verified`). */
88
88
  pendingNow: number;
89
89
  /** Now: never signed in. */
90
90
  neverSignedIn: number;
@@ -104,12 +104,16 @@ export interface AccountAnalyticsAccounts {
104
104
  recency: AccountAnalyticsCount<AccountRecencyBand>[];
105
105
  }
106
106
  /**
107
- * How somebody signed in:
108
- * - PASSWORD e-mail and password (the admin and the web);
109
- * - OTP phone number and a one-time code (the app);
110
- * - REVIEWER the app-store reviewers' account.
107
+ * How somebody signed in - or, for a sign-up, made their account:
108
+ * - PASSWORD e-mail and password (the admin and the web);
109
+ * - OTP the older app (before 1.0.18): phone number and one code sent by SMS and e-mail together;
110
+ * - PHONE_CODE a code to the phone by SMS or a call, or a WhatsApp message from it - proves the number;
111
+ * - EMAIL_CODE a code to the e-mail - proves the e-mail only;
112
+ * - GOOGLE Google vouches for the e-mail;
113
+ * - APPLE Apple vouches for the e-mail (possibly a private relay address);
114
+ * - REVIEWER the app-store reviewers' account.
111
115
  */
112
- export type AccountSignInMethod = 'PASSWORD' | 'OTP' | 'REVIEWER';
116
+ export type AccountSignInMethod = 'PASSWORD' | 'OTP' | 'PHONE_CODE' | 'EMAIL_CODE' | 'GOOGLE' | 'APPLE' | 'REVIEWER';
113
117
  export interface AccountAnalyticsMethodRow {
114
118
  method: string;
115
119
  succeeded: number;
@@ -127,8 +131,13 @@ export interface AccountAnalyticsSignIns {
127
131
  firstSignIns: number;
128
132
  /** Failed for an e-mail or a code that matches no account (counted, never stored). */
129
133
  unknownAccount: number;
134
+ /**
135
+ * By AccountSignInMethod. A wrong phone or e-mail code is not a failed sign-in - it is
136
+ * counted with the codes (`AccountAnalyticsVerificationCodes`) - so PHONE_CODE and
137
+ * EMAIL_CODE fail only for a switched-off account.
138
+ */
130
139
  byMethod: AccountAnalyticsMethodRow[];
131
- /** INVALID_CREDENTIALS, UNVERIFIED, UNKNOWN_ACCOUNT, INVALID_TOKEN, ERROR... */
140
+ /** INVALID_CREDENTIALS, UNVERIFIED, UNKNOWN_ACCOUNT, INVALID_TOKEN, INVALID_ID_TOKEN, DISABLED, EMAIL_IN_USE, EMAIL_REQUIRED, ERROR... */
132
141
  failureReasons: AccountAnalyticsCount[];
133
142
  averageDailyUsers: number;
134
143
  peakDailyUsers: number;
@@ -141,6 +150,11 @@ export interface AccountAnalyticsOtpActionRow {
141
150
  sent: number;
142
151
  verified: number;
143
152
  }
153
+ /**
154
+ * The older app's one-time codes (before 1.0.18): one code to the e-mail and the phone
155
+ * together, for signing up, in and confirming. The current app's codes are in
156
+ * `AccountAnalyticsSignInOptions.codes`.
157
+ */
144
158
  export interface AccountAnalyticsOtp {
145
159
  /** First sends and resends. */
146
160
  sent: number;
@@ -237,6 +251,166 @@ export interface AccountAnalyticsPrevious {
237
251
  deletionRequests: number;
238
252
  guardianLinks: number;
239
253
  }
254
+ /** How a code travels. SMS and VOICE carry it to the phone; WHATSAPP is the person messaging us FROM the phone; EMAIL. */
255
+ export type AccountVerificationChannel = 'SMS' | 'VOICE' | 'WHATSAPP' | 'EMAIL';
256
+ /** What a code is for: signing in (or up), or proving the phone number of an account already signed in. */
257
+ export type AccountVerificationPurpose = 'SIGN_IN' | 'VERIFY_PHONE';
258
+ /** One channel's codes for one purpose, in the period. */
259
+ export interface AccountAnalyticsCodeChannelRow {
260
+ purpose: AccountVerificationPurpose | string;
261
+ channel: AccountVerificationChannel | string;
262
+ /** Codes sent - for WhatsApp, the message the person was asked to send us. */
263
+ sent: number;
264
+ /** Refused before anything was sent: asked for too often, a number already on another account, a channel that cannot reach it. */
265
+ refused: number;
266
+ /** The SMS or call provider could not take it. The app offers the other channels. */
267
+ notDelivered: number;
268
+ confirmed: number;
269
+ wrongCode: number;
270
+ expired: number;
271
+ /** WhatsApp: the message came from a number other than the one being proven. */
272
+ wrongNumber: number;
273
+ /** confirmed / sent; null with none sent. */
274
+ confirmationRate: number | null;
275
+ }
276
+ /** Codes by the country of the number (or of the app, for an e-mail code) and channel, in the period. */
277
+ export interface AccountAnalyticsCodeCountryRow {
278
+ /** KE, UG, TZ - or UNKNOWN. */
279
+ country: string;
280
+ channel: AccountVerificationChannel | string;
281
+ sent: number;
282
+ notDelivered: number;
283
+ confirmed: number;
284
+ }
285
+ /** The current app's codes (1.0.18 on): to the phone only, or to the e-mail only - never both. */
286
+ export interface AccountAnalyticsVerificationCodes {
287
+ sent: number;
288
+ refused: number;
289
+ notDelivered: number;
290
+ confirmed: number;
291
+ wrongCode: number;
292
+ expired: number;
293
+ wrongNumber: number;
294
+ confirmationRate: number | null;
295
+ /** Biggest first. */
296
+ byChannel: AccountAnalyticsCodeChannelRow[];
297
+ byCountry: AccountAnalyticsCodeCountryRow[];
298
+ /** Why codes were refused: RATE_LIMITED, PHONE_IN_USE, CHANNEL_UNAVAILABLE. */
299
+ refusals: AccountAnalyticsCount[];
300
+ }
301
+ /** App users making their own account, in the period. */
302
+ export interface AccountAnalyticsSignUps {
303
+ /** A phone or e-mail code confirmed that matched no account: the app showed the short sign-up form. */
304
+ formsStarted: number;
305
+ /** Accounts made from that form. Google and Apple make the account straight away, with no form. */
306
+ formsCompleted: number;
307
+ /** formsCompleted / formsStarted; null with none started. */
308
+ completionRate: number | null;
309
+ /** Sign-ups refused - the e-mail or number already has an account, the form came back too late. */
310
+ refused: number;
311
+ /** EMAIL_IN_USE, PHONE_IN_USE, EMAIL_REQUIRED, REGISTRATION_EXPIRED. */
312
+ failureReasons: AccountAnalyticsCount[];
313
+ /**
314
+ * App (Mobile-User) accounts created in the period, by how: PHONE_CODE, EMAIL_CODE,
315
+ * GOOGLE, APPLE, OTP (the older app) - and OTHER: made for the person (a corporate
316
+ * member, a partner's caller) or before sign-ups were recorded.
317
+ */
318
+ byMethod: AccountAnalyticsCount[];
319
+ }
320
+ export interface AccountAnalyticsPhoneCountryRow {
321
+ country: string;
322
+ appUsers: number;
323
+ verified: number;
324
+ unverified: number;
325
+ noNumber: number;
326
+ }
327
+ /**
328
+ * App users' phone numbers - the number a responder calls - as they stand now. A number
329
+ * is verified only when a code to it, or a WhatsApp message from it, proved it; a number
330
+ * saved with "Verify later" is shown to the dispatcher as not verified.
331
+ */
332
+ export interface AccountAnalyticsPhoneNumbers {
333
+ appUsers: number;
334
+ withNumber: number;
335
+ verified: number;
336
+ unverified: number;
337
+ noNumber: number;
338
+ /** verified / appUsers; null with none. */
339
+ verifiedRate: number | null;
340
+ /**
341
+ * Every app user once: how the number was proven - SMS, VOICE, WHATSAPP, LEGACY_OTP (the
342
+ * older app's code, counted where its SMS always arrived) - or UNVERIFIED, or NONE.
343
+ */
344
+ byState: AccountAnalyticsCount[];
345
+ byCountry: AccountAnalyticsPhoneCountryRow[];
346
+ /** In the period: numbers proven by somebody already signed in (after Google, Apple or an e-mail code), by channel. */
347
+ verifiedInPeriod: AccountAnalyticsCount[];
348
+ /** In the period: "Verify later" - a number saved without proving it. */
349
+ deferred: number;
350
+ /** Now: app users whose e-mail is proven (an e-mail code, Google or Apple). */
351
+ emailVerified: number;
352
+ }
353
+ /** Google or Apple. */
354
+ export interface AccountAnalyticsProviderRow {
355
+ provider: 'GOOGLE' | 'APPLE' | string;
356
+ /** Accounts linked to it now. */
357
+ linkedAccounts: number;
358
+ /** In the period. */
359
+ signIns: number;
360
+ /** Accounts it created, in the period. */
361
+ newAccounts: number;
362
+ /** Linked to an account that already had the same proven e-mail, in the period. */
363
+ linkedExisting: number;
364
+ /** The provider's token did not check out, or the account could not be used (switched off, e-mail taken or missing). */
365
+ failed: number;
366
+ }
367
+ /** Sign-ins in one country by one way in, in the period. */
368
+ export interface AccountAnalyticsMethodCountryRow {
369
+ /** The account's country (KE, UG, TZ), or UNKNOWN. */
370
+ country: string;
371
+ method: AccountSignInMethod | string;
372
+ signIns: number;
373
+ }
374
+ export interface AccountAnalyticsSignInOptionsPoint {
375
+ /** As `AccountAnalyticsPoint.bucket`. */
376
+ bucket: string;
377
+ /** Successful sign-ins in the bucket by AccountSignInMethod; methods with none are left out. */
378
+ byMethod: Record<string, number>;
379
+ /** The current app's codes. */
380
+ codesSent: number;
381
+ codesConfirmed: number;
382
+ }
383
+ /** The same figures for the previous period of the same length. */
384
+ export interface AccountAnalyticsSignInOptionsPrevious {
385
+ /** Sign-ins by PHONE_CODE, EMAIL_CODE, GOOGLE or APPLE. */
386
+ currentAppSignIns: number;
387
+ /** Sign-ins by the older app's code (OTP). */
388
+ olderAppSignIns: number;
389
+ codesSent: number;
390
+ codesConfirmed: number;
391
+ phonesVerified: number;
392
+ deferred: number;
393
+ formsCompleted: number;
394
+ }
395
+ /**
396
+ * The ways into the app since 1.0.18 - a code to the phone (SMS, a call, WhatsApp), a code
397
+ * to the e-mail, Google, Apple - next to the older app's SMS-and-e-mail code, and whether
398
+ * the phone numbers responders call are proven.
399
+ */
400
+ export interface AccountAnalyticsSignInOptions {
401
+ /** People who signed in during the period, each by the way they signed in LAST. */
402
+ lastMethodUsed: AccountAnalyticsCount[];
403
+ byCountry: AccountAnalyticsMethodCountryRow[];
404
+ /** One point per bucket, as `AccountAnalytics.timeline`. */
405
+ timeline: AccountAnalyticsSignInOptionsPoint[];
406
+ codes: AccountAnalyticsVerificationCodes;
407
+ signUps: AccountAnalyticsSignUps;
408
+ phones: AccountAnalyticsPhoneNumbers;
409
+ /** GOOGLE and APPLE, always both. */
410
+ providers: AccountAnalyticsProviderRow[];
411
+ /** Absent for "forever". */
412
+ previous: AccountAnalyticsSignInOptionsPrevious | null;
413
+ }
240
414
  /** A Super-Admin's view of every organization: one row each, biggest first. */
241
415
  export interface AccountAnalyticsOrganizationRow {
242
416
  organizationId: number;
@@ -266,6 +440,8 @@ export interface AccountAnalytics {
266
440
  passwords: AccountAnalyticsPasswords;
267
441
  guardians: AccountAnalyticsGuardians;
268
442
  deletions: AccountAnalyticsDeletions;
443
+ /** The ways into the app, codes by channel and proven phone numbers. Absent only from a clarion-authentication older than this field. */
444
+ signInOptions?: AccountAnalyticsSignInOptions;
269
445
  /** A Super-Admin looking at every organization only. */
270
446
  byOrganization?: AccountAnalyticsOrganizationRow[];
271
447
  }
@@ -1,5 +1,12 @@
1
1
  import { GuardianRelationship } from "../enums/guardian-relationship.enum";
2
2
  export interface Guardian {
3
+ /**
4
+ * The guardian entry's own id. External and app-user guardians share one table
5
+ * and one id space, so either kind can be removed or made primary by it
6
+ * (`GuardianIdentifierDto.relationshipId`). Absent only from responses of
7
+ * clarion-authentication builds older than grm-shared-library 1.1.248.
8
+ */
9
+ id?: number;
3
10
  userId?: number;
4
11
  name: string;
5
12
  phoneNumber: string;
@@ -0,0 +1,59 @@
1
+ import { Roles } from '../../role/enums/role.enum';
2
+ /**
3
+ * App accounts and staff accounts.
4
+ *
5
+ * Each brand's mobile app (G4S Kenya, GeoSHIELD, SGA Security, ...) is its own
6
+ * product for one organization's customers, so an account made in one app is an
7
+ * account with that organization only. Signing in to another brand's app means
8
+ * registering with that brand. One person may therefore hold several app
9
+ * accounts - one per organization - with the same phone number and e-mail.
10
+ *
11
+ * Staff (Super-Admin, organization and control-centre staff, responders,
12
+ * corporate-client admins) keep one platform-wide account each: their e-mail and
13
+ * phone number stay unique across the whole platform.
14
+ *
15
+ * An APP ACCOUNT is one whose only role is Mobile-User. That is the same rule the
16
+ * database's unique indexes use (`roles = '{Mobile-User}'`), so code and schema
17
+ * can never disagree about which kind an account is. An account holding
18
+ * Mobile-User beside a staff role is a staff account that also uses an app.
19
+ */
20
+ export declare const APP_ACCOUNT_ROLE = Roles.MOBILE_USER;
21
+ /** An account whose only role is Mobile-User: unique within its organization, not platform-wide. */
22
+ export declare function isAppAccount(roles: readonly string[] | null | undefined): boolean;
23
+ /** Holds the Mobile-User role, alone or beside staff roles: someone who can use a brand's app. */
24
+ export declare function hasAppRole(roles: readonly string[] | null | undefined): boolean;
25
+ /**
26
+ * Which organization each brand's app belongs to, as configured in
27
+ * `APP_ORGANIZATIONS` - for example `GardaWorld:48,G4S:49,SGA:51`. The ids differ
28
+ * per environment (Dev has its own organizations), which is why this is
29
+ * configuration and not code.
30
+ */
31
+ export type AppOrganizations = ReadonlyMap<string, number>;
32
+ /**
33
+ * Parses `APP_ORGANIZATIONS`. Blank means "none configured". A malformed entry
34
+ * throws: a typo here would let an app sign people in to the wrong organization,
35
+ * so it must stop the service at boot rather than be skipped.
36
+ */
37
+ export declare function parseAppOrganizations(raw: string | null | undefined): AppOrganizations;
38
+ /**
39
+ * Whether a signed-in account is being used from another organization's app: the
40
+ * request names an app (`X-App-Id`) that belongs to organization A, and the account
41
+ * is an app user of organization B.
42
+ *
43
+ * Unknown here means "not a mismatch": no app named, an app with no configured
44
+ * organization, or an account that is staff only. Those keep working as before.
45
+ */
46
+ export declare function isAccountFromAnotherApp(appOrganizations: AppOrganizations, appId: string | null | undefined, account: {
47
+ roles?: readonly string[] | null;
48
+ organizationId?: number | string | null;
49
+ }): boolean;
50
+ /** Error codes a client can act on, for the account rules above. */
51
+ export declare const APP_ACCOUNT_ERROR_CODES: {
52
+ /** A token or session belongs to another organization's app: sign out and sign in again here. */
53
+ readonly APP_ACCOUNT_MISMATCH: "APP_ACCOUNT_MISMATCH";
54
+ /** A sign-in names an app and an organization that do not belong together. */
55
+ readonly APP_ORGANIZATION_MISMATCH: "APP_ORGANIZATION_MISMATCH";
56
+ /** An older app asked for "the" account of a number that has accounts with several organizations. */
57
+ readonly ACCOUNT_AMBIGUOUS: "ACCOUNT_AMBIGUOUS";
58
+ };
59
+ export type AppAccountErrorCode = typeof APP_ACCOUNT_ERROR_CODES[keyof typeof APP_ACCOUNT_ERROR_CODES];
package/package.json CHANGED
@@ -1,72 +1,72 @@
1
- {
2
- "name": "grm-shared-library",
3
- "version": "1.1.246",
4
- "main": "dist/cjs/index.js",
5
- "module": "dist/esm/index.js",
6
- "types": "dist/types/index.d.ts",
7
- "exports": {
8
- ".": {
9
- "types": "./dist/types/index.d.ts",
10
- "import": "./dist/esm/index.js",
11
- "require": "./dist/cjs/index.js"
12
- },
13
- "./dist/modules/*": {
14
- "types": "./dist/types/modules/*.d.ts",
15
- "import": "./dist/esm/modules/*.js",
16
- "require": "./dist/cjs/modules/*.js"
17
- }
18
- },
19
- "files": [
20
- "dist/**/*"
21
- ],
22
- "scripts": {
23
- "clean": "rimraf dist dist-test",
24
- "build:cjs": "tsc -p tsconfig.cjs.json",
25
- "build:esm": "tsc -p tsconfig.esm.json",
26
- "build:types": "tsc -p tsconfig.types.json",
27
- "build": "npm run clean && npm run build:types && npm run build:cjs && npm run build:esm",
28
- "prepublishOnly": "npm run build",
29
- "pretest": "rimraf dist-test",
30
- "test": "tsc -p tsconfig.spec.json && node --test \"dist-test/**/*.spec.js\""
31
- },
32
- "keywords": [],
33
- "author": "",
34
- "license": "ISC",
35
- "description": "",
36
- "publishConfig": {
37
- "access": "public"
38
- },
39
- "devDependencies": {
40
- "@types/express": "^5.0.3",
41
- "@types/geojson": "^7946.0.14",
42
- "@types/node": "^22.10.5",
43
- "rimraf": "^5.0.5",
44
- "typescript": "^5.7.3"
45
- },
46
- "dependencies": {
47
- "@nestjs/common": "^11.0.0",
48
- "@nestjs/core": "^11.0.0",
49
- "@nestjs/mapped-types": "^2.0.6",
50
- "@nestjs/microservices": "^11.0.0",
51
- "@nestjs/swagger": "^11.2.0",
52
- "@sentry/node": "^8.0.0",
53
- "class-transformer": "^0.5.0",
54
- "class-validator": "^0.14.0",
55
- "express": "^5.1.0",
56
- "geojson": "^0.5.0",
57
- "grm-shared-library": "^1.1.101",
58
- "libphonenumber-js": "^1.13.8",
59
- "rxjs": "^7.8.2",
60
- "swagger-ui-express": "^5.0.1",
61
- "@nestjs/config": "^4.0.0"
62
- },
63
- "peerDependencies": {
64
- "@nestjs/common": "^11.0.0",
65
- "@nestjs/core": "^11.0.0",
66
- "@nestjs/microservices": "^11.0.0",
67
- "@sentry/node": "^8.0.0",
68
- "class-transformer": "^0.5.0",
69
- "class-validator": "^0.14.0",
70
- "@nestjs/config": "^4.0.0"
71
- }
72
- }
1
+ {
2
+ "name": "grm-shared-library",
3
+ "version": "1.1.248",
4
+ "main": "dist/cjs/index.js",
5
+ "module": "dist/esm/index.js",
6
+ "types": "dist/types/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/types/index.d.ts",
10
+ "import": "./dist/esm/index.js",
11
+ "require": "./dist/cjs/index.js"
12
+ },
13
+ "./dist/modules/*": {
14
+ "types": "./dist/types/modules/*.d.ts",
15
+ "import": "./dist/esm/modules/*.js",
16
+ "require": "./dist/cjs/modules/*.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist/**/*"
21
+ ],
22
+ "scripts": {
23
+ "clean": "rimraf dist dist-test",
24
+ "build:cjs": "tsc -p tsconfig.cjs.json",
25
+ "build:esm": "tsc -p tsconfig.esm.json",
26
+ "build:types": "tsc -p tsconfig.types.json",
27
+ "build": "npm run clean && npm run build:types && npm run build:cjs && npm run build:esm",
28
+ "prepublishOnly": "npm run build",
29
+ "pretest": "rimraf dist-test",
30
+ "test": "tsc -p tsconfig.spec.json && node --test \"dist-test/**/*.spec.js\""
31
+ },
32
+ "keywords": [],
33
+ "author": "",
34
+ "license": "ISC",
35
+ "description": "",
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "devDependencies": {
40
+ "@types/express": "^5.0.3",
41
+ "@types/geojson": "^7946.0.14",
42
+ "@types/node": "^22.10.5",
43
+ "rimraf": "^5.0.5",
44
+ "typescript": "^5.7.3"
45
+ },
46
+ "dependencies": {
47
+ "@nestjs/common": "^11.0.0",
48
+ "@nestjs/config": "^4.0.0",
49
+ "@nestjs/core": "^11.0.0",
50
+ "@nestjs/mapped-types": "^2.0.6",
51
+ "@nestjs/microservices": "^11.0.0",
52
+ "@nestjs/swagger": "^11.2.0",
53
+ "@sentry/node": "^8.0.0",
54
+ "class-transformer": "^0.5.0",
55
+ "class-validator": "^0.14.0",
56
+ "express": "^5.1.0",
57
+ "geojson": "^0.5.0",
58
+ "grm-shared-library": "^1.1.101",
59
+ "libphonenumber-js": "^1.13.8",
60
+ "rxjs": "^7.8.2",
61
+ "swagger-ui-express": "^5.0.1"
62
+ },
63
+ "peerDependencies": {
64
+ "@nestjs/common": "^11.0.0",
65
+ "@nestjs/config": "^4.0.0",
66
+ "@nestjs/core": "^11.0.0",
67
+ "@nestjs/microservices": "^11.0.0",
68
+ "@sentry/node": "^8.0.0",
69
+ "class-transformer": "^0.5.0",
70
+ "class-validator": "^0.14.0"
71
+ }
72
+ }