[mod] strikte Typisierung

This commit is contained in:
roydfalk 2024-05-27 17:32:42 +02:00
parent d2393e01e3
commit 553ced9038
14 changed files with 331 additions and 214 deletions

View file

@ -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
});
}
} }
} }
); );

View file

@ -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
})
)
);
}
}, },
} }
) )

View file

@ -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
});
}
}, },
} }
) )

View file

@ -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
});
}
} }
} }
); );

View file

@ -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
})
)
);
}
}, },
} }
) )

View file

@ -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,
})
);
}
} }
} }
); );

View file

@ -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,
});
}
} }
}, },
} }

View file

@ -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 (

View file

@ -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;
}; };

View file

@ -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,
} }
); );

View file

@ -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,
} }
); );
} }

View file

@ -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)
) )
); );
} }

View file

@ -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),
] ]
); );
} }

View file

@ -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