[mod] notifications
This commit is contained in:
parent
1483bf95a8
commit
8a33c029c7
4 changed files with 252 additions and 119 deletions
|
@ -29,6 +29,7 @@ namespace _espe.api
|
||||||
email_use_nominal_address : boolean;
|
email_use_nominal_address : boolean;
|
||||||
email_redirect_to_private_address : boolean;
|
email_redirect_to_private_address : boolean;
|
||||||
password : (null | string);
|
password : (null | string);
|
||||||
|
notification_target_url_template ?: (null | string);
|
||||||
},
|
},
|
||||||
Array<
|
Array<
|
||||||
{
|
{
|
||||||
|
@ -67,6 +68,11 @@ namespace _espe.api
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
"description": "Passwort für alle Netz-Dienste",
|
"description": "Passwort für alle Netz-Dienste",
|
||||||
},
|
},
|
||||||
|
"notification_target_url_template": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"description": "Platz-Halter: id"
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"email_use_veiled_address",
|
"email_use_veiled_address",
|
||||||
|
@ -128,6 +134,9 @@ namespace _espe.api
|
||||||
"email_use_nominal_address": input.email_use_nominal_address,
|
"email_use_nominal_address": input.email_use_nominal_address,
|
||||||
"email_redirect_to_private_address": input.email_redirect_to_private_address,
|
"email_redirect_to_private_address": input.email_redirect_to_private_address,
|
||||||
"password": input.password,
|
"password": input.password,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"notification_target_url_template": (input.notification_target_url_template ?? null),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then(
|
.then(
|
||||||
|
|
|
@ -96,12 +96,21 @@ namespace _espe.conf
|
||||||
settings : {
|
settings : {
|
||||||
target_domain : string;
|
target_domain : string;
|
||||||
frontend_url_base : (null | string);
|
frontend_url_base : (null | string);
|
||||||
|
login_url : (null | string);
|
||||||
prefix_for_nominal_email_addresses : string;
|
prefix_for_nominal_email_addresses : string;
|
||||||
facultative_membership_number : boolean;
|
facultative_membership_number : boolean;
|
||||||
|
summon_email : {
|
||||||
|
subject : string;
|
||||||
|
body : string;
|
||||||
|
};
|
||||||
registration_email : {
|
registration_email : {
|
||||||
subject : string;
|
subject : string;
|
||||||
body : string;
|
body : string;
|
||||||
};
|
};
|
||||||
|
activation_email : {
|
||||||
|
subject : string;
|
||||||
|
body : string;
|
||||||
|
};
|
||||||
password_policy : {
|
password_policy : {
|
||||||
minimum_length : (null | int);
|
minimum_length : (null | int);
|
||||||
maximum_length : (null | int);
|
maximum_length : (null | int);
|
||||||
|
@ -248,12 +257,21 @@ namespace _espe.conf
|
||||||
((node_settings) => ({
|
((node_settings) => ({
|
||||||
"target_domain": (node_settings["target_domain"] ?? "example.org"),
|
"target_domain": (node_settings["target_domain"] ?? "example.org"),
|
||||||
"frontend_url_base": (node_settings["frontend_url_base"] ?? null), // TODO: mandatory?
|
"frontend_url_base": (node_settings["frontend_url_base"] ?? null), // TODO: mandatory?
|
||||||
|
"login_url": (node_settings["login_url"] ?? null),
|
||||||
"prefix_for_nominal_email_addresses": (node_settings["prefix_for_nominal_email_addresses"] ?? "member-"),
|
"prefix_for_nominal_email_addresses": (node_settings["prefix_for_nominal_email_addresses"] ?? "member-"),
|
||||||
"facultative_membership_number": (node_settings["facultative_membership_number"] ?? false),
|
"facultative_membership_number": (node_settings["facultative_membership_number"] ?? false),
|
||||||
|
"summon_email": {
|
||||||
|
"subject": ((node_settings["summon_email"] ?? {})["subject"] ?? "Please register"),
|
||||||
|
"body": ((node_settings["summon_email"] ?? {})["body"] ?? "URL: {{url}}"),
|
||||||
|
},
|
||||||
"registration_email": {
|
"registration_email": {
|
||||||
"subject": ((node_settings["registration_email"] ?? {})["subject"] ?? "Registration"),
|
"subject": ((node_settings["registration_email"] ?? {})["subject"] ?? "Mmeber registered"),
|
||||||
"body": ((node_settings["registration_email"] ?? {})["body"] ?? "URL: {{url}}"),
|
"body": ((node_settings["registration_email"] ?? {})["body"] ?? "URL: {{url}}"),
|
||||||
},
|
},
|
||||||
|
"activation_email": {
|
||||||
|
"subject": ((node_settings["activation_email"] ?? {})["subject"] ?? "Account activated"),
|
||||||
|
"body": ((node_settings["activation_email"] ?? {})["body"] ?? "URL: {{url}}\n\nLogin name: {{name_login}}\n\n"),
|
||||||
|
},
|
||||||
"password_policy": (
|
"password_policy": (
|
||||||
((node_settings_password_policy) => ({
|
((node_settings_password_policy) => ({
|
||||||
"minimum_length": (
|
"minimum_length": (
|
||||||
|
|
|
@ -268,4 +268,64 @@ namespace _espe.helpers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export function frontend_url_check(
|
||||||
|
) : void
|
||||||
|
{
|
||||||
|
const frontend_url_base : (null | string) = _espe.conf.get().settings.frontend_url_base;
|
||||||
|
if (frontend_url_base === null) {
|
||||||
|
throw (new Error("no frontend url base set; add in conf as 'settings.frontend_url_base'!"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export function frontend_url_get(
|
||||||
|
template : string,
|
||||||
|
arguments_ : Record<string, string>
|
||||||
|
) : (null | string)
|
||||||
|
{
|
||||||
|
const frontend_url_base : (null | string) = _espe.conf.get().settings.frontend_url_base;
|
||||||
|
if (frontend_url_base === null) {
|
||||||
|
// throw (new Error("no frontend url base set; add in conf as 'settings.frontend_url_base'!"));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return lib_plankton.string.coin(
|
||||||
|
"{{base}}/{{rest}}",
|
||||||
|
{
|
||||||
|
"base": frontend_url_base,
|
||||||
|
"rest": lib_plankton.string.coin(template, arguments_),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export async function notify_admins(
|
||||||
|
subject : string,
|
||||||
|
body : string
|
||||||
|
) : Promise<void>
|
||||||
|
{
|
||||||
|
await _espe.helpers.email_send(
|
||||||
|
(
|
||||||
|
(
|
||||||
|
_espe.conf.get().admins
|
||||||
|
.map(admin => admin.email_address)
|
||||||
|
.filter(x => (x !== null))
|
||||||
|
) as Array<string>
|
||||||
|
),
|
||||||
|
subject,
|
||||||
|
body
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace _espe.service.member
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
function notify_change(
|
function signal_change(
|
||||||
) : void
|
) : void
|
||||||
{
|
{
|
||||||
_hooks_change.forEach(
|
_hooks_change.forEach(
|
||||||
|
@ -251,6 +251,40 @@ namespace _espe.service.member
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
async function send_activation_email(
|
||||||
|
member_object : _espe.type.member_object
|
||||||
|
) : Promise<void>
|
||||||
|
{
|
||||||
|
if (! member_object.enabled) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (member_object.email_address_private === null) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
await _espe.helpers.email_send(
|
||||||
|
[
|
||||||
|
member_object.email_address_private,
|
||||||
|
],
|
||||||
|
_espe.conf.get().settings.activation_email.subject,
|
||||||
|
lib_plankton.string.coin(
|
||||||
|
_espe.conf.get().settings.activation_email.body,
|
||||||
|
{
|
||||||
|
"name_display": name_display(member_object),
|
||||||
|
"name_login": name_login(member_object),
|
||||||
|
"url": (_espe.conf.get().settings.login_url ?? "--"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gibt die vollständigen Daten aller Mitglieder aus
|
* gibt die vollständigen Daten aller Mitglieder aus
|
||||||
*/
|
*/
|
||||||
|
@ -330,47 +364,49 @@ namespace _espe.service.member
|
||||||
"password_change_token": null,
|
"password_change_token": null,
|
||||||
};
|
};
|
||||||
const id : _espe.type.member_id = await _espe.repository.member.create(object);
|
const id : _espe.type.member_id = await _espe.repository.member.create(object);
|
||||||
notify_change();
|
signal_change();
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sendet an ein Mitglied eine E-Mail mit Aufforderung zur Registrierung
|
* sendet an ein Mitglied eine E-Mail mit Aufforderung zur Registrierung
|
||||||
*
|
|
||||||
* @todo conf:settings.frontend_url_base verwenden
|
|
||||||
*/
|
*/
|
||||||
export async function summon(
|
export async function summon(
|
||||||
member_id : _espe.type.member_id,
|
member_id : _espe.type.member_id,
|
||||||
url_template : string
|
url_template : string
|
||||||
) : Promise<(null | string)>
|
) : Promise<(null | string)>
|
||||||
{
|
{
|
||||||
|
_espe.helpers.frontend_url_check();
|
||||||
const member_object : _espe.type.member_object = await get(member_id);
|
const member_object : _espe.type.member_object = await get(member_id);
|
||||||
if (member_object.email_address_private === null) {
|
if (member_object.email_address_private === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const verification : string = await _espe.helpers.verification_get(member_id);
|
const url : (null | string) = _espe.helpers.frontend_url_get(
|
||||||
|
|
||||||
const url : string = lib_plankton.string.coin(
|
|
||||||
url_template,
|
url_template,
|
||||||
{
|
{
|
||||||
"verification": verification,
|
"verification": await _espe.helpers.verification_get(member_id),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
if (url === null) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
else {
|
||||||
await _espe.helpers.email_send(
|
await _espe.helpers.email_send(
|
||||||
[
|
[
|
||||||
member_object.email_address_private,
|
member_object.email_address_private,
|
||||||
],
|
],
|
||||||
_espe.conf.get().settings.registration_email.subject,
|
_espe.conf.get().settings.summon_email.subject,
|
||||||
lib_plankton.string.coin(
|
lib_plankton.string.coin(
|
||||||
_espe.conf.get().settings.registration_email.body,
|
_espe.conf.get().settings.summon_email.body,
|
||||||
{
|
{
|
||||||
"name": member_object.name_real_value,
|
"name": name_display(member_object),
|
||||||
"url": url,
|
"url": url,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,13 +461,13 @@ namespace _espe.service.member
|
||||||
password : (null | string);
|
password : (null | string);
|
||||||
},
|
},
|
||||||
options : {
|
options : {
|
||||||
notify_admins ?: boolean;
|
notification_target_url_template ?: (null | string);
|
||||||
} = {}
|
} = {}
|
||||||
) : Promise<Array<{incident : string; details : Record<string, any>;}>>
|
) : Promise<Array<{incident : string; details : Record<string, any>;}>>
|
||||||
{
|
{
|
||||||
options = Object.assign(
|
options = Object.assign(
|
||||||
{
|
{
|
||||||
"notify_admins": false,
|
"notification_target_url_template": null,
|
||||||
},
|
},
|
||||||
options
|
options
|
||||||
);
|
);
|
||||||
|
@ -472,26 +508,40 @@ namespace _espe.service.member
|
||||||
member_object.password_image = await password_image(data.password);
|
member_object.password_image = await password_image(data.password);
|
||||||
member_object.registered = true;
|
member_object.registered = true;
|
||||||
await _espe.repository.member.update(member_id, member_object);
|
await _espe.repository.member.update(member_id, member_object);
|
||||||
|
signal_change();
|
||||||
notify_change();
|
{
|
||||||
|
const url : (null | string) = (
|
||||||
if (! options.notify_admins) {
|
(
|
||||||
|
(options.notification_target_url_template === undefined)
|
||||||
|
||
|
||||||
|
(options.notification_target_url_template === null)
|
||||||
|
)
|
||||||
|
? null
|
||||||
|
: _espe.helpers.frontend_url_get(
|
||||||
|
options.notification_target_url_template,
|
||||||
|
{
|
||||||
|
"id": member_id.toFixed(0),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (url === null) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
await _espe.helpers.email_send(
|
/*await*/ _espe.helpers.notify_admins(
|
||||||
(
|
_espe.conf.get().settings.registration_email.subject,
|
||||||
(
|
lib_plankton.string.coin(
|
||||||
_espe.conf.get().admins
|
_espe.conf.get().settings.registration_email.body,
|
||||||
.map(admin => admin.email_address)
|
{
|
||||||
.filter(x => (x !== null))
|
"name_display": name_display(member_object),
|
||||||
) as Array<string>
|
"url": url,
|
||||||
),
|
}
|
||||||
"Eingegangene Registrierung", // TODO
|
)
|
||||||
("Member-ID: " + member_id.toFixed(0))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*await*/ send_activation_email(member_object);
|
||||||
|
}
|
||||||
|
|
||||||
return Promise.resolve(flaws);
|
return Promise.resolve(flaws);
|
||||||
}
|
}
|
||||||
|
@ -526,7 +576,8 @@ namespace _espe.service.member
|
||||||
"password_change_token": member_object_old.password_change_token,
|
"password_change_token": member_object_old.password_change_token,
|
||||||
};
|
};
|
||||||
await _espe.repository.member.update(member_id, member_object_new);
|
await _espe.repository.member.update(member_id, member_object_new);
|
||||||
notify_change();
|
signal_change();
|
||||||
|
/*await*/ send_activation_email(member_object_new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -540,11 +591,7 @@ namespace _espe.service.member
|
||||||
url_template : string
|
url_template : string
|
||||||
) : Promise<void>
|
) : Promise<void>
|
||||||
{
|
{
|
||||||
const frontend_url_base : (null | string) = _espe.conf.get().settings.frontend_url_base;
|
_espe.helpers.frontend_url_check();
|
||||||
if (frontend_url_base === null) {
|
|
||||||
return Promise.reject<void>(new Error("no frontend url base set; add in conf as 'settings.frontend_url_base'!"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const now : int = lib_plankton.base.get_current_timestamp(true);
|
const now : int = lib_plankton.base.get_current_timestamp(true);
|
||||||
const cooldown_time : int = _espe.conf.get().settings.password_change.cooldown_time;
|
const cooldown_time : int = _espe.conf.get().settings.password_change.cooldown_time;
|
||||||
const member_ids : Array<_espe.type.member_id> = await (
|
const member_ids : Array<_espe.type.member_id> = await (
|
||||||
|
@ -616,8 +663,19 @@ namespace _espe.service.member
|
||||||
"password_change_token": token,
|
"password_change_token": token,
|
||||||
};
|
};
|
||||||
await _espe.repository.member.update(member_id, member_object_new);
|
await _espe.repository.member.update(member_id, member_object_new);
|
||||||
// notify_change();
|
// signal_change();
|
||||||
// do NOT wait in order to reduce information for potential attackers
|
// do NOT wait in order to reduce information for potential attackers
|
||||||
|
const url : (null | string) = _espe.helpers.frontend_url_get(
|
||||||
|
url_template,
|
||||||
|
{
|
||||||
|
"id": member_id.toFixed(0),
|
||||||
|
"token": token,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (url === null) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
else {
|
||||||
/*await*/ _espe.helpers.email_send(
|
/*await*/ _espe.helpers.email_send(
|
||||||
[
|
[
|
||||||
member_object_old.email_address_private,
|
member_object_old.email_address_private,
|
||||||
|
@ -627,19 +685,7 @@ namespace _espe.service.member
|
||||||
_espe.conf.get().settings.password_change.initialization_email.body,
|
_espe.conf.get().settings.password_change.initialization_email.body,
|
||||||
{
|
{
|
||||||
"name": name_display(member_object_old),
|
"name": name_display(member_object_old),
|
||||||
"url": lib_plankton.string.coin(
|
"url": url,
|
||||||
"{{base}}{{rest}}",
|
|
||||||
{
|
|
||||||
"base": frontend_url_base,
|
|
||||||
"rest": lib_plankton.string.coin(
|
|
||||||
url_template,
|
|
||||||
{
|
|
||||||
"id": member_id.toFixed(0),
|
|
||||||
"token": token,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -706,7 +752,7 @@ namespace _espe.service.member
|
||||||
"password_change_token": null,
|
"password_change_token": null,
|
||||||
};
|
};
|
||||||
await _espe.repository.member.update(member_id, member_object_new);
|
await _espe.repository.member.update(member_id, member_object_new);
|
||||||
notify_change();
|
signal_change();
|
||||||
await _espe.helpers.email_send(
|
await _espe.helpers.email_send(
|
||||||
[
|
[
|
||||||
member_object_old.email_address_private,
|
member_object_old.email_address_private,
|
||||||
|
@ -732,7 +778,7 @@ namespace _espe.service.member
|
||||||
) : Promise<void>
|
) : Promise<void>
|
||||||
{
|
{
|
||||||
await _espe.repository.member.delete(id);
|
await _espe.repository.member.delete(id);
|
||||||
notify_change();
|
signal_change();
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue