391 lines
7.2 KiB
TypeScript
391 lines
7.2 KiB
TypeScript
/*
|
|
This file is part of »zeitbild«.
|
|
|
|
Copyright 2025 'kcf' <fenris@folksprak.org>
|
|
|
|
»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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
namespace _zeitbild.repository.user
|
|
{
|
|
|
|
/**
|
|
*/
|
|
type type_core_row = {
|
|
name : string;
|
|
email_address : (null | string);
|
|
dav_token : (null | string);
|
|
};
|
|
|
|
|
|
/**
|
|
*/
|
|
type type_group_row_slim = {
|
|
group_id : int;
|
|
};
|
|
|
|
|
|
/**
|
|
*/
|
|
type type_group_row_fat = {
|
|
user_id : int;
|
|
group_id : int;
|
|
};
|
|
|
|
|
|
/**
|
|
*/
|
|
type type_preview = {
|
|
name : string;
|
|
};
|
|
|
|
|
|
/**
|
|
*/
|
|
type type_dispersal = {
|
|
core : type_core_row;
|
|
groups : Array<type_group_row_slim>;
|
|
};
|
|
|
|
|
|
/**
|
|
*/
|
|
var _store_core : (
|
|
null
|
|
|
|
|
lib_plankton.storage.type_store<
|
|
_zeitbild.type_user_id,
|
|
/*type_core_row*/Record<string, any>,
|
|
{},
|
|
lib_plankton.storage.type_sql_table_autokey_search_term,
|
|
/*type_preview*/Record<string, any>
|
|
>
|
|
) = null;
|
|
|
|
|
|
/**
|
|
*/
|
|
var _store_groups : (
|
|
null
|
|
|
|
|
lib_plankton.storage.type_store<
|
|
int,
|
|
/*type_group_row_fat*/Record<string, any>,
|
|
{},
|
|
lib_plankton.storage.type_sql_table_autokey_search_term,
|
|
Record<string, any>
|
|
>
|
|
) = null;
|
|
|
|
|
|
/**
|
|
*/
|
|
function get_store_core(
|
|
)
|
|
: lib_plankton.storage.type_store<
|
|
_zeitbild.type_user_id,
|
|
/*type_core_row*/Record<string, any>,
|
|
{},
|
|
lib_plankton.storage.type_sql_table_autokey_search_term,
|
|
/*type_preview*/Record<string, any>
|
|
>
|
|
{
|
|
if (_store_core === null)
|
|
{
|
|
_store_core = lib_plankton.storage.sql_table_autokey_store(
|
|
{
|
|
"database_implementation": _zeitbild.database.get_implementation(),
|
|
"table_name": "users",
|
|
"key_name": "id",
|
|
}
|
|
);
|
|
}
|
|
else
|
|
{
|
|
// do nothing
|
|
}
|
|
return _store_core;
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
function get_store_groups(
|
|
)
|
|
: lib_plankton.storage.type_store<
|
|
int,
|
|
/*type_group_row_fat*/Record<string, any>,
|
|
{},
|
|
lib_plankton.storage.type_sql_table_autokey_search_term,
|
|
Record<string, any>
|
|
>
|
|
{
|
|
if (_store_groups === null)
|
|
{
|
|
_store_groups = lib_plankton.storage.sql_table_autokey_store(
|
|
{
|
|
"database_implementation": _zeitbild.database.get_implementation(),
|
|
"table_name": "user_groups",
|
|
"key_name": "id",
|
|
}
|
|
);
|
|
}
|
|
else
|
|
{
|
|
// do nothing
|
|
}
|
|
return _store_groups;
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
function encode(
|
|
user_object : _zeitbild.type_user_object
|
|
)
|
|
: type_dispersal
|
|
{
|
|
return {
|
|
"core": {
|
|
"name": user_object.name,
|
|
"email_address": user_object.email_address,
|
|
"dav_token": user_object.dav_token,
|
|
},
|
|
"groups": (
|
|
user_object.groups.map(
|
|
group_id => (
|
|
{
|
|
"group_id": group_id,
|
|
}
|
|
)
|
|
)
|
|
),
|
|
};
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
function decode(
|
|
dispersal : type_dispersal
|
|
)
|
|
: _zeitbild.type_user_object
|
|
{
|
|
return {
|
|
"name": dispersal.core.name,
|
|
"groups": (
|
|
dispersal.groups.map(
|
|
group_row => group_row.group_id,
|
|
)
|
|
),
|
|
"email_address": dispersal.core.email_address,
|
|
"dav_token": dispersal.core.dav_token,
|
|
};
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function list(
|
|
)
|
|
: Promise<
|
|
Array<
|
|
{
|
|
id : _zeitbild.type_user_id;
|
|
name : string;
|
|
}
|
|
>
|
|
>
|
|
{
|
|
const hits : Array<{key : int; preview : /*type_preview*/Record<string, any>;}> = await get_store_core().search(
|
|
{
|
|
"expression": "TRUE",
|
|
"arguments": {}
|
|
}
|
|
);
|
|
return Promise.resolve(
|
|
hits
|
|
.map(
|
|
(hit) => ({
|
|
"id": hit.key,
|
|
"name": hit.preview.name,
|
|
})
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function read(
|
|
user_id : _zeitbild.type_user_id
|
|
)
|
|
: Promise<_zeitbild.type_user_object>
|
|
{
|
|
const core_row : type_core_row = ((await get_store_core().read(user_id)) as type_core_row);
|
|
const group_rows : Array<type_group_row_fat> = (
|
|
(
|
|
await get_store_groups().search(
|
|
{
|
|
"expression": "(user_id = $user_id)",
|
|
"arguments": {
|
|
"user_id": user_id,
|
|
}
|
|
}
|
|
)
|
|
)
|
|
.map(
|
|
hit => (
|
|
{
|
|
"user_id": hit.preview.user_id,
|
|
"group_id": hit.preview.group_id,
|
|
}
|
|
)
|
|
)
|
|
);
|
|
const dispersal : type_dispersal = {
|
|
"core": core_row,
|
|
"groups": (
|
|
group_rows.map(
|
|
group_row_fat => (
|
|
{
|
|
"group_id": group_row_fat.group_id,
|
|
}
|
|
)
|
|
)
|
|
)
|
|
};
|
|
const user_object : _zeitbild.type_user_object = decode(dispersal);
|
|
return Promise.resolve<_zeitbild.type_user_object>(user_object);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function create(
|
|
user_object : _zeitbild.type_user_object
|
|
)
|
|
: Promise<_zeitbild.type_user_id>
|
|
{
|
|
const dispersal : type_dispersal = encode(user_object);
|
|
// core
|
|
const user_id : _zeitbild.type_user_id = await (() => {
|
|
return get_store_core().create(dispersal.core);
|
|
}) ();
|
|
// groups
|
|
{
|
|
for (const group_row_slim of dispersal.groups)
|
|
{
|
|
const group_row_fat : type_group_row_fat = {
|
|
"user_id": user_id,
|
|
"group_id": group_row_slim.group_id,
|
|
};
|
|
await get_store_groups().create(group_row_fat);
|
|
}
|
|
}
|
|
return Promise.resolve<_zeitbild.type_user_id>(user_id);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function update(
|
|
user_id : _zeitbild.type_user_id,
|
|
user_object : _zeitbild.type_user_object
|
|
)
|
|
: Promise<void>
|
|
{
|
|
const dispersal : type_dispersal = encode(user_object);
|
|
// core
|
|
{
|
|
await get_store_core().update(user_id, dispersal.core);
|
|
}
|
|
// groups
|
|
{
|
|
const hits : Array<{key : int; preview : Record<string, any>;}> = await get_store_groups().search(
|
|
{
|
|
"expression": "(user_id = $user_id)",
|
|
"arguments": {
|
|
"user_id": user_id,
|
|
}
|
|
}
|
|
);
|
|
const contrast = lib_plankton.list.contrast(
|
|
hits,
|
|
hit => hit.preview.group_id.toFixed(0),
|
|
dispersal.groups,
|
|
group_row_slim => group_row_slim.group_id.toFixed(0)
|
|
);
|
|
// delete
|
|
{
|
|
for (const entry of contrast.only_left)
|
|
{
|
|
await get_store_groups().delete(entry.left.key);
|
|
}
|
|
}
|
|
// update
|
|
{
|
|
for (const entry of contrast.both)
|
|
{
|
|
const row_group_fat : type_group_row_fat = {
|
|
"user_id": user_id,
|
|
"group_id": entry.right.group_id,
|
|
};
|
|
await get_store_groups().update(entry.left.key, row_group_fat);
|
|
}
|
|
}
|
|
// create
|
|
{
|
|
for (const entry of contrast.only_right)
|
|
{
|
|
const row_group_fat : type_group_row_fat = {
|
|
"user_id": user_id,
|
|
"group_id": entry.right.group_id,
|
|
};
|
|
await get_store_groups().create(row_group_fat);
|
|
}
|
|
}
|
|
}
|
|
return Promise.resolve<void>(undefined);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
export async function identify(
|
|
name : string
|
|
)
|
|
: Promise<_zeitbild.type_user_id>
|
|
{
|
|
const hits : Array<{key : _zeitbild.type_user_id; preview : /*type_preview*/Record<string, any>;}> = await get_store_core().search(
|
|
{
|
|
"expression": "(name = $name)",
|
|
"arguments": {
|
|
"name": name,
|
|
}
|
|
}
|
|
);
|
|
if (hits.length <= 0)
|
|
{
|
|
return Promise.reject<_zeitbild.type_user_id>(new Error("not found"));
|
|
}
|
|
else
|
|
{
|
|
return Promise.resolve<_zeitbild.type_user_id>(hits[0].key);
|
|
}
|
|
}
|
|
|
|
}
|