/* Espe | Ein schlichtes Werkzeug zur Mitglieder-Verwaltung | Backend 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 . */ namespace _espe.service.invite { /** */ export function list( ) : Promise< Array< { id : _espe.type.invite_id; key : _espe.type.invite_key; expiry : (null | int); name_value : string; } > > { return ( _espe.repository.invite.dump() .then( entries => Promise.resolve( entries.map( entry => ({ "id": entry.id, "key": entry.object.key, "expiry": entry.object.expiry, "name_value": entry.object.name_value }) ) ) ) ); } /** */ export async function create( { "membership_number_changeable": membership_number_changeable, "membership_number_value": membership_number_value, "name_changeable": name_changeable, "name_value": name_value, "email_address_changeable": email_address_changeable, "email_address_value": email_address_value, "groups_changeable": groups_changeable, "groups_value": groups_value, } : { membership_number_changeable : boolean; membership_number_value : (null | string); name_changeable : boolean; name_value : string; email_address_changeable : boolean; email_address_value : (null | string); groups_changeable : boolean; groups_value : Array; }, { "expiry": expiry = -1, "notification_target_url_template": notification_target_url_template = null, "send_immediatly": send_immediatly = true, } : { expiry ?: (null | int); notification_target_url_template ?: (null | string); send_immediatly ?: boolean; } = { } ) : Promise<{id : _espe.type.invite_id; key : _espe.type.invite_key}> { /** * @todo outsource to conf */ const default_lifetime : int = (60 * 60 * 24 * 7 * 2); /** * @todo proper salt */ const invite_key : _espe.type.invite_key = lib_plankton.sha256.get( ( name_value + "/" + lib_plankton.base.get_current_timestamp(true).toFixed(0) ), "secret" ); const invite_object : _espe.type.invite_object = { "key": invite_key, "expiry": ( ((expiry !== null) && (expiry < 0)) ? (lib_plankton.base.get_current_timestamp(true) + default_lifetime) : expiry ), "membership_number_changeable": membership_number_changeable, "membership_number_value": membership_number_value, "name_changeable": name_changeable, "name_value": name_value, "email_address_changeable": email_address_changeable, "email_address_value": email_address_value, "groups_changeable": groups_changeable, "groups_value": groups_value, }; const invite_id : _espe.type.invite_id = await _espe.repository.invite.create(invite_object); // send link { if (! send_immediatly) { // do nothing } else { if ( ! ( ( (email_address_value !== null) && (email_address_value !== "") ) && (notification_target_url_template !== null) ) ) { lib_plankton.log._warning( "espe.service.invite.create.email.condition_unmet", { "details": { "provided_address": email_address_value, "notification_target_url_template": notification_target_url_template, }, } ); } else { const url : (null | string) = _espe.helpers.frontend_url_get( notification_target_url_template, { "key": invite_key, } ); try { await _espe.helpers.email_send( [email_address_value], lib_plankton.translate.get( "email.invitation.subject", { } ), lib_plankton.translate.get( "email.invitation.body", { "url": (url ?? "?"), } ), ); } catch (error) { lib_plankton.log._error( "espe.service.invite.create.email.could_not_be_sent", { "details": { "provided_address": email_address_value, "error": String(error), }, } ); } } } } return { "id": invite_id, "key": invite_key, }; } /** */ export function get_by_id( id : _espe.type.invite_id ) : Promise<_espe.type.invite_object> { return _espe.repository.invite.read(id) } /** */ function get_by_key( key : _espe.type.invite_key ) : Promise<_espe.type.invite_object> { return ( _espe.repository.invite.identify(key) .then( (id) => _espe.repository.invite.read(id) ) ); } /** */ export async function examine( key : _espe.type.invite_key ) : Promise<_espe.type.invite_object> { let invite_object : (null | _espe.type.invite_object); try { invite_object = await get_by_key(key); } catch (error) { invite_object = null; } if (invite_object === null) { return Promise.reject(new Error("not found")) } else { const now : int = lib_plankton.base.get_current_timestamp(true); if ((invite_object.expiry !== null) && (invite_object.expiry < now)) { return Promise.reject(new Error("expired")); } else { return Promise.resolve(invite_object); } } } /** * @todo heed expiry * @todo password? */ export async function accept( key : _espe.type.invite_key, membership_number_value : (null | string), name_value : (null | string), email_address_value : (null | string), groups_value : Array ) : Promise { const invite_id : _espe.type.invite_id = await _espe.repository.invite.identify(key); const invite_object : _espe.type.invite_object = await _espe.repository.invite.read(invite_id); const now : int = lib_plankton.base.get_current_timestamp(true); if ((invite_object.expiry !== null) && (invite_object.expiry < now)) { return Promise.reject(new Error("expired")); } else { const member_id : _espe.type.member_id = await _espe.service.member.project( { "membership_number": ( invite_object.membership_number_changeable ? membership_number_value : invite_object.membership_number_value ), "name_real_value": ( ( invite_object.name_changeable && (name_value !== null) ) ? name_value : invite_object.name_value ), "email_address_private": ( ( invite_object.email_address_changeable && (email_address_value !== null) ) ? email_address_value : invite_object.email_address_value ), "groups": ( invite_object.groups_changeable ? groups_value : invite_object.groups_value ), } ); await _espe.repository.invite.delete_(invite_id); } } }