From baae6d0c52c6f4ffb5e2dd21ff080956ff4c1c72 Mon Sep 17 00:00:00 2001 From: Fenris Wolf Date: Fri, 27 Mar 2026 11:19:56 +0100 Subject: [PATCH] [add] user_settings --- source/api/actions/user_get.ts | 130 +++++++++++++++++++++++++++ source/api/functions.ts | 1 + source/auth.ts | 4 + source/database.ts | 2 +- source/repositories/user.ts | 156 ++++++++++++++++++++++++++++++--- source/sample.ts | 4 + source/types.ts | 4 + tools/makefile | 1 + 8 files changed, 290 insertions(+), 12 deletions(-) create mode 100644 source/api/actions/user_get.ts diff --git a/source/api/actions/user_get.ts b/source/api/actions/user_get.ts new file mode 100644 index 0000000..60a43f6 --- /dev/null +++ b/source/api/actions/user_get.ts @@ -0,0 +1,130 @@ +/* +This file is part of »zeitbild«. + +Copyright 2025 'kcf' + +»zeitbild« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»zeitbild« 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »zeitbild«. If not, see . + */ + + +namespace _zeitbild.api +{ + + /** + */ + export function register_user_get( + rest_subject : lib_plankton.rest_http.type_rest + ) : void + { + register< + null, + { + name : string; + groups : Array< + int + >; + email_address : ( + null + | + string + ); + dav_token : ( + null + | + string + ); + settings : { + use_fallback_for_date_and_time_inputs : boolean; + weekview_vertical_default : boolean; + }; + } + >( + rest_subject, + lib_plankton.http.enum_method.get, + "/user", + { + "description": "gibt die Angaben eines Nutzers aus", + "output_schema": () => ({ + "nullable": false, + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "nullable": false, + "type": "number", + }, + "name": { + "nullable": false, + "type": "string", + }, + "groups": { + "nullable": false, + "type": "array", + "items": { + "nullable": false, + "type": "int", + } + }, + "email_address": { + "nullable": true, + "type": "string", + }, + "dav_token": { + "nullable": true, + "type": "string", + }, + "settings": { + "nullable": false, + "type": "object", + "additionalProperties": false, + "properties": { + "use_fallback_for_date_and_time_inputs": { + "nullable": false, + "type": "boolean", + }, + "weekview_vertical_default": { + "nullable": false, + "type": "boolean", + }, + }, + "required": [ + "use_fallback_for_date_and_time_inputs", + "weekview_vertical_default", + ], + }, + }, + "required": [ + "id", + "name", + ], + }), + "restriction": restriction_logged_in, + "execution": async (stuff) => { + const session : {key : string; value : lib_plankton.session.type_session;} = await session_from_stuff(stuff); + const user_id : _zeitbild.type_user_id = await _zeitbild.service.user.identify(session.value.name); + + const result : _zeitbild.type_user_object = await _zeitbild.service.user.get(user_id); + return Promise.resolve( + { + "status_code": 200, + "data": result, + } + ); + } + } + ); + } + +} + diff --git a/source/api/functions.ts b/source/api/functions.ts index 343ed4a..f581511 100644 --- a/source/api/functions.ts +++ b/source/api/functions.ts @@ -58,6 +58,7 @@ namespace _zeitbild.api // user { _zeitbild.api.register_users(rest_subject); + _zeitbild.api.register_user_get(rest_subject); // caldav { _zeitbild.api.register_user_dav_conf(rest_subject); diff --git a/source/auth.ts b/source/auth.ts index 82b797b..3e134b3 100644 --- a/source/auth.ts +++ b/source/auth.ts @@ -324,6 +324,10 @@ namespace _zeitbild.auth "groups": group_ids, "email_address": userinfo.email, "dav_token": null, + "settings": { + "use_fallback_for_date_and_time_inputs": false, + "weekview_vertical_default": false, + } }; const user_id : _zeitbild.type_user_id = await _zeitbild.service.user.add( user_object diff --git a/source/database.ts b/source/database.ts index 0b9f47f..4b3ed83 100644 --- a/source/database.ts +++ b/source/database.ts @@ -24,7 +24,7 @@ namespace _zeitbild.database /** */ const _compatible_revisions : Array = [ - "r6", + "r7", ]; diff --git a/source/repositories/user.ts b/source/repositories/user.ts index 941cc38..0944fc3 100644 --- a/source/repositories/user.ts +++ b/source/repositories/user.ts @@ -45,6 +45,23 @@ namespace _zeitbild.repository.user }; + /** + */ + type type_settings_row_slim = { + use_fallback_for_date_and_time_inputs : int; + weekview_vertical_default : int; + }; + + + /** + */ + type type_settings_row_fat = { + user_id : int; + use_fallback_for_date_and_time_inputs : int; + weekview_vertical_default : int; + }; + + /** */ type type_preview = { @@ -57,6 +74,7 @@ namespace _zeitbild.repository.user type type_dispersal = { core : type_core_row; groups : Array; + settings : type_settings_row_slim; }; @@ -90,6 +108,21 @@ namespace _zeitbild.repository.user ) = null; + /** + */ + var _store_settings : ( + null + | + lib_plankton.storage.type_store< + int, + /*type_settings_row_fat*/Record, + {}, + lib_plankton.storage.type_sql_table_autokey_search_term, + Record + > + ) = null; + + /** */ function get_store_core( @@ -150,6 +183,36 @@ namespace _zeitbild.repository.user } + /** + */ + function get_store_settings( + ) + : lib_plankton.storage.type_store< + int, + /*type_group_row_fat*/Record, + {}, + lib_plankton.storage.type_sql_table_autokey_search_term, + Record + > + { + if (_store_settings === null) + { + _store_settings = lib_plankton.storage.sql_table_autokey_store( + { + "database_implementation": _zeitbild.database.get_implementation(), + "table_name": "user_settings", + "key_name": "id", + } + ); + } + else + { + // do nothing + } + return _store_settings; + } + + /** */ function encode( @@ -172,6 +235,10 @@ namespace _zeitbild.repository.user ) ) ), + "settings": { + "use_fallback_for_date_and_time_inputs": (user_object.settings.use_fallback_for_date_and_time_inputs ? 0 : 1), + "weekview_vertical_default": (user_object.settings.weekview_vertical_default ? 0 : 1), + }, }; } @@ -192,6 +259,10 @@ namespace _zeitbild.repository.user ), "email_address": dispersal.core.email_address, "dav_token": dispersal.core.dav_token, + "settings": { + "use_fallback_for_date_and_time_inputs": (dispersal.settings.use_fallback_for_date_and_time_inputs > 0), + "weekview_vertical_default": (dispersal.settings.weekview_vertical_default > 0), + } }; } @@ -255,20 +326,50 @@ namespace _zeitbild.repository.user ) ) ); - const dispersal : type_dispersal = { - "core": core_row, - "groups": ( - group_rows.map( - group_row_fat => ( - { - "group_id": group_row_fat.group_id, + const settings_rows : Array = ( + ( + await get_store_settings().search( + { + "expression": "(user_id = $user_id)", + "arguments": { + "user_id": user_id, } - ) + } ) ) - }; - const user_object : _zeitbild.type_user_object = decode(dispersal); - return Promise.resolve<_zeitbild.type_user_object>(user_object); + .map( + hit => ( + { + // "user_id": hit.preview.user_id, + "use_fallback_for_date_and_time_inputs": hit.preview.use_fallback_for_date_and_time_inputs, + "weekview_vertical_default": hit.preview.weekview_vertical_default, + } + ) + ) + ); + if (settings_rows.length !== 1) + { + return Promise.reject(new Error("no settings bound")); + } + else + { + const settings_row : type_settings_row_slim = settings_rows[0]; + const dispersal : type_dispersal = { + "core": core_row, + "groups": ( + group_rows.map( + group_row_fat => ( + { + "group_id": group_row_fat.group_id, + } + ) + ) + ), + "settings": settings_row, + }; + const user_object : _zeitbild.type_user_object = decode(dispersal); + return Promise.resolve<_zeitbild.type_user_object>(user_object); + } } @@ -295,6 +396,15 @@ namespace _zeitbild.repository.user await get_store_groups().create(group_row_fat); } } + // settings + { + const settings_row_fat : type_settings_row_fat = { + "user_id": user_id, + "use_fallback_for_date_and_time_inputs": dispersal.settings.use_fallback_for_date_and_time_inputs, + "weekview_vertical_default": dispersal.settings.weekview_vertical_default, + }; + await get_store_settings().create(settings_row_fat); + } return Promise.resolve<_zeitbild.type_user_id>(user_id); } @@ -358,6 +468,30 @@ namespace _zeitbild.repository.user } } } + // settings + { + const settings_row_fat : type_settings_row_fat = { + "user_id": user_id, + "use_fallback_for_date_and_time_inputs": dispersal.settings.use_fallback_for_date_and_time_inputs, + "weekview_vertical_default": dispersal.settings.weekview_vertical_default, + }; + const hits : Array<{key : int; preview : Record;}> = await get_store_settings().search( + { + "expression": "(user_id = $user_id)", + "arguments": { + "user_id": user_id, + } + } + ); + if (hits.length >= 1) + { + await get_store_settings().update(hits[0].key, settings_row_fat); + } + else + { + await get_store_settings().create(settings_row_fat); + } + } return Promise.resolve(undefined); } diff --git a/source/sample.ts b/source/sample.ts index 4cbe509..64ce291 100644 --- a/source/sample.ts +++ b/source/sample.ts @@ -276,6 +276,10 @@ namespace _zeitbild.sample "groups": (user_raw.groups ?? []), "email_address": user_raw.email_address, "dav_token": (user_raw.dav_token ?? null), + "settings": { + "use_fallback_for_date_and_time_inputs": false, + "weekview_vertical_default": false, + }, }; const user_id : _zeitbild.type_user_id = await _zeitbild.service.user.add( user_object diff --git a/source/types.ts b/source/types.ts index be3c8db..8ccbf87 100644 --- a/source/types.ts +++ b/source/types.ts @@ -68,6 +68,10 @@ namespace _zeitbild | string ); + settings : { + use_fallback_for_date_and_time_inputs : boolean; + weekview_vertical_default : boolean; + }; }; diff --git a/tools/makefile b/tools/makefile index 6561f79..b55e642 100644 --- a/tools/makefile +++ b/tools/makefile @@ -62,6 +62,7 @@ ${dir_temp}/zeitbild-unlinked.js: \ ${dir_source}/api/actions/session_status.ts \ ${dir_source}/api/actions/group_list.ts \ ${dir_source}/api/actions/users.ts \ + ${dir_source}/api/actions/user_get.ts \ ${dir_source}/api/actions/user_dav_conf.ts \ ${dir_source}/api/actions/user_dav_token.ts \ ${dir_source}/api/actions/calendar_list.ts \