clarion-shared-types 1.0.97 → 1.0.98
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/cjs/modules/notification/enums/notification-settings.enums.js +84 -0
- package/dist/cjs/modules/notification/enums/notification-settings.enums.js.map +1 -0
- package/dist/cjs/modules/notification/enums/sms-provider-name.enum.js +5 -0
- package/dist/cjs/modules/notification/enums/sms-provider-name.enum.js.map +1 -1
- package/dist/cjs/modules/notification/index.js +5 -0
- package/dist/cjs/modules/notification/index.js.map +1 -1
- package/dist/cjs/modules/notification/interfaces/organization-notification-settings.dto.js +3 -0
- package/dist/cjs/modules/notification/interfaces/organization-notification-settings.dto.js.map +1 -0
- package/dist/cjs/modules/notification/utils/notification-sender.util.js +96 -0
- package/dist/cjs/modules/notification/utils/notification-sender.util.js.map +1 -0
- package/dist/cjs/modules/permission/enums/permission-actions.enum.js +9 -0
- package/dist/cjs/modules/permission/enums/permission-actions.enum.js.map +1 -1
- package/dist/cjs/modules/permission/enums/permissions-moudule.enum.js +1 -0
- package/dist/cjs/modules/permission/enums/permissions-moudule.enum.js.map +1 -1
- package/dist/esm/modules/notification/enums/notification-settings.enums.js +81 -0
- package/dist/esm/modules/notification/enums/notification-settings.enums.js.map +1 -0
- package/dist/esm/modules/notification/enums/sms-provider-name.enum.js +5 -0
- package/dist/esm/modules/notification/enums/sms-provider-name.enum.js.map +1 -1
- package/dist/esm/modules/notification/index.js +5 -0
- package/dist/esm/modules/notification/index.js.map +1 -1
- package/dist/esm/modules/notification/interfaces/organization-notification-settings.dto.js +2 -0
- package/dist/esm/modules/notification/interfaces/organization-notification-settings.dto.js.map +1 -0
- package/dist/esm/modules/notification/utils/notification-sender.util.js +89 -0
- package/dist/esm/modules/notification/utils/notification-sender.util.js.map +1 -0
- package/dist/esm/modules/permission/enums/permission-actions.enum.js +9 -0
- package/dist/esm/modules/permission/enums/permission-actions.enum.js.map +1 -1
- package/dist/esm/modules/permission/enums/permissions-moudule.enum.js +1 -0
- package/dist/esm/modules/permission/enums/permissions-moudule.enum.js.map +1 -1
- package/dist/types/modules/notification/enums/notification-settings.enums.d.ts +74 -0
- package/dist/types/modules/notification/enums/sms-provider-name.enum.d.ts +6 -1
- package/dist/types/modules/notification/index.d.ts +3 -0
- package/dist/types/modules/notification/interfaces/organization-notification-settings.dto.d.ts +213 -0
- package/dist/types/modules/notification/utils/notification-sender.util.d.ts +44 -0
- package/dist/types/modules/permission/enums/permission-actions.enum.d.ts +4 -1
- package/dist/types/modules/permission/enums/permissions-moudule.enum.d.ts +2 -1
- package/package.json +1 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Organization notification settings enums.
|
|
4
|
+
*
|
|
5
|
+
* MIRRORS grm-shared-library (`modules/notification/enums`), values included. The
|
|
6
|
+
* admin renders and submits these strings and clarion-notification validates the
|
|
7
|
+
* same ones, so any drift is a form the API refuses. `notification-settings.spec.ts`
|
|
8
|
+
* pins the values.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.NotificationBrandingSource = exports.NotificationSenderSource = exports.EmailSenderVerificationMethod = exports.EmailSenderVerificationStatus = exports.NotificationSenderStatus = exports.SmsSenderType = void 0;
|
|
12
|
+
/** What kind of identity an SMS is sent from. Decides how the value is validated. */
|
|
13
|
+
var SmsSenderType;
|
|
14
|
+
(function (SmsSenderType) {
|
|
15
|
+
/** A registered alphanumeric sender name, e.g. `G4S`. At most 11 characters. */
|
|
16
|
+
SmsSenderType["ALPHANUMERIC"] = "ALPHANUMERIC";
|
|
17
|
+
/** An E.164 long number, e.g. `+254711000000`. */
|
|
18
|
+
SmsSenderType["PHONE_NUMBER"] = "PHONE_NUMBER";
|
|
19
|
+
/** A telco short code, e.g. `22384`. */
|
|
20
|
+
SmsSenderType["SHORT_CODE"] = "SHORT_CODE";
|
|
21
|
+
/** A provider-side sender pool (Twilio Messaging Service SID, `MG...`). */
|
|
22
|
+
SmsSenderType["MESSAGING_SERVICE"] = "MESSAGING_SERVICE";
|
|
23
|
+
})(SmsSenderType || (exports.SmsSenderType = SmsSenderType = {}));
|
|
24
|
+
/**
|
|
25
|
+
* Lifecycle of an organization-owned SMS sender. An organization REQUESTS a sender
|
|
26
|
+
* (PENDING) and a platform operator ACTIVATES it once the provider and the telco
|
|
27
|
+
* have registered it. Only ACTIVE senders are ever used to send.
|
|
28
|
+
*/
|
|
29
|
+
var NotificationSenderStatus;
|
|
30
|
+
(function (NotificationSenderStatus) {
|
|
31
|
+
NotificationSenderStatus["PENDING"] = "PENDING";
|
|
32
|
+
NotificationSenderStatus["ACTIVE"] = "ACTIVE";
|
|
33
|
+
NotificationSenderStatus["SUSPENDED"] = "SUSPENDED";
|
|
34
|
+
NotificationSenderStatus["REJECTED"] = "REJECTED";
|
|
35
|
+
})(NotificationSenderStatus || (exports.NotificationSenderStatus = NotificationSenderStatus = {}));
|
|
36
|
+
/**
|
|
37
|
+
* Whether an email provider will accept mail FROM an organization's address.
|
|
38
|
+
* Tracked per provider: an address can be verified in Twilio SendGrid while its
|
|
39
|
+
* domain is unknown to Mailgun. A provider only sends from an address it has
|
|
40
|
+
* VERIFIED; otherwise it falls back to the platform sender.
|
|
41
|
+
*/
|
|
42
|
+
var EmailSenderVerificationStatus;
|
|
43
|
+
(function (EmailSenderVerificationStatus) {
|
|
44
|
+
/** The provider does not know this address or its domain. */
|
|
45
|
+
EmailSenderVerificationStatus["UNVERIFIED"] = "UNVERIFIED";
|
|
46
|
+
/** Verification was started and is waiting on the owner (inbox click or DNS records). */
|
|
47
|
+
EmailSenderVerificationStatus["PENDING"] = "PENDING";
|
|
48
|
+
/** The provider accepts mail from this address. */
|
|
49
|
+
EmailSenderVerificationStatus["VERIFIED"] = "VERIFIED";
|
|
50
|
+
/** The last check could not be completed (provider error). */
|
|
51
|
+
EmailSenderVerificationStatus["FAILED"] = "FAILED";
|
|
52
|
+
})(EmailSenderVerificationStatus || (exports.EmailSenderVerificationStatus = EmailSenderVerificationStatus = {}));
|
|
53
|
+
/** How the provider recognises the address. */
|
|
54
|
+
var EmailSenderVerificationMethod;
|
|
55
|
+
(function (EmailSenderVerificationMethod) {
|
|
56
|
+
/** The exact address was verified on its own (SendGrid Single Sender Verification). */
|
|
57
|
+
EmailSenderVerificationMethod["SINGLE_SENDER"] = "SINGLE_SENDER";
|
|
58
|
+
/** The whole domain is authenticated (SendGrid domain authentication, Mailgun domain). */
|
|
59
|
+
EmailSenderVerificationMethod["DOMAIN"] = "DOMAIN";
|
|
60
|
+
})(EmailSenderVerificationMethod || (exports.EmailSenderVerificationMethod = EmailSenderVerificationMethod = {}));
|
|
61
|
+
/** Whose identity a message actually went out under. */
|
|
62
|
+
var NotificationSenderSource;
|
|
63
|
+
(function (NotificationSenderSource) {
|
|
64
|
+
/** The organization's own verified email address / active SMS sender. */
|
|
65
|
+
NotificationSenderSource["ORGANIZATION"] = "ORGANIZATION";
|
|
66
|
+
/** The platform's default (country-aware) sender. */
|
|
67
|
+
NotificationSenderSource["PLATFORM_DEFAULT"] = "PLATFORM_DEFAULT";
|
|
68
|
+
})(NotificationSenderSource || (exports.NotificationSenderSource = NotificationSenderSource = {}));
|
|
69
|
+
/**
|
|
70
|
+
* Where one resolved branding value came from. Branding resolves field by field,
|
|
71
|
+
* highest precedence first, so a half-filled profile still produces a complete email.
|
|
72
|
+
*/
|
|
73
|
+
var NotificationBrandingSource;
|
|
74
|
+
(function (NotificationBrandingSource) {
|
|
75
|
+
/** The organization's notification settings. */
|
|
76
|
+
NotificationBrandingSource["PROFILE"] = "PROFILE";
|
|
77
|
+
/** The organization record (clarion-organization). */
|
|
78
|
+
NotificationBrandingSource["ORGANIZATION"] = "ORGANIZATION";
|
|
79
|
+
/** The legacy per-app defaults (deprecated). */
|
|
80
|
+
NotificationBrandingSource["APP_DEFAULT"] = "APP_DEFAULT";
|
|
81
|
+
/** The platform's own branding. */
|
|
82
|
+
NotificationBrandingSource["PLATFORM_DEFAULT"] = "PLATFORM_DEFAULT";
|
|
83
|
+
})(NotificationBrandingSource || (exports.NotificationBrandingSource = NotificationBrandingSource = {}));
|
|
84
|
+
//# sourceMappingURL=notification-settings.enums.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-settings.enums.js","sourceRoot":"","sources":["../../../../../src/modules/notification/enums/notification-settings.enums.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAEH,qFAAqF;AACrF,IAAY,aASX;AATD,WAAY,aAAa;IACrB,gFAAgF;IAChF,8CAA6B,CAAA;IAC7B,kDAAkD;IAClD,8CAA6B,CAAA;IAC7B,wCAAwC;IACxC,0CAAyB,CAAA;IACzB,2EAA2E;IAC3E,wDAAuC,CAAA;AAC3C,CAAC,EATW,aAAa,6BAAb,aAAa,QASxB;AAED;;;;GAIG;AACH,IAAY,wBAKX;AALD,WAAY,wBAAwB;IAChC,+CAAmB,CAAA;IACnB,6CAAiB,CAAA;IACjB,mDAAuB,CAAA;IACvB,iDAAqB,CAAA;AACzB,CAAC,EALW,wBAAwB,wCAAxB,wBAAwB,QAKnC;AAED;;;;;GAKG;AACH,IAAY,6BASX;AATD,WAAY,6BAA6B;IACrC,6DAA6D;IAC7D,0DAAyB,CAAA;IACzB,yFAAyF;IACzF,oDAAmB,CAAA;IACnB,mDAAmD;IACnD,sDAAqB,CAAA;IACrB,8DAA8D;IAC9D,kDAAiB,CAAA;AACrB,CAAC,EATW,6BAA6B,6CAA7B,6BAA6B,QASxC;AAED,+CAA+C;AAC/C,IAAY,6BAKX;AALD,WAAY,6BAA6B;IACrC,uFAAuF;IACvF,gEAA+B,CAAA;IAC/B,0FAA0F;IAC1F,kDAAiB,CAAA;AACrB,CAAC,EALW,6BAA6B,6CAA7B,6BAA6B,QAKxC;AAED,wDAAwD;AACxD,IAAY,wBAKX;AALD,WAAY,wBAAwB;IAChC,yEAAyE;IACzE,yDAA6B,CAAA;IAC7B,qDAAqD;IACrD,iEAAqC,CAAA;AACzC,CAAC,EALW,wBAAwB,wCAAxB,wBAAwB,QAKnC;AAED;;;GAGG;AACH,IAAY,0BASX;AATD,WAAY,0BAA0B;IAClC,gDAAgD;IAChD,iDAAmB,CAAA;IACnB,sDAAsD;IACtD,2DAA6B,CAAA;IAC7B,gDAAgD;IAChD,yDAA2B,CAAA;IAC3B,mCAAmC;IACnC,mEAAqC,CAAA;AACzC,CAAC,EATW,0BAA0B,0CAA1B,0BAA0B,QASrC"}
|
|
@@ -4,11 +4,16 @@ exports.SmsProviderName = void 0;
|
|
|
4
4
|
/**
|
|
5
5
|
* Identifiers for the SMS providers the notification service can dispatch through.
|
|
6
6
|
* Provider order/fallback is configuration-driven; new providers can be appended.
|
|
7
|
+
*
|
|
8
|
+
* A code here only RESERVES the name. Whether a provider can actually be used is
|
|
9
|
+
* answered by the notification service's provider catalogue
|
|
10
|
+
* (`SmsProviderDescriptor`), which lists only providers with a registered adapter.
|
|
7
11
|
*/
|
|
8
12
|
var SmsProviderName;
|
|
9
13
|
(function (SmsProviderName) {
|
|
10
14
|
SmsProviderName["TWILIO"] = "twilio";
|
|
11
15
|
SmsProviderName["UWAZII"] = "uwazii";
|
|
12
16
|
SmsProviderName["AFRICASTALKING"] = "africastalking";
|
|
17
|
+
SmsProviderName["CELCOM"] = "celcom";
|
|
13
18
|
})(SmsProviderName || (exports.SmsProviderName = SmsProviderName = {}));
|
|
14
19
|
//# sourceMappingURL=sms-provider-name.enum.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sms-provider-name.enum.js","sourceRoot":"","sources":["../../../../../src/modules/notification/enums/sms-provider-name.enum.ts"],"names":[],"mappings":";;;AAAA
|
|
1
|
+
{"version":3,"file":"sms-provider-name.enum.js","sourceRoot":"","sources":["../../../../../src/modules/notification/enums/sms-provider-name.enum.ts"],"names":[],"mappings":";;;AAAA;;;;;;;GAOG;AACH,IAAY,eAKX;AALD,WAAY,eAAe;IACvB,oCAAiB,CAAA;IACjB,oCAAiB,CAAA;IACjB,oDAAiC,CAAA;IACjC,oCAAiB,CAAA;AACrB,CAAC,EALW,eAAe,+BAAf,eAAe,QAK1B"}
|
|
@@ -20,10 +20,15 @@ __exportStar(require("./enums/sms-provider-name.enum"), exports);
|
|
|
20
20
|
__exportStar(require("./enums/email-provider-name.enum"), exports);
|
|
21
21
|
__exportStar(require("./enums/notification-overall-status.enum"), exports);
|
|
22
22
|
__exportStar(require("./enums/provider-failure-reason.enum"), exports);
|
|
23
|
+
__exportStar(require("./enums/notification-settings.enums"), exports);
|
|
23
24
|
// Result/interface contracts (display-safe)
|
|
24
25
|
__exportStar(require("./interfaces/provider-attempt"), exports);
|
|
25
26
|
__exportStar(require("./interfaces/per-channel-result"), exports);
|
|
26
27
|
__exportStar(require("./interfaces/sms-send-result"), exports);
|
|
27
28
|
__exportStar(require("./interfaces/email-send-result"), exports);
|
|
28
29
|
__exportStar(require("./interfaces/notification-dispatch-result"), exports);
|
|
30
|
+
// Organization notification settings (branding + sender identity)
|
|
31
|
+
__exportStar(require("./interfaces/organization-notification-settings.dto"), exports);
|
|
32
|
+
// Utilities
|
|
33
|
+
__exportStar(require("./utils/notification-sender.util"), exports);
|
|
29
34
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/notification/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,QAAQ;AACR,oEAAkD;AAClD,iEAA+C;AAC/C,mEAAiD;AACjD,2EAAyD;AACzD,uEAAqD;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/notification/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,QAAQ;AACR,oEAAkD;AAClD,iEAA+C;AAC/C,mEAAiD;AACjD,2EAAyD;AACzD,uEAAqD;AACrD,sEAAoD;AAEpD,4CAA4C;AAC5C,gEAA8C;AAC9C,kEAAgD;AAChD,+DAA6C;AAC7C,iEAA+C;AAC/C,4EAA0D;AAE1D,kEAAkE;AAClE,sFAAoE;AAEpE,YAAY;AACZ,mEAAiD"}
|
package/dist/cjs/modules/notification/interfaces/organization-notification-settings.dto.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization-notification-settings.dto.js","sourceRoot":"","sources":["../../../../../src/modules/notification/interfaces/organization-notification-settings.dto.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MIN_ACCENT_COLOUR_CONTRAST = exports.MIN_PRIMARY_COLOUR_CONTRAST = exports.MAX_SMS_SENDERS_PER_ORGANIZATION = exports.MAX_EMAIL_SENDERS_PER_ORGANIZATION = exports.SMS_SENDER_ID_HINTS = exports.SMS_SENDER_ID_PATTERNS = exports.BRAND_COLOUR_PATTERN = void 0;
|
|
4
|
+
exports.validateSmsSenderId = validateSmsSenderId;
|
|
5
|
+
exports.emailDomainOf = emailDomainOf;
|
|
6
|
+
exports.contrastRatioWithWhite = contrastRatioWithWhite;
|
|
7
|
+
exports.darkenHexColour = darkenHexColour;
|
|
8
|
+
const notification_settings_enums_1 = require("../enums/notification-settings.enums");
|
|
9
|
+
/**
|
|
10
|
+
* MIRRORS grm-shared-library (`modules/notification/constants` and `utils`),
|
|
11
|
+
* patterns and thresholds included. The settings form validates with these and
|
|
12
|
+
* clarion-notification validates with the originals, so they must agree to the
|
|
13
|
+
* character: a form that accepts what the API refuses is worse than no check.
|
|
14
|
+
*/
|
|
15
|
+
/** `#RRGGBB`. The only colour format accepted, because it is inlined into email CSS. */
|
|
16
|
+
exports.BRAND_COLOUR_PATTERN = /^#[0-9a-fA-F]{6}$/;
|
|
17
|
+
/**
|
|
18
|
+
* What a sender value must look like, per type. ALPHANUMERIC follows the GSM rule
|
|
19
|
+
* every supported provider enforces: 3-11 characters, at least one letter (an
|
|
20
|
+
* all-digit "name" is a number, and telcos reject it as spoofing).
|
|
21
|
+
*/
|
|
22
|
+
exports.SMS_SENDER_ID_PATTERNS = Object.freeze({
|
|
23
|
+
[notification_settings_enums_1.SmsSenderType.ALPHANUMERIC]: /^(?=.*[A-Za-z])[A-Za-z0-9 _.&-]{3,11}$/,
|
|
24
|
+
[notification_settings_enums_1.SmsSenderType.PHONE_NUMBER]: /^\+[1-9]\d{6,14}$/,
|
|
25
|
+
[notification_settings_enums_1.SmsSenderType.SHORT_CODE]: /^\d{3,8}$/,
|
|
26
|
+
[notification_settings_enums_1.SmsSenderType.MESSAGING_SERVICE]: /^MG[0-9a-fA-F]{32}$/,
|
|
27
|
+
});
|
|
28
|
+
/** Human-readable form of {@link SMS_SENDER_ID_PATTERNS}, for validation messages and form hints. */
|
|
29
|
+
exports.SMS_SENDER_ID_HINTS = Object.freeze({
|
|
30
|
+
[notification_settings_enums_1.SmsSenderType.ALPHANUMERIC]: '3-11 characters (letters, digits, space, _ . & -) with at least one letter, e.g. G4S',
|
|
31
|
+
[notification_settings_enums_1.SmsSenderType.PHONE_NUMBER]: 'an E.164 number, e.g. +254711000000',
|
|
32
|
+
[notification_settings_enums_1.SmsSenderType.SHORT_CODE]: '3-8 digits, e.g. 22384',
|
|
33
|
+
[notification_settings_enums_1.SmsSenderType.MESSAGING_SERVICE]: 'a Twilio Messaging Service SID (MG followed by 32 hex characters)',
|
|
34
|
+
});
|
|
35
|
+
/** Upper bounds that keep one organization from turning its settings into a list to page through. */
|
|
36
|
+
exports.MAX_EMAIL_SENDERS_PER_ORGANIZATION = 10;
|
|
37
|
+
exports.MAX_SMS_SENDERS_PER_ORGANIZATION = 30;
|
|
38
|
+
/** Large text and UI components (WCAG 1.4.11): buttons and links in the primary colour. */
|
|
39
|
+
exports.MIN_PRIMARY_COLOUR_CONTRAST = 3;
|
|
40
|
+
/** Body-size white text sits on the accent colour (WCAG 1.4.3). */
|
|
41
|
+
exports.MIN_ACCENT_COLOUR_CONTRAST = 4.5;
|
|
42
|
+
/**
|
|
43
|
+
* Validates an SMS sender value against its declared type.
|
|
44
|
+
* Returns null when valid, otherwise a message fit to show an operator.
|
|
45
|
+
*/
|
|
46
|
+
function validateSmsSenderId(senderType, senderId) {
|
|
47
|
+
const pattern = exports.SMS_SENDER_ID_PATTERNS[senderType];
|
|
48
|
+
if (!pattern)
|
|
49
|
+
return `Unsupported sender type: ${senderType}`;
|
|
50
|
+
const value = (senderId !== null && senderId !== void 0 ? senderId : '').trim();
|
|
51
|
+
if (!value)
|
|
52
|
+
return 'Sender ID is required';
|
|
53
|
+
return pattern.test(value) ? null : `A ${senderType} sender must be ${exports.SMS_SENDER_ID_HINTS[senderType]}`;
|
|
54
|
+
}
|
|
55
|
+
/** The domain part of an email address, lower-cased. Null when there is none. */
|
|
56
|
+
function emailDomainOf(address) {
|
|
57
|
+
const value = (address !== null && address !== void 0 ? address : '').trim().toLowerCase();
|
|
58
|
+
const at = value.lastIndexOf('@');
|
|
59
|
+
if (at <= 0 || at === value.length - 1)
|
|
60
|
+
return null;
|
|
61
|
+
return value.slice(at + 1);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* WCAG contrast ratio of a `#RRGGBB` colour against white, from 1 (white) to 21
|
|
65
|
+
* (black). The email templates put WHITE text on the primary colour (buttons) and
|
|
66
|
+
* on the accent colour (header banner, footer), so a pale brand colour produces
|
|
67
|
+
* an email nobody can read. Returns 0 for anything that is not a hex colour.
|
|
68
|
+
*/
|
|
69
|
+
function contrastRatioWithWhite(hex) {
|
|
70
|
+
const match = /^#([0-9a-fA-F]{6})$/.exec((hex !== null && hex !== void 0 ? hex : '').trim());
|
|
71
|
+
if (!match)
|
|
72
|
+
return 0;
|
|
73
|
+
const [r, g, b] = [0, 2, 4].map(offset => {
|
|
74
|
+
const channel = parseInt(match[1].slice(offset, offset + 2), 16) / 255;
|
|
75
|
+
return channel <= 0.03928 ? channel / 12.92 : Math.pow((channel + 0.055) / 1.055, 2.4);
|
|
76
|
+
});
|
|
77
|
+
const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
78
|
+
return Math.round((1.05 / (luminance + 0.05)) * 100) / 100;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Darkens a `#RRGGBB` colour by a fraction (0-1). Used to derive the hover/pressed
|
|
82
|
+
* shade of a brand colour so an organization only has to choose one.
|
|
83
|
+
* Returns the input unchanged when it is not a valid hex colour.
|
|
84
|
+
*/
|
|
85
|
+
function darkenHexColour(hex, fraction = 0.15) {
|
|
86
|
+
const match = /^#([0-9a-fA-F]{6})$/.exec((hex !== null && hex !== void 0 ? hex : '').trim());
|
|
87
|
+
if (!match)
|
|
88
|
+
return hex;
|
|
89
|
+
const clamped = Math.min(Math.max(fraction, 0), 1);
|
|
90
|
+
const channels = [0, 2, 4].map(offset => {
|
|
91
|
+
const channel = parseInt(match[1].slice(offset, offset + 2), 16);
|
|
92
|
+
return Math.round(channel * (1 - clamped)).toString(16).padStart(2, '0');
|
|
93
|
+
});
|
|
94
|
+
return `#${channels.join('')}`;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=notification-sender.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-sender.util.js","sourceRoot":"","sources":["../../../../../src/modules/notification/utils/notification-sender.util.ts"],"names":[],"mappings":"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"}
|
|
@@ -109,5 +109,14 @@ var PermissionActions;
|
|
|
109
109
|
PermissionActions["READ_SUPPORT_REPORT"] = "read:support-report";
|
|
110
110
|
PermissionActions["READ_SUPPORT_SYNC"] = "read:support-sync";
|
|
111
111
|
PermissionActions["MANAGE_SUPPORT_SYNC"] = "manage:support-sync";
|
|
112
|
+
// Module: Notification
|
|
113
|
+
// An organization's notification settings (clarion-notification): how its
|
|
114
|
+
// emails are branded, the address they are sent from, and the sender ID its
|
|
115
|
+
// SMS arrive under. Mirrors grm-shared-library.
|
|
116
|
+
PermissionActions["READ_NOTIFICATION_SETTINGS"] = "read:notification-settings";
|
|
117
|
+
PermissionActions["MANAGE_NOTIFICATION_SETTINGS"] = "manage:notification-settings";
|
|
118
|
+
// Confirming that an SMS sender ID really is registered with the provider.
|
|
119
|
+
// Granted to NO role on the backend: only Super-Admin ('*') passes it.
|
|
120
|
+
PermissionActions["APPROVE_NOTIFICATION_SENDER"] = "approve:notification-sender";
|
|
112
121
|
})(PermissionActions || (exports.PermissionActions = PermissionActions = {}));
|
|
113
122
|
//# sourceMappingURL=permission-actions.enum.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permission-actions.enum.js","sourceRoot":"","sources":["../../../../../src/modules/permission/enums/permission-actions.enum.ts"],"names":[],"mappings":";;;AAAA,IAAY,
|
|
1
|
+
{"version":3,"file":"permission-actions.enum.js","sourceRoot":"","sources":["../../../../../src/modules/permission/enums/permission-actions.enum.ts"],"names":[],"mappings":";;;AAAA,IAAY,iBA6HX;AA7HD,WAAY,iBAAiB;IACzB,uBAAuB;IACvB,gEAA2C,CAAA;IAC3C,4DAAuC,CAAA;IACvC,gEAA2C,CAAA;IAC3C,gEAA2C,CAAA;IAE3C,kBAAkB;IAClB,sDAAiC,CAAA;IACjC,kDAA6B,CAAA;IAC7B,sDAAiC,CAAA;IACjC,sDAAiC,CAAA;IACjC,wEAAwE;IACxE,mEAAmE;IACnE,oEAA+C,CAAA;IAC/C,0EAAqD,CAAA;IACrD,wEAAmD,CAAA;IACnD,wEAAmD,CAAA;IACnD,wEAAmD,CAAA;IACnD,2EAA2E;IAC3E,4EAA4E;IAC5E,qEAAqE;IACrE,uDAAuD;IACvD,wEAAmD,CAAA;IACnD,4EAAuD,CAAA;IAEvD,wBAAwB;IACxB,oEAA+C,CAAA;IAC/C,gEAA2C,CAAA;IAC3C,oEAA+C,CAAA;IAC/C,oEAA+C,CAAA;IAE/C,eAAe;IACf,gDAA2B,CAAA;IAC3B,4CAAuB,CAAA;IACvB,gDAA2B,CAAA;IAC3B,gDAA2B,CAAA;IAE3B,eAAe;IACf,gDAA2B,CAAA;IAC3B,4CAAuB,CAAA;IACvB,gDAA2B,CAAA;IAC3B,gDAA2B,CAAA;IAE3B,mBAAmB;IACnB,wDAAmC,CAAA;IACnC,oDAA+B,CAAA;IAC/B,wDAAmC,CAAA;IACnC,wDAAmC,CAAA;IACnC,oFAA+D,CAAA;IAC/D,gFAA2D,CAAA;IAC3D,oFAA+D,CAAA;IAC/D,oFAA+D,CAAA;IAE/D,uBAAuB;IACvB,kEAA6C,CAAA;IAC7C,8DAAyC,CAAA;IACzC,kEAA6C,CAAA;IAC7C,kEAA6C,CAAA;IAE7C,4EAA4E;IAC5E,wEAAwE;IACxE,6EAA6E;IAC7E,qDAAqD;IACrD,gGAA2E,CAAA;IAC3E,4FAAuE,CAAA;IACvE,gGAA2E,CAAA;IAC3E,gGAA2E,CAAA;IAC3E,sFAAiE,CAAA;IACjE,kFAA6D,CAAA;IAC7D,sFAAiE,CAAA;IACjE,sFAAiE,CAAA;IACjE,sEAAiD,CAAA;IACjD,oEAA+C,CAAA;IAC/C,0EAAqD,CAAA;IACrD,8EAAyD,CAAA;IAEzD,kBAAkB;IAClB,EAAE;IACF,2EAA2E;IAC3E,0EAA0E;IAC1E,uEAAuE;IACvE,+BAA+B;IAC/B,oEAA+C,CAAA;IAC/C,gEAA2C,CAAA;IAC3C,oEAA+C,CAAA;IAC/C,oEAA+C,CAAA;IAC/C,kEAA6C,CAAA;IAC7C,gEAA2C,CAAA;IAC3C,kFAA6D,CAAA;IAC7D,sFAAiE,CAAA;IACjE,kEAA6C,CAAA;IAC7C,oEAA+C,CAAA;IAC/C,yEAAyE;IACzE,gEAA2C,CAAA;IAC3C;;;OAGG;IACH,8DAAyC,CAAA;IACzC,mFAAmF;IACnF,wEAAmD,CAAA;IACnD,oEAA+C,CAAA;IAC/C,gFAAgF;IAChF,sEAAiD,CAAA;IACjD,wEAAmD,CAAA;IACnD,0EAAqD,CAAA;IACrD,0EAAqD,CAAA;IACrD,kEAA6C,CAAA;IAC7C,gEAA2C,CAAA;IAC3C,8DAAyC,CAAA;IACzC,kFAA6D,CAAA;IAC7D,gEAA2C,CAAA;IAC3C,4DAAuC,CAAA;IACvC,gEAA2C,CAAA;IAE3C,uBAAuB;IACvB,0EAA0E;IAC1E,4EAA4E;IAC5E,gDAAgD;IAChD,8EAAyD,CAAA;IACzD,kFAA6D,CAAA;IAC7D,2EAA2E;IAC3E,uEAAuE;IACvE,gFAA2D,CAAA;AAC/D,CAAC,EA7HW,iBAAiB,iCAAjB,iBAAiB,QA6H5B"}
|
|
@@ -13,5 +13,6 @@ var PermissionsModule;
|
|
|
13
13
|
PermissionsModule["RESPONSE_UNIT"] = "Response Unit";
|
|
14
14
|
PermissionsModule["TRACKING"] = "Tracking";
|
|
15
15
|
PermissionsModule["SUPPORT"] = "Support";
|
|
16
|
+
PermissionsModule["NOTIFICATION"] = "Notification";
|
|
16
17
|
})(PermissionsModule || (exports.PermissionsModule = PermissionsModule = {}));
|
|
17
18
|
//# sourceMappingURL=permissions-moudule.enum.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions-moudule.enum.js","sourceRoot":"","sources":["../../../../../src/modules/permission/enums/permissions-moudule.enum.ts"],"names":[],"mappings":";;;AAAA,IAAY,
|
|
1
|
+
{"version":3,"file":"permissions-moudule.enum.js","sourceRoot":"","sources":["../../../../../src/modules/permission/enums/permissions-moudule.enum.ts"],"names":[],"mappings":";;;AAAA,IAAY,iBAYX;AAZD,WAAY,iBAAiB;IACzB,kDAA6B,CAAA;IAC7B,wCAAmB,CAAA;IACnB,sDAAiC,CAAA;IACjC,kCAAa,CAAA;IACb,kCAAa,CAAA;IACb,kCAAa,CAAA;IACb,2CAAsB,CAAA;IACtB,oDAA+B,CAAA;IAC/B,0CAAqB,CAAA;IACrB,wCAAmB,CAAA;IACnB,kDAA6B,CAAA;AACjC,CAAC,EAZW,iBAAiB,iCAAjB,iBAAiB,QAY5B"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Organization notification settings enums.
|
|
3
|
+
*
|
|
4
|
+
* MIRRORS grm-shared-library (`modules/notification/enums`), values included. The
|
|
5
|
+
* admin renders and submits these strings and clarion-notification validates the
|
|
6
|
+
* same ones, so any drift is a form the API refuses. `notification-settings.spec.ts`
|
|
7
|
+
* pins the values.
|
|
8
|
+
*/
|
|
9
|
+
/** What kind of identity an SMS is sent from. Decides how the value is validated. */
|
|
10
|
+
export var SmsSenderType;
|
|
11
|
+
(function (SmsSenderType) {
|
|
12
|
+
/** A registered alphanumeric sender name, e.g. `G4S`. At most 11 characters. */
|
|
13
|
+
SmsSenderType["ALPHANUMERIC"] = "ALPHANUMERIC";
|
|
14
|
+
/** An E.164 long number, e.g. `+254711000000`. */
|
|
15
|
+
SmsSenderType["PHONE_NUMBER"] = "PHONE_NUMBER";
|
|
16
|
+
/** A telco short code, e.g. `22384`. */
|
|
17
|
+
SmsSenderType["SHORT_CODE"] = "SHORT_CODE";
|
|
18
|
+
/** A provider-side sender pool (Twilio Messaging Service SID, `MG...`). */
|
|
19
|
+
SmsSenderType["MESSAGING_SERVICE"] = "MESSAGING_SERVICE";
|
|
20
|
+
})(SmsSenderType || (SmsSenderType = {}));
|
|
21
|
+
/**
|
|
22
|
+
* Lifecycle of an organization-owned SMS sender. An organization REQUESTS a sender
|
|
23
|
+
* (PENDING) and a platform operator ACTIVATES it once the provider and the telco
|
|
24
|
+
* have registered it. Only ACTIVE senders are ever used to send.
|
|
25
|
+
*/
|
|
26
|
+
export var NotificationSenderStatus;
|
|
27
|
+
(function (NotificationSenderStatus) {
|
|
28
|
+
NotificationSenderStatus["PENDING"] = "PENDING";
|
|
29
|
+
NotificationSenderStatus["ACTIVE"] = "ACTIVE";
|
|
30
|
+
NotificationSenderStatus["SUSPENDED"] = "SUSPENDED";
|
|
31
|
+
NotificationSenderStatus["REJECTED"] = "REJECTED";
|
|
32
|
+
})(NotificationSenderStatus || (NotificationSenderStatus = {}));
|
|
33
|
+
/**
|
|
34
|
+
* Whether an email provider will accept mail FROM an organization's address.
|
|
35
|
+
* Tracked per provider: an address can be verified in Twilio SendGrid while its
|
|
36
|
+
* domain is unknown to Mailgun. A provider only sends from an address it has
|
|
37
|
+
* VERIFIED; otherwise it falls back to the platform sender.
|
|
38
|
+
*/
|
|
39
|
+
export var EmailSenderVerificationStatus;
|
|
40
|
+
(function (EmailSenderVerificationStatus) {
|
|
41
|
+
/** The provider does not know this address or its domain. */
|
|
42
|
+
EmailSenderVerificationStatus["UNVERIFIED"] = "UNVERIFIED";
|
|
43
|
+
/** Verification was started and is waiting on the owner (inbox click or DNS records). */
|
|
44
|
+
EmailSenderVerificationStatus["PENDING"] = "PENDING";
|
|
45
|
+
/** The provider accepts mail from this address. */
|
|
46
|
+
EmailSenderVerificationStatus["VERIFIED"] = "VERIFIED";
|
|
47
|
+
/** The last check could not be completed (provider error). */
|
|
48
|
+
EmailSenderVerificationStatus["FAILED"] = "FAILED";
|
|
49
|
+
})(EmailSenderVerificationStatus || (EmailSenderVerificationStatus = {}));
|
|
50
|
+
/** How the provider recognises the address. */
|
|
51
|
+
export var EmailSenderVerificationMethod;
|
|
52
|
+
(function (EmailSenderVerificationMethod) {
|
|
53
|
+
/** The exact address was verified on its own (SendGrid Single Sender Verification). */
|
|
54
|
+
EmailSenderVerificationMethod["SINGLE_SENDER"] = "SINGLE_SENDER";
|
|
55
|
+
/** The whole domain is authenticated (SendGrid domain authentication, Mailgun domain). */
|
|
56
|
+
EmailSenderVerificationMethod["DOMAIN"] = "DOMAIN";
|
|
57
|
+
})(EmailSenderVerificationMethod || (EmailSenderVerificationMethod = {}));
|
|
58
|
+
/** Whose identity a message actually went out under. */
|
|
59
|
+
export var NotificationSenderSource;
|
|
60
|
+
(function (NotificationSenderSource) {
|
|
61
|
+
/** The organization's own verified email address / active SMS sender. */
|
|
62
|
+
NotificationSenderSource["ORGANIZATION"] = "ORGANIZATION";
|
|
63
|
+
/** The platform's default (country-aware) sender. */
|
|
64
|
+
NotificationSenderSource["PLATFORM_DEFAULT"] = "PLATFORM_DEFAULT";
|
|
65
|
+
})(NotificationSenderSource || (NotificationSenderSource = {}));
|
|
66
|
+
/**
|
|
67
|
+
* Where one resolved branding value came from. Branding resolves field by field,
|
|
68
|
+
* highest precedence first, so a half-filled profile still produces a complete email.
|
|
69
|
+
*/
|
|
70
|
+
export var NotificationBrandingSource;
|
|
71
|
+
(function (NotificationBrandingSource) {
|
|
72
|
+
/** The organization's notification settings. */
|
|
73
|
+
NotificationBrandingSource["PROFILE"] = "PROFILE";
|
|
74
|
+
/** The organization record (clarion-organization). */
|
|
75
|
+
NotificationBrandingSource["ORGANIZATION"] = "ORGANIZATION";
|
|
76
|
+
/** The legacy per-app defaults (deprecated). */
|
|
77
|
+
NotificationBrandingSource["APP_DEFAULT"] = "APP_DEFAULT";
|
|
78
|
+
/** The platform's own branding. */
|
|
79
|
+
NotificationBrandingSource["PLATFORM_DEFAULT"] = "PLATFORM_DEFAULT";
|
|
80
|
+
})(NotificationBrandingSource || (NotificationBrandingSource = {}));
|
|
81
|
+
//# sourceMappingURL=notification-settings.enums.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-settings.enums.js","sourceRoot":"","sources":["../../../../../src/modules/notification/enums/notification-settings.enums.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,qFAAqF;AACrF,MAAM,CAAN,IAAY,aASX;AATD,WAAY,aAAa;IACrB,gFAAgF;IAChF,8CAA6B,CAAA;IAC7B,kDAAkD;IAClD,8CAA6B,CAAA;IAC7B,wCAAwC;IACxC,0CAAyB,CAAA;IACzB,2EAA2E;IAC3E,wDAAuC,CAAA;AAC3C,CAAC,EATW,aAAa,KAAb,aAAa,QASxB;AAED;;;;GAIG;AACH,MAAM,CAAN,IAAY,wBAKX;AALD,WAAY,wBAAwB;IAChC,+CAAmB,CAAA;IACnB,6CAAiB,CAAA;IACjB,mDAAuB,CAAA;IACvB,iDAAqB,CAAA;AACzB,CAAC,EALW,wBAAwB,KAAxB,wBAAwB,QAKnC;AAED;;;;;GAKG;AACH,MAAM,CAAN,IAAY,6BASX;AATD,WAAY,6BAA6B;IACrC,6DAA6D;IAC7D,0DAAyB,CAAA;IACzB,yFAAyF;IACzF,oDAAmB,CAAA;IACnB,mDAAmD;IACnD,sDAAqB,CAAA;IACrB,8DAA8D;IAC9D,kDAAiB,CAAA;AACrB,CAAC,EATW,6BAA6B,KAA7B,6BAA6B,QASxC;AAED,+CAA+C;AAC/C,MAAM,CAAN,IAAY,6BAKX;AALD,WAAY,6BAA6B;IACrC,uFAAuF;IACvF,gEAA+B,CAAA;IAC/B,0FAA0F;IAC1F,kDAAiB,CAAA;AACrB,CAAC,EALW,6BAA6B,KAA7B,6BAA6B,QAKxC;AAED,wDAAwD;AACxD,MAAM,CAAN,IAAY,wBAKX;AALD,WAAY,wBAAwB;IAChC,yEAAyE;IACzE,yDAA6B,CAAA;IAC7B,qDAAqD;IACrD,iEAAqC,CAAA;AACzC,CAAC,EALW,wBAAwB,KAAxB,wBAAwB,QAKnC;AAED;;;GAGG;AACH,MAAM,CAAN,IAAY,0BASX;AATD,WAAY,0BAA0B;IAClC,gDAAgD;IAChD,iDAAmB,CAAA;IACnB,sDAAsD;IACtD,2DAA6B,CAAA;IAC7B,gDAAgD;IAChD,yDAA2B,CAAA;IAC3B,mCAAmC;IACnC,mEAAqC,CAAA;AACzC,CAAC,EATW,0BAA0B,KAA1B,0BAA0B,QASrC"}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Identifiers for the SMS providers the notification service can dispatch through.
|
|
3
3
|
* Provider order/fallback is configuration-driven; new providers can be appended.
|
|
4
|
+
*
|
|
5
|
+
* A code here only RESERVES the name. Whether a provider can actually be used is
|
|
6
|
+
* answered by the notification service's provider catalogue
|
|
7
|
+
* (`SmsProviderDescriptor`), which lists only providers with a registered adapter.
|
|
4
8
|
*/
|
|
5
9
|
export var SmsProviderName;
|
|
6
10
|
(function (SmsProviderName) {
|
|
7
11
|
SmsProviderName["TWILIO"] = "twilio";
|
|
8
12
|
SmsProviderName["UWAZII"] = "uwazii";
|
|
9
13
|
SmsProviderName["AFRICASTALKING"] = "africastalking";
|
|
14
|
+
SmsProviderName["CELCOM"] = "celcom";
|
|
10
15
|
})(SmsProviderName || (SmsProviderName = {}));
|
|
11
16
|
//# sourceMappingURL=sms-provider-name.enum.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sms-provider-name.enum.js","sourceRoot":"","sources":["../../../../../src/modules/notification/enums/sms-provider-name.enum.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sms-provider-name.enum.js","sourceRoot":"","sources":["../../../../../src/modules/notification/enums/sms-provider-name.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAN,IAAY,eAKX;AALD,WAAY,eAAe;IACvB,oCAAiB,CAAA;IACjB,oCAAiB,CAAA;IACjB,oDAAiC,CAAA;IACjC,oCAAiB,CAAA;AACrB,CAAC,EALW,eAAe,KAAf,eAAe,QAK1B"}
|
|
@@ -4,10 +4,15 @@ export * from './enums/sms-provider-name.enum';
|
|
|
4
4
|
export * from './enums/email-provider-name.enum';
|
|
5
5
|
export * from './enums/notification-overall-status.enum';
|
|
6
6
|
export * from './enums/provider-failure-reason.enum';
|
|
7
|
+
export * from './enums/notification-settings.enums';
|
|
7
8
|
// Result/interface contracts (display-safe)
|
|
8
9
|
export * from './interfaces/provider-attempt';
|
|
9
10
|
export * from './interfaces/per-channel-result';
|
|
10
11
|
export * from './interfaces/sms-send-result';
|
|
11
12
|
export * from './interfaces/email-send-result';
|
|
12
13
|
export * from './interfaces/notification-dispatch-result';
|
|
14
|
+
// Organization notification settings (branding + sender identity)
|
|
15
|
+
export * from './interfaces/organization-notification-settings.dto';
|
|
16
|
+
// Utilities
|
|
17
|
+
export * from './utils/notification-sender.util';
|
|
13
18
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/notification/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/notification/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,qCAAqC,CAAC;AAEpD,4CAA4C;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2CAA2C,CAAC;AAE1D,kEAAkE;AAClE,cAAc,qDAAqD,CAAC;AAEpE,YAAY;AACZ,cAAc,kCAAkC,CAAC"}
|
package/dist/esm/modules/notification/interfaces/organization-notification-settings.dto.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization-notification-settings.dto.js","sourceRoot":"","sources":["../../../../../src/modules/notification/interfaces/organization-notification-settings.dto.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { SmsSenderType } from '../enums/notification-settings.enums';
|
|
2
|
+
/**
|
|
3
|
+
* MIRRORS grm-shared-library (`modules/notification/constants` and `utils`),
|
|
4
|
+
* patterns and thresholds included. The settings form validates with these and
|
|
5
|
+
* clarion-notification validates with the originals, so they must agree to the
|
|
6
|
+
* character: a form that accepts what the API refuses is worse than no check.
|
|
7
|
+
*/
|
|
8
|
+
/** `#RRGGBB`. The only colour format accepted, because it is inlined into email CSS. */
|
|
9
|
+
export const BRAND_COLOUR_PATTERN = /^#[0-9a-fA-F]{6}$/;
|
|
10
|
+
/**
|
|
11
|
+
* What a sender value must look like, per type. ALPHANUMERIC follows the GSM rule
|
|
12
|
+
* every supported provider enforces: 3-11 characters, at least one letter (an
|
|
13
|
+
* all-digit "name" is a number, and telcos reject it as spoofing).
|
|
14
|
+
*/
|
|
15
|
+
export const SMS_SENDER_ID_PATTERNS = Object.freeze({
|
|
16
|
+
[SmsSenderType.ALPHANUMERIC]: /^(?=.*[A-Za-z])[A-Za-z0-9 _.&-]{3,11}$/,
|
|
17
|
+
[SmsSenderType.PHONE_NUMBER]: /^\+[1-9]\d{6,14}$/,
|
|
18
|
+
[SmsSenderType.SHORT_CODE]: /^\d{3,8}$/,
|
|
19
|
+
[SmsSenderType.MESSAGING_SERVICE]: /^MG[0-9a-fA-F]{32}$/,
|
|
20
|
+
});
|
|
21
|
+
/** Human-readable form of {@link SMS_SENDER_ID_PATTERNS}, for validation messages and form hints. */
|
|
22
|
+
export const SMS_SENDER_ID_HINTS = Object.freeze({
|
|
23
|
+
[SmsSenderType.ALPHANUMERIC]: '3-11 characters (letters, digits, space, _ . & -) with at least one letter, e.g. G4S',
|
|
24
|
+
[SmsSenderType.PHONE_NUMBER]: 'an E.164 number, e.g. +254711000000',
|
|
25
|
+
[SmsSenderType.SHORT_CODE]: '3-8 digits, e.g. 22384',
|
|
26
|
+
[SmsSenderType.MESSAGING_SERVICE]: 'a Twilio Messaging Service SID (MG followed by 32 hex characters)',
|
|
27
|
+
});
|
|
28
|
+
/** Upper bounds that keep one organization from turning its settings into a list to page through. */
|
|
29
|
+
export const MAX_EMAIL_SENDERS_PER_ORGANIZATION = 10;
|
|
30
|
+
export const MAX_SMS_SENDERS_PER_ORGANIZATION = 30;
|
|
31
|
+
/** Large text and UI components (WCAG 1.4.11): buttons and links in the primary colour. */
|
|
32
|
+
export const MIN_PRIMARY_COLOUR_CONTRAST = 3;
|
|
33
|
+
/** Body-size white text sits on the accent colour (WCAG 1.4.3). */
|
|
34
|
+
export const MIN_ACCENT_COLOUR_CONTRAST = 4.5;
|
|
35
|
+
/**
|
|
36
|
+
* Validates an SMS sender value against its declared type.
|
|
37
|
+
* Returns null when valid, otherwise a message fit to show an operator.
|
|
38
|
+
*/
|
|
39
|
+
export function validateSmsSenderId(senderType, senderId) {
|
|
40
|
+
const pattern = SMS_SENDER_ID_PATTERNS[senderType];
|
|
41
|
+
if (!pattern)
|
|
42
|
+
return `Unsupported sender type: ${senderType}`;
|
|
43
|
+
const value = (senderId !== null && senderId !== void 0 ? senderId : '').trim();
|
|
44
|
+
if (!value)
|
|
45
|
+
return 'Sender ID is required';
|
|
46
|
+
return pattern.test(value) ? null : `A ${senderType} sender must be ${SMS_SENDER_ID_HINTS[senderType]}`;
|
|
47
|
+
}
|
|
48
|
+
/** The domain part of an email address, lower-cased. Null when there is none. */
|
|
49
|
+
export function emailDomainOf(address) {
|
|
50
|
+
const value = (address !== null && address !== void 0 ? address : '').trim().toLowerCase();
|
|
51
|
+
const at = value.lastIndexOf('@');
|
|
52
|
+
if (at <= 0 || at === value.length - 1)
|
|
53
|
+
return null;
|
|
54
|
+
return value.slice(at + 1);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* WCAG contrast ratio of a `#RRGGBB` colour against white, from 1 (white) to 21
|
|
58
|
+
* (black). The email templates put WHITE text on the primary colour (buttons) and
|
|
59
|
+
* on the accent colour (header banner, footer), so a pale brand colour produces
|
|
60
|
+
* an email nobody can read. Returns 0 for anything that is not a hex colour.
|
|
61
|
+
*/
|
|
62
|
+
export function contrastRatioWithWhite(hex) {
|
|
63
|
+
const match = /^#([0-9a-fA-F]{6})$/.exec((hex !== null && hex !== void 0 ? hex : '').trim());
|
|
64
|
+
if (!match)
|
|
65
|
+
return 0;
|
|
66
|
+
const [r, g, b] = [0, 2, 4].map(offset => {
|
|
67
|
+
const channel = parseInt(match[1].slice(offset, offset + 2), 16) / 255;
|
|
68
|
+
return channel <= 0.03928 ? channel / 12.92 : Math.pow((channel + 0.055) / 1.055, 2.4);
|
|
69
|
+
});
|
|
70
|
+
const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
71
|
+
return Math.round((1.05 / (luminance + 0.05)) * 100) / 100;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Darkens a `#RRGGBB` colour by a fraction (0-1). Used to derive the hover/pressed
|
|
75
|
+
* shade of a brand colour so an organization only has to choose one.
|
|
76
|
+
* Returns the input unchanged when it is not a valid hex colour.
|
|
77
|
+
*/
|
|
78
|
+
export function darkenHexColour(hex, fraction = 0.15) {
|
|
79
|
+
const match = /^#([0-9a-fA-F]{6})$/.exec((hex !== null && hex !== void 0 ? hex : '').trim());
|
|
80
|
+
if (!match)
|
|
81
|
+
return hex;
|
|
82
|
+
const clamped = Math.min(Math.max(fraction, 0), 1);
|
|
83
|
+
const channels = [0, 2, 4].map(offset => {
|
|
84
|
+
const channel = parseInt(match[1].slice(offset, offset + 2), 16);
|
|
85
|
+
return Math.round(channel * (1 - clamped)).toString(16).padStart(2, '0');
|
|
86
|
+
});
|
|
87
|
+
return `#${channels.join('')}`;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=notification-sender.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-sender.util.js","sourceRoot":"","sources":["../../../../../src/modules/notification/utils/notification-sender.util.ts"],"names":[],"mappings":"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"}
|
|
@@ -106,5 +106,14 @@ export var PermissionActions;
|
|
|
106
106
|
PermissionActions["READ_SUPPORT_REPORT"] = "read:support-report";
|
|
107
107
|
PermissionActions["READ_SUPPORT_SYNC"] = "read:support-sync";
|
|
108
108
|
PermissionActions["MANAGE_SUPPORT_SYNC"] = "manage:support-sync";
|
|
109
|
+
// Module: Notification
|
|
110
|
+
// An organization's notification settings (clarion-notification): how its
|
|
111
|
+
// emails are branded, the address they are sent from, and the sender ID its
|
|
112
|
+
// SMS arrive under. Mirrors grm-shared-library.
|
|
113
|
+
PermissionActions["READ_NOTIFICATION_SETTINGS"] = "read:notification-settings";
|
|
114
|
+
PermissionActions["MANAGE_NOTIFICATION_SETTINGS"] = "manage:notification-settings";
|
|
115
|
+
// Confirming that an SMS sender ID really is registered with the provider.
|
|
116
|
+
// Granted to NO role on the backend: only Super-Admin ('*') passes it.
|
|
117
|
+
PermissionActions["APPROVE_NOTIFICATION_SENDER"] = "approve:notification-sender";
|
|
109
118
|
})(PermissionActions || (PermissionActions = {}));
|
|
110
119
|
//# sourceMappingURL=permission-actions.enum.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permission-actions.enum.js","sourceRoot":"","sources":["../../../../../src/modules/permission/enums/permission-actions.enum.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,
|
|
1
|
+
{"version":3,"file":"permission-actions.enum.js","sourceRoot":"","sources":["../../../../../src/modules/permission/enums/permission-actions.enum.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,iBA6HX;AA7HD,WAAY,iBAAiB;IACzB,uBAAuB;IACvB,gEAA2C,CAAA;IAC3C,4DAAuC,CAAA;IACvC,gEAA2C,CAAA;IAC3C,gEAA2C,CAAA;IAE3C,kBAAkB;IAClB,sDAAiC,CAAA;IACjC,kDAA6B,CAAA;IAC7B,sDAAiC,CAAA;IACjC,sDAAiC,CAAA;IACjC,wEAAwE;IACxE,mEAAmE;IACnE,oEAA+C,CAAA;IAC/C,0EAAqD,CAAA;IACrD,wEAAmD,CAAA;IACnD,wEAAmD,CAAA;IACnD,wEAAmD,CAAA;IACnD,2EAA2E;IAC3E,4EAA4E;IAC5E,qEAAqE;IACrE,uDAAuD;IACvD,wEAAmD,CAAA;IACnD,4EAAuD,CAAA;IAEvD,wBAAwB;IACxB,oEAA+C,CAAA;IAC/C,gEAA2C,CAAA;IAC3C,oEAA+C,CAAA;IAC/C,oEAA+C,CAAA;IAE/C,eAAe;IACf,gDAA2B,CAAA;IAC3B,4CAAuB,CAAA;IACvB,gDAA2B,CAAA;IAC3B,gDAA2B,CAAA;IAE3B,eAAe;IACf,gDAA2B,CAAA;IAC3B,4CAAuB,CAAA;IACvB,gDAA2B,CAAA;IAC3B,gDAA2B,CAAA;IAE3B,mBAAmB;IACnB,wDAAmC,CAAA;IACnC,oDAA+B,CAAA;IAC/B,wDAAmC,CAAA;IACnC,wDAAmC,CAAA;IACnC,oFAA+D,CAAA;IAC/D,gFAA2D,CAAA;IAC3D,oFAA+D,CAAA;IAC/D,oFAA+D,CAAA;IAE/D,uBAAuB;IACvB,kEAA6C,CAAA;IAC7C,8DAAyC,CAAA;IACzC,kEAA6C,CAAA;IAC7C,kEAA6C,CAAA;IAE7C,4EAA4E;IAC5E,wEAAwE;IACxE,6EAA6E;IAC7E,qDAAqD;IACrD,gGAA2E,CAAA;IAC3E,4FAAuE,CAAA;IACvE,gGAA2E,CAAA;IAC3E,gGAA2E,CAAA;IAC3E,sFAAiE,CAAA;IACjE,kFAA6D,CAAA;IAC7D,sFAAiE,CAAA;IACjE,sFAAiE,CAAA;IACjE,sEAAiD,CAAA;IACjD,oEAA+C,CAAA;IAC/C,0EAAqD,CAAA;IACrD,8EAAyD,CAAA;IAEzD,kBAAkB;IAClB,EAAE;IACF,2EAA2E;IAC3E,0EAA0E;IAC1E,uEAAuE;IACvE,+BAA+B;IAC/B,oEAA+C,CAAA;IAC/C,gEAA2C,CAAA;IAC3C,oEAA+C,CAAA;IAC/C,oEAA+C,CAAA;IAC/C,kEAA6C,CAAA;IAC7C,gEAA2C,CAAA;IAC3C,kFAA6D,CAAA;IAC7D,sFAAiE,CAAA;IACjE,kEAA6C,CAAA;IAC7C,oEAA+C,CAAA;IAC/C,yEAAyE;IACzE,gEAA2C,CAAA;IAC3C;;;OAGG;IACH,8DAAyC,CAAA;IACzC,mFAAmF;IACnF,wEAAmD,CAAA;IACnD,oEAA+C,CAAA;IAC/C,gFAAgF;IAChF,sEAAiD,CAAA;IACjD,wEAAmD,CAAA;IACnD,0EAAqD,CAAA;IACrD,0EAAqD,CAAA;IACrD,kEAA6C,CAAA;IAC7C,gEAA2C,CAAA;IAC3C,8DAAyC,CAAA;IACzC,kFAA6D,CAAA;IAC7D,gEAA2C,CAAA;IAC3C,4DAAuC,CAAA;IACvC,gEAA2C,CAAA;IAE3C,uBAAuB;IACvB,0EAA0E;IAC1E,4EAA4E;IAC5E,gDAAgD;IAChD,8EAAyD,CAAA;IACzD,kFAA6D,CAAA;IAC7D,2EAA2E;IAC3E,uEAAuE;IACvE,gFAA2D,CAAA;AAC/D,CAAC,EA7HW,iBAAiB,KAAjB,iBAAiB,QA6H5B"}
|
|
@@ -10,5 +10,6 @@ export var PermissionsModule;
|
|
|
10
10
|
PermissionsModule["RESPONSE_UNIT"] = "Response Unit";
|
|
11
11
|
PermissionsModule["TRACKING"] = "Tracking";
|
|
12
12
|
PermissionsModule["SUPPORT"] = "Support";
|
|
13
|
+
PermissionsModule["NOTIFICATION"] = "Notification";
|
|
13
14
|
})(PermissionsModule || (PermissionsModule = {}));
|
|
14
15
|
//# sourceMappingURL=permissions-moudule.enum.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions-moudule.enum.js","sourceRoot":"","sources":["../../../../../src/modules/permission/enums/permissions-moudule.enum.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,
|
|
1
|
+
{"version":3,"file":"permissions-moudule.enum.js","sourceRoot":"","sources":["../../../../../src/modules/permission/enums/permissions-moudule.enum.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,iBAYX;AAZD,WAAY,iBAAiB;IACzB,kDAA6B,CAAA;IAC7B,wCAAmB,CAAA;IACnB,sDAAiC,CAAA;IACjC,kCAAa,CAAA;IACb,kCAAa,CAAA;IACb,kCAAa,CAAA;IACb,2CAAsB,CAAA;IACtB,oDAA+B,CAAA;IAC/B,0CAAqB,CAAA;IACrB,wCAAmB,CAAA;IACnB,kDAA6B,CAAA;AACjC,CAAC,EAZW,iBAAiB,KAAjB,iBAAiB,QAY5B"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Organization notification settings enums.
|
|
3
|
+
*
|
|
4
|
+
* MIRRORS grm-shared-library (`modules/notification/enums`), values included. The
|
|
5
|
+
* admin renders and submits these strings and clarion-notification validates the
|
|
6
|
+
* same ones, so any drift is a form the API refuses. `notification-settings.spec.ts`
|
|
7
|
+
* pins the values.
|
|
8
|
+
*/
|
|
9
|
+
/** What kind of identity an SMS is sent from. Decides how the value is validated. */
|
|
10
|
+
export declare enum SmsSenderType {
|
|
11
|
+
/** A registered alphanumeric sender name, e.g. `G4S`. At most 11 characters. */
|
|
12
|
+
ALPHANUMERIC = "ALPHANUMERIC",
|
|
13
|
+
/** An E.164 long number, e.g. `+254711000000`. */
|
|
14
|
+
PHONE_NUMBER = "PHONE_NUMBER",
|
|
15
|
+
/** A telco short code, e.g. `22384`. */
|
|
16
|
+
SHORT_CODE = "SHORT_CODE",
|
|
17
|
+
/** A provider-side sender pool (Twilio Messaging Service SID, `MG...`). */
|
|
18
|
+
MESSAGING_SERVICE = "MESSAGING_SERVICE"
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Lifecycle of an organization-owned SMS sender. An organization REQUESTS a sender
|
|
22
|
+
* (PENDING) and a platform operator ACTIVATES it once the provider and the telco
|
|
23
|
+
* have registered it. Only ACTIVE senders are ever used to send.
|
|
24
|
+
*/
|
|
25
|
+
export declare enum NotificationSenderStatus {
|
|
26
|
+
PENDING = "PENDING",
|
|
27
|
+
ACTIVE = "ACTIVE",
|
|
28
|
+
SUSPENDED = "SUSPENDED",
|
|
29
|
+
REJECTED = "REJECTED"
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Whether an email provider will accept mail FROM an organization's address.
|
|
33
|
+
* Tracked per provider: an address can be verified in Twilio SendGrid while its
|
|
34
|
+
* domain is unknown to Mailgun. A provider only sends from an address it has
|
|
35
|
+
* VERIFIED; otherwise it falls back to the platform sender.
|
|
36
|
+
*/
|
|
37
|
+
export declare enum EmailSenderVerificationStatus {
|
|
38
|
+
/** The provider does not know this address or its domain. */
|
|
39
|
+
UNVERIFIED = "UNVERIFIED",
|
|
40
|
+
/** Verification was started and is waiting on the owner (inbox click or DNS records). */
|
|
41
|
+
PENDING = "PENDING",
|
|
42
|
+
/** The provider accepts mail from this address. */
|
|
43
|
+
VERIFIED = "VERIFIED",
|
|
44
|
+
/** The last check could not be completed (provider error). */
|
|
45
|
+
FAILED = "FAILED"
|
|
46
|
+
}
|
|
47
|
+
/** How the provider recognises the address. */
|
|
48
|
+
export declare enum EmailSenderVerificationMethod {
|
|
49
|
+
/** The exact address was verified on its own (SendGrid Single Sender Verification). */
|
|
50
|
+
SINGLE_SENDER = "SINGLE_SENDER",
|
|
51
|
+
/** The whole domain is authenticated (SendGrid domain authentication, Mailgun domain). */
|
|
52
|
+
DOMAIN = "DOMAIN"
|
|
53
|
+
}
|
|
54
|
+
/** Whose identity a message actually went out under. */
|
|
55
|
+
export declare enum NotificationSenderSource {
|
|
56
|
+
/** The organization's own verified email address / active SMS sender. */
|
|
57
|
+
ORGANIZATION = "ORGANIZATION",
|
|
58
|
+
/** The platform's default (country-aware) sender. */
|
|
59
|
+
PLATFORM_DEFAULT = "PLATFORM_DEFAULT"
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Where one resolved branding value came from. Branding resolves field by field,
|
|
63
|
+
* highest precedence first, so a half-filled profile still produces a complete email.
|
|
64
|
+
*/
|
|
65
|
+
export declare enum NotificationBrandingSource {
|
|
66
|
+
/** The organization's notification settings. */
|
|
67
|
+
PROFILE = "PROFILE",
|
|
68
|
+
/** The organization record (clarion-organization). */
|
|
69
|
+
ORGANIZATION = "ORGANIZATION",
|
|
70
|
+
/** The legacy per-app defaults (deprecated). */
|
|
71
|
+
APP_DEFAULT = "APP_DEFAULT",
|
|
72
|
+
/** The platform's own branding. */
|
|
73
|
+
PLATFORM_DEFAULT = "PLATFORM_DEFAULT"
|
|
74
|
+
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Identifiers for the SMS providers the notification service can dispatch through.
|
|
3
3
|
* Provider order/fallback is configuration-driven; new providers can be appended.
|
|
4
|
+
*
|
|
5
|
+
* A code here only RESERVES the name. Whether a provider can actually be used is
|
|
6
|
+
* answered by the notification service's provider catalogue
|
|
7
|
+
* (`SmsProviderDescriptor`), which lists only providers with a registered adapter.
|
|
4
8
|
*/
|
|
5
9
|
export declare enum SmsProviderName {
|
|
6
10
|
TWILIO = "twilio",
|
|
7
11
|
UWAZII = "uwazii",
|
|
8
|
-
AFRICASTALKING = "africastalking"
|
|
12
|
+
AFRICASTALKING = "africastalking",
|
|
13
|
+
CELCOM = "celcom"
|
|
9
14
|
}
|
|
@@ -3,8 +3,11 @@ export * from './enums/sms-provider-name.enum';
|
|
|
3
3
|
export * from './enums/email-provider-name.enum';
|
|
4
4
|
export * from './enums/notification-overall-status.enum';
|
|
5
5
|
export * from './enums/provider-failure-reason.enum';
|
|
6
|
+
export * from './enums/notification-settings.enums';
|
|
6
7
|
export * from './interfaces/provider-attempt';
|
|
7
8
|
export * from './interfaces/per-channel-result';
|
|
8
9
|
export * from './interfaces/sms-send-result';
|
|
9
10
|
export * from './interfaces/email-send-result';
|
|
10
11
|
export * from './interfaces/notification-dispatch-result';
|
|
12
|
+
export * from './interfaces/organization-notification-settings.dto';
|
|
13
|
+
export * from './utils/notification-sender.util';
|
package/dist/types/modules/notification/interfaces/organization-notification-settings.dto.d.ts
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { CountryCode } from '../../country/enums/country-code.enum';
|
|
2
|
+
import { IncidentAppId } from '../../incident/enums/incident-app-id.enum';
|
|
3
|
+
import { EmailProviderName } from '../enums/email-provider-name.enum';
|
|
4
|
+
import { EmailSenderVerificationMethod, EmailSenderVerificationStatus, NotificationBrandingSource, NotificationSenderSource, NotificationSenderStatus, SmsSenderType } from '../enums/notification-settings.enums';
|
|
5
|
+
import { SmsProviderName } from '../enums/sms-provider-name.enum';
|
|
6
|
+
/**
|
|
7
|
+
* Organization notification settings: what a customer sees in a notification - the
|
|
8
|
+
* logo and colours of an email, the address it came from, the name an SMS arrives
|
|
9
|
+
* under. `organizationId` is the single key; the legacy `appId` survives only as an
|
|
10
|
+
* alias for events that still carry nothing but an app id.
|
|
11
|
+
*
|
|
12
|
+
* MIRRORS grm-shared-library (`modules/notification/interfaces` and `dtos`). The
|
|
13
|
+
* response shapes are interfaces on both sides; the request shapes are class-validator
|
|
14
|
+
* DTOs on the backend and plain interfaces here. Owned by clarion-notification,
|
|
15
|
+
* proxied by the gateway, rendered by the admin. Nothing here is a secret.
|
|
16
|
+
*/
|
|
17
|
+
export interface NotificationSocialLinks {
|
|
18
|
+
facebook?: string | null;
|
|
19
|
+
x?: string | null;
|
|
20
|
+
instagram?: string | null;
|
|
21
|
+
linkedin?: string | null;
|
|
22
|
+
}
|
|
23
|
+
/** The values a notification template can brand itself with. */
|
|
24
|
+
export interface NotificationBrandingFields {
|
|
25
|
+
/** Legal/trading name shown in the footer, e.g. `G4S Kenya Ltd`. */
|
|
26
|
+
companyName: string;
|
|
27
|
+
/** Product name the customer knows, e.g. `G4S Kenya`. Used in subjects and sign-offs. */
|
|
28
|
+
appName: string;
|
|
29
|
+
/** HTTPS URL of the logo. Email clients will not load anything else. */
|
|
30
|
+
logoUrl: string;
|
|
31
|
+
/** `#RRGGBB`. Buttons, links and accents. */
|
|
32
|
+
primaryColour: string;
|
|
33
|
+
/** `#RRGGBB`. Hover/pressed shade; derived from the primary when not chosen. */
|
|
34
|
+
primaryColourDark: string;
|
|
35
|
+
/** `#RRGGBB`. Header banner and footer background. */
|
|
36
|
+
accentColour: string;
|
|
37
|
+
physicalAddress: string;
|
|
38
|
+
phoneNumber: string;
|
|
39
|
+
/** General contact address printed in the footer. Not the address mail is sent FROM. */
|
|
40
|
+
contactEmail: string;
|
|
41
|
+
supportEmail: string;
|
|
42
|
+
websiteUrl: string;
|
|
43
|
+
/** Base URL that links in a notification point at (the organization's web client). */
|
|
44
|
+
clientBaseUrl: string;
|
|
45
|
+
social: NotificationSocialLinks;
|
|
46
|
+
}
|
|
47
|
+
/** What an organization has chosen to override. Every field is optional: gaps are resolved, not rejected. */
|
|
48
|
+
export interface OrganizationNotificationBranding extends Partial<NotificationBrandingFields> {
|
|
49
|
+
organizationId: number;
|
|
50
|
+
/** Legacy alias: an appId-only event resolves to the organization that claims it. */
|
|
51
|
+
appId?: string | null;
|
|
52
|
+
createdAt?: string;
|
|
53
|
+
updatedAt?: string;
|
|
54
|
+
updatedBy?: number | null;
|
|
55
|
+
}
|
|
56
|
+
/** Branding after resolution: complete, and honest about where each value came from. */
|
|
57
|
+
export interface ResolvedNotificationBranding extends NotificationBrandingFields {
|
|
58
|
+
organizationId: number | null;
|
|
59
|
+
sources: Record<keyof NotificationBrandingFields, NotificationBrandingSource>;
|
|
60
|
+
}
|
|
61
|
+
/** One provider's answer to "will you send mail from this address?". */
|
|
62
|
+
export interface EmailSenderProviderVerification {
|
|
63
|
+
provider: EmailProviderName;
|
|
64
|
+
status: EmailSenderVerificationStatus;
|
|
65
|
+
method?: EmailSenderVerificationMethod | null;
|
|
66
|
+
/** Operator-facing explanation, e.g. "Domain ke.g4s.com is not added to Mailgun". */
|
|
67
|
+
detail?: string | null;
|
|
68
|
+
checkedAt?: string | null;
|
|
69
|
+
}
|
|
70
|
+
export interface OrganizationEmailSender {
|
|
71
|
+
id: string;
|
|
72
|
+
organizationId: number;
|
|
73
|
+
/** The address mail is sent FROM, e.g. `notifications@ke.g4s.com`. */
|
|
74
|
+
fromEmail: string;
|
|
75
|
+
/** Display name. Falls back to the resolved company name. */
|
|
76
|
+
fromName?: string | null;
|
|
77
|
+
/** Falls back to `fromEmail`. */
|
|
78
|
+
replyTo?: string | null;
|
|
79
|
+
/** The sender used when a notification does not ask for a specific one. One per organization. */
|
|
80
|
+
isDefault: boolean;
|
|
81
|
+
active: boolean;
|
|
82
|
+
verifications: EmailSenderProviderVerification[];
|
|
83
|
+
/** True when at least one configured provider has VERIFIED the address. */
|
|
84
|
+
usable: boolean;
|
|
85
|
+
createdAt?: string;
|
|
86
|
+
updatedAt?: string;
|
|
87
|
+
}
|
|
88
|
+
export interface OrganizationSmsSender {
|
|
89
|
+
id: string;
|
|
90
|
+
organizationId: number;
|
|
91
|
+
/** The provider account this sender is registered with. */
|
|
92
|
+
provider: SmsProviderName;
|
|
93
|
+
/** The destination country it is registered for. Null = every country the provider serves. */
|
|
94
|
+
countryCode?: CountryCode | null;
|
|
95
|
+
senderType: SmsSenderType;
|
|
96
|
+
senderId: string;
|
|
97
|
+
status: NotificationSenderStatus;
|
|
98
|
+
/** Registration reference, telco ticket, anything the operator needs later. */
|
|
99
|
+
notes?: string | null;
|
|
100
|
+
reviewedBy?: number | null;
|
|
101
|
+
reviewedAt?: string | null;
|
|
102
|
+
createdAt?: string;
|
|
103
|
+
updatedAt?: string;
|
|
104
|
+
}
|
|
105
|
+
/** A sender type a provider accepts, with everything a form needs to collect it. */
|
|
106
|
+
export interface SmsProviderSenderTypeDescriptor {
|
|
107
|
+
type: SmsSenderType;
|
|
108
|
+
label: string;
|
|
109
|
+
placeholder?: string;
|
|
110
|
+
description?: string;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Self-description of an SMS provider, published by clarion-notification. Adding a
|
|
114
|
+
* provider (Celcom, Africa's Talking, ...) changes no client code. Only providers
|
|
115
|
+
* with a registered adapter are described.
|
|
116
|
+
*/
|
|
117
|
+
export interface SmsProviderDescriptor {
|
|
118
|
+
provider: SmsProviderName;
|
|
119
|
+
displayName: string;
|
|
120
|
+
description: string;
|
|
121
|
+
/** Countries the adapter can deliver to. */
|
|
122
|
+
supportedCountries: CountryCode[];
|
|
123
|
+
senderTypes: SmsProviderSenderTypeDescriptor[];
|
|
124
|
+
/** Whether the platform's account for this provider is configured and enabled right now. */
|
|
125
|
+
configured: boolean;
|
|
126
|
+
documentationUrl?: string;
|
|
127
|
+
}
|
|
128
|
+
/** The platform senders an organization falls back to. Display-only. */
|
|
129
|
+
export interface PlatformNotificationDefaults {
|
|
130
|
+
email: {
|
|
131
|
+
fromEmail: string | null;
|
|
132
|
+
fromName: string | null;
|
|
133
|
+
};
|
|
134
|
+
/** Per-country default SMS provider chain, e.g. `{ KE: ['twilio', 'uwazii'] }`. */
|
|
135
|
+
smsProviderChains: Partial<Record<CountryCode, SmsProviderName[]>>;
|
|
136
|
+
/** Email providers currently able to send, in order. */
|
|
137
|
+
emailProviders: EmailProviderName[];
|
|
138
|
+
}
|
|
139
|
+
/** Everything the settings page needs, in one read. */
|
|
140
|
+
export interface OrganizationNotificationSettings {
|
|
141
|
+
organizationId: number;
|
|
142
|
+
/** Null until the organization saves a profile. */
|
|
143
|
+
branding: OrganizationNotificationBranding | null;
|
|
144
|
+
effectiveBranding: ResolvedNotificationBranding;
|
|
145
|
+
emailSenders: OrganizationEmailSender[];
|
|
146
|
+
smsSenders: OrganizationSmsSender[];
|
|
147
|
+
platformDefaults: PlatformNotificationDefaults;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Saves an organization's branding. A field sent as null (or "") stops overriding
|
|
151
|
+
* and inherits again; a field left out is untouched.
|
|
152
|
+
*/
|
|
153
|
+
export interface UpsertOrganizationNotificationBranding {
|
|
154
|
+
/** Super-admin only. */
|
|
155
|
+
appId?: IncidentAppId | null;
|
|
156
|
+
companyName?: string | null;
|
|
157
|
+
appName?: string | null;
|
|
158
|
+
/** HTTPS only. */
|
|
159
|
+
logoUrl?: string | null;
|
|
160
|
+
primaryColour?: string | null;
|
|
161
|
+
primaryColourDark?: string | null;
|
|
162
|
+
accentColour?: string | null;
|
|
163
|
+
physicalAddress?: string | null;
|
|
164
|
+
phoneNumber?: string | null;
|
|
165
|
+
contactEmail?: string | null;
|
|
166
|
+
supportEmail?: string | null;
|
|
167
|
+
websiteUrl?: string | null;
|
|
168
|
+
clientBaseUrl?: string | null;
|
|
169
|
+
social?: NotificationSocialLinks | null;
|
|
170
|
+
}
|
|
171
|
+
export interface CreateOrganizationEmailSender {
|
|
172
|
+
fromEmail: string;
|
|
173
|
+
fromName?: string | null;
|
|
174
|
+
replyTo?: string | null;
|
|
175
|
+
isDefault?: boolean;
|
|
176
|
+
}
|
|
177
|
+
export interface UpdateOrganizationEmailSender {
|
|
178
|
+
fromName?: string | null;
|
|
179
|
+
replyTo?: string | null;
|
|
180
|
+
isDefault?: boolean;
|
|
181
|
+
active?: boolean;
|
|
182
|
+
}
|
|
183
|
+
export interface CreateOrganizationSmsSender {
|
|
184
|
+
provider: SmsProviderName;
|
|
185
|
+
countryCode?: CountryCode | null;
|
|
186
|
+
senderType: SmsSenderType;
|
|
187
|
+
senderId: string;
|
|
188
|
+
notes?: string | null;
|
|
189
|
+
}
|
|
190
|
+
export interface UpdateOrganizationSmsSender {
|
|
191
|
+
countryCode?: CountryCode | null;
|
|
192
|
+
senderType?: SmsSenderType;
|
|
193
|
+
/** Changing the value sends the sender back to PENDING. */
|
|
194
|
+
senderId?: string;
|
|
195
|
+
notes?: string | null;
|
|
196
|
+
}
|
|
197
|
+
/** Platform operators only. */
|
|
198
|
+
export interface ReviewOrganizationSmsSender {
|
|
199
|
+
status: NotificationSenderStatus;
|
|
200
|
+
notes?: string | null;
|
|
201
|
+
}
|
|
202
|
+
export interface SendTestNotificationEmail {
|
|
203
|
+
to: string;
|
|
204
|
+
}
|
|
205
|
+
/** What the test-email endpoint answers with. */
|
|
206
|
+
export interface TestNotificationEmailResult {
|
|
207
|
+
success: boolean;
|
|
208
|
+
provider: string | null;
|
|
209
|
+
/** The address the email actually went out from. */
|
|
210
|
+
sender: string | null;
|
|
211
|
+
senderSource: NotificationSenderSource | null;
|
|
212
|
+
errorMessage: string | null;
|
|
213
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { SmsSenderType } from '../enums/notification-settings.enums';
|
|
2
|
+
/**
|
|
3
|
+
* MIRRORS grm-shared-library (`modules/notification/constants` and `utils`),
|
|
4
|
+
* patterns and thresholds included. The settings form validates with these and
|
|
5
|
+
* clarion-notification validates with the originals, so they must agree to the
|
|
6
|
+
* character: a form that accepts what the API refuses is worse than no check.
|
|
7
|
+
*/
|
|
8
|
+
/** `#RRGGBB`. The only colour format accepted, because it is inlined into email CSS. */
|
|
9
|
+
export declare const BRAND_COLOUR_PATTERN: RegExp;
|
|
10
|
+
/**
|
|
11
|
+
* What a sender value must look like, per type. ALPHANUMERIC follows the GSM rule
|
|
12
|
+
* every supported provider enforces: 3-11 characters, at least one letter (an
|
|
13
|
+
* all-digit "name" is a number, and telcos reject it as spoofing).
|
|
14
|
+
*/
|
|
15
|
+
export declare const SMS_SENDER_ID_PATTERNS: Readonly<Record<SmsSenderType, RegExp>>;
|
|
16
|
+
/** Human-readable form of {@link SMS_SENDER_ID_PATTERNS}, for validation messages and form hints. */
|
|
17
|
+
export declare const SMS_SENDER_ID_HINTS: Readonly<Record<SmsSenderType, string>>;
|
|
18
|
+
/** Upper bounds that keep one organization from turning its settings into a list to page through. */
|
|
19
|
+
export declare const MAX_EMAIL_SENDERS_PER_ORGANIZATION = 10;
|
|
20
|
+
export declare const MAX_SMS_SENDERS_PER_ORGANIZATION = 30;
|
|
21
|
+
/** Large text and UI components (WCAG 1.4.11): buttons and links in the primary colour. */
|
|
22
|
+
export declare const MIN_PRIMARY_COLOUR_CONTRAST = 3;
|
|
23
|
+
/** Body-size white text sits on the accent colour (WCAG 1.4.3). */
|
|
24
|
+
export declare const MIN_ACCENT_COLOUR_CONTRAST = 4.5;
|
|
25
|
+
/**
|
|
26
|
+
* Validates an SMS sender value against its declared type.
|
|
27
|
+
* Returns null when valid, otherwise a message fit to show an operator.
|
|
28
|
+
*/
|
|
29
|
+
export declare function validateSmsSenderId(senderType: SmsSenderType, senderId: string): string | null;
|
|
30
|
+
/** The domain part of an email address, lower-cased. Null when there is none. */
|
|
31
|
+
export declare function emailDomainOf(address: string | null | undefined): string | null;
|
|
32
|
+
/**
|
|
33
|
+
* WCAG contrast ratio of a `#RRGGBB` colour against white, from 1 (white) to 21
|
|
34
|
+
* (black). The email templates put WHITE text on the primary colour (buttons) and
|
|
35
|
+
* on the accent colour (header banner, footer), so a pale brand colour produces
|
|
36
|
+
* an email nobody can read. Returns 0 for anything that is not a hex colour.
|
|
37
|
+
*/
|
|
38
|
+
export declare function contrastRatioWithWhite(hex: string): number;
|
|
39
|
+
/**
|
|
40
|
+
* Darkens a `#RRGGBB` colour by a fraction (0-1). Used to derive the hover/pressed
|
|
41
|
+
* shade of a brand colour so an organization only has to choose one.
|
|
42
|
+
* Returns the input unchanged when it is not a valid hex colour.
|
|
43
|
+
*/
|
|
44
|
+
export declare function darkenHexColour(hex: string, fraction?: number): string;
|
|
@@ -81,5 +81,8 @@ export declare enum PermissionActions {
|
|
|
81
81
|
MANAGE_SUPPORT_CONFIGURATION = "manage:support-configuration",
|
|
82
82
|
READ_SUPPORT_REPORT = "read:support-report",
|
|
83
83
|
READ_SUPPORT_SYNC = "read:support-sync",
|
|
84
|
-
MANAGE_SUPPORT_SYNC = "manage:support-sync"
|
|
84
|
+
MANAGE_SUPPORT_SYNC = "manage:support-sync",
|
|
85
|
+
READ_NOTIFICATION_SETTINGS = "read:notification-settings",
|
|
86
|
+
MANAGE_NOTIFICATION_SETTINGS = "manage:notification-settings",
|
|
87
|
+
APPROVE_NOTIFICATION_SENDER = "approve:notification-sender"
|
|
85
88
|
}
|