488 lines
8.8 KiB
TypeScript
488 lines
8.8 KiB
TypeScript
/*
|
|
Espe | Ein schlichtes Werkzeug zur Mitglieder-Verwaltung | Frontend
|
|
Copyright (C) 2024 Christian Fraß
|
|
|
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
|
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
|
|
version.
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with this program. If not, see
|
|
<https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
namespace _espe.backend
|
|
{
|
|
|
|
/**
|
|
*/
|
|
var _session_key_chest : lib_plankton.storage.type_chest<string, string, void, string, string>;
|
|
|
|
|
|
/**
|
|
* @todo use backend call
|
|
*/
|
|
export async function logged_in(
|
|
) : Promise<boolean>
|
|
{
|
|
let session_key : (null | string);
|
|
try {
|
|
session_key = (await _session_key_chest.read("session_key"));
|
|
}
|
|
catch (error) {
|
|
session_key = null;
|
|
}
|
|
return Promise.resolve<boolean>(session_key !== null);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export function init(
|
|
) : Promise<void>
|
|
{
|
|
_session_key_chest = lib_plankton.storage.localstorage.implementation_chest(
|
|
{
|
|
"corner": "aum",
|
|
}
|
|
);
|
|
return Promise.resolve<void>(undefined);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
async function abstract_call<type_input, type_output>(
|
|
http_method : string,
|
|
path : string,
|
|
options : {
|
|
data ?: type_input;
|
|
custom_response_handlers ?: Record<int, ((output_data_raw : any) => Promise<type_output>)>;
|
|
} = {}
|
|
) : Promise<type_output>
|
|
{
|
|
options = Object.assign(
|
|
{
|
|
"data": null,
|
|
"custom_response_handlers": [],
|
|
},
|
|
options
|
|
);
|
|
|
|
let session_key : (null | string);
|
|
try {
|
|
session_key = (await _session_key_chest.read("session_key"));
|
|
}
|
|
catch (error) {
|
|
session_key = null;
|
|
}
|
|
|
|
const without_content : boolean = ["HEAD","OPTIONS","GET"].includes(http_method);
|
|
return (
|
|
fetch(
|
|
lib_plankton.string.coin(
|
|
("{{scheme}}://{{host}}:{{port}}{{path_base}}{{path_action}}"),
|
|
{
|
|
"scheme": _espe.conf.get().backend.scheme,
|
|
"host": _espe.conf.get().backend.host,
|
|
"port": _espe.conf.get().backend.port.toFixed(0),
|
|
"path_base": _espe.conf.get().backend.path_base,
|
|
"path_action": path,
|
|
}
|
|
),
|
|
{
|
|
"method": http_method,
|
|
"headers": Object.assign(
|
|
{},
|
|
((! without_content) ? {"Content-Type": "application/json"} : {}),
|
|
((session_key !== null) ? {"X-Session-Key": session_key} : {})
|
|
),
|
|
"body": (
|
|
without_content
|
|
? null
|
|
: JSON.stringify(options.data)
|
|
),
|
|
}
|
|
)
|
|
.then(
|
|
x => {
|
|
if (x.status in options.custom_response_handlers) {
|
|
return x.json().then(output_data_raw => options.custom_response_handlers[x.status](output_data_raw));
|
|
}
|
|
else {
|
|
if ((x.status >= 200) && (x.status < 300)) {
|
|
return x.json();
|
|
}
|
|
else {
|
|
return Promise.reject<type_output>(new Error("irregular response status code"));
|
|
}
|
|
}
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function login(
|
|
name : string,
|
|
password : string
|
|
) : Promise<void>
|
|
{
|
|
const session_key : string = await abstract_call<{name : string; password : string;}, string>(
|
|
"POST",
|
|
"/session/begin",
|
|
{
|
|
"data": {
|
|
"name": name,
|
|
"password": password,
|
|
}
|
|
}
|
|
);
|
|
await _session_key_chest.write("session_key", session_key);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function logout(
|
|
) : Promise<void>
|
|
{
|
|
try {
|
|
await abstract_call<void, null>(
|
|
"DELETE",
|
|
"/session/end"
|
|
);
|
|
}
|
|
catch (error) {
|
|
// do nothing
|
|
}
|
|
await _session_key_chest.delete("session_key");
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function email(
|
|
receivers : Array<string>,
|
|
subject : string,
|
|
content : string
|
|
) : Promise<void>
|
|
{
|
|
return (
|
|
abstract_call(
|
|
"POST",
|
|
"/email",
|
|
{
|
|
"data": {
|
|
"receivers": receivers,
|
|
"subject": subject,
|
|
"content": content,
|
|
},
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function verification_get(
|
|
data : any
|
|
) : Promise<string>
|
|
{
|
|
return (
|
|
abstract_call(
|
|
"POST",
|
|
"/verification/get",
|
|
{
|
|
"data": {
|
|
"data": data,
|
|
},
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function verification_check(
|
|
data : any,
|
|
verification : string
|
|
) : Promise<boolean>
|
|
{
|
|
return (
|
|
abstract_call(
|
|
"POST",
|
|
"/verification/check",
|
|
{
|
|
"data": {
|
|
"data": data,
|
|
"verification": verification,
|
|
}
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function member_list(
|
|
search_term : (null | string)
|
|
) : Promise<
|
|
Array<
|
|
{
|
|
id : int;
|
|
preview : {
|
|
membership_number : string;
|
|
name_real_value : string;
|
|
name_real_index : int;
|
|
};
|
|
}
|
|
>
|
|
>
|
|
{
|
|
return (
|
|
abstract_call(
|
|
"GET",
|
|
("/member/list" + ((search_term === null) ? "" : ("?search_term=" + search_term)))
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function member_get(
|
|
id : int
|
|
) : Promise<
|
|
{
|
|
membership_number : string;
|
|
name_real_value : string;
|
|
name_real_index : int;
|
|
email_address_private : (null | string);
|
|
groups : Array<string>;
|
|
registered : boolean;
|
|
enabled : boolean;
|
|
email_use_veiled_address : boolean;
|
|
email_use_nominal_address : boolean;
|
|
email_redirect_to_private_address : boolean;
|
|
email_allow_sending : boolean;
|
|
password_set : boolean;
|
|
email_address_veiled : string;
|
|
email_address_nominal : string;
|
|
name_login : string;
|
|
}
|
|
>
|
|
{
|
|
return abstract_call(
|
|
"GET",
|
|
("/member/read/" + id.toFixed(0))
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function member_project(
|
|
data : {
|
|
membership_number : string;
|
|
name_real_value : string;
|
|
email_address_private : (null | string);
|
|
groups : Array<string>;
|
|
},
|
|
notification_target_url_template : string
|
|
) : Promise<int>
|
|
{
|
|
return abstract_call(
|
|
"POST",
|
|
"/member/project",
|
|
{
|
|
"data": {
|
|
"membership_number": data.membership_number,
|
|
"name_real_value": data.name_real_value,
|
|
"email_address_private": data.email_address_private,
|
|
"groups": data.groups,
|
|
"notification_target_url_template": notification_target_url_template,
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function member_info(
|
|
id : int,
|
|
key : string
|
|
) : Promise<
|
|
{
|
|
name_real_value : string;
|
|
name_real_index : int;
|
|
name_login : string;
|
|
email_address_veiled : string;
|
|
email_address_nominal : string;
|
|
}
|
|
>
|
|
{
|
|
return abstract_call(
|
|
"GET",
|
|
lib_plankton.string.coin(
|
|
"/member/info/{{id}}?key={{key}}",
|
|
{
|
|
"id": id.toFixed(0),
|
|
"key": key,
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function member_register(
|
|
id : int,
|
|
verification : string,
|
|
data : {
|
|
email_use_veiled_address : boolean;
|
|
email_use_nominal_address : boolean;
|
|
email_redirect_to_private_address : boolean;
|
|
password : (null | string);
|
|
},
|
|
notification_target_url_template : string
|
|
) : Promise<
|
|
Array<
|
|
{
|
|
incident : string;
|
|
details : Record<string, any>;
|
|
}
|
|
>
|
|
>
|
|
{
|
|
return (
|
|
abstract_call(
|
|
"POST",
|
|
lib_plankton.string.coin(
|
|
"/member/register/{{id}}?key={{key}}",
|
|
{
|
|
"id": id.toFixed(0),
|
|
"key": verification,
|
|
}
|
|
),
|
|
{
|
|
"data": Object.assign(
|
|
data,
|
|
{"notification_target_url_template": notification_target_url_template}
|
|
),
|
|
"custom_response_handlers": {
|
|
409: (output_data_raw) => output_data_raw,
|
|
},
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function member_modify(
|
|
id : int,
|
|
data : {
|
|
email_address_private : (null | string);
|
|
groups : Array<string>;
|
|
registered : boolean;
|
|
enabled : boolean;
|
|
}
|
|
) : Promise<void>
|
|
{
|
|
return abstract_call(
|
|
"PATCH",
|
|
("/member/modify/" + id.toFixed(0)),
|
|
{
|
|
"data": data
|
|
}
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function member_summon(
|
|
id : int,
|
|
url_template : string
|
|
) : Promise<string>
|
|
{
|
|
return (
|
|
abstract_call(
|
|
"POST",
|
|
("/member/summon/" + id.toFixed(0)),
|
|
{
|
|
"data": {
|
|
"url_template": url_template,
|
|
},
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function member_password_change_initialize(
|
|
identifier : string,
|
|
url_template : string
|
|
) : Promise<string>
|
|
{
|
|
return (
|
|
abstract_call(
|
|
"POST",
|
|
"/member/password_change/initialize",
|
|
{
|
|
"data": {
|
|
"identifier": identifier,
|
|
"url_template": url_template,
|
|
},
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function member_password_change_execute(
|
|
id : int,
|
|
token : string,
|
|
password_new : string
|
|
) : Promise<
|
|
Array<
|
|
{
|
|
incident : string;
|
|
details : Record<string, any>;
|
|
}
|
|
>
|
|
>
|
|
{
|
|
return (
|
|
abstract_call(
|
|
"PATCH",
|
|
("/member/password_change/execute/" + id.toFixed(0)),
|
|
{
|
|
"data": {
|
|
"token": token,
|
|
"password_new": password_new,
|
|
},
|
|
"custom_response_handlers": {
|
|
409: (output_data_raw) => output_data_raw,
|
|
},
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
}
|