[mod] strikte Typisierung
This commit is contained in:
parent
d2393e01e3
commit
553ced9038
14 changed files with 331 additions and 214 deletions
|
@ -64,19 +64,24 @@ namespace _espe.api
|
||||||
}),
|
}),
|
||||||
"restriction": restriction_logged_in,
|
"restriction": restriction_logged_in,
|
||||||
"execution": async ({"path_parameters": path_parameters, "input": input}) => {
|
"execution": async ({"path_parameters": path_parameters, "input": input}) => {
|
||||||
const member_id : _espe.type.member_id = parseInt(path_parameters["id"]);
|
if (input === null) {
|
||||||
await _espe.service.member.modify(
|
return Promise.reject(new Error("impossible"));
|
||||||
member_id,
|
}
|
||||||
{
|
else {
|
||||||
"email_address_private": input.email_address_private,
|
const member_id : _espe.type.member_id = parseInt(path_parameters["id"]);
|
||||||
"registered": input.registered,
|
await _espe.service.member.modify(
|
||||||
"enabled": input.enabled,
|
member_id,
|
||||||
}
|
{
|
||||||
);
|
"email_address_private": input.email_address_private,
|
||||||
return Promise.resolve({
|
"registered": input.registered,
|
||||||
"status_code": 200,
|
"enabled": input.enabled,
|
||||||
"data": null
|
}
|
||||||
});
|
);
|
||||||
|
return Promise.resolve({
|
||||||
|
"status_code": 200,
|
||||||
|
"data": null
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -90,24 +90,29 @@ namespace _espe.api
|
||||||
}),
|
}),
|
||||||
"restriction": restriction_none,
|
"restriction": restriction_none,
|
||||||
"execution": ({"path_parameters": path_parameters, "input": input}) => {
|
"execution": ({"path_parameters": path_parameters, "input": input}) => {
|
||||||
const member_id : _espe.type.member_id = parseInt(path_parameters["id"]);
|
if (input === null) {
|
||||||
return (
|
return Promise.reject(new Error("impossible"));
|
||||||
_espe.service.member.password_change_execute(
|
}
|
||||||
member_id,
|
else {
|
||||||
input.token,
|
const member_id : _espe.type.member_id = parseInt(path_parameters["id"]);
|
||||||
input.password_new
|
return (
|
||||||
)
|
_espe.service.member.password_change_execute(
|
||||||
.then(
|
member_id,
|
||||||
flaws => Promise.resolve({
|
input.token,
|
||||||
"status_code": (
|
input.password_new
|
||||||
(flaws.length <= 0)
|
)
|
||||||
? 200
|
.then(
|
||||||
: 409
|
flaws => Promise.resolve({
|
||||||
),
|
"status_code": (
|
||||||
"data": flaws
|
(flaws.length <= 0)
|
||||||
})
|
? 200
|
||||||
)
|
: 409
|
||||||
);
|
),
|
||||||
|
"data": flaws
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -62,11 +62,16 @@ namespace _espe.api
|
||||||
}),
|
}),
|
||||||
"restriction": restriction_none,
|
"restriction": restriction_none,
|
||||||
"execution": async ({"input": input}) => {
|
"execution": async ({"input": input}) => {
|
||||||
await _espe.service.member.password_change_initialize(input.identifier, input.url_template);
|
if (input === null) {
|
||||||
return Promise.resolve({
|
return Promise.reject(new Error("impossible"));
|
||||||
"status_code": 200,
|
}
|
||||||
"data": null
|
else {
|
||||||
});
|
await _espe.service.member.password_change_initialize(input.identifier, input.url_template);
|
||||||
|
return Promise.resolve({
|
||||||
|
"status_code": 200,
|
||||||
|
"data": null
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -67,17 +67,22 @@ namespace _espe.api
|
||||||
}),
|
}),
|
||||||
"restriction": restriction_logged_in,
|
"restriction": restriction_logged_in,
|
||||||
"execution": async ({"input": input}) => {
|
"execution": async ({"input": input}) => {
|
||||||
const member_id : _espe.type.member_id = await _espe.service.member.project(
|
if (input === null) {
|
||||||
{
|
return Promise.reject(new Error("impossible"));
|
||||||
"membership_number": input.membership_number,
|
}
|
||||||
"name_real_value": input.name_real_value,
|
else {
|
||||||
"email_address_private": (input.email_address_private ?? null),
|
const member_id : _espe.type.member_id = await _espe.service.member.project(
|
||||||
}
|
{
|
||||||
);
|
"membership_number": input.membership_number,
|
||||||
return Promise.resolve({
|
"name_real_value": input.name_real_value,
|
||||||
"status_code": 201,
|
"email_address_private": (input.email_address_private ?? null),
|
||||||
"data": member_id
|
}
|
||||||
});
|
);
|
||||||
|
return Promise.resolve({
|
||||||
|
"status_code": 201,
|
||||||
|
"data": member_id
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -115,28 +115,33 @@ namespace _espe.api
|
||||||
stuff => stuff.query_parameters["key"]
|
stuff => stuff.query_parameters["key"]
|
||||||
),
|
),
|
||||||
"execution": ({"path_parameters": path_parameters, "input": input}) => {
|
"execution": ({"path_parameters": path_parameters, "input": input}) => {
|
||||||
const member_id : _espe.type.member_id = parseInt(path_parameters["id"]);
|
if (input === null) {
|
||||||
return (
|
return Promise.reject(new Error("impossible"));
|
||||||
_espe.service.member.register(
|
}
|
||||||
member_id,
|
else {
|
||||||
{
|
const member_id : _espe.type.member_id = parseInt(path_parameters["id"]);
|
||||||
"email_use_veiled_address": input.email_use_veiled_address,
|
return (
|
||||||
"email_use_nominal_address": input.email_use_nominal_address,
|
_espe.service.member.register(
|
||||||
"email_redirect_to_private_address": input.email_redirect_to_private_address,
|
member_id,
|
||||||
"password": input.password,
|
{
|
||||||
}
|
"email_use_veiled_address": input.email_use_veiled_address,
|
||||||
)
|
"email_use_nominal_address": input.email_use_nominal_address,
|
||||||
.then(
|
"email_redirect_to_private_address": input.email_redirect_to_private_address,
|
||||||
flaws => Promise.resolve({
|
"password": input.password,
|
||||||
"status_code": (
|
}
|
||||||
(flaws.length <= 0)
|
)
|
||||||
? 200
|
.then(
|
||||||
: 409
|
flaws => Promise.resolve({
|
||||||
),
|
"status_code": (
|
||||||
"data": flaws
|
(flaws.length <= 0)
|
||||||
})
|
? 200
|
||||||
)
|
: 409
|
||||||
);
|
),
|
||||||
|
"data": flaws
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -26,7 +26,11 @@ namespace _espe.api
|
||||||
{
|
{
|
||||||
url_template : string;
|
url_template : string;
|
||||||
},
|
},
|
||||||
string
|
(
|
||||||
|
null
|
||||||
|
|
|
||||||
|
string
|
||||||
|
)
|
||||||
>(
|
>(
|
||||||
rest_subject,
|
rest_subject,
|
||||||
lib_plankton.http.enum_method.post,
|
lib_plankton.http.enum_method.post,
|
||||||
|
@ -35,13 +39,25 @@ namespace _espe.api
|
||||||
"description": "sendet an ein Mitglied eine E-Mail mit Aufforderung zur Registrierung",
|
"description": "sendet an ein Mitglied eine E-Mail mit Aufforderung zur Registrierung",
|
||||||
"restriction": restriction_logged_in,
|
"restriction": restriction_logged_in,
|
||||||
"execution": async ({"path_parameters": path_parameters, "input": input}) => {
|
"execution": async ({"path_parameters": path_parameters, "input": input}) => {
|
||||||
const member_id : _espe.type.member_id = parseInt(path_parameters["id"]);
|
if (input === null) {
|
||||||
const url : string = await _espe.service.member.summon(member_id, input.url_template);
|
return Promise.reject(new Error("impossible"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const member_id : _espe.type.member_id = parseInt(path_parameters["id"]);
|
||||||
|
const url : (null | string) = await _espe.service.member.summon(member_id, input.url_template);
|
||||||
|
|
||||||
return Promise.resolve({
|
return (
|
||||||
"status_code": 200,
|
(url === null)
|
||||||
"data": url,
|
? Promise.resolve({
|
||||||
});
|
"status_code": 409,
|
||||||
|
"data": null,
|
||||||
|
})
|
||||||
|
: Promise.resolve({
|
||||||
|
"status_code": 200,
|
||||||
|
"data": url,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -22,7 +22,17 @@ namespace _espe.api
|
||||||
rest_subject : lib_plankton.rest.type_rest
|
rest_subject : lib_plankton.rest.type_rest
|
||||||
) : void
|
) : void
|
||||||
{
|
{
|
||||||
lib_plankton.rest.register<{name : string; password : string;}, string>(
|
lib_plankton.rest.register<
|
||||||
|
{
|
||||||
|
name : string;
|
||||||
|
password : string;
|
||||||
|
},
|
||||||
|
(
|
||||||
|
null
|
||||||
|
|
|
||||||
|
string
|
||||||
|
)
|
||||||
|
>(
|
||||||
rest_subject,
|
rest_subject,
|
||||||
lib_plankton.http.enum_method.post,
|
lib_plankton.http.enum_method.post,
|
||||||
_espe.conf.get().server.path_base + "/session/begin",
|
_espe.conf.get().server.path_base + "/session/begin",
|
||||||
|
@ -50,19 +60,24 @@ namespace _espe.api
|
||||||
}),
|
}),
|
||||||
"restriction": restriction_none,
|
"restriction": restriction_none,
|
||||||
"execution": async ({"input": input}) => {
|
"execution": async ({"input": input}) => {
|
||||||
const admin : (null | _espe.service.admin.type_value) = await _espe.service.admin.login(input.name, input.password);
|
if (input === null) {
|
||||||
if (admin === null) {
|
return Promise.reject(new Error("impossible"));
|
||||||
return Promise.resolve({
|
|
||||||
"status_code": 403,
|
|
||||||
"data": null,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const session_key : string = await lib_plankton.session.begin(admin.name);
|
const admin : (null | _espe.service.admin.type_value) = await _espe.service.admin.login(input.name, input.password);
|
||||||
return Promise.resolve({
|
if (admin === null) {
|
||||||
"status_code": 201,
|
return Promise.resolve({
|
||||||
"data": session_key,
|
"status_code": 403,
|
||||||
});
|
"data": null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const session_key : string = await lib_plankton.session.begin(admin.name);
|
||||||
|
return Promise.resolve({
|
||||||
|
"status_code": 201,
|
||||||
|
"data": session_key,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,17 @@ You should have received a copy of the GNU General Public License along with thi
|
||||||
namespace _espe.api
|
namespace _espe.api
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo zu plankton auslagern?
|
||||||
|
*/
|
||||||
|
type type_stuff = {
|
||||||
|
version: (null | string);
|
||||||
|
headers: Record<string, string>;
|
||||||
|
path_parameters: Record<string, string>;
|
||||||
|
query_parameters: Record<string, string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
export async function session_from_stuff(
|
export async function session_from_stuff(
|
||||||
|
@ -69,8 +80,8 @@ namespace _espe.api
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
export function restriction_verification(
|
export function restriction_verification(
|
||||||
extract_data : ((stuff) => any),
|
extract_data : ((stuff : type_stuff) => any),
|
||||||
extract_verification : ((stuff) => string)
|
extract_verification : ((stuff : type_stuff) => string)
|
||||||
) : lib_plankton.rest.type_restriction<any>
|
) : lib_plankton.rest.type_restriction<any>
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -16,16 +16,6 @@ You should have received a copy of the GNU General Public License along with thi
|
||||||
namespace _espe.conf
|
namespace _espe.conf
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
type type_smtp_credentials = {
|
|
||||||
host : string;
|
|
||||||
port : int;
|
|
||||||
username : string;
|
|
||||||
password : string;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
export type type_conf = {
|
export type type_conf = {
|
||||||
|
@ -72,7 +62,7 @@ namespace _espe.conf
|
||||||
{
|
{
|
||||||
kind : "regular";
|
kind : "regular";
|
||||||
data : {
|
data : {
|
||||||
smtp_credentials : type_smtp_credentials;
|
smtp_credentials : _espe.helpers.type_smtp_credentials;
|
||||||
sender : string;
|
sender : string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -80,7 +70,7 @@ namespace _espe.conf
|
||||||
{
|
{
|
||||||
kind : "redirect";
|
kind : "redirect";
|
||||||
data : {
|
data : {
|
||||||
smtp_credentials : type_smtp_credentials;
|
smtp_credentials : _espe.helpers.type_smtp_credentials;
|
||||||
sender : string;
|
sender : string;
|
||||||
target : string;
|
target : string;
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,9 +30,13 @@ namespace _espe.database
|
||||||
{
|
{
|
||||||
switch (_espe.conf.get().database.kind) {
|
switch (_espe.conf.get().database.kind) {
|
||||||
case "sqlite": {
|
case "sqlite": {
|
||||||
|
type type_parameters = {
|
||||||
|
path : string;
|
||||||
|
};
|
||||||
|
const parameters : type_parameters = (_espe.conf.get().database.data as type_parameters);
|
||||||
return lib_plankton.database.sqlite_database(
|
return lib_plankton.database.sqlite_database(
|
||||||
{
|
{
|
||||||
"path": _espe.conf.get().database.data["path"],
|
"path": parameters.path,
|
||||||
"verbose": false,
|
"verbose": false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -16,6 +16,16 @@ You should have received a copy of the GNU General Public License along with thi
|
||||||
namespace _espe.helpers
|
namespace _espe.helpers
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export type type_smtp_credentials = {
|
||||||
|
host : string;
|
||||||
|
port : int;
|
||||||
|
username : string;
|
||||||
|
password : string;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
|
@ -188,30 +198,41 @@ namespace _espe.helpers
|
||||||
);
|
);
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case "regular": {
|
case "regular": {
|
||||||
if (_espe.conf.get().email_sending.data["smtp_credentials"] === null) {
|
type type_parameters = {
|
||||||
|
smtp_credentials : type_smtp_credentials;
|
||||||
|
sender : string;
|
||||||
|
};
|
||||||
|
const parameters : type_parameters = (_espe.conf.get().email_sending.data as type_parameters);
|
||||||
|
if (parameters.smtp_credentials === null) {
|
||||||
return Promise.reject<void>("no smtp credentials specified; add in conf as 'email_sending.data.smtp_credentials'!");
|
return Promise.reject<void>("no smtp credentials specified; add in conf as 'email_sending.data.smtp_credentials'!");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return email_send_real(
|
return email_send_real(
|
||||||
_espe.conf.get().email_sending.data["smtp_credentials"],
|
parameters.smtp_credentials,
|
||||||
receivers,
|
receivers,
|
||||||
subject,
|
subject,
|
||||||
content,
|
content,
|
||||||
{
|
{
|
||||||
"sender": _espe.conf.get().email_sending.data["sender"],
|
"sender": parameters.sender,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "redirect": {
|
case "redirect": {
|
||||||
if (_espe.conf.get().email_sending.data["smtp_credentials"] === null) {
|
type type_parameters = {
|
||||||
|
smtp_credentials : type_smtp_credentials;
|
||||||
|
sender : string;
|
||||||
|
target : string;
|
||||||
|
};
|
||||||
|
const parameters : type_parameters = (_espe.conf.get().email_sending.data as type_parameters);
|
||||||
|
if (parameters.smtp_credentials === null) {
|
||||||
return Promise.reject<void>("no smtp credentials specified; add in conf as 'email_sending.data.smtp_credentials'!");
|
return Promise.reject<void>("no smtp credentials specified; add in conf as 'email_sending.data.smtp_credentials'!");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return email_send_real(
|
return email_send_real(
|
||||||
_espe.conf.get().email_sending.data["smtp_credentials"],
|
parameters.smtp_credentials,
|
||||||
[_espe.conf.get().email_sending.data["target"]],
|
[parameters.target],
|
||||||
lib_plankton.string.coin(
|
lib_plankton.string.coin(
|
||||||
"[REDIRECTION] {{receivers}} | {{original_subject}}",
|
"[REDIRECTION] {{receivers}} | {{original_subject}}",
|
||||||
{
|
{
|
||||||
|
@ -221,7 +242,7 @@ namespace _espe.helpers
|
||||||
),
|
),
|
||||||
content,
|
content,
|
||||||
{
|
{
|
||||||
"sender": _espe.conf.get().email_sending.data["sender"],
|
"sender": parameters.sender,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ namespace _espe.repository.name_index
|
||||||
? name
|
? name
|
||||||
: await lib_plankton.sha256.get(
|
: await lib_plankton.sha256.get(
|
||||||
lib_plankton.json.encode(name),
|
lib_plankton.json.encode(name),
|
||||||
_espe.conf.get().settings.name_index.salt
|
(_espe.conf.get().settings.name_index.salt ?? undefined)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,38 +52,45 @@ namespace _espe.service.member
|
||||||
) : Array<{incident : string; details : Record<string, any>}>
|
) : Array<{incident : string; details : Record<string, any>}>
|
||||||
{
|
{
|
||||||
let flaws : Array<{incident : string; details : Record<string, any>}> = [];
|
let flaws : Array<{incident : string; details : Record<string, any>}> = [];
|
||||||
|
const settings : {
|
||||||
|
minimum_length : (null | int);
|
||||||
|
maximum_length : (null | int);
|
||||||
|
must_contain_letter : boolean;
|
||||||
|
must_contain_number : boolean;
|
||||||
|
must_contain_special_character : boolean;
|
||||||
|
} = _espe.conf.get().settings.password_policy;
|
||||||
if (
|
if (
|
||||||
(_espe.conf.get().settings.password_policy.minimum_length !== null)
|
(settings.minimum_length !== null)
|
||||||
&&
|
&&
|
||||||
(password.length < _espe.conf.get().settings.password_policy.minimum_length)
|
(password.length < settings.minimum_length)
|
||||||
) {
|
) {
|
||||||
flaws.push(
|
flaws.push(
|
||||||
{
|
{
|
||||||
"incident": "too_short",
|
"incident": "too_short",
|
||||||
"details": {
|
"details": {
|
||||||
"minimum_length": _espe.conf.get().settings.password_policy.minimum_length,
|
"minimum_length": settings.minimum_length,
|
||||||
"actual_length": password.length,
|
"actual_length": password.length,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
(_espe.conf.get().settings.password_policy.maximum_length !== null)
|
(settings.maximum_length !== null)
|
||||||
&&
|
&&
|
||||||
(password.length > _espe.conf.get().settings.password_policy.maximum_length)
|
(password.length > settings.maximum_length)
|
||||||
) {
|
) {
|
||||||
flaws.push(
|
flaws.push(
|
||||||
{
|
{
|
||||||
"incident": "too_long",
|
"incident": "too_long",
|
||||||
"details": {
|
"details": {
|
||||||
"maximum_length": _espe.conf.get().settings.password_policy.maximum_length,
|
"maximum_length": settings.maximum_length,
|
||||||
"actual_length": password.length,
|
"actual_length": password.length,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
_espe.conf.get().settings.password_policy.must_contain_letter
|
settings.must_contain_letter
|
||||||
&&
|
&&
|
||||||
(! (new RegExp("[a-zA-Z]")).test(password))
|
(! (new RegExp("[a-zA-Z]")).test(password))
|
||||||
) {
|
) {
|
||||||
|
@ -96,7 +103,7 @@ namespace _espe.service.member
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
_espe.conf.get().settings.password_policy.must_contain_number
|
settings.must_contain_number
|
||||||
&&
|
&&
|
||||||
(! (new RegExp("[0-9]")).test(password))
|
(! (new RegExp("[0-9]")).test(password))
|
||||||
) {
|
) {
|
||||||
|
@ -109,7 +116,7 @@ namespace _espe.service.member
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
_espe.conf.get().settings.password_policy.must_contain_special_character
|
settings.must_contain_special_character
|
||||||
&&
|
&&
|
||||||
(! (new RegExp("[!?-_.,;/\~%&$'()\\[\\]{}^'#|+*<>=\"`:@]")).test(password))
|
(! (new RegExp("[!?-_.,;/\~%&$'()\\[\\]{}^'#|+*<>=\"`:@]")).test(password))
|
||||||
) {
|
) {
|
||||||
|
@ -138,13 +145,13 @@ namespace _espe.service.member
|
||||||
"object": lib_plankton.call.convey(
|
"object": lib_plankton.call.convey(
|
||||||
object.name_real_value,
|
object.name_real_value,
|
||||||
[
|
[
|
||||||
x => x.toLowerCase(),
|
(x : string) => x.toLowerCase(),
|
||||||
x => x.replace(new RegExp(" ", "g"), "."),
|
(x : string) => x.replace(new RegExp(" ", "g"), "."),
|
||||||
x => x.replace(new RegExp("[äÄ]", "g"), "ae"),
|
(x : string) => x.replace(new RegExp("[äÄ]", "g"), "ae"),
|
||||||
x => x.replace(new RegExp("[öÖ]", "g"), "oe"),
|
(x : string) => x.replace(new RegExp("[öÖ]", "g"), "oe"),
|
||||||
x => x.replace(new RegExp("[üÜ]", "g"), "ue"),
|
(x : string) => x.replace(new RegExp("[üÜ]", "g"), "ue"),
|
||||||
x => x.replace(new RegExp("[ß]", "g"), "ss"),
|
(x : string) => x.replace(new RegExp("[ß]", "g"), "ss"),
|
||||||
x => x.replace(new RegExp("[^a-z-\.]", "g"), "_"),
|
(x : string) => x.replace(new RegExp("[^a-z-\.]", "g"), "_"),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
"extension": (
|
"extension": (
|
||||||
|
@ -227,7 +234,7 @@ namespace _espe.service.member
|
||||||
*/
|
*/
|
||||||
function password_image(
|
function password_image(
|
||||||
password : (null | string)
|
password : (null | string)
|
||||||
) : Promise<string>
|
) : Promise<(null | string)>
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
(
|
(
|
||||||
|
@ -236,7 +243,7 @@ namespace _espe.service.member
|
||||||
(! (password === ""))
|
(! (password === ""))
|
||||||
)
|
)
|
||||||
? _espe.helpers.bcrypt_compute(password)
|
? _espe.helpers.bcrypt_compute(password)
|
||||||
: null
|
: Promise.resolve<(null | string)>(null)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,31 +339,36 @@ namespace _espe.service.member
|
||||||
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<string>
|
) : Promise<(null | string)>
|
||||||
{
|
{
|
||||||
const member_object : _espe.type.member_object = await get(member_id);
|
const member_object : _espe.type.member_object = await get(member_id);
|
||||||
const verification : string = await _espe.helpers.verification_get(member_id);
|
if (member_object.email_address_private === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const verification : string = await _espe.helpers.verification_get(member_id);
|
||||||
|
|
||||||
const url : string = lib_plankton.string.coin(
|
const url : string = lib_plankton.string.coin(
|
||||||
url_template,
|
url_template,
|
||||||
{
|
|
||||||
"verification": verification,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
await _espe.helpers.email_send(
|
|
||||||
[
|
|
||||||
member_object.email_address_private,
|
|
||||||
],
|
|
||||||
_espe.conf.get().settings.registration_email.subject,
|
|
||||||
lib_plankton.string.coin(
|
|
||||||
_espe.conf.get().settings.registration_email.body,
|
|
||||||
{
|
{
|
||||||
"name": member_object.name_real_value,
|
"verification": verification,
|
||||||
"url": url,
|
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
);
|
await _espe.helpers.email_send(
|
||||||
return url;
|
[
|
||||||
|
member_object.email_address_private,
|
||||||
|
],
|
||||||
|
_espe.conf.get().settings.registration_email.subject,
|
||||||
|
lib_plankton.string.coin(
|
||||||
|
_espe.conf.get().settings.registration_email.body,
|
||||||
|
{
|
||||||
|
"name": member_object.name_real_value,
|
||||||
|
"url": url,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return url;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -406,7 +418,7 @@ namespace _espe.service.member
|
||||||
email_use_veiled_address : boolean;
|
email_use_veiled_address : boolean;
|
||||||
email_use_nominal_address : boolean;
|
email_use_nominal_address : boolean;
|
||||||
email_redirect_to_private_address : boolean;
|
email_redirect_to_private_address : boolean;
|
||||||
password : string;
|
password : (null | string);
|
||||||
},
|
},
|
||||||
options : {
|
options : {
|
||||||
notify_admins ?: boolean;
|
notify_admins ?: boolean;
|
||||||
|
@ -431,7 +443,11 @@ namespace _espe.service.member
|
||||||
flaws.push({"incident": "already_registered", "details": {}});
|
flaws.push({"incident": "already_registered", "details": {}});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (password_set) {
|
if (
|
||||||
|
password_set
|
||||||
|
&&
|
||||||
|
(data.password !== null)
|
||||||
|
) {
|
||||||
flaws = flaws.concat(
|
flaws = flaws.concat(
|
||||||
validate_password(data.password)
|
validate_password(data.password)
|
||||||
.map(flaw => ({"incident": ("password_" + flaw.incident), "details": flaw.details}))
|
.map(flaw => ({"incident": ("password_" + flaw.incident), "details": flaw.details}))
|
||||||
|
@ -461,9 +477,11 @@ namespace _espe.service.member
|
||||||
else {
|
else {
|
||||||
await _espe.helpers.email_send(
|
await _espe.helpers.email_send(
|
||||||
(
|
(
|
||||||
_espe.conf.get().admins
|
(
|
||||||
.map(admin => admin.email_address)
|
_espe.conf.get().admins
|
||||||
.filter(x => (x !== null))
|
.map(admin => admin.email_address)
|
||||||
|
.filter(x => (x !== null))
|
||||||
|
) as Array<string>
|
||||||
),
|
),
|
||||||
"Eingegangene Registrierung", // TODO
|
"Eingegangene Registrierung", // TODO
|
||||||
("Member-ID: " + member_id.toFixed(0))
|
("Member-ID: " + member_id.toFixed(0))
|
||||||
|
@ -518,7 +536,8 @@ namespace _espe.service.member
|
||||||
url_template : string
|
url_template : string
|
||||||
) : Promise<void>
|
) : Promise<void>
|
||||||
{
|
{
|
||||||
if (_espe.conf.get().settings.frontend_url_base === null) {
|
const frontend_url_base : (null | string) = _espe.conf.get().settings.frontend_url_base;
|
||||||
|
if (frontend_url_base === null) {
|
||||||
return Promise.reject<void>(new Error("no frontend url base set; add in conf as 'settings.frontend_url_base'!"));
|
return Promise.reject<void>(new Error("no frontend url base set; add in conf as 'settings.frontend_url_base'!"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -607,7 +626,7 @@ namespace _espe.service.member
|
||||||
"url": lib_plankton.string.coin(
|
"url": lib_plankton.string.coin(
|
||||||
"{{base}}{{rest}}",
|
"{{base}}{{rest}}",
|
||||||
{
|
{
|
||||||
"base": _espe.conf.get().settings.frontend_url_base,
|
"base": frontend_url_base,
|
||||||
"rest": lib_plankton.string.coin(
|
"rest": lib_plankton.string.coin(
|
||||||
url_template,
|
url_template,
|
||||||
{
|
{
|
||||||
|
@ -639,62 +658,67 @@ namespace _espe.service.member
|
||||||
) : Promise<Array<{incident : string; details : Record<string, any>;}>>
|
) : Promise<Array<{incident : string; details : Record<string, any>;}>>
|
||||||
{
|
{
|
||||||
const member_object_old : _espe.type.member_object = await _espe.repository.member.read(member_id);
|
const member_object_old : _espe.type.member_object = await _espe.repository.member.read(member_id);
|
||||||
let flaws : Array<{incident : string; details : Record<string, any>;}> = [];
|
if (member_object_old.email_address_private === null) {
|
||||||
if (
|
return Promise.reject(new Error("private e-mail address missing"));
|
||||||
(member_object_old.password_change_token === null)
|
|
||||||
||
|
|
||||||
(! (token === member_object_old.password_change_token))
|
|
||||||
) {
|
|
||||||
lib_plankton.log.notice(
|
|
||||||
"member_password_change_token_invalid",
|
|
||||||
{
|
|
||||||
"member_id": member_id,
|
|
||||||
"token_sent": token,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
flaws.push({"incident": "token_invalid", "details": {}});
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
flaws = flaws.concat(
|
let flaws : Array<{incident : string; details : Record<string, any>;}> = [];
|
||||||
validate_password(password_new)
|
if (
|
||||||
.map(flaw => ({"incident": ("password_" + flaw.incident), "details": flaw.details}))
|
(member_object_old.password_change_token === null)
|
||||||
);
|
||
|
||||||
if (flaws.length > 0) {
|
(! (token === member_object_old.password_change_token))
|
||||||
// do nothing
|
) {
|
||||||
|
lib_plankton.log.notice(
|
||||||
|
"member_password_change_token_invalid",
|
||||||
|
{
|
||||||
|
"member_id": member_id,
|
||||||
|
"token_sent": token,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
flaws.push({"incident": "token_invalid", "details": {}});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const member_object_new : _espe.type.member_object = {
|
flaws = flaws.concat(
|
||||||
"membership_number": member_object_old.membership_number,
|
validate_password(password_new)
|
||||||
"name_real_value": member_object_old.name_real_value,
|
.map(flaw => ({"incident": ("password_" + flaw.incident), "details": flaw.details}))
|
||||||
"name_real_index": member_object_old.name_real_index,
|
|
||||||
"email_address_private": member_object_old.email_address_private,
|
|
||||||
"registered": member_object_old.registered,
|
|
||||||
"enabled": member_object_old.enabled,
|
|
||||||
"email_use_veiled_address": member_object_old.email_use_veiled_address,
|
|
||||||
"email_use_nominal_address": member_object_old.email_use_nominal_address,
|
|
||||||
"email_redirect_to_private_address": member_object_old.email_redirect_to_private_address,
|
|
||||||
"email_allow_sending": member_object_old.email_allow_sending,
|
|
||||||
"password_image": await password_image(password_new),
|
|
||||||
"password_change_last_attempt": member_object_old.password_change_last_attempt,
|
|
||||||
"password_change_token": null,
|
|
||||||
};
|
|
||||||
await _espe.repository.member.update(member_id, member_object_new);
|
|
||||||
notify_change();
|
|
||||||
await _espe.helpers.email_send(
|
|
||||||
[
|
|
||||||
member_object_old.email_address_private,
|
|
||||||
],
|
|
||||||
_espe.conf.get().settings.password_change.execution_email.subject,
|
|
||||||
lib_plankton.string.coin(
|
|
||||||
_espe.conf.get().settings.password_change.execution_email.body,
|
|
||||||
{
|
|
||||||
"name": name_display(member_object_old),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
if (flaws.length > 0) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const member_object_new : _espe.type.member_object = {
|
||||||
|
"membership_number": member_object_old.membership_number,
|
||||||
|
"name_real_value": member_object_old.name_real_value,
|
||||||
|
"name_real_index": member_object_old.name_real_index,
|
||||||
|
"email_address_private": member_object_old.email_address_private,
|
||||||
|
"registered": member_object_old.registered,
|
||||||
|
"enabled": member_object_old.enabled,
|
||||||
|
"email_use_veiled_address": member_object_old.email_use_veiled_address,
|
||||||
|
"email_use_nominal_address": member_object_old.email_use_nominal_address,
|
||||||
|
"email_redirect_to_private_address": member_object_old.email_redirect_to_private_address,
|
||||||
|
"email_allow_sending": member_object_old.email_allow_sending,
|
||||||
|
"password_image": await password_image(password_new),
|
||||||
|
"password_change_last_attempt": member_object_old.password_change_last_attempt,
|
||||||
|
"password_change_token": null,
|
||||||
|
};
|
||||||
|
await _espe.repository.member.update(member_id, member_object_new);
|
||||||
|
notify_change();
|
||||||
|
await _espe.helpers.email_send(
|
||||||
|
[
|
||||||
|
member_object_old.email_address_private,
|
||||||
|
],
|
||||||
|
_espe.conf.get().settings.password_change.execution_email.subject,
|
||||||
|
lib_plankton.string.coin(
|
||||||
|
_espe.conf.get().settings.password_change.execution_email.body,
|
||||||
|
{
|
||||||
|
"name": name_display(member_object_old),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return flaws;
|
||||||
}
|
}
|
||||||
return flaws;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -727,20 +751,31 @@ namespace _espe.service.member
|
||||||
|
|
||||||
const nm_yaml = require("yaml");
|
const nm_yaml = require("yaml");
|
||||||
|
|
||||||
|
type type_entry = {
|
||||||
|
disabled : boolean;
|
||||||
|
displayname : string;
|
||||||
|
email : string;
|
||||||
|
groups : Array<string>;
|
||||||
|
password : string;
|
||||||
|
};
|
||||||
return lib_plankton.call.convey(
|
return lib_plankton.call.convey(
|
||||||
(
|
(
|
||||||
(options.custom_data !== null)
|
(
|
||||||
|
(options.custom_data !== undefined)
|
||||||
|
&&
|
||||||
|
(options.custom_data !== null)
|
||||||
|
)
|
||||||
? (options.custom_data.map((member_object, index) => ({"id": index, "object": member_object})))
|
? (options.custom_data.map((member_object, index) => ({"id": index, "object": member_object})))
|
||||||
: await dump()
|
: await dump()
|
||||||
),
|
),
|
||||||
[
|
[
|
||||||
x => x.map(
|
(x : Array<any>) => x.map(
|
||||||
entry => Object.assign(
|
entry => Object.assign(
|
||||||
entry,
|
entry,
|
||||||
{"email_address": email_address(entry.object)}
|
{"email_address": email_address(entry.object)}
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
x => x.filter(
|
(x : Array<any>) => x.filter(
|
||||||
entry => (
|
entry => (
|
||||||
entry.object.registered
|
entry.object.registered
|
||||||
&&
|
&&
|
||||||
|
@ -753,7 +788,7 @@ namespace _espe.service.member
|
||||||
(entry.email_address !== null)
|
(entry.email_address !== null)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
x => x.map(
|
(x : Array<any>) => x.map(
|
||||||
entry => ([
|
entry => ([
|
||||||
name_login(entry.object),
|
name_login(entry.object),
|
||||||
{
|
{
|
||||||
|
@ -766,8 +801,8 @@ namespace _espe.service.member
|
||||||
])
|
])
|
||||||
),
|
),
|
||||||
Object.fromEntries,
|
Object.fromEntries,
|
||||||
x => ({"users": x}),
|
(x : Record<string, type_entry>) => ({"users": x}),
|
||||||
x => nm_yaml.stringify(x),
|
(x : {users : Record<string, type_entry>}) => nm_yaml.stringify(x),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ ${dir_temp}/espe-core.js ${dir_temp}/espe-core.d.ts: \
|
||||||
${dir_source}/conf.ts
|
${dir_source}/conf.ts
|
||||||
@ ${cmd_log} "compile | core …"
|
@ ${cmd_log} "compile | core …"
|
||||||
@ ${cmd_mkdir} $(dir $@)
|
@ ${cmd_mkdir} $(dir $@)
|
||||||
@ tsc --lib es2020 $^ --outFile ${dir_temp}/espe-core.js --declaration
|
@ tsc --lib es2020 --strict $^ --outFile ${dir_temp}/espe-core.js --declaration
|
||||||
|
|
||||||
.PHONY: main
|
.PHONY: main
|
||||||
main: core ${dir_build}/espe
|
main: core ${dir_build}/espe
|
||||||
|
|
Loading…
Add table
Reference in a new issue