From 4b6ed73bd3001d4632ebd4789e609501c42ca77c Mon Sep 17 00:00:00 2001 From: Fenris Wolf Date: Mon, 6 Oct 2025 18:06:15 +0200 Subject: [PATCH] [mod] namespace: espe -> zackeneule [mod] page:invitation_handle [mod] tools:deploy:default target path --- source/data/localization/deu.loc.json | 20 +- source/data/localization/eng.loc.json | 54 +++--- source/helpers.ts | 2 +- source/logic.ts | 4 +- source/main.ts | 12 +- source/pages/group_create/logic.ts | 4 +- source/pages/group_list/logic.ts | 4 +- source/pages/group_view/logic.ts | 6 +- source/pages/invitation_create/logic.ts | 12 +- source/pages/invitation_handle/logic.ts | 176 +++++++++++++++--- source/pages/invitation_handle/style.css | 15 +- source/pages/invitation_list/logic.ts | 6 +- source/pages/invitation_view/logic.ts | 23 ++- source/pages/login/logic.ts | 4 +- source/pages/logout/logic.ts | 2 +- source/pages/member_list/logic.ts | 4 +- source/pages/member_view/logic.ts | 8 +- source/pages/password_change_exec/logic.ts | 4 +- source/pages/password_change_init/logic.ts | 4 +- source/resources/backend.ts | 115 ++++-------- source/resources/conf.ts | 2 +- source/style/main.css | 105 ++++++++++- source/widgets/password_policy/logic.ts | 152 +++++++++++++++ source/widgets/password_policy/structure.html | 6 + source/widgets/password_policy/style.css | 13 ++ tools/deploy | 2 +- tools/makefile | 3 + 27 files changed, 577 insertions(+), 185 deletions(-) create mode 100644 source/widgets/password_policy/logic.ts create mode 100644 source/widgets/password_policy/structure.html create mode 100644 source/widgets/password_policy/style.css diff --git a/source/data/localization/deu.loc.json b/source/data/localization/deu.loc.json index 7cde0d5..b7d05af 100644 --- a/source/data/localization/deu.loc.json +++ b/source/data/localization/deu.loc.json @@ -9,6 +9,8 @@ "common.timezone_shift": "Zeitzonen-Verschiebung", "common.date": "Datum", "common.time": "Uhzeit", + "common.loading": "laden …", + "common.checking": "prüfen …", "domain.group.name.label": "Name", "domain.group.label.label": "Beschriftung", "domain.member.member": "Mitglied", @@ -17,6 +19,7 @@ "domain.member.label.label": "Anzeigename", "domain.member.label.help": "wie du angezeigt wirst\n\nkann später geändert werden", "domain.member.groups.label": "Gruppen", + "domain.member.groups.help": "die Gruppen, denen du zugeordnet bist", "domain.member.registered.label": "registriert", "domain.member.enabled.label": "aktiviert", "domain.member.email_address.label": "E-Mail-Adresse", @@ -25,6 +28,12 @@ "domain.invitation.key.label": "Schlüssel", "domain.invitation.expiry.label": "Ablaufzeitpunkt", "domain.invitation.url.label": "URL", + "widget.password_policy.title": "Passwort-Richtlinien", + "widget.password_policy.minimum_length": "mindestens {{minimum_length}} Zeichen", + "widget.password_policy.maximum_length": "höchstens {{maximum_length}} Zeichen", + "widget.password_policy.must_contain_letter": "muss einen Buchstaben beinhalten", + "widget.password_policy.must_contain_number": "muss eine Zahl beinhalten", + "widget.password_policy.must_contain_special_character": "muss ein Sonderzeichen beinhalten", "page.login.title": "Anmelden", "page.login.name": "Name", "page.login.password": "Passwort", @@ -33,6 +42,7 @@ "page.group_list.title": "Gruppen", "page.group_create.title": "Gruppe anlegen", "page.group_create.form.submit": "Abschicken", + "page.group_view.title": "Gruppe bearbeiten", "page.member_create.title": "Mitglied anlegen", "page.member_list.title": "Mitglieder", "page.member_view.title": "Mitglied", @@ -61,22 +71,18 @@ "page.invitation_create.title": "Einladung anlegen", "page.invitation_create.form.field.send_immediatly.label": "Link sofort versenden", "page.invitation_create.form.action.submit": "anlegen", + "page.invitation_view.form.action.delete": "löschen", "page.invitation_view.title": "Einladung", "page.invitation_handle.title": "Einladung", "page.invitation_handle.message.invalid": "ungültig", "page.invitation_handle.message.successful": "erfolgreich; eine E-Mail mit Zugangsdaten wird an die angegebene Adresse geschickt", "page.invitation_handle.form.action.submit": "annehmen", "page.invitation_handle.form.field.password_value.label": "Passwort", - "page.invitation_handle.form.field.password_value.help": "das Passwort für die Anmeldung bei den Netz-Diensten.\n\nDu solltest dir merken oder geeignet abspeichern, was du hier einträgst.\n\nSolltest du dieses Passwort mal vergessen oder verlieren, hast du die Möglichkeit ein neues zu setzen.", + "page.invitation_handle.form.field.password_value.help": "das Passwort für die Anmeldung bei den Netz-Diensten.\n\ndu solltest dir merken oder geeignet abspeichern, was du hier einträgst.\n\nsolltest du dieses Passwort mal vergessen oder verlieren, hast du die Möglichkeit ein neues zu setzen.", "page.invitation_handle.form.field.password_confirmation.label": "Passwort wiederholen", - "page.invitation_handle.form.field.password_confirmation.help": "", "page.invitation_handle.flaw.already_registered": "bereits registriert", + "page.invitation_handle.flaw.password_invalid": "Passwort ungültig", "page.invitation_handle.flaw.password_mismatch": "die Passwörter stimmen nicht überein", - "page.invitation_handle.flaw.password_too_short": "das Passwort muss mindestens {{minimum_length}} Zeichen haben", - "page.invitation_handle.flaw.password_too_long": "das Passwort darf höchstens {{maximum_length}} Zeichen haben", - "page.invitation_handle.flaw.password_lacks_letter": "das Passwort muss einen Buchstaben beinhalten", - "page.invitation_handle.flaw.password_lacks_number": "das Passwort muss eine Zahl beinhalten", - "page.invitation_handle.flaw.password_lacks_special_character": "das Passwort muss ein Sonderzeichen beinhalten", "page.invitation_handle.flaw.unhandled_error": "da ist etwas schief gelaufen :/" } } diff --git a/source/data/localization/eng.loc.json b/source/data/localization/eng.loc.json index 3071f71..a1f1f56 100644 --- a/source/data/localization/eng.loc.json +++ b/source/data/localization/eng.loc.json @@ -9,6 +9,8 @@ "common.timezone_shift": "timezone shift", "common.date": "date", "common.time": "time", + "common.loading": "loading …", + "common.checking": "checking …", "domain.group.name.label": "name", "domain.group.label.label": "label", "domain.member.member": "member", @@ -17,6 +19,7 @@ "domain.member.label.label": "display name", "domain.member.label.help": "how you are displayed\n\ncan be changed later on", "domain.member.groups.label": "groups", + "domain.member.groups.help": "groups, which you belong to", "domain.member.registered.label": "registered", "domain.member.enabled.label": "enabled", "domain.member.email_address.label": "e-mail address", @@ -25,58 +28,61 @@ "domain.invitation.key.label": "key", "domain.invitation.expiry.label": "expiration", "domain.invitation.url.url": "URL", + "widget.password_policy.title": "password policy", + "widget.password_policy.minimum_length": "at least {{minimum_length}} characters", + "widget.password_policy.maximum_length": "at most {{maximum_length}} characters", + "widget.password_policy.must_contain_letter": "must contain a letter", + "widget.password_policy.must_contain_number": "must contain a number", + "widget.password_policy.must_contain_special_character": "must contain a special character", "page.login.title": "login", "page.login.name": "name", "page.login.password": "password", "page.login.submit": "login", "page.logout.title": "logout", "page.group_list.title": "groups", - "page.group_create.title": "Create group", + "page.group_create.title": "create group", "page.group_create.form.submit": "submit", + "page.group_view.title": "edit group", "page.member_create.title": "Create member", - "page.member_list.title": "Members", - "page.member_view.title": "Member", + "page.member_list.title": "members", + "page.member_view.title": "member", "page.member_view.form.action.save": "save changes", - "page.password_change_init.title": "Change Password", - "page.password_change_init.info": "In case your member account can be found, an e-mail with further instructions will be sent to your private e-mail address.", - "page.password_change_init.identifier": "Login name or private e-mail address", - "page.password_change_init.submit": "Procede", + "page.password_change_init.title": "change Password", + "page.password_change_init.info": "in case your member account can be found, an e-mail with further instructions will be sent to your private e-mail address.", + "page.password_change_init.identifier": "login name or private e-mail address", + "page.password_change_init.submit": "procede", "page.password_change_init.status.wait": "just a second …", "page.password_change_init.status.success": "Done. Take a look into your e-mail inbox", - "page.password_change_init.status.fail": "Something went wrong :/", - "page.password_change_exec.title": "Change Password", + "page.password_change_init.status.fail": "something went wrong :/", + "page.password_change_exec.title": "change password", "page.password_change_exec.form.field.password_value.label": "password", "page.password_change_exec.form.field.password_confirmation.label": "confirm password", - "page.password_change_exec.form.submit": "Change", + "page.password_change_exec.form.submit": "change", "page.password_change_exec.flaw.token_invalid": "permission expired", - "page.password_change_exec.flaw.password_mismatch": "die Passwörter stimmen nicht überein", - "page.password_change_exec.flaw.password_too_short": "das Passwort muss mindestens {{minimum_length}} Zeichen haben", - "page.password_change_exec.flaw.password_too_long": "das Passwort darf höchstens {{maximum_length}} Zeichen haben", - "page.password_change_exec.flaw.password_lacks_letter": "das Passwort muss einen Buchstaben beinhalten", - "page.password_change_exec.flaw.password_lacks_number": "das Passwort muss ein Zahl beinhalten", - "page.password_change_exec.flaw.password_lacks_special_character": "das Passwort muss ein Sonderzeichen beinhalten", - "page.password_change_exec.flaw.unhandled_error": "da ist etwas schief gelaufen :/", + "page.password_change_exec.flaw.password_mismatch": "the passwords do not match", + "page.password_change_exec.flaw.password_too_short": "the password must have at least {{minimum_length}} characters", + "page.password_change_exec.flaw.password_too_long": "the password must have at most {{maximum_length}} characters", + "page.password_change_exec.flaw.password_lacks_letter": "the password must contain a letter", + "page.password_change_exec.flaw.password_lacks_number": "the password must contain a number", + "page.password_change_exec.flaw.password_lacks_special_character": "the password must contain a special character", + "page.password_change_exec.flaw.unhandled_error": "something went wrong :/", "page.password_change_exec.status.success": "done", "page.invitation_list.title": "invitations", "page.invitation_create.title": "create invitation", "page.invitation_create.form.field.send_immediatly.label": "send link immediatly", "page.invitation_create.form.action.submit": "create", + "page.invitation_view.form.action.delete": "delete", "page.invitation_view.title": "invitation", "page.invitation_handle.title": "invitation", "page.invitation_handle.message.invalid": "invalid", "page.invitation_handle.message.successful": "successful; an e-mail, containing the credentials, is sent to the provided address", "page.invitation_handle.form.action.submit": "accept", "page.invitation_handle.form.field.password_value.label": "password", - "page.invitation_handle.form.field.password_value.help": "the password for logging in to the online services\n\nYou should remember, denote or save properly, what you enter here.\n\nIn case you forget or lose the password some day, you can reset it.", + "page.invitation_handle.form.field.password_value.help": "the password for logging in to the online services\n\nyou should remember, denote or save properly, what you enter here.\n\nin case you forget or lose the password some day, you can reset it.", "page.invitation_handle.form.field.password_confirmation.label": "confirm password", - "page.invitation_handle.form.field.password_confirmation.help": "", "page.invitation_handle.flaw.already_registered": "already registered", + "page.invitation_handle.flaw.password_invalid": "invalid password", "page.invitation_handle.flaw.password_mismatch": "passwords do not match", - "page.invitation_handle.flaw.password_too_short": "the password must have at least {{minimum_length}} characters", - "page.invitation_handle.flaw.password_too_long": "the password must not have more than {{maximum_length}} characters", - "page.invitation_handle.flaw.password_lacks_letter": "the password must contain a letter", - "page.invitation_handle.flaw.password_lacks_number": "the password must contain a number", - "page.invitation_handle.flaw.password_lacks_special_character": "the password must contain a special character", "page.invitation_handle.flaw.unhandled_error": "something went wrong :/" } } diff --git a/source/helpers.ts b/source/helpers.ts index 4cc537c..20c4e50 100644 --- a/source/helpers.ts +++ b/source/helpers.ts @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with thi */ -namespace _espe.helpers +namespace _zackeneule.helpers { /** diff --git a/source/logic.ts b/source/logic.ts index 48cc08a..7cdf417 100644 --- a/source/logic.ts +++ b/source/logic.ts @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with thi */ -namespace _espe.logic +namespace _zackeneule.logic { /** @@ -78,7 +78,7 @@ namespace _espe.logic label : string; }; } - > = await _espe.backend.group_list(); + > = await _zackeneule.backend.group_list(); const pool : Map = new Map(); const order : Array = new Array(); for (const entry of array) diff --git a/source/main.ts b/source/main.ts index 486fd41..d37db58 100644 --- a/source/main.ts +++ b/source/main.ts @@ -25,7 +25,7 @@ async function update_nav( options = Object.assign( { "mode": ( - (await _espe.backend.logged_in()) + (await _zackeneule.backend.logged_in()) ? "logged_in" : "logged_out" ), @@ -104,9 +104,9 @@ function setup_nav( async function main( ) : Promise { - await _espe.conf.load(); + await _zackeneule.conf.load(); - await _espe.backend.init(); + await _zackeneule.backend.init(); await lib_plankton.translate.initialize( { @@ -120,7 +120,7 @@ async function main( } ); - await _espe.logic.init(); + await _zackeneule.logic.init(); await lib_plankton.zoo_page.init( document.querySelector("main"), @@ -130,8 +130,8 @@ async function main( ); // set title - document.querySelector("header > h1").textContent = _espe.conf.get().settings.title; - document.querySelector("title").textContent = _espe.conf.get().settings.title; + document.querySelector("header > h1").textContent = _zackeneule.conf.get().settings.title; + document.querySelector("title").textContent = _zackeneule.conf.get().settings.title; setup_nav(); diff --git a/source/pages/group_create/logic.ts b/source/pages/group_create/logic.ts index d7db1f0..f9aa9c8 100644 --- a/source/pages/group_create/logic.ts +++ b/source/pages/group_create/logic.ts @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with thi lib_plankton.zoo_page.register( "group_create", (parameters, target_element) => { - target_element.appendChild(_espe.helpers.template_request("group_create")); + target_element.appendChild(_zackeneule.helpers.template_request("group_create")); target_element.querySelector(".group_create-title").textContent = lib_plankton.translate.get("page.group_create.title"); @@ -51,7 +51,7 @@ lib_plankton.zoo_page.register( "label": lib_plankton.translate.get("page.group_create.form.submit"), "procedure": async (get_value, get_representation) => { const value = await get_value(); - const id : int = await _espe.backend.group_add(value); + const id : int = await _zackeneule.backend.group_add(value); // lib_plankton.zoo_page.set({"name": "group_view", "parameters": {"id": id}}); lib_plankton.zoo_page.set({"name": "group_list", "parameters": {}}); }, diff --git a/source/pages/group_list/logic.ts b/source/pages/group_list/logic.ts index 9d796e8..5023970 100644 --- a/source/pages/group_list/logic.ts +++ b/source/pages/group_list/logic.ts @@ -25,7 +25,7 @@ lib_plankton.zoo_page.register( }; const term : (null | string) = (parameters["term"] ?? ""); - target_element.appendChild(_espe.helpers.template_request("group_list")); + target_element.appendChild(_zackeneule.helpers.template_request("group_list")); target_element.querySelector(".group_list-title").textContent = lib_plankton.translate.get("page.group_list.title"); @@ -46,7 +46,7 @@ lib_plankton.zoo_page.register( } const search : lib_plankton.zoo_search.type_search = lib_plankton.zoo_search.make( - (term) => _espe.backend.group_list(), + (term) => _zackeneule.backend.group_list(), { "encode_item": (item) => lib_plankton.string.coin( "{{label}}", diff --git a/source/pages/group_view/logic.ts b/source/pages/group_view/logic.ts index b1283aa..9bad12d 100644 --- a/source/pages/group_view/logic.ts +++ b/source/pages/group_view/logic.ts @@ -18,11 +18,11 @@ lib_plankton.zoo_page.register( async (parameters, target_element) => { const id : int = parseInt(parameters["id"]); - let dom_fragment : DocumentFragment = _espe.helpers.template_request("group_view"); + let dom_fragment : DocumentFragment = _zackeneule.helpers.template_request("group_view"); dom_fragment.querySelector(".group_view-title").textContent = lib_plankton.translate.get("page.group_view.title"); - const group_object = await _espe.backend.group_get(id); + const group_object = await _zackeneule.backend.group_get(id); const form = new lib_plankton.zoo_form.class_form< { @@ -55,7 +55,7 @@ lib_plankton.zoo_page.register( "label": lib_plankton.translate.get("page.group_create.form.submit"), "procedure": async (get_value, get_representation) => { const value = await get_value(); - await _espe.backend.group_modify(id, value); + await _zackeneule.backend.group_modify(id, value); lib_plankton.zoo_page.set({"name": "group_list", "parameters": {}}); }, } diff --git a/source/pages/invitation_create/logic.ts b/source/pages/invitation_create/logic.ts index 1675a69..2a103b1 100644 --- a/source/pages/invitation_create/logic.ts +++ b/source/pages/invitation_create/logic.ts @@ -16,13 +16,13 @@ You should have received a copy of the GNU General Public License along with thi lib_plankton.zoo_page.register( "invitation_create", async (parameters, target_element) => { - target_element.appendChild(_espe.helpers.template_request("invitation_create")); + target_element.appendChild(_zackeneule.helpers.template_request("invitation_create")); target_element.querySelector(".invitation_create-title").textContent = lib_plankton.translate.get("page.invitation_create.title"); const indent = str => (/*"... " + */str); - const group_data = await _espe.logic.group_data(); + const group_data = await _zackeneule.logic.group_data(); /** * @todo unify with form of "invitation_view" @@ -92,11 +92,11 @@ lib_plankton.zoo_page.register( representation => ({ "data": { "name_changeable": representation.name.changeable, - "name_value": _espe.helpers.null_when_empty(representation.name.value), + "name_value": _zackeneule.helpers.null_when_empty(representation.name.value), "label_changeable": representation.label.changeable, - "label_value": _espe.helpers.null_when_empty(representation.label.value), + "label_value": _zackeneule.helpers.null_when_empty(representation.label.value), "email_address_changeable": representation.email_address.changeable, - "email_address_value": _espe.helpers.null_when_empty(representation.email_address.value), + "email_address_value": _zackeneule.helpers.null_when_empty(representation.email_address.value), "groups_changeable": representation.groups.changeable, "groups_value": representation.groups.value, "expiry": ( @@ -224,7 +224,7 @@ lib_plankton.zoo_page.register( "label": lib_plankton.translate.get("page.invitation_create.form.action.submit"), "procedure": async (get_value, get_representation) => { const value = await get_value(); - const result : {id : int; key : string;} = await _espe.backend.invitation_create( + const result : {id : int; key : string;} = await _zackeneule.backend.invitation_create( value.data, value.send_immediatly ); diff --git a/source/pages/invitation_handle/logic.ts b/source/pages/invitation_handle/logic.ts index a48e677..334833b 100644 --- a/source/pages/invitation_handle/logic.ts +++ b/source/pages/invitation_handle/logic.ts @@ -16,32 +16,57 @@ You should have received a copy of the GNU General Public License along with thi lib_plankton.zoo_page.register( "invitation_handle", async (parameters, target_element) => { - function set_state( - state : ("load" | "fill" | "wait" | "done"), + async function set_state( + state : ("load" | "fill" | "wait" | "error" | "success"), messages : Array = [] - ) : void + ) : Promise { target_element.querySelector(".invitation_handle").setAttribute("rel", state); target_element.querySelector(".invitation_handle-message").textContent = ""; - let dom_list = document.createElement("ul"); - messages.forEach( - message => { - let dom_message = document.createElement("li"); - dom_message.textContent = message; - dom_list.appendChild(dom_message); + const class_ = (() => { + switch (state) + { + case "load": return lib_plankton.zoo_widget.class_panel_info; + case "wait": return lib_plankton.zoo_widget.class_panel_info; + case "error": return lib_plankton.zoo_widget.class_panel_error; + case "success": return lib_plankton.zoo_widget.class_panel_success; + default: return lib_plankton.zoo_widget.class_panel; } + }) (); + const widget : lib_plankton.zoo_widget.interface_widget = ( + (messages.length <= 0) + ? + new lib_plankton.zoo_widget.class_empty() + : + new class_( + ( + (messages.length === 1) + ? + new lib_plankton.zoo_widget.class_string(messages[0]) + : + new lib_plankton.zoo_widget.class_list( + messages + .map(x => new lib_plankton.zoo_widget.class_string(x)) + ) + ), + { + "collapseable": false, + "collapsed_initial_value": false, + } + ) ); - target_element.querySelector(".invitation_handle-message").appendChild(dom_list); + await widget.load(target_element.querySelector(".invitation_handle-message")); } // parameters const key : string = parameters["key"]; update_nav({"mode": null}); - target_element.appendChild(_espe.helpers.template_request("invitation_handle")); - set_state( + target_element.appendChild(_zackeneule.helpers.template_request("invitation_handle")); + await set_state( "load", [ + lib_plankton.translate.get("common.loading"), ] ); @@ -63,7 +88,7 @@ lib_plankton.zoo_page.register( ); try { - data = await _espe.backend.invitation_examine(key); + data = await _zackeneule.backend.invitation_examine(key); } catch (error) { @@ -72,8 +97,8 @@ lib_plankton.zoo_page.register( if (data === null) { - set_state( - "done", + await set_state( + "error", [ lib_plankton.translate.get("page.invitation_handle.message.invalid"), ] @@ -81,7 +106,8 @@ lib_plankton.zoo_page.register( } else { - const group_data = await _espe.logic.group_data(); + const password_policy : lib_plankton.password.type_policy = await _zackeneule.backend.password_policy(); + const group_data = await _zackeneule.logic.group_data(); const form = new lib_plankton.zoo_form.class_form< { @@ -128,7 +154,17 @@ lib_plankton.zoo_page.register( } ), "label": lib_plankton.translate.get("domain.member.name.label"), - "help": lib_plankton.translate.get("domain.member.name.help"), + "help": new lib_plankton.zoo_widget.class_panel_info( + new lib_plankton.zoo_widget.class_list( + lib_plankton.translate.get("domain.member.name.help") + .split("\n\n") + .map(x => new lib_plankton.zoo_widget.class_string(x)) + ), + { + "collapseable": true, + "collapsed_initial_value": true, + } + ), }, { "name": "label", @@ -138,7 +174,17 @@ lib_plankton.zoo_page.register( } ), "label": lib_plankton.translate.get("domain.member.label.label"), - "help": lib_plankton.translate.get("domain.member.label.help"), + "help": new lib_plankton.zoo_widget.class_panel_info( + new lib_plankton.zoo_widget.class_list( + lib_plankton.translate.get("domain.member.label.help") + .split("\n\n") + .map(x => new lib_plankton.zoo_widget.class_string(x)) + ), + { + "collapseable": true, + "collapsed_initial_value": true, + } + ), }, { "name": "email_address", @@ -148,7 +194,17 @@ lib_plankton.zoo_page.register( } ), "label": lib_plankton.translate.get("domain.member.email_address.label"), - "help": lib_plankton.translate.get("domain.member.email_address.help"), + "help": new lib_plankton.zoo_widget.class_panel_info( + new lib_plankton.zoo_widget.class_list( + lib_plankton.translate.get("domain.member.email_address.help") + .split("\n\n") + .map(x => new lib_plankton.zoo_widget.class_string(x)) + ), + { + "collapseable": true, + "collapsed_initial_value": true, + } + ), }, { "name": "groups", @@ -173,20 +229,68 @@ lib_plankton.zoo_page.register( (value_outer) => new Set(value_outer.map(group_id => group_id.toFixed(0))) ), "label": lib_plankton.translate.get("domain.member.groups.label"), + "help": new lib_plankton.zoo_widget.class_panel_info( + new lib_plankton.zoo_widget.class_list( + ( + lib_plankton.translate.get("domain.member.groups.help") + .split("\n\n") + .map(x => new lib_plankton.zoo_widget.class_string(x)) + ) + ), + { + "collapseable": true, + "collapsed_initial_value": true, + } + ), }, { "name": "password_value", "input": new lib_plankton.zoo_input.class_input_password( + { + "exhibit_initial_value": true, + } ), "label": lib_plankton.translate.get("page.invitation_handle.form.field.password_value.label"), - "help": lib_plankton.translate.get("page.invitation_handle.form.field.password_value.help"), + "help": new lib_plankton.zoo_widget.class_panel_info( + new lib_plankton.zoo_widget.class_list( + ( + lib_plankton.translate.get("page.invitation_handle.form.field.password_value.help") + .split("\n\n") + .map(x => new lib_plankton.zoo_widget.class_string(x)) + ) + .concat( + [ + new _zackeneule.widget.password_policy.class_password_policy( + password_policy, + { + "title": "Richtlinien", + } + ), + ] + ) + ), + { + "collapseable": true, + "collapsed_initial_value": true, + } + ), }, { "name": "password_confirmation", "input": new lib_plankton.zoo_input.class_input_password( ), "label": lib_plankton.translate.get("page.invitation_handle.form.field.password_confirmation.label"), - // "help": lib_plankton.translate.get("page.invitation_handle.form.field.password_confirmation.help"), + /* + "help": new lib_plankton.zoo_widget.class_panel_info( + new lib_plankton.zoo_widget.class_string( + lib_plankton.translate.get("page.invitation_handle.form.field.password_confirmation.help") + ), + { + "collapseable": true, + "collapsed_initial_value": true, + } + ), + */ }, ] ), @@ -196,9 +300,10 @@ lib_plankton.zoo_page.register( "procedure": async (get_value, get_representation) => { const value = await get_value(); let flaws : Array<{incident : string; details : Record;}>; - set_state( + await set_state( "wait", [ + lib_plankton.translate.get("common.checking"), ] ); if (value.password_value !== value.password_confirmation) @@ -211,7 +316,7 @@ lib_plankton.zoo_page.register( { try { - flaws = await _espe.backend.invitation_accept( + const flaws_ = await _zackeneule.backend.invitation_accept( key, { "label": value.label, @@ -221,6 +326,21 @@ lib_plankton.zoo_page.register( "password": value.password_value, } ); + flaws = ( + ( + flaws_ + .filter( + flaw => (! flaw.incident.startsWith("password_")) + ) + ) + .concat( + (flaws_.find(flaw => flaw.incident.startsWith("password_")) !== undefined) + ? + [{"incident": "password_invalid", "details": {}}] + : + [] + ) + ); } catch (error) { @@ -231,8 +351,8 @@ lib_plankton.zoo_page.register( } if (flaws.length > 0) { - set_state( - "fill", + await set_state( + "error", flaws.map( flaw => lib_plankton.string.coin( lib_plankton.translate.get("page.invitation_handle.flaw." + flaw.incident), @@ -243,8 +363,8 @@ lib_plankton.zoo_page.register( } else { - set_state( - "done", + await set_state( + "success", [ lib_plankton.translate.get("page.invitation_handle.message.successful"), ] @@ -261,7 +381,7 @@ lib_plankton.zoo_page.register( "label": data.label_value, "email_address": data.email_address_value, "groups": data.groups_value, - "password_value": "", + "password_value": lib_plankton.password.generate(password_policy), "password_confirmation": "", } ); diff --git a/source/pages/invitation_handle/style.css b/source/pages/invitation_handle/style.css index 12c4ba7..e93f89a 100644 --- a/source/pages/invitation_handle/style.css +++ b/source/pages/invitation_handle/style.css @@ -14,14 +14,25 @@ You should have received a copy of the GNU General Public License along with thi */ +.invitation_handle-message +{ + margin-bottom: 16px; +} + .invitation_handle:not([rel]) .invitation_handle-message {display: none;} .invitation_handle:not([rel]) .invitation_handle-form {display: none;} +.invitation_handle[rel="load"] .invitation_handle-message {} +.invitation_handle[rel="load"] .invitation_handle-form {display: none;} + .invitation_handle[rel="fill"] .invitation_handle-message {} .invitation_handle[rel="fill"] .invitation_handle-form {} .invitation_handle[rel="wait"] .invitation_handle-message {} .invitation_handle[rel="wait"] .invitation_handle-form {display: none;} -.invitation_handle[rel="done"] .invitation_handle-message {} -.invitation_handle[rel="done"] .invitation_handle-form {display: none;} +.invitation_handle[rel="error"] .invitation_handle-message {} +.invitation_handle[rel="error"] .invitation_handle-form {} + +.invitation_handle[rel="success"] .invitation_handle-message {} +.invitation_handle[rel="success"] .invitation_handle-form {display: none;} diff --git a/source/pages/invitation_list/logic.ts b/source/pages/invitation_list/logic.ts index b57342e..3d3a13f 100644 --- a/source/pages/invitation_list/logic.ts +++ b/source/pages/invitation_list/logic.ts @@ -31,7 +31,7 @@ lib_plankton.zoo_page.register( const term : (null | string) = (parameters["term"] ?? ""); // exec - target_element.appendChild(_espe.helpers.template_request("invitation_list")); + target_element.appendChild(_zackeneule.helpers.template_request("invitation_list")); target_element.querySelector(".invitation_list-title").textContent = lib_plankton.translate.get("page.invitation_list.title"); @@ -52,7 +52,7 @@ lib_plankton.zoo_page.register( } const search : lib_plankton.zoo_search.type_search = lib_plankton.zoo_search.make( - (term) => _espe.backend.invitation_list(), + (term) => _zackeneule.backend.invitation_list(), { "encode_item": (item) => ( item.preview.label_value @@ -98,7 +98,7 @@ lib_plankton.zoo_page.register( ); /* - const data = await _espe.backend.invitation_list(); + const data = await _zackeneule.backend.invitation_list(); (target_element.querySelector(".invitation_list-data") as HTMLElement).textContent = JSON.stringify( data, undefined, diff --git a/source/pages/invitation_view/logic.ts b/source/pages/invitation_view/logic.ts index 02b364b..9590a3a 100644 --- a/source/pages/invitation_view/logic.ts +++ b/source/pages/invitation_view/logic.ts @@ -31,7 +31,7 @@ lib_plankton.zoo_page.register( // parameters const id : int = parseInt(parameters["id"]); - target_element.appendChild(_espe.helpers.template_request("invitation_view")); + target_element.appendChild(_zackeneule.helpers.template_request("invitation_view")); target_element.querySelector(".invitation_view-title").textContent = lib_plankton.translate.get("page.invitation_view.title"); @@ -48,7 +48,7 @@ lib_plankton.zoo_page.register( label : string; }; } - > = await _espe.backend.group_list(); + > = await _zackeneule.backend.group_list(); const groups_as_map : Map< int, { @@ -152,7 +152,7 @@ lib_plankton.zoo_page.register( "label_changeable": representation.label.changeable, "label_value": representation.label.value, "email_address_changeable": representation.email_address.changeable, - "email_address_value": _espe.helpers.null_when_empty(representation.email_address.value), + "email_address_value": _zackeneule.helpers.null_when_empty(representation.email_address.value), "groups_changeable": representation.groups.changeable, "groups_value": representation.groups.value, "url": "", @@ -161,7 +161,7 @@ lib_plankton.zoo_page.register( [ { "name": "url", - "input": new lib_plankton.zoo_input.class_input_text({"read_only": true}), + "input": new lib_plankton.zoo_input.class_input_text({"read_only": false}), "label": lib_plankton.translate.get("domain.invitation.url.label"), }, { @@ -275,6 +275,19 @@ lib_plankton.zoo_page.register( ] ), [ + { + "label": lib_plankton.translate.get("page.invitation_view.form.action.delete"), + "procedure": async () => { + await _zackeneule.backend.invitation_delete(id); + lib_plankton.zoo_page.set( + { + "name": "invitation_list", + "parameters": { + } + } + ); + }, + }, ] ); await form.setup(target_element.querySelector(".invitation_view-form") as HTMLElement); @@ -290,7 +303,7 @@ lib_plankton.zoo_page.register( email_address_value : (null | string); groups_changeable : boolean; groups_value : Array; - } = await _espe.backend.invitation_read(id); + } = await _zackeneule.backend.invitation_read(id); form.input_write(data); } diff --git a/source/pages/login/logic.ts b/source/pages/login/logic.ts index 15b6864..7163f18 100644 --- a/source/pages/login/logic.ts +++ b/source/pages/login/logic.ts @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with thi lib_plankton.zoo_page.register( "login", (parameters, target_element) => { - target_element.appendChild(_espe.helpers.template_request("login")); + target_element.appendChild(_zackeneule.helpers.template_request("login")); target_element.querySelector(".login-title").textContent = lib_plankton.translate.get("page.login.title"); @@ -52,7 +52,7 @@ lib_plankton.zoo_page.register( "procedure": async (get_value, get_representation) => { const value = await get_value(); ( - _espe.backend.login(value.name, value.password) + _zackeneule.backend.login(value.name, value.password) .then( () => { lib_plankton.zoo_page.set({"name": "member_list", "parameters": {}}); diff --git a/source/pages/logout/logic.ts b/source/pages/logout/logic.ts index 55d161a..5f03417 100644 --- a/source/pages/logout/logic.ts +++ b/source/pages/logout/logic.ts @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with thi lib_plankton.zoo_page.register( "logout", async (parameters, target_element) => { - await _espe.backend.logout(); + await _zackeneule.backend.logout(); lib_plankton.zoo_page.set({"name": "index", "parameters": {}}); update_nav({"mode": "logged_out"}); } diff --git a/source/pages/member_list/logic.ts b/source/pages/member_list/logic.ts index f919a0c..fd74541 100644 --- a/source/pages/member_list/logic.ts +++ b/source/pages/member_list/logic.ts @@ -25,7 +25,7 @@ lib_plankton.zoo_page.register( }; const term : (null | string) = (parameters["term"] ?? ""); - target_element.appendChild(_espe.helpers.template_request("member_list")); + target_element.appendChild(_zackeneule.helpers.template_request("member_list")); target_element.querySelector(".member_list-title").textContent = lib_plankton.translate.get("page.member_list.title"); @@ -48,7 +48,7 @@ lib_plankton.zoo_page.register( */ const search : lib_plankton.zoo_search.type_search = lib_plankton.zoo_search.make( - (term) => _espe.backend.member_list(term), + (term) => _zackeneule.backend.member_list(term), { "encode_item": (item) => lib_plankton.string.coin( "{{label}}", diff --git a/source/pages/member_view/logic.ts b/source/pages/member_view/logic.ts index b238ab6..86d8df6 100644 --- a/source/pages/member_view/logic.ts +++ b/source/pages/member_view/logic.ts @@ -18,13 +18,13 @@ lib_plankton.zoo_page.register( async (parameters, target_element) => { const id : int = parseInt(parameters["id"]); - let dom_fragment : DocumentFragment = _espe.helpers.template_request("member_view"); + let dom_fragment : DocumentFragment = _zackeneule.helpers.template_request("member_view"); dom_fragment.querySelector(".member_view-title").textContent = lib_plankton.translate.get("page.member_view.title"); - const group_data = await _espe.logic.group_data(); + const group_data = await _zackeneule.logic.group_data(); - const member_data = await _espe.backend.member_get(id); + const member_data = await _zackeneule.backend.member_get(id); const form = new lib_plankton.zoo_form.class_form< { @@ -116,7 +116,7 @@ lib_plankton.zoo_page.register( "label": lib_plankton.translate.get("page.member_view.form.action.save"), "procedure": async (get_value, get_representation) => { const value = await get_value(); - await _espe.backend.member_modify( + await _zackeneule.backend.member_modify( id, { "label": value.label, diff --git a/source/pages/password_change_exec/logic.ts b/source/pages/password_change_exec/logic.ts index aa84fa3..f6f41ac 100644 --- a/source/pages/password_change_exec/logic.ts +++ b/source/pages/password_change_exec/logic.ts @@ -38,7 +38,7 @@ lib_plankton.zoo_page.register( const token : string = parameters.token; update_nav({"mode": null}); - target_element.appendChild(_espe.helpers.template_request("password_change_exec")); + target_element.appendChild(_zackeneule.helpers.template_request("password_change_exec")); target_element.querySelector(".password_change_exec-title").textContent = lib_plankton.translate.get("page.password_change_exec.title"); set_state( "load", @@ -90,7 +90,7 @@ lib_plankton.zoo_page.register( } else { try { - flaws = await _espe.backend.member_password_change_execute( + flaws = await _zackeneule.backend.member_password_change_execute( id, token, value.password_value diff --git a/source/pages/password_change_init/logic.ts b/source/pages/password_change_init/logic.ts index e2142c0..0405874 100644 --- a/source/pages/password_change_init/logic.ts +++ b/source/pages/password_change_init/logic.ts @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with thi lib_plankton.zoo_page.register( "password_change_init", (parameters, target_element) => { - target_element.appendChild(_espe.helpers.template_request("password_change_init")); + target_element.appendChild(_zackeneule.helpers.template_request("password_change_init")); target_element.querySelector(".password_change_init-title").textContent = lib_plankton.translate.get("page.password_change_init.title"); target_element.querySelector(".password_change_init-info").textContent = lib_plankton.translate.get("page.password_change_init.info"); @@ -49,7 +49,7 @@ lib_plankton.zoo_page.register( target_element.querySelector(".password_change_init-stat").textContent = lib_plankton.translate.get("page.password_change_init.status.wait"); const value = await get_value(); ( - _espe.backend.member_password_change_initialize( + _zackeneule.backend.member_password_change_initialize( value.identifier ) .then( diff --git a/source/resources/backend.ts b/source/resources/backend.ts index 0c0582e..8ac1f2f 100644 --- a/source/resources/backend.ts +++ b/source/resources/backend.ts @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with thi . */ -namespace _espe.backend +namespace _zackeneule.backend { /** @@ -85,10 +85,10 @@ namespace _espe.backend 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, + "scheme": _zackeneule.conf.get().backend.scheme, + "host": _zackeneule.conf.get().backend.host, + "port": _zackeneule.conf.get().backend.port.toFixed(0), + "path_base": _zackeneule.conf.get().backend.path_base, "path_action": path, } ), @@ -166,65 +166,21 @@ namespace _espe.backend /** */ - export async function email( - receivers : Array, - subject : string, - content : string - ) : Promise + export async function password_policy( + ) : Promise< + { + minimum_length : (null | int); + maximum_length : (null | int); + must_contain_letter : boolean; + must_contain_number : boolean; + must_contain_special_character : boolean; + } + > { return ( abstract_call( - "POST", - "/email", - { - "data": { - "receivers": receivers, - "subject": subject, - "content": content, - }, - } - ) - ); - } - - - /** - */ - export async function verification_get( - data : any - ) : Promise - { - return ( - abstract_call( - "POST", - "/verification/get", - { - "data": { - "data": data, - }, - } - ) - ); - } - - - /** - */ - export async function verification_check( - data : any, - verification : string - ) : Promise - { - return ( - abstract_call( - "POST", - "/verification/check", - { - "data": { - "data": data, - "verification": verification, - } - } + "GET", + "/password_policy" ) ); } @@ -268,7 +224,7 @@ namespace _espe.backend return ( abstract_call( "GET", - ("/group/read/" + group_id.toFixed(0)) + lib_plankton.string.coin("/group/read/{{id}}", {"id": group_id.toFixed(0)}) ) ); } @@ -311,7 +267,7 @@ namespace _espe.backend return ( abstract_call( "PATCH", - ("/group/modify/" + group_id.toFixed(0)), + lib_plankton.string.coin("/group/modify/{{id}}", {"id": group_id.toFixed(0)}), { "data": group_object_data } @@ -362,7 +318,7 @@ namespace _espe.backend { return abstract_call( "GET", - ("/member/read/" + id.toFixed(0)) + lib_plankton.string.coin("/member/read/{{id}}", {"id": id.toFixed(0)}) ); } @@ -381,7 +337,7 @@ namespace _espe.backend { return abstract_call( "PATCH", - ("/member/modify/" + id.toFixed(0)), + lib_plankton.string.coin("/member/modify/{{id}}", {"id": id.toFixed(0)}), { "data": data } @@ -427,7 +383,7 @@ namespace _espe.backend return ( abstract_call( "PATCH", - ("/member/password_change/execute/" + id.toFixed(0)), + lib_plankton.string.coin("/member/password_change/execute/{{id}}", {"id": id.toFixed(0)}), { "data": { "token": token, @@ -491,12 +447,7 @@ namespace _espe.backend { return abstract_call( "GET", - lib_plankton.string.coin( - "/invitation/read?id={{id}}", - { - "id": id.toFixed(0), - } - ) + lib_plankton.string.coin("/invitation/read/{{id}}", {"id": id.toFixed(0)}) ); } @@ -536,6 +487,19 @@ namespace _espe.backend } + /** + */ + export async function invitation_delete( + id : int + ) : Promise + { + return abstract_call( + "DELETE", + lib_plankton.string.coin("/invitation/delete/{{id}}", {"id": id.toFixed(0)}), + ); + } + + /** */ export async function invitation_examine( @@ -555,12 +519,7 @@ namespace _espe.backend { return abstract_call( "GET", - lib_plankton.string.coin( - "/invitation/examine?key={{key}}", - { - "key": key - } - ) + lib_plankton.string.coin("/invitation/examine?key={{key}}", {"key": key}) ); } diff --git a/source/resources/conf.ts b/source/resources/conf.ts index 46f7e48..8ad03bb 100644 --- a/source/resources/conf.ts +++ b/source/resources/conf.ts @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with thi . */ -namespace _espe.conf +namespace _zackeneule.conf { /** diff --git a/source/style/main.css b/source/style/main.css index 27d8676..4543699 100644 --- a/source/style/main.css +++ b/source/style/main.css @@ -157,6 +157,78 @@ nav > ul > li:hover::after } */ +.widget-panel +{ + display: flex; + flex-direction: row; + flex-wrap: nowrap; +} + +.widget-panel-rule +{ + flex-basis: 2%; + + min-height: 8px; + cursor: pointer; +} + +.widget-panel-content +{ + flex-basis: 98%; +} + +.widget-panel:not(.widget-panel-collapsed) +{ + padding: 8px; + + border-radius: 4px; +} + +.widget-panel:not(.widget-panel-collapsed) > .widget-panel-rule +{ + border-left: 4px solid hsl(var(--hue), 0%, 75%); +} + +.widget-panel.widget-panel-collapsed > .widget-panel-rule::after +{ + content: "(?)"; +} + +.widget-panel.widget-panel-collapsed > .widget-panel-content +{ + display: none; +} + +.widget-list +{ + margin: 0; + padding: 0; +} + +.widget-panel_info:not(.widget-panel-collapsed) +{ + background-color: hsl(240, 25%, 25%); + color: hsl(240, 50%, 75%); +} + +.widget-panel_warning:not(.widget-panel-collapsed) +{ + background-color: hsl(60, 25%, 25%); + color: hsl(60, 50%, 75%); +} + +.widget-panel_error:not(.widget-panel-collapsed) +{ + background-color: hsl(0, 25%, 25%); + color: hsl(0, 50%, 75%); +} + +.widget-panel_success:not(.widget-panel-collapsed) +{ + background-color: hsl(120, 25%, 25%); + color: hsl(120, 50%, 75%); +} + .plankton_form_field { margin-bottom: 16px; @@ -174,6 +246,7 @@ nav > ul > li:hover::after { display: block; margin: 8px; + text-transform: capitalize; } .plankton_search_item @@ -181,9 +254,39 @@ nav > ul > li:hover::after cursor: pointer; } +.plankton_input_password_input +{ + display: inline-block; +} + +.plankton_input_password_exhibit +{ + margin-left: 4px; +} + +.plankton_input_group_field_help_content +{ + display: block; + font-size: 0.75em; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 8px; +} + +/* +.plankton_input_group_field.plankton_input_group_field_help_active > .plankton_input_group_field_help_content +{ +} + +.plankton_input_group_field:not(.plankton_input_group_field_help_active) > .plankton_input_group_field_help_content +{ + display: none; +} + */ + .plankton_input_group_field { - margin-bottom: 16px; + margin-bottom: 32px; } .plankton_input_group_field_label diff --git a/source/widgets/password_policy/logic.ts b/source/widgets/password_policy/logic.ts new file mode 100644 index 0000000..f541460 --- /dev/null +++ b/source/widgets/password_policy/logic.ts @@ -0,0 +1,152 @@ +/* +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 +. + */ + + +namespace _zackeneule.widget.password_policy +{ + + /** + */ + export class class_password_policy implements lib_plankton.zoo_widget.interface_widget + { + + /** + */ + private data : lib_plankton.password.type_policy; + + + /** + */ + private title : (null | string); + + + /** + */ + public constructor( + data : lib_plankton.password.type_policy, + { + "title": title = lib_plankton.translate.get("widget.password_policy.title"), + } + : + { + title ?: (null | string); + } + = + { + } + ) + { + this.data = data; + this.title = title; + } + + + /** + */ + public load( + target_element : Element + ) : Promise + { + const entries : Array = ( + [] + // minimum_length + .concat( + (this.data.minimum_length === null) + ? + [] + : + lib_plankton.translate.get( + "widget.password_policy.minimum_length", + { + "minimum_length": this.data.minimum_length.toFixed(0), + } + ) + ) + // maximum_length + .concat( + (this.data.minimum_length === null) + ? + [] + : + lib_plankton.translate.get( + "widget.password_policy.maximum_length", + { + "maximum_length": this.data.maximum_length.toFixed(0), + } + ) + ) + // must_contain_letter + .concat( + (! this.data.must_contain_letter) + ? + [] + : + lib_plankton.translate.get( + "widget.password_policy.must_contain_letter", + { + } + ) + ) + // must_contain_number + .concat( + (! this.data.must_contain_number) + ? + [] + : + lib_plankton.translate.get( + "widget.password_policy.must_contain_number", + { + } + ) + ) + // must_contain_special_character + .concat( + (! this.data.must_contain_special_character) + ? + [] + : + lib_plankton.translate.get( + "widget.password_policy.must_contain_special_character", + { + } + ) + ) + ); + + + target_element.appendChild(_zackeneule.helpers.template_request("widget-password_policy")); + + target_element.querySelector(".widget-password_policy").classList.toggle( + "widget-password_policy-without_title", + (this.title === null) + ); + + target_element.querySelector(".widget-password_policy-title").textContent = (this.title ?? ""); + + const element_ul : HTMLElement = target_element.querySelector(".widget-password_policy-entries"); + entries.forEach( + entry => { + const element_li : HTMLElement = document.createElement("li"); + element_li.textContent = entry; + element_ul.appendChild(element_li); + } + ); + + return Promise.resolve(undefined); + } + + } + +} diff --git a/source/widgets/password_policy/structure.html b/source/widgets/password_policy/structure.html new file mode 100644 index 0000000..b198713 --- /dev/null +++ b/source/widgets/password_policy/structure.html @@ -0,0 +1,6 @@ + diff --git a/source/widgets/password_policy/style.css b/source/widgets/password_policy/style.css new file mode 100644 index 0000000..03b9e03 --- /dev/null +++ b/source/widgets/password_policy/style.css @@ -0,0 +1,13 @@ +.widget-password_policy-title +{ + display: block; + /* + font-weight: bold; + */ +} + +.widget-password_policy-without_title .widget-password_policy-title +{ + display: none; +} + diff --git a/tools/deploy b/tools/deploy index fe5201d..150ed5d 100755 --- a/tools/deploy +++ b/tools/deploy @@ -19,7 +19,7 @@ def main(): "--target-directory", type = str, dest = "target_directory", - default = "/opt/espe", + default = "/opt/zackeneule", metavar = "", help = "directory on the target system, where the files shall be put; default: /opt/espe", ) diff --git a/tools/makefile b/tools/makefile index 3cb8dce..df38900 100644 --- a/tools/makefile +++ b/tools/makefile @@ -39,6 +39,7 @@ ${dir_temp}/logic-unlinked.js: \ ${dir_source}/resources/backend.ts \ ${dir_source}/resources/conf.ts \ ${dir_source}/logic.ts \ + ${dir_source}/widgets/password_policy/logic.ts \ ${dir_source}/pages/index/logic.ts \ ${dir_source}/pages/login/logic.ts \ ${dir_source}/pages/logout/logic.ts \ @@ -65,6 +66,7 @@ ${dir_build}/logic.js: ${dir_lib}/plankton/plankton.js ${dir_temp}/logic-unlinke ${dir_build}/style.css: \ ${dir_source}/style/main.css \ + ${dir_source}/widgets/password_policy/style.css \ ${dir_source}/pages/index/style.css \ ${dir_source}/pages/login/style.css \ ${dir_source}/pages/logout/style.css \ @@ -85,6 +87,7 @@ ${dir_build}/style.css: \ ${dir_build}/index.html: \ ${dir_source}/index.html.tpl \ + ${dir_source}/widgets/password_policy/structure.html \ ${dir_source}/pages/index/structure.html \ ${dir_source}/pages/login/structure.html \ ${dir_source}/pages/logout/structure.html \