Compare commits
No commits in common. "78729c611134d02496d899c522929f4797a20655" and "d8c0e553404fe36705df6fd973ca8e67609b1eee" have entirely different histories.
78729c6111
...
d8c0e55340
4
lib/plankton/plankton.d.ts
vendored
4
lib/plankton/plankton.d.ts
vendored
|
|
@ -658,9 +658,6 @@ declare namespace lib_plankton.call {
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
export function sleep(seconds: float): Promise<void>;
|
export function sleep(seconds: float): Promise<void>;
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export function null_prop<type_value_from, type_value_to>(value_from: (null | type_value_from), function_: ((value: type_value_from) => type_value_to)): (null | type_value_to);
|
|
||||||
export {};
|
export {};
|
||||||
}
|
}
|
||||||
declare namespace lib_plankton.email {
|
declare namespace lib_plankton.email {
|
||||||
|
|
@ -4601,7 +4598,6 @@ declare namespace lib_plankton.auth.oidc {
|
||||||
name: (null | string);
|
name: (null | string);
|
||||||
label: (null | string);
|
label: (null | string);
|
||||||
email: (null | string);
|
email: (null | string);
|
||||||
groups: (null | Array<string>);
|
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1491,16 +1491,6 @@ var lib_plankton;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
call.sleep = sleep;
|
call.sleep = sleep;
|
||||||
/**
|
|
||||||
*/
|
|
||||||
function null_prop(value_from, function_) {
|
|
||||||
return ((value_from === null)
|
|
||||||
?
|
|
||||||
null
|
|
||||||
:
|
|
||||||
function_(value_from));
|
|
||||||
}
|
|
||||||
call.null_prop = null_prop;
|
|
||||||
})(call = lib_plankton.call || (lib_plankton.call = {}));
|
})(call = lib_plankton.call || (lib_plankton.call = {}));
|
||||||
})(lib_plankton || (lib_plankton = {}));
|
})(lib_plankton || (lib_plankton = {}));
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
|
@ -4066,10 +4056,10 @@ var lib_plankton;
|
||||||
options = Object.assign({
|
options = Object.assign({
|
||||||
"compare_value": instance_compare
|
"compare_value": instance_compare
|
||||||
}, options);
|
}, options);
|
||||||
/*if (is_empty<type_element>(list)) {
|
if (is_empty(list)) {
|
||||||
throw (new Error("the max-arg of an empty list is not defined"));
|
throw (new Error("the max-arg of an empty list is not defined"));
|
||||||
}
|
}
|
||||||
else */ {
|
else {
|
||||||
return (list
|
return (list
|
||||||
.reduce(function (result, element, index) {
|
.reduce(function (result, element, index) {
|
||||||
var value = target_function(element);
|
var value = target_function(element);
|
||||||
|
|
@ -14476,7 +14466,8 @@ var lib_plankton;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
lib_plankton.log.info("plankton.server.client_connected");
|
lib_plankton.log.info("plankton.server.client_connected");
|
||||||
socket.on("data", (input_chunk_raw) => {
|
socket.on("data", (input_chunk_raw, x2, x3, x4, x5) => {
|
||||||
|
process.stderr.write(JSON.stringify({ x2, x3, x4, x5 }) + "\n");
|
||||||
lib_plankton.log.debug("plankton.server.reading_chunk", {
|
lib_plankton.log.debug("plankton.server.reading_chunk", {
|
||||||
"chunk_raw": ((input_chunk_raw instanceof Buffer)
|
"chunk_raw": ((input_chunk_raw instanceof Buffer)
|
||||||
?
|
?
|
||||||
|
|
@ -16240,11 +16231,6 @@ var lib_plankton;
|
||||||
"name": (data["preferred_username"] ?? null),
|
"name": (data["preferred_username"] ?? null),
|
||||||
"label": (data["name"] ?? null),
|
"label": (data["name"] ?? null),
|
||||||
"email": (data["email"] ?? null),
|
"email": (data["email"] ?? null),
|
||||||
"groups": (((data["groups"] === undefined) || (data["groups"] === null))
|
|
||||||
?
|
|
||||||
null
|
|
||||||
:
|
|
||||||
data["groups"].split(",")),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,18 @@
|
||||||
{
|
{
|
||||||
"groups": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"name": "gaertner",
|
|
||||||
"label": "Gärtner"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"name": "bewohner",
|
|
||||||
"label": "Bewohner"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"users": [
|
"users": [
|
||||||
{
|
{
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"name": "alice",
|
"name": "alice",
|
||||||
"groups": [1],
|
|
||||||
"email_address": "alice@example.org",
|
"email_address": "alice@example.org",
|
||||||
"dav_token": null,
|
"dav_token": "alice_dav",
|
||||||
"password": "alice"
|
"password": "alice"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"name": "bob",
|
"name": "bob",
|
||||||
"groups": [2],
|
|
||||||
"email_address": "bob@example.org",
|
"email_address": "bob@example.org",
|
||||||
"dav_token": null,
|
"dav_token": null,
|
||||||
"password": "bob"
|
"password": "bob"
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"name": "charlie",
|
|
||||||
"groups": [1, 2],
|
|
||||||
"email_address": "charlie@example.org",
|
|
||||||
"dav_token": "charlie_dav",
|
|
||||||
"password": "charlie"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"calendars": [
|
"calendars": [
|
||||||
|
|
@ -44,14 +22,8 @@
|
||||||
"hue": 0.0000,
|
"hue": 0.0000,
|
||||||
"access": {
|
"access": {
|
||||||
"public": true,
|
"public": true,
|
||||||
"default_level": "view",
|
"default_level": "edit",
|
||||||
"attributed_group": [
|
"attributed": [
|
||||||
],
|
|
||||||
"attributed_user": [
|
|
||||||
{
|
|
||||||
"user_id": 3,
|
|
||||||
"level": "admin"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"resource": {
|
"resource": {
|
||||||
|
|
@ -114,16 +86,14 @@
|
||||||
"access": {
|
"access": {
|
||||||
"public": false,
|
"public": false,
|
||||||
"default_level": "none",
|
"default_level": "none",
|
||||||
"attributed_group": [
|
"attributed": [
|
||||||
{
|
|
||||||
"group_id": 1,
|
|
||||||
"level": "view"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"attributed_user": [
|
|
||||||
{
|
{
|
||||||
"user_id": 1,
|
"user_id": 1,
|
||||||
"level": "admin"
|
"level": "admin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"user_id": 2,
|
||||||
|
"level": "view"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -234,13 +204,11 @@
|
||||||
"access": {
|
"access": {
|
||||||
"public": false,
|
"public": false,
|
||||||
"default_level": "none",
|
"default_level": "none",
|
||||||
"attributed_group": [
|
"attributed": [
|
||||||
{
|
{
|
||||||
"group_id": 2,
|
"user_id": 1,
|
||||||
"level": "view"
|
"level": "none"
|
||||||
}
|
},
|
||||||
],
|
|
||||||
"attributed_user": [
|
|
||||||
{
|
{
|
||||||
"user_id": 2,
|
"user_id": 2,
|
||||||
"level": "admin"
|
"level": "admin"
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,7 @@ namespace _zeitbild.api
|
||||||
access : {
|
access : {
|
||||||
public : boolean;
|
public : boolean;
|
||||||
default_level : string;
|
default_level : string;
|
||||||
attributed_group : Array<
|
attributed : Array<
|
||||||
{
|
|
||||||
group_id : int;
|
|
||||||
level : string;
|
|
||||||
}
|
|
||||||
>;
|
|
||||||
attributed_user : Array<
|
|
||||||
{
|
{
|
||||||
user_id : int;
|
user_id : int;
|
||||||
level : string;
|
level : string;
|
||||||
|
|
@ -118,33 +112,17 @@ namespace _zeitbild.api
|
||||||
"name": stuff.input.name,
|
"name": stuff.input.name,
|
||||||
"access": {
|
"access": {
|
||||||
"public": stuff.input.access.public,
|
"public": stuff.input.access.public,
|
||||||
"default_level": _zeitbild.access_level_from_string(stuff.input.access.default_level),
|
"default_level": _zeitbild.value_object.access_level.from_string(stuff.input.access.default_level),
|
||||||
"attributed_group": lib_plankton.map.hashmap.implementation_map(
|
"attributed": lib_plankton.map.hashmap.implementation_map(
|
||||||
lib_plankton.map.hashmap.make(
|
lib_plankton.map.hashmap.make(
|
||||||
x => x.toFixed(0),
|
x => x.toFixed(0),
|
||||||
{
|
{
|
||||||
"pairs": (
|
"pairs": (
|
||||||
stuff.input.access.attributed_group
|
stuff.input.access.attributed
|
||||||
.map(
|
|
||||||
(entry) => ({
|
|
||||||
"key": entry.group_id,
|
|
||||||
"value": _zeitbild.access_level_from_string(entry.level),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"attributed_user": lib_plankton.map.hashmap.implementation_map(
|
|
||||||
lib_plankton.map.hashmap.make(
|
|
||||||
x => x.toFixed(0),
|
|
||||||
{
|
|
||||||
"pairs": (
|
|
||||||
stuff.input.access.attributed_user
|
|
||||||
.map(
|
.map(
|
||||||
(entry) => ({
|
(entry) => ({
|
||||||
"key": entry.user_id,
|
"key": entry.user_id,
|
||||||
"value": _zeitbild.access_level_from_string(entry.level),
|
"value": _zeitbild.value_object.access_level.from_string(entry.level),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.concat(
|
.concat(
|
||||||
|
|
|
||||||
|
|
@ -34,13 +34,7 @@ namespace _zeitbild.api
|
||||||
access : {
|
access : {
|
||||||
public : boolean;
|
public : boolean;
|
||||||
default_level : string;
|
default_level : string;
|
||||||
attributed_group : Array<
|
attributed : Array<
|
||||||
{
|
|
||||||
group_id : int;
|
|
||||||
level : string;
|
|
||||||
}
|
|
||||||
>;
|
|
||||||
attributed_user : Array<
|
|
||||||
{
|
{
|
||||||
user_id : int;
|
user_id : int;
|
||||||
level : string;
|
level : string;
|
||||||
|
|
@ -83,33 +77,17 @@ namespace _zeitbild.api
|
||||||
"hue": stuff.input.hue,
|
"hue": stuff.input.hue,
|
||||||
"access": {
|
"access": {
|
||||||
"public": stuff.input.access.public,
|
"public": stuff.input.access.public,
|
||||||
"default_level": _zeitbild.access_level_from_string(stuff.input.access.default_level),
|
"default_level": _zeitbild.value_object.access_level.from_string(stuff.input.access.default_level),
|
||||||
"attributed_group": lib_plankton.map.hashmap.implementation_map(
|
"attributed": lib_plankton.map.hashmap.implementation_map(
|
||||||
lib_plankton.map.hashmap.make(
|
lib_plankton.map.hashmap.make(
|
||||||
x => x.toFixed(0),
|
x => x.toFixed(0),
|
||||||
{
|
{
|
||||||
"pairs": (
|
"pairs": (
|
||||||
stuff.input.access.attributed_group
|
stuff.input.access.attributed
|
||||||
.map(
|
|
||||||
(entry) => ({
|
|
||||||
"key": entry.group_id,
|
|
||||||
"value": _zeitbild.access_level_from_string(entry.level),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"attributed_user": lib_plankton.map.hashmap.implementation_map(
|
|
||||||
lib_plankton.map.hashmap.make(
|
|
||||||
x => x.toFixed(0),
|
|
||||||
{
|
|
||||||
"pairs": (
|
|
||||||
stuff.input.access.attributed_user
|
|
||||||
.map(
|
.map(
|
||||||
(entry) => ({
|
(entry) => ({
|
||||||
"key": entry.user_id,
|
"key": entry.user_id,
|
||||||
"value": _zeitbild.access_level_from_string(entry.level),
|
"value": _zeitbild.value_object.access_level.from_string(entry.level),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -35,18 +35,12 @@ namespace _zeitbild.api
|
||||||
access : {
|
access : {
|
||||||
public : boolean;
|
public : boolean;
|
||||||
default_level : string;
|
default_level : string;
|
||||||
attributed_group : Array<
|
attributed : Array<
|
||||||
{
|
|
||||||
group_id : int;
|
|
||||||
level : string;
|
|
||||||
}
|
|
||||||
>;
|
|
||||||
attributed_user : Array<
|
|
||||||
{
|
{
|
||||||
user_id : int;
|
user_id : int;
|
||||||
level : string;
|
level : string;
|
||||||
}
|
}
|
||||||
>;
|
>
|
||||||
};
|
};
|
||||||
resource_id : int;
|
resource_id : int;
|
||||||
}
|
}
|
||||||
|
|
@ -75,23 +69,8 @@ namespace _zeitbild.api
|
||||||
"access": {
|
"access": {
|
||||||
"public": calendar_object.access.public,
|
"public": calendar_object.access.public,
|
||||||
"default_level": _zeitbild.api.access_level_encode(calendar_object.access.default_level),
|
"default_level": _zeitbild.api.access_level_encode(calendar_object.access.default_level),
|
||||||
"attributed_group": lib_plankton.call.convey(
|
"attributed": lib_plankton.call.convey(
|
||||||
calendar_object.access.attributed_group,
|
calendar_object.access.attributed,
|
||||||
[
|
|
||||||
lib_plankton.map.dump,
|
|
||||||
(pairs : Array<{key : _zeitbild.type_group_id; value : _zeitbild.enum_access_level;}>) => (
|
|
||||||
pairs
|
|
||||||
.map(
|
|
||||||
(pair : {key : _zeitbild.type_group_id; value : _zeitbild.enum_access_level;}) => ({
|
|
||||||
"group_id": pair.key,
|
|
||||||
"level": _zeitbild.api.access_level_encode(pair.value)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
),
|
|
||||||
"attributed_user": lib_plankton.call.convey(
|
|
||||||
calendar_object.access.attributed_user,
|
|
||||||
[
|
[
|
||||||
lib_plankton.map.dump,
|
lib_plankton.map.dump,
|
||||||
(pairs : Array<{key : _zeitbild.type_user_id; value : _zeitbild.enum_access_level;}>) => (
|
(pairs : Array<{key : _zeitbild.type_user_id; value : _zeitbild.enum_access_level;}>) => (
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ namespace _zeitbild.api
|
||||||
"id": entry.id,
|
"id": entry.id,
|
||||||
"name": entry.name,
|
"name": entry.name,
|
||||||
"hue": entry.hue,
|
"hue": entry.hue,
|
||||||
"access_level": _zeitbild.access_level_to_string(entry.access_level),
|
"access_level": _zeitbild.value_object.access_level.to_string(entry.access_level),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
/*
|
|
||||||
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.api
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export function register_group_list(
|
|
||||||
rest_subject : lib_plankton.rest_http.type_rest
|
|
||||||
) : void
|
|
||||||
{
|
|
||||||
register<
|
|
||||||
null,
|
|
||||||
Array<
|
|
||||||
{
|
|
||||||
id : int;
|
|
||||||
name : string;
|
|
||||||
label : string;
|
|
||||||
}
|
|
||||||
>
|
|
||||||
>(
|
|
||||||
rest_subject,
|
|
||||||
lib_plankton.http.enum_method.get,
|
|
||||||
"/groups",
|
|
||||||
{
|
|
||||||
"description": "listet alle Gruppen auf",
|
|
||||||
"query_parameters": () => ([
|
|
||||||
{
|
|
||||||
"name": "term",
|
|
||||||
"required": false,
|
|
||||||
"description": "search term",
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
"output_schema": () => ({
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"nullable": false,
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"nullable": false,
|
|
||||||
"type": "number",
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"nullable": false,
|
|
||||||
"type": "string",
|
|
||||||
},
|
|
||||||
"label": {
|
|
||||||
"nullable": false,
|
|
||||||
"type": "string",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"id",
|
|
||||||
"name",
|
|
||||||
"label",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
"restriction": restriction_logged_in,
|
|
||||||
"execution": async (stuff) => {
|
|
||||||
const result : Array<
|
|
||||||
{
|
|
||||||
id : _zeitbild.type_group_id;
|
|
||||||
name : string;
|
|
||||||
label : string;
|
|
||||||
}
|
|
||||||
> = (
|
|
||||||
(await _zeitbild.service.group.list())
|
|
||||||
.map(
|
|
||||||
entry => (
|
|
||||||
{
|
|
||||||
"id": entry.id,
|
|
||||||
"name": entry.object.name,
|
|
||||||
"label": entry.object.label,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return Promise.resolve(
|
|
||||||
{
|
|
||||||
"status_code": 200,
|
|
||||||
"data": result,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -21,38 +21,6 @@ along with »zeitbild«. If not, see <http://www.gnu.org/licenses/>.
|
||||||
namespace _zeitbild.api
|
namespace _zeitbild.api
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
function get_group_name(
|
|
||||||
group_name_raw : string
|
|
||||||
)
|
|
||||||
: string
|
|
||||||
{
|
|
||||||
return lib_plankton.string.coin(
|
|
||||||
"auto-{{name_raw}}",
|
|
||||||
{
|
|
||||||
"name_raw": group_name_raw,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
function get_group_label(
|
|
||||||
group_name_raw : string
|
|
||||||
)
|
|
||||||
: string
|
|
||||||
{
|
|
||||||
return lib_plankton.string.coin(
|
|
||||||
"{{name_raw}}",
|
|
||||||
{
|
|
||||||
"name_raw": group_name_raw,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
export function register_session_oidc(
|
export function register_session_oidc(
|
||||||
|
|
@ -106,7 +74,6 @@ namespace _zeitbild.api
|
||||||
userinfo : {
|
userinfo : {
|
||||||
name : (null | string);
|
name : (null | string);
|
||||||
email : (null | string);
|
email : (null | string);
|
||||||
groups : (null | Array<string>);
|
|
||||||
};
|
};
|
||||||
redirect_uri_template : string;
|
redirect_uri_template : string;
|
||||||
} = await _zeitbild.auth.oidc_handle_authorization_callback(
|
} = await _zeitbild.auth.oidc_handle_authorization_callback(
|
||||||
|
|
@ -125,50 +92,9 @@ namespace _zeitbild.api
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// groups
|
|
||||||
const group_ids : Array<_zeitbild.type_group_id> = await Promise.all<_zeitbild.type_group_id>(
|
|
||||||
(data.userinfo.groups ?? [])
|
|
||||||
.map(
|
|
||||||
async (group_name_raw) => {
|
|
||||||
const group_name : string = get_group_name(group_name_raw);
|
|
||||||
let group_id : (null | _zeitbild.type_group_id) = await (() => {
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return _zeitbild.repository.group.identify(group_name);
|
|
||||||
}
|
|
||||||
catch (error)
|
|
||||||
{
|
|
||||||
return Promise.resolve(null);
|
|
||||||
}
|
|
||||||
}) ();
|
|
||||||
if (group_id === null)
|
|
||||||
{
|
|
||||||
group_id = await _zeitbild.service.group.add(
|
|
||||||
{
|
|
||||||
"name": group_name,
|
|
||||||
"label": get_group_label(group_name_raw),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return group_id;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await _zeitbild.service.group.change(
|
|
||||||
group_id,
|
|
||||||
{
|
|
||||||
"name": group_name,
|
|
||||||
"label": get_group_label(group_name_raw),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return group_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
await _zeitbild.service.user.add(
|
await _zeitbild.service.user.add(
|
||||||
{
|
{
|
||||||
"name": data.userinfo.name,
|
"name": data.userinfo.name,
|
||||||
"groups": group_ids,
|
|
||||||
"email_address": data.userinfo.email,
|
"email_address": data.userinfo.email,
|
||||||
"dav_token": null,
|
"dav_token": null,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,10 +51,6 @@ namespace _zeitbild.api
|
||||||
_zeitbild.api.register_session_oidc(rest_subject);
|
_zeitbild.api.register_session_oidc(rest_subject);
|
||||||
_zeitbild.api.register_session_status(rest_subject);
|
_zeitbild.api.register_session_status(rest_subject);
|
||||||
}
|
}
|
||||||
// groups
|
|
||||||
{
|
|
||||||
_zeitbild.api.register_group_list(rest_subject);
|
|
||||||
}
|
|
||||||
// user
|
// user
|
||||||
{
|
{
|
||||||
_zeitbild.api.register_users(rest_subject);
|
_zeitbild.api.register_users(rest_subject);
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,6 @@ namespace _zeitbild.auth
|
||||||
userinfo : {
|
userinfo : {
|
||||||
name : (null | string);
|
name : (null | string);
|
||||||
email : (null | string);
|
email : (null | string);
|
||||||
groups : (null | Array<string>);
|
|
||||||
};
|
};
|
||||||
redirect_uri_template : string;
|
redirect_uri_template : string;
|
||||||
}
|
}
|
||||||
|
|
@ -208,7 +207,6 @@ namespace _zeitbild.auth
|
||||||
userinfo : {
|
userinfo : {
|
||||||
name : (null | string);
|
name : (null | string);
|
||||||
email : (null | string);
|
email : (null | string);
|
||||||
groups : (null | Array<string>);
|
|
||||||
};
|
};
|
||||||
} = await lib_plankton.auth.oidc.handle_authorization_callback(
|
} = await lib_plankton.auth.oidc.handle_authorization_callback(
|
||||||
_subject_oidc,
|
_subject_oidc,
|
||||||
|
|
@ -221,7 +219,6 @@ namespace _zeitbild.auth
|
||||||
userinfo : {
|
userinfo : {
|
||||||
name : (null | string);
|
name : (null | string);
|
||||||
email : (null | string);
|
email : (null | string);
|
||||||
groups : (null | Array<string>);
|
|
||||||
};
|
};
|
||||||
redirect_uri_template : string;
|
redirect_uri_template : string;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace _zeitbild.database
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
const _compatible_revisions : Array<string> = [
|
const _compatible_revisions : Array<string> = [
|
||||||
"r6",
|
"r5",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
199
source/logic.ts
199
source/logic.ts
|
|
@ -1,199 +0,0 @@
|
||||||
/*
|
|
||||||
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
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export function access_level_to_string(
|
|
||||||
access_level : _zeitbild.enum_access_level
|
|
||||||
)
|
|
||||||
: string
|
|
||||||
{
|
|
||||||
switch (access_level)
|
|
||||||
{
|
|
||||||
case _zeitbild.enum_access_level.none: {return "none";}
|
|
||||||
case _zeitbild.enum_access_level.view: {return "view";}
|
|
||||||
case _zeitbild.enum_access_level.edit: {return "edit";}
|
|
||||||
case _zeitbild.enum_access_level.admin: {return "admin";}
|
|
||||||
default: {throw (new Error("invalid access level: " + String(access_level)));}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export function access_level_from_string(
|
|
||||||
representation : string
|
|
||||||
)
|
|
||||||
: _zeitbild.enum_access_level
|
|
||||||
{
|
|
||||||
switch (representation)
|
|
||||||
{
|
|
||||||
case "none": {return _zeitbild.enum_access_level.none;}
|
|
||||||
case "view": {return _zeitbild.enum_access_level.view;}
|
|
||||||
case "edit": {return _zeitbild.enum_access_level.edit;}
|
|
||||||
case "admin": {return _zeitbild.enum_access_level.admin;}
|
|
||||||
default: {throw (new Error("invalid encoded access level: " + String(representation)));}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export function access_level_order(
|
|
||||||
x : _zeitbild.enum_access_level,
|
|
||||||
y : _zeitbild.enum_access_level
|
|
||||||
)
|
|
||||||
: boolean
|
|
||||||
{
|
|
||||||
const list : Array<_zeitbild.enum_access_level> = [
|
|
||||||
_zeitbild.enum_access_level.none,
|
|
||||||
_zeitbild.enum_access_level.view,
|
|
||||||
_zeitbild.enum_access_level.edit,
|
|
||||||
_zeitbild.enum_access_level.admin,
|
|
||||||
];
|
|
||||||
return (list.indexOf(x) <= list.indexOf(y));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export function access_level_determine_raw(
|
|
||||||
public_ : boolean,
|
|
||||||
access_level_attributed : (
|
|
||||||
null
|
|
||||||
|
|
|
||||||
{
|
|
||||||
default : _zeitbild.enum_access_level,
|
|
||||||
group : Array<_zeitbild.enum_access_level>;
|
|
||||||
user : (null | _zeitbild.enum_access_level);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
: _zeitbild.enum_access_level
|
|
||||||
{
|
|
||||||
return lib_plankton.call.convey(
|
|
||||||
_zeitbild.enum_access_level.none,
|
|
||||||
[
|
|
||||||
// if public
|
|
||||||
(x : _zeitbild.enum_access_level) => (
|
|
||||||
public_
|
|
||||||
?
|
|
||||||
_zeitbild.enum_access_level.view
|
|
||||||
:
|
|
||||||
x
|
|
||||||
),
|
|
||||||
// if logged in
|
|
||||||
(x : _zeitbild.enum_access_level) => (
|
|
||||||
(access_level_attributed === null)
|
|
||||||
?
|
|
||||||
x
|
|
||||||
:
|
|
||||||
lib_plankton.call.convey(
|
|
||||||
x,
|
|
||||||
[
|
|
||||||
// default
|
|
||||||
(y : _zeitbild.enum_access_level) => access_level_attributed.default,
|
|
||||||
// group
|
|
||||||
(y : _zeitbild.enum_access_level) => (
|
|
||||||
lib_plankton.call.null_prop(
|
|
||||||
lib_plankton.list.max<_zeitbild.enum_access_level, _zeitbild.enum_access_level>(
|
|
||||||
access_level_attributed.group,
|
|
||||||
z => z,
|
|
||||||
{
|
|
||||||
"compare_value": _zeitbild.access_level_order,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
z => z.value
|
|
||||||
)
|
|
||||||
??
|
|
||||||
y
|
|
||||||
),
|
|
||||||
// user
|
|
||||||
(y : _zeitbild.enum_access_level) => (
|
|
||||||
(access_level_attributed.user === null)
|
|
||||||
?
|
|
||||||
y
|
|
||||||
:
|
|
||||||
access_level_attributed.user
|
|
||||||
),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export function access_level_determine(
|
|
||||||
calendar_object : _zeitbild.type_calendar_object,
|
|
||||||
user : (
|
|
||||||
null
|
|
||||||
|
|
|
||||||
{
|
|
||||||
id : _zeitbild.type_user_id;
|
|
||||||
object : _zeitbild.type_user_object;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
: _zeitbild.enum_access_level
|
|
||||||
{
|
|
||||||
return access_level_determine_raw(
|
|
||||||
calendar_object.access.public,
|
|
||||||
(
|
|
||||||
(user === null)
|
|
||||||
?
|
|
||||||
null
|
|
||||||
:
|
|
||||||
{
|
|
||||||
"default": calendar_object.access.default_level,
|
|
||||||
"group": (
|
|
||||||
user.object.groups
|
|
||||||
.map<(null | _zeitbild.enum_access_level)>(
|
|
||||||
group_id => (
|
|
||||||
calendar_object.access.attributed_group.has(group_id)
|
|
||||||
?
|
|
||||||
calendar_object.access.attributed_group.get(group_id)
|
|
||||||
:
|
|
||||||
null
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.filter(
|
|
||||||
x => (x !== null)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"user": (
|
|
||||||
lib_plankton.call.try_catch_wrap<_zeitbild.enum_access_level>(
|
|
||||||
() => calendar_object.access.attributed_user.get(user.id)
|
|
||||||
).value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -34,16 +34,7 @@ namespace _zeitbild.repository.calendar
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
type type_access_attributed_group_row = {
|
type type_access_attributed_row = {
|
||||||
// calendar_id : int;
|
|
||||||
group_id : int;
|
|
||||||
level : int;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
type type_access_attributed_user_row = {
|
|
||||||
// calendar_id : int;
|
// calendar_id : int;
|
||||||
user_id : int;
|
user_id : int;
|
||||||
level : int;
|
level : int;
|
||||||
|
|
@ -54,8 +45,7 @@ namespace _zeitbild.repository.calendar
|
||||||
*/
|
*/
|
||||||
type type_dispersal = {
|
type type_dispersal = {
|
||||||
core_row : type_core_row;
|
core_row : type_core_row;
|
||||||
access_attributed_group_rows : Array<type_access_attributed_group_row>;
|
access_attributed_rows : Array<type_access_attributed_row>;
|
||||||
access_attributed_user_rows : Array<type_access_attributed_user_row>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -81,22 +71,7 @@ namespace _zeitbild.repository.calendar
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
var _access_attributed_group_chest : (
|
var _access_attributed_chest : (
|
||||||
null
|
|
||||||
|
|
|
||||||
lib_plankton.storage.type_chest<
|
|
||||||
Array<any>,
|
|
||||||
Record<string, any>,
|
|
||||||
lib_plankton.database.type_description_create_table,
|
|
||||||
lib_plankton.storage.sql_table_common.type_sql_table_common_search_term,
|
|
||||||
Record<string, any>
|
|
||||||
>
|
|
||||||
) = null;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
var _access_attributed_user_chest : (
|
|
||||||
null
|
null
|
||||||
|
|
|
|
||||||
lib_plankton.storage.type_chest<
|
lib_plankton.storage.type_chest<
|
||||||
|
|
@ -112,8 +87,7 @@ namespace _zeitbild.repository.calendar
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
function get_core_store(
|
function get_core_store(
|
||||||
)
|
) : lib_plankton.storage.type_store<
|
||||||
: lib_plankton.storage.type_store<
|
|
||||||
_zeitbild.type_calendar_id,
|
_zeitbild.type_calendar_id,
|
||||||
Record<string, any>,
|
Record<string, any>,
|
||||||
{},
|
{},
|
||||||
|
|
@ -121,8 +95,7 @@ namespace _zeitbild.repository.calendar
|
||||||
Record<string, any>
|
Record<string, any>
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
if (_core_store === null)
|
if (_core_store === null) {
|
||||||
{
|
|
||||||
_core_store = lib_plankton.storage.sql_table_autokey_store(
|
_core_store = lib_plankton.storage.sql_table_autokey_store(
|
||||||
{
|
{
|
||||||
"database_implementation": _zeitbild.database.get_implementation(),
|
"database_implementation": _zeitbild.database.get_implementation(),
|
||||||
|
|
@ -131,8 +104,7 @@ namespace _zeitbild.repository.calendar
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
return _core_store;
|
return _core_store;
|
||||||
|
|
@ -141,7 +113,7 @@ namespace _zeitbild.repository.calendar
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
function get_access_attributed_group_chest(
|
function get_access_attributed_chest(
|
||||||
) : lib_plankton.storage.type_chest<
|
) : lib_plankton.storage.type_chest<
|
||||||
Array<any>,
|
Array<any>,
|
||||||
Record<string, any>,
|
Record<string, any>,
|
||||||
|
|
@ -150,51 +122,19 @@ namespace _zeitbild.repository.calendar
|
||||||
Record<string, any>
|
Record<string, any>
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
if (_access_attributed_group_chest === null)
|
if (_access_attributed_chest === null) {
|
||||||
{
|
_access_attributed_chest = lib_plankton.storage.sql_table_common.chest(
|
||||||
_access_attributed_group_chest = lib_plankton.storage.sql_table_common.chest(
|
|
||||||
{
|
{
|
||||||
"database_implementation": _zeitbild.database.get_implementation(),
|
"database_implementation": _zeitbild.database.get_implementation(),
|
||||||
"table_name": "calendar_access_attributed_group",
|
"table_name": "calendar_access_attributed",
|
||||||
"key_names": ["calendar_id","group_id"],
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
return _access_attributed_group_chest;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
function get_access_attributed_user_chest(
|
|
||||||
)
|
|
||||||
: lib_plankton.storage.type_chest<
|
|
||||||
Array<any>,
|
|
||||||
Record<string, any>,
|
|
||||||
lib_plankton.database.type_description_create_table,
|
|
||||||
lib_plankton.storage.sql_table_common.type_sql_table_common_search_term,
|
|
||||||
Record<string, any>
|
|
||||||
>
|
|
||||||
{
|
|
||||||
if (_access_attributed_user_chest === null)
|
|
||||||
{
|
|
||||||
_access_attributed_user_chest = lib_plankton.storage.sql_table_common.chest(
|
|
||||||
{
|
|
||||||
"database_implementation": _zeitbild.database.get_implementation(),
|
|
||||||
"table_name": "calendar_access_attributed_user",
|
|
||||||
"key_names": ["calendar_id","user_id"],
|
"key_names": ["calendar_id","user_id"],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
return _access_attributed_user_chest;
|
return _access_attributed_chest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -236,8 +176,7 @@ namespace _zeitbild.repository.calendar
|
||||||
*/
|
*/
|
||||||
function encode(
|
function encode(
|
||||||
object : _zeitbild.type_calendar_object
|
object : _zeitbild.type_calendar_object
|
||||||
)
|
) : type_dispersal
|
||||||
: type_dispersal
|
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
"core_row": {
|
"core_row": {
|
||||||
|
|
@ -247,18 +186,8 @@ namespace _zeitbild.repository.calendar
|
||||||
"access_level_default": encode_access_level(object.access.default_level),
|
"access_level_default": encode_access_level(object.access.default_level),
|
||||||
"resource_id": object.resource_id,
|
"resource_id": object.resource_id,
|
||||||
},
|
},
|
||||||
"access_attributed_group_rows": (
|
"access_attributed_rows": (
|
||||||
lib_plankton.map.dump(object.access.attributed_group)
|
lib_plankton.map.dump(object.access.attributed)
|
||||||
.map(
|
|
||||||
({"key": group_id, "value": level}) => ({
|
|
||||||
// "calendar_id": calendar_id,
|
|
||||||
"group_id": group_id,
|
|
||||||
"level": encode_access_level(level),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"access_attributed_user_rows": (
|
|
||||||
lib_plankton.map.dump(object.access.attributed_user)
|
|
||||||
.map(
|
.map(
|
||||||
({"key": user_id, "value": level}) => ({
|
({"key": user_id, "value": level}) => ({
|
||||||
// "calendar_id": calendar_id,
|
// "calendar_id": calendar_id,
|
||||||
|
|
@ -275,8 +204,7 @@ namespace _zeitbild.repository.calendar
|
||||||
*/
|
*/
|
||||||
function decode(
|
function decode(
|
||||||
dispersal : type_dispersal
|
dispersal : type_dispersal
|
||||||
)
|
) : _zeitbild.type_calendar_object
|
||||||
: _zeitbild.type_calendar_object
|
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
"name": dispersal.core_row.name,
|
"name": dispersal.core_row.name,
|
||||||
|
|
@ -284,38 +212,19 @@ namespace _zeitbild.repository.calendar
|
||||||
"access": {
|
"access": {
|
||||||
"public": dispersal.core_row.access_public,
|
"public": dispersal.core_row.access_public,
|
||||||
"default_level": decode_access_level(dispersal.core_row.access_level_default),
|
"default_level": decode_access_level(dispersal.core_row.access_level_default),
|
||||||
"attributed_group": lib_plankton.map.hashmap.implementation_map(
|
"attributed": lib_plankton.map.hashmap.implementation_map(
|
||||||
lib_plankton.map.hashmap.make<_zeitbild.type_group_id, _zeitbild.enum_access_level>(
|
|
||||||
x => x.toFixed(0),
|
|
||||||
{
|
|
||||||
"pairs": (
|
|
||||||
dispersal.access_attributed_group_rows
|
|
||||||
.map(
|
|
||||||
(access_attributed_group_row) => ({
|
|
||||||
// "calendar_id": access_attributed_group_row["calendar_id"],
|
|
||||||
// "key": access_attributed_group_row["preview"]["user_id"],
|
|
||||||
"key": access_attributed_group_row.group_id,
|
|
||||||
// "value": decode_access_level(access_attributed_group_row["preview"]["level"]),
|
|
||||||
"value": decode_access_level(access_attributed_group_row.level),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"attributed_user": lib_plankton.map.hashmap.implementation_map(
|
|
||||||
lib_plankton.map.hashmap.make<_zeitbild.type_user_id, _zeitbild.enum_access_level>(
|
lib_plankton.map.hashmap.make<_zeitbild.type_user_id, _zeitbild.enum_access_level>(
|
||||||
x => x.toFixed(0),
|
x => x.toFixed(0),
|
||||||
{
|
{
|
||||||
"pairs": (
|
"pairs": (
|
||||||
dispersal.access_attributed_user_rows
|
dispersal.access_attributed_rows
|
||||||
.map(
|
.map(
|
||||||
(access_attributed_user_row) => ({
|
(access_attributed_row) => ({
|
||||||
// "calendar_id": access_attributed_user_row["calendar_id"],
|
// "calendar_id": access_attributed_row["calendar_id"],
|
||||||
// "key": access_attributed_user_row["preview"]["user_id"],
|
// "key": access_attributed_row["preview"]["user_id"],
|
||||||
"key": access_attributed_user_row.user_id,
|
"key": access_attributed_row.user_id,
|
||||||
// "value": decode_access_level(access_attributed_user_row["preview"]["level"]),
|
// "value": decode_access_level(access_attributed_row["preview"]["level"]),
|
||||||
"value": decode_access_level(access_attributed_user_row.level),
|
"value": decode_access_level(access_attributed_row.level),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
@ -331,67 +240,52 @@ namespace _zeitbild.repository.calendar
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
export async function read(
|
export function read(
|
||||||
id : _zeitbild.type_calendar_id
|
id : _zeitbild.type_calendar_id
|
||||||
)
|
) : Promise<_zeitbild.type_calendar_object>
|
||||||
: Promise<_zeitbild.type_calendar_object>
|
|
||||||
{
|
{
|
||||||
const core_row : type_core_row = ((await get_core_store().read(id)) as type_core_row);
|
return (
|
||||||
const access_attributed_group_rows : Array<type_access_attributed_group_row> = await (
|
get_core_store().read(id)
|
||||||
get_access_attributed_group_chest().search(
|
|
||||||
{
|
|
||||||
"expression": "(calendar_id = $calendar_id)",
|
|
||||||
"arguments": {
|
|
||||||
"calendar_id": id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then(
|
.then(
|
||||||
(hits) => Promise.resolve<Array<type_access_attributed_group_row>>(
|
(core_row_raw) => {
|
||||||
hits
|
const core_row : type_core_row = (core_row_raw as type_core_row);
|
||||||
.map(
|
return (
|
||||||
hit => (
|
get_access_attributed_chest().search(
|
||||||
{
|
{
|
||||||
// "calendar_id": null,
|
"expression": "(calendar_id = $calendar_id)",
|
||||||
"group_id": hit.preview.group_id,
|
"arguments": {
|
||||||
"level": hit.preview.level,
|
"calendar_id": id,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
.then(
|
||||||
)
|
(hits) => Promise.resolve<type_dispersal>(
|
||||||
)
|
{
|
||||||
);
|
"core_row": core_row,
|
||||||
const access_attributed_user_rows : Array<type_access_attributed_user_row> = await (
|
"access_attributed_rows": (
|
||||||
get_access_attributed_user_chest().search(
|
hits
|
||||||
{
|
.map(
|
||||||
"expression": "(calendar_id = $calendar_id)",
|
hit => (
|
||||||
"arguments": {
|
{
|
||||||
"calendar_id": id,
|
// "calendar_id": null,
|
||||||
}
|
"user_id": hit.preview.user_id,
|
||||||
|
"level": hit.preview.level,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(dispersal) => Promise.resolve<_zeitbild.type_calendar_object>(
|
||||||
|
decode(dispersal)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then(
|
|
||||||
(hits) => Promise.resolve<Array<type_access_attributed_user_row>>(
|
|
||||||
hits
|
|
||||||
.map(
|
|
||||||
hit => (
|
|
||||||
{
|
|
||||||
// "calendar_id": null,
|
|
||||||
"user_id": hit.preview.user_id,
|
|
||||||
"level": hit.preview.level,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
const dispersal : type_dispersal = {
|
|
||||||
"core_row": core_row,
|
|
||||||
"access_attributed_group_rows": access_attributed_group_rows,
|
|
||||||
"access_attributed_user_rows": access_attributed_user_rows,
|
|
||||||
};
|
|
||||||
const calendar_object : _zeitbild.type_calendar_object = decode(dispersal);
|
|
||||||
return calendar_object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -406,16 +300,10 @@ namespace _zeitbild.repository.calendar
|
||||||
const calendar_id : _zeitbild.type_calendar_id = await core_store.create(
|
const calendar_id : _zeitbild.type_calendar_id = await core_store.create(
|
||||||
dispersal.core_row
|
dispersal.core_row
|
||||||
);
|
);
|
||||||
for await (const access_attributed_group_row of dispersal.access_attributed_group_rows) {
|
for await (const access_attributed_row of dispersal.access_attributed_rows) {
|
||||||
get_access_attributed_group_chest().write(
|
get_access_attributed_chest().write(
|
||||||
[calendar_id, access_attributed_group_row["group_id"]],
|
[calendar_id, access_attributed_row["user_id"]],
|
||||||
{"level": access_attributed_group_row["level"]}
|
{"level": access_attributed_row["level"]}
|
||||||
);
|
|
||||||
}
|
|
||||||
for await (const access_attributed_user_row of dispersal.access_attributed_user_rows) {
|
|
||||||
get_access_attributed_user_chest().write(
|
|
||||||
[calendar_id, access_attributed_user_row["user_id"]],
|
|
||||||
{"level": access_attributed_user_row["level"]}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await lib_plankton.cache.clear(_zeitbild.cache_regular);
|
await lib_plankton.cache.clear(_zeitbild.cache_regular);
|
||||||
|
|
@ -439,51 +327,10 @@ namespace _zeitbild.repository.calendar
|
||||||
dispersal.core_row
|
dispersal.core_row
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// attributed:group
|
// attributed access
|
||||||
{
|
{
|
||||||
const access_attributed_group_chest = get_access_attributed_group_chest();
|
const access_attributed_chest = get_access_attributed_chest();
|
||||||
const hits : Array<Record<string, any>> = await access_attributed_group_chest.search(
|
const hits : Array<Record<string, any>> = await access_attributed_chest.search(
|
||||||
{
|
|
||||||
"expression": "(calendar_id = $calendar_id)",
|
|
||||||
"arguments": {
|
|
||||||
"calendar_id": calendar_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const contrast = lib_plankton.list.contrast<
|
|
||||||
Record<string, any>,
|
|
||||||
Record<string, any>
|
|
||||||
>(
|
|
||||||
hits,
|
|
||||||
hit => hit["group_id"],
|
|
||||||
dispersal.access_attributed_group_rows,
|
|
||||||
row => row["group_id"]
|
|
||||||
);
|
|
||||||
// delete
|
|
||||||
for await (const entry of contrast.only_left) {
|
|
||||||
await access_attributed_group_chest.delete(
|
|
||||||
[calendar_id, entry.left["group_id"]]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// update
|
|
||||||
for await (const entry of contrast.both) {
|
|
||||||
await access_attributed_group_chest.write(
|
|
||||||
[calendar_id, entry.right["group_id"]],
|
|
||||||
{"level": entry.right["level"]}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// create
|
|
||||||
for await (const entry of contrast.only_right) {
|
|
||||||
await access_attributed_group_chest.write(
|
|
||||||
[calendar_id, entry.right["group_id"]],
|
|
||||||
{"level": entry.right["level"]}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// attributed:user
|
|
||||||
{
|
|
||||||
const access_attributed_user_chest = get_access_attributed_user_chest();
|
|
||||||
const hits : Array<Record<string, any>> = await access_attributed_user_chest.search(
|
|
||||||
{
|
{
|
||||||
"expression": "(calendar_id = $calendar_id)",
|
"expression": "(calendar_id = $calendar_id)",
|
||||||
"arguments": {
|
"arguments": {
|
||||||
|
|
@ -497,25 +344,25 @@ namespace _zeitbild.repository.calendar
|
||||||
>(
|
>(
|
||||||
hits,
|
hits,
|
||||||
hit => hit["user_id"],
|
hit => hit["user_id"],
|
||||||
dispersal.access_attributed_user_rows,
|
dispersal.access_attributed_rows,
|
||||||
row => row["user_id"]
|
row => row["user_id"]
|
||||||
);
|
);
|
||||||
// delete
|
// delete
|
||||||
for await (const entry of contrast.only_left) {
|
for await (const entry of contrast.only_left) {
|
||||||
await access_attributed_user_chest.delete(
|
await access_attributed_chest.delete(
|
||||||
[calendar_id, entry.left["user_id"]]
|
[calendar_id, entry.left["user_id"]]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// update
|
// update
|
||||||
for await (const entry of contrast.both) {
|
for await (const entry of contrast.both) {
|
||||||
await access_attributed_user_chest.write(
|
await access_attributed_chest.write(
|
||||||
[calendar_id, entry.right["user_id"]],
|
[calendar_id, entry.right["user_id"]],
|
||||||
{"level": entry.right["level"]}
|
{"level": entry.right["level"]}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// create
|
// create
|
||||||
for await (const entry of contrast.only_right) {
|
for await (const entry of contrast.only_right) {
|
||||||
await access_attributed_user_chest.write(
|
await access_attributed_chest.write(
|
||||||
[calendar_id, entry.right["user_id"]],
|
[calendar_id, entry.right["user_id"]],
|
||||||
{"level": entry.right["level"]}
|
{"level": entry.right["level"]}
|
||||||
);
|
);
|
||||||
|
|
@ -537,16 +384,15 @@ namespace _zeitbild.repository.calendar
|
||||||
{
|
{
|
||||||
await lib_plankton.cache.clear(_zeitbild.cache_regular);
|
await lib_plankton.cache.clear(_zeitbild.cache_regular);
|
||||||
const core_store = get_core_store();
|
const core_store = get_core_store();
|
||||||
const access_attributed_user_chest = get_access_attributed_user_chest();
|
const access_attributed_chest = get_access_attributed_chest();
|
||||||
// attributed:user
|
// attributed access
|
||||||
{
|
{
|
||||||
const chest = get_access_attributed_user_chest();
|
|
||||||
const hits : Array<
|
const hits : Array<
|
||||||
{
|
{
|
||||||
key : Array<any>;
|
key : Array<any>;
|
||||||
preview : Record<string, any>;
|
preview : Record<string, any>;
|
||||||
}
|
}
|
||||||
> = await chest.search(
|
> = await access_attributed_chest.search(
|
||||||
{
|
{
|
||||||
"expression": "(calendar_id = $calendar_id)",
|
"expression": "(calendar_id = $calendar_id)",
|
||||||
"arguments": {
|
"arguments": {
|
||||||
|
|
@ -556,28 +402,9 @@ namespace _zeitbild.repository.calendar
|
||||||
);
|
);
|
||||||
for (const hit of hits)
|
for (const hit of hits)
|
||||||
{
|
{
|
||||||
await chest.delete(hit.key);
|
await access_attributed_chest.delete(
|
||||||
}
|
hit.key
|
||||||
}
|
);
|
||||||
// attributed:group
|
|
||||||
{
|
|
||||||
const chest = get_access_attributed_group_chest();
|
|
||||||
const hits : Array<
|
|
||||||
{
|
|
||||||
key : Array<any>;
|
|
||||||
preview : Record<string, any>;
|
|
||||||
}
|
|
||||||
> = await chest.search(
|
|
||||||
{
|
|
||||||
"expression": "(calendar_id = $calendar_id)",
|
|
||||||
"arguments": {
|
|
||||||
"calendar_id": calendar_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
for (const hit of hits)
|
|
||||||
{
|
|
||||||
await chest.delete(hit.key);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// core
|
// core
|
||||||
|
|
@ -605,8 +432,7 @@ namespace _zeitbild.repository.calendar
|
||||||
*/
|
*/
|
||||||
export async function overview(
|
export async function overview(
|
||||||
user_id : (null | _zeitbild.type_user_id)
|
user_id : (null | _zeitbild.type_user_id)
|
||||||
)
|
) : Promise<
|
||||||
: Promise<
|
|
||||||
Array<
|
Array<
|
||||||
type_overview_entry
|
type_overview_entry
|
||||||
>
|
>
|
||||||
|
|
@ -642,37 +468,25 @@ namespace _zeitbild.repository.calendar
|
||||||
"name": row["name"],
|
"name": row["name"],
|
||||||
"hue": (row["hue"] / hue_scaling),
|
"hue": (row["hue"] / hue_scaling),
|
||||||
/**
|
/**
|
||||||
* @todo use _zeitbild.access_level_determine
|
* @todo unite with _zeitbild.service.calendar.get_access_level
|
||||||
*/
|
*/
|
||||||
"access_level": _zeitbild.access_level_determine_raw(
|
"access_level": decode_access_level(
|
||||||
row["access_public"],
|
Math.max(
|
||||||
(
|
(row["access_public"] ? 1 : 0),
|
||||||
(user_id === null)
|
(
|
||||||
?
|
(user_id === null)
|
||||||
null
|
?
|
||||||
:
|
0
|
||||||
{
|
:
|
||||||
"default": decode_access_level(row["access_level_default"]),
|
(row["access_level_attributed"] ?? row["access_level_default"])
|
||||||
"group": (
|
)
|
||||||
lib_plankton.call.null_prop<string, Array<_zeitbild.enum_access_level>>(
|
|
||||||
row["access_level_attributed_group"],
|
|
||||||
x => x.split(",").map(parseInt).map(decode_access_level)
|
|
||||||
)
|
|
||||||
??
|
|
||||||
[]
|
|
||||||
),
|
|
||||||
"user": lib_plankton.call.null_prop<int, _zeitbild.enum_access_level>(
|
|
||||||
row["access_level_attributed_user"],
|
|
||||||
decode_access_level
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
(x : Array<type_overview_entry>) => x.filter(
|
(x : Array<type_overview_entry>) => x.filter(
|
||||||
(row) => (
|
(row) => (
|
||||||
! _zeitbild.access_level_order(
|
! _zeitbild.value_object.access_level.order(
|
||||||
row.access_level,
|
row.access_level,
|
||||||
_zeitbild.enum_access_level.none
|
_zeitbild.enum_access_level.none
|
||||||
)
|
)
|
||||||
|
|
@ -685,7 +499,7 @@ namespace _zeitbild.repository.calendar
|
||||||
row => row.access_level,
|
row => row.access_level,
|
||||||
row => row.id,
|
row => row.id,
|
||||||
{
|
{
|
||||||
"order_first": (a, b) => _zeitbild.access_level_order(b, a),
|
"order_first": (a, b) => _zeitbild.value_object.access_level.order(b, a),
|
||||||
"order_second": (a, b) => (a <= b)
|
"order_second": (a, b) => (a <= b)
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,207 +0,0 @@
|
||||||
/*
|
|
||||||
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.group
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
type type_row = {
|
|
||||||
name : string;
|
|
||||||
label : string;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
type type_preview = {
|
|
||||||
name : string;
|
|
||||||
label : string;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
var _store : (
|
|
||||||
null
|
|
||||||
|
|
|
||||||
lib_plankton.storage.type_store<
|
|
||||||
_zeitbild.type_user_id,
|
|
||||||
/*type_row*/Record<string, any>,
|
|
||||||
{},
|
|
||||||
lib_plankton.storage.type_sql_table_autokey_search_term,
|
|
||||||
/*type_preview*/Record<string, any>
|
|
||||||
>
|
|
||||||
) = null;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
function get_store(
|
|
||||||
)
|
|
||||||
: lib_plankton.storage.type_store<
|
|
||||||
_zeitbild.type_user_id,
|
|
||||||
/*type_row*/Record<string, any>,
|
|
||||||
{},
|
|
||||||
lib_plankton.storage.type_sql_table_autokey_search_term,
|
|
||||||
/*type_preview*/Record<string, any>
|
|
||||||
>
|
|
||||||
{
|
|
||||||
if (_store === null)
|
|
||||||
{
|
|
||||||
_store = lib_plankton.storage.sql_table_autokey_store(
|
|
||||||
{
|
|
||||||
"database_implementation": _zeitbild.database.get_implementation(),
|
|
||||||
"table_name": "groups",
|
|
||||||
"key_name": "id",
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
return _store;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
function encode(
|
|
||||||
group_object : _zeitbild.type_group_object
|
|
||||||
)
|
|
||||||
: type_row
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
"name": group_object.name,
|
|
||||||
"label": group_object.label,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
function decode(
|
|
||||||
row : type_row
|
|
||||||
)
|
|
||||||
: _zeitbild.type_group_object
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
"name": row.name,
|
|
||||||
"label": row.label,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export async function list(
|
|
||||||
)
|
|
||||||
: Promise<
|
|
||||||
Array<
|
|
||||||
{
|
|
||||||
id : _zeitbild.type_group_id;
|
|
||||||
object : _zeitbild.type_group_object;
|
|
||||||
}
|
|
||||||
>
|
|
||||||
>
|
|
||||||
{
|
|
||||||
const hits : Array<{key : int; preview : /*type_preview*/Record<string, any>;}> = await get_store().search({"expression": "TRUE", "arguments": {}});
|
|
||||||
return Promise.resolve(
|
|
||||||
hits
|
|
||||||
.map(
|
|
||||||
(hit) => ({
|
|
||||||
"id": hit.key,
|
|
||||||
"object": {
|
|
||||||
"name": hit.preview.name,
|
|
||||||
"label": hit.preview.label,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export async function read(
|
|
||||||
group_id : _zeitbild.type_group_id
|
|
||||||
)
|
|
||||||
: Promise<_zeitbild.type_group_object>
|
|
||||||
{
|
|
||||||
const row : type_row = ((await get_store().read(group_id)) as type_row);
|
|
||||||
const group_object : _zeitbild.type_group_object = decode(row);
|
|
||||||
return Promise.resolve<_zeitbild.type_group_object>(group_object);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export async function create(
|
|
||||||
group_object : _zeitbild.type_group_object
|
|
||||||
)
|
|
||||||
: Promise<_zeitbild.type_group_id>
|
|
||||||
{
|
|
||||||
const row : type_row = encode(group_object);
|
|
||||||
const group_id : _zeitbild.type_group_id = await get_store().create(row);
|
|
||||||
return Promise.resolve<_zeitbild.type_group_id>(group_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export async function update(
|
|
||||||
group_id : _zeitbild.type_group_id,
|
|
||||||
group_object : _zeitbild.type_group_object
|
|
||||||
)
|
|
||||||
: Promise<void>
|
|
||||||
{
|
|
||||||
const row : type_row = encode(group_object);
|
|
||||||
await get_store().update(group_id, row);
|
|
||||||
return Promise.resolve<void>(undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export async function identify(
|
|
||||||
name : string
|
|
||||||
)
|
|
||||||
: Promise<_zeitbild.type_group_id>
|
|
||||||
{
|
|
||||||
const hits : Array<{key : _zeitbild.type_group_id; preview : /*type_preview*/Record<string, any>;}> = await get_store().search(
|
|
||||||
{
|
|
||||||
"expression": "(name = $name)",
|
|
||||||
"arguments": {
|
|
||||||
"name": name,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (hits.length <= 0)
|
|
||||||
{
|
|
||||||
return Promise.reject<_zeitbild.type_group_id>(new Error("not found"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Promise.resolve<_zeitbild.type_group_id>(hits[0].key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
|
-- Für gewöhnlich würde man hier gruppieren. Aufgrund des UNIQUE-constraints in "calendar_access_attributed" ist das
|
||||||
|
-- jedoch nicht nötig, da dadurch für jeden Eintrag in "calendar" mit gegebener "user_id" höchstens ein Eintrag in
|
||||||
|
-- "calendar_access_attributed" passt und da es ein LEFT OUTER JOIN ist, wird es _genau_ ein Eintrag sein
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
x.id AS id,
|
x.id AS id,
|
||||||
MAX(x.name) AS name,
|
x.name AS name,
|
||||||
MAX(x.hue) AS hue,
|
x.hue AS hue,
|
||||||
MAX(x.access_public) AS access_public,
|
x.access_public AS access_public,
|
||||||
MAX(x.access_level_default) AS access_level_default,
|
x.access_level_default AS access_level_default,
|
||||||
GROUP_CONCAT(y1.level, ',') AS access_level_attributed_group,
|
y.level AS access_level_attributed
|
||||||
GROUP_CONCAT(y2.level, ',') AS access_level_attributed_user
|
|
||||||
FROM
|
FROM
|
||||||
calendars AS x
|
calendars AS x
|
||||||
LEFT OUTER JOIN calendar_access_attributed_group AS y1 ON ((x.id = y1.calendar_id) AND (y1.group_id IN (SELECT group_id FROM user_groups WHERE (user_id = $user_id))))
|
LEFT OUTER JOIN calendar_access_attributed AS y ON ((x.id = y.calendar_id) AND (y.user_id = $user_id))
|
||||||
LEFT OUTER JOIN calendar_access_attributed_user AS y2 ON ((x.id = y2.calendar_id) AND (y2.user_id = $user_id))
|
|
||||||
GROUP BY
|
|
||||||
x.id
|
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -23,28 +23,13 @@ namespace _zeitbild.repository.user
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
type type_core_row = {
|
type type_row = {
|
||||||
name : string;
|
name : string;
|
||||||
email_address : (null | string);
|
email_address : (null | string);
|
||||||
dav_token : (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 = {
|
type type_preview = {
|
||||||
|
|
@ -54,20 +39,12 @@ namespace _zeitbild.repository.user
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
type type_dispersal = {
|
var _store : (
|
||||||
core : type_core_row;
|
|
||||||
groups : Array<type_group_row_slim>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
var _store_core : (
|
|
||||||
null
|
null
|
||||||
|
|
|
|
||||||
lib_plankton.storage.type_store<
|
lib_plankton.storage.type_store<
|
||||||
_zeitbild.type_user_id,
|
_zeitbild.type_user_id,
|
||||||
/*type_core_row*/Record<string, any>,
|
/*type_row*/Record<string, any>,
|
||||||
{},
|
{},
|
||||||
lib_plankton.storage.type_sql_table_autokey_search_term,
|
lib_plankton.storage.type_sql_table_autokey_search_term,
|
||||||
/*type_preview*/Record<string, any>
|
/*type_preview*/Record<string, any>
|
||||||
|
|
@ -77,34 +54,19 @@ namespace _zeitbild.repository.user
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
var _store_groups : (
|
function get_store(
|
||||||
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<
|
: lib_plankton.storage.type_store<
|
||||||
_zeitbild.type_user_id,
|
_zeitbild.type_user_id,
|
||||||
/*type_core_row*/Record<string, any>,
|
/*type_row*/Record<string, any>,
|
||||||
{},
|
{},
|
||||||
lib_plankton.storage.type_sql_table_autokey_search_term,
|
lib_plankton.storage.type_sql_table_autokey_search_term,
|
||||||
/*type_preview*/Record<string, any>
|
/*type_preview*/Record<string, any>
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
if (_store_core === null)
|
if (_store === null)
|
||||||
{
|
{
|
||||||
_store_core = lib_plankton.storage.sql_table_autokey_store(
|
_store = lib_plankton.storage.sql_table_autokey_store(
|
||||||
{
|
{
|
||||||
"database_implementation": _zeitbild.database.get_implementation(),
|
"database_implementation": _zeitbild.database.get_implementation(),
|
||||||
"table_name": "users",
|
"table_name": "users",
|
||||||
|
|
@ -115,38 +77,8 @@ namespace _zeitbild.repository.user
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
return _store_core;
|
return _store;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -155,23 +87,12 @@ namespace _zeitbild.repository.user
|
||||||
function encode(
|
function encode(
|
||||||
user_object : _zeitbild.type_user_object
|
user_object : _zeitbild.type_user_object
|
||||||
)
|
)
|
||||||
: type_dispersal
|
: type_row
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
"core": {
|
"name": user_object.name,
|
||||||
"name": user_object.name,
|
"email_address": user_object.email_address,
|
||||||
"email_address": user_object.email_address,
|
"dav_token": user_object.dav_token,
|
||||||
"dav_token": user_object.dav_token,
|
|
||||||
},
|
|
||||||
"groups": (
|
|
||||||
user_object.groups.map(
|
|
||||||
group_id => (
|
|
||||||
{
|
|
||||||
"group_id": group_id,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,19 +100,14 @@ namespace _zeitbild.repository.user
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
function decode(
|
function decode(
|
||||||
dispersal : type_dispersal
|
row : type_row
|
||||||
)
|
)
|
||||||
: _zeitbild.type_user_object
|
: _zeitbild.type_user_object
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
"name": dispersal.core.name,
|
"name": row.name,
|
||||||
"groups": (
|
"email_address": row.email_address,
|
||||||
dispersal.groups.map(
|
"dav_token": row.dav_token,
|
||||||
group_row => group_row.group_id,
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"email_address": dispersal.core.email_address,
|
|
||||||
"dav_token": dispersal.core.dav_token,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -209,12 +125,7 @@ namespace _zeitbild.repository.user
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
const hits : Array<{key : int; preview : /*type_preview*/Record<string, any>;}> = await get_store_core().search(
|
const hits : Array<{key : int; preview : /*type_preview*/Record<string, any>;}> = await get_store().search({"expression": "TRUE", "arguments": {}});
|
||||||
{
|
|
||||||
"expression": "TRUE",
|
|
||||||
"arguments": {}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return Promise.resolve(
|
return Promise.resolve(
|
||||||
hits
|
hits
|
||||||
.map(
|
.map(
|
||||||
|
|
@ -234,40 +145,8 @@ namespace _zeitbild.repository.user
|
||||||
)
|
)
|
||||||
: Promise<_zeitbild.type_user_object>
|
: Promise<_zeitbild.type_user_object>
|
||||||
{
|
{
|
||||||
const core_row : type_core_row = ((await get_store_core().read(user_id)) as type_core_row);
|
const row : type_row = ((await get_store().read(user_id)) as type_row);
|
||||||
const group_rows : Array<type_group_row_fat> = (
|
const user_object : _zeitbild.type_user_object = decode(row);
|
||||||
(
|
|
||||||
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);
|
return Promise.resolve<_zeitbild.type_user_object>(user_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -279,22 +158,8 @@ namespace _zeitbild.repository.user
|
||||||
)
|
)
|
||||||
: Promise<_zeitbild.type_user_id>
|
: Promise<_zeitbild.type_user_id>
|
||||||
{
|
{
|
||||||
const dispersal : type_dispersal = encode(user_object);
|
const row : type_row = encode(user_object);
|
||||||
// core
|
const user_id : _zeitbild.type_user_id = await get_store().create(row);
|
||||||
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);
|
return Promise.resolve<_zeitbild.type_user_id>(user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,57 +172,8 @@ namespace _zeitbild.repository.user
|
||||||
)
|
)
|
||||||
: Promise<void>
|
: Promise<void>
|
||||||
{
|
{
|
||||||
const dispersal : type_dispersal = encode(user_object);
|
const row : type_row = encode(user_object);
|
||||||
// core
|
await get_store().update(user_id, row);
|
||||||
{
|
|
||||||
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);
|
return Promise.resolve<void>(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -369,7 +185,7 @@ namespace _zeitbild.repository.user
|
||||||
)
|
)
|
||||||
: Promise<_zeitbild.type_user_id>
|
: Promise<_zeitbild.type_user_id>
|
||||||
{
|
{
|
||||||
const hits : Array<{key : _zeitbild.type_user_id; preview : /*type_preview*/Record<string, any>;}> = await get_store_core().search(
|
const hits : Array<{key : _zeitbild.type_user_id; preview : /*type_preview*/Record<string, any>;}> = await get_store().search(
|
||||||
{
|
{
|
||||||
"expression": "(name = $name)",
|
"expression": "(name = $name)",
|
||||||
"arguments": {
|
"arguments": {
|
||||||
|
|
|
||||||
254
source/sample.ts
254
source/sample.ts
|
|
@ -91,20 +91,12 @@ namespace _zeitbild.sample
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
type type_data = {
|
type type_data = {
|
||||||
groups : Array<
|
|
||||||
{
|
|
||||||
id : int;
|
|
||||||
name : string;
|
|
||||||
label ?: string;
|
|
||||||
}
|
|
||||||
>;
|
|
||||||
users : Array<
|
users : Array<
|
||||||
{
|
{
|
||||||
id : int;
|
id : int;
|
||||||
name : string;
|
name : string;
|
||||||
groups ?: Array<int>;
|
|
||||||
email_address : string;
|
email_address : string;
|
||||||
dav_token ?: (null | string);
|
dav_token : (null | string);
|
||||||
password : string;
|
password : string;
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
|
|
@ -115,13 +107,7 @@ namespace _zeitbild.sample
|
||||||
access : {
|
access : {
|
||||||
public ?: boolean;
|
public ?: boolean;
|
||||||
default_level : ("none" | "view" | "edit" | "admin");
|
default_level : ("none" | "view" | "edit" | "admin");
|
||||||
attributed_group ?: Array<
|
attributed : Array<
|
||||||
{
|
|
||||||
group_id : int;
|
|
||||||
level : ("none" | "view" | "edit" | "admin");
|
|
||||||
}
|
|
||||||
>;
|
|
||||||
attributed_user ?: Array<
|
|
||||||
{
|
{
|
||||||
user_id : int;
|
user_id : int;
|
||||||
level : ("none" | "view" | "edit" | "admin");
|
level : ("none" | "view" | "edit" | "admin");
|
||||||
|
|
@ -236,10 +222,6 @@ namespace _zeitbild.sample
|
||||||
) : Promise<void>
|
) : Promise<void>
|
||||||
{
|
{
|
||||||
let track : {
|
let track : {
|
||||||
group : Record<
|
|
||||||
int,
|
|
||||||
_zeitbild.type_group_id
|
|
||||||
>;
|
|
||||||
user : Record<
|
user : Record<
|
||||||
int,
|
int,
|
||||||
_zeitbild.type_user_id
|
_zeitbild.type_user_id
|
||||||
|
|
@ -249,153 +231,115 @@ namespace _zeitbild.sample
|
||||||
_zeitbild.type_user_id
|
_zeitbild.type_user_id
|
||||||
>;
|
>;
|
||||||
} = {
|
} = {
|
||||||
"group": {},
|
|
||||||
"user": {},
|
"user": {},
|
||||||
"calendar": {},
|
"calendar": {},
|
||||||
};
|
};
|
||||||
// groups
|
for await (const user_raw of data.users)
|
||||||
{
|
{
|
||||||
for await (const group_raw of data.groups)
|
const user_object : _zeitbild.type_user_object = {
|
||||||
{
|
"name": user_raw.name,
|
||||||
const group_object : _zeitbild.type_group_object = {
|
"email_address": user_raw.email_address,
|
||||||
"name": group_raw.name,
|
"dav_token": user_raw.dav_token,
|
||||||
"label": (group_raw.label ?? group_raw.name),
|
};
|
||||||
};
|
const user_id : _zeitbild.type_user_id = await _zeitbild.service.user.add(
|
||||||
const group_id : _zeitbild.type_group_id = await _zeitbild.service.group.add(
|
user_object
|
||||||
group_object
|
);
|
||||||
);
|
await _zeitbild.service.auth_internal.set(
|
||||||
track.group[group_raw.id] = group_id;
|
user_raw.name,
|
||||||
}
|
user_raw.password
|
||||||
|
);
|
||||||
|
track.user[user_raw.id] = user_id;
|
||||||
}
|
}
|
||||||
// users
|
for await (const calendar_raw of data.calendars)
|
||||||
{
|
{
|
||||||
for await (const user_raw of data.users)
|
let resource_object : _zeitbild.type_resource_object;
|
||||||
|
let resource_id : _zeitbild.type_resource_id;
|
||||||
|
switch (calendar_raw.resource.kind)
|
||||||
{
|
{
|
||||||
const user_object : _zeitbild.type_user_object = {
|
case "local":
|
||||||
"name": user_raw.name,
|
|
||||||
"groups": (user_raw.groups ?? []),
|
|
||||||
"email_address": user_raw.email_address,
|
|
||||||
"dav_token": (user_raw.dav_token ?? null),
|
|
||||||
};
|
|
||||||
const user_id : _zeitbild.type_user_id = await _zeitbild.service.user.add(
|
|
||||||
user_object
|
|
||||||
);
|
|
||||||
await _zeitbild.service.auth_internal.set(
|
|
||||||
user_raw.name,
|
|
||||||
user_raw.password
|
|
||||||
);
|
|
||||||
track.user[user_raw.id] = user_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// calendars
|
|
||||||
{
|
|
||||||
for await (const calendar_raw of data.calendars)
|
|
||||||
{
|
|
||||||
let resource_object : _zeitbild.type_resource_object;
|
|
||||||
let resource_id : _zeitbild.type_resource_id;
|
|
||||||
switch (calendar_raw.resource.kind)
|
|
||||||
{
|
{
|
||||||
case "local":
|
resource_object = {
|
||||||
{
|
"kind": "local",
|
||||||
resource_object = {
|
"data": {
|
||||||
"kind": "local",
|
"event_ids": [],
|
||||||
"data": {
|
}
|
||||||
"event_ids": [],
|
};
|
||||||
|
resource_id = await _zeitbild.service.resource.add(
|
||||||
|
resource_object
|
||||||
|
);
|
||||||
|
/*const event_ids : Array<_zeitbild.type_local_resource_event_id> = */await Promise.all(
|
||||||
|
calendar_raw.resource.data.events
|
||||||
|
.map(
|
||||||
|
(event_raw) => {
|
||||||
|
const event : _zeitbild.type_event_object = {
|
||||||
|
"name": event_raw.name,
|
||||||
|
"begin": decode_datetime(event_raw.begin),
|
||||||
|
"end": (
|
||||||
|
(event_raw.end === null)
|
||||||
|
?
|
||||||
|
null
|
||||||
|
:
|
||||||
|
decode_datetime(event_raw.end)
|
||||||
|
),
|
||||||
|
"location": event_raw.location,
|
||||||
|
"link": event_raw.link,
|
||||||
|
"description": event_raw.description,
|
||||||
|
};
|
||||||
|
return _zeitbild.service.resource.event_add(resource_id, event);
|
||||||
}
|
}
|
||||||
};
|
)
|
||||||
resource_id = await _zeitbild.service.resource.add(
|
);
|
||||||
resource_object
|
break;
|
||||||
);
|
|
||||||
/*const event_ids : Array<_zeitbild.type_local_resource_event_id> = */await Promise.all(
|
|
||||||
calendar_raw.resource.data.events
|
|
||||||
.map(
|
|
||||||
(event_raw) => {
|
|
||||||
const event : _zeitbild.type_event_object = {
|
|
||||||
"name": event_raw.name,
|
|
||||||
"begin": decode_datetime(event_raw.begin),
|
|
||||||
"end": (
|
|
||||||
(event_raw.end === null)
|
|
||||||
?
|
|
||||||
null
|
|
||||||
:
|
|
||||||
decode_datetime(event_raw.end)
|
|
||||||
),
|
|
||||||
"location": event_raw.location,
|
|
||||||
"link": event_raw.link,
|
|
||||||
"description": event_raw.description,
|
|
||||||
};
|
|
||||||
return _zeitbild.service.resource.event_add(resource_id, event);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ics_feed":
|
|
||||||
{
|
|
||||||
resource_object = {
|
|
||||||
"kind": "ics_feed",
|
|
||||||
"data": {
|
|
||||||
"url": calendar_raw.resource.data.url,
|
|
||||||
"from_fucked_up_wordpress": (calendar_raw.resource.data.from_fucked_up_wordpress ?? false),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
resource_id = await _zeitbild.service.resource.add(
|
|
||||||
resource_object
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const calendar_object : _zeitbild.type_calendar_object =
|
case "ics_feed":
|
||||||
{
|
{
|
||||||
"name": calendar_raw.name,
|
resource_object = {
|
||||||
"hue": (
|
"kind": "ics_feed",
|
||||||
calendar_raw.hue
|
"data": {
|
||||||
??
|
"url": calendar_raw.resource.data.url,
|
||||||
((calendar_raw.id * phi) % 1)
|
"from_fucked_up_wordpress": (calendar_raw.resource.data.from_fucked_up_wordpress ?? false),
|
||||||
),
|
}
|
||||||
"access": {
|
};
|
||||||
"public": (calendar_raw.access.public ?? false),
|
resource_id = await _zeitbild.service.resource.add(
|
||||||
"default_level": _zeitbild.access_level_from_string(calendar_raw.access.default_level),
|
resource_object
|
||||||
"attributed_group": lib_plankton.map.hashmap.implementation_map(
|
);
|
||||||
lib_plankton.map.hashmap.make(
|
break;
|
||||||
x => x.toFixed(0),
|
}
|
||||||
{
|
|
||||||
"pairs": (
|
|
||||||
(calendar_raw.access.attributed_group ?? [])
|
|
||||||
.map(
|
|
||||||
(entry) => ({
|
|
||||||
"key": track.user[entry.group_id],
|
|
||||||
"value": _zeitbild.access_level_from_string(entry.level),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"attributed_user": lib_plankton.map.hashmap.implementation_map(
|
|
||||||
lib_plankton.map.hashmap.make(
|
|
||||||
x => x.toFixed(0),
|
|
||||||
{
|
|
||||||
"pairs": (
|
|
||||||
(calendar_raw.access.attributed_user ?? [])
|
|
||||||
.map(
|
|
||||||
(entry) => ({
|
|
||||||
"key": track.user[entry.user_id],
|
|
||||||
"value": _zeitbild.access_level_from_string(entry.level),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
),
|
|
||||||
},
|
|
||||||
"resource_id": resource_id,
|
|
||||||
};
|
|
||||||
const calendar_id : _zeitbild.type_calendar_id = await _zeitbild.service.calendar.add(
|
|
||||||
calendar_object
|
|
||||||
);
|
|
||||||
track.calendar[calendar_raw.id] = calendar_id;
|
|
||||||
}
|
}
|
||||||
|
const calendar_object : _zeitbild.type_calendar_object =
|
||||||
|
{
|
||||||
|
"name": calendar_raw.name,
|
||||||
|
"hue": (
|
||||||
|
calendar_raw.hue
|
||||||
|
??
|
||||||
|
((calendar_raw.id * phi) % 1)
|
||||||
|
),
|
||||||
|
"access": {
|
||||||
|
"public": (calendar_raw.access.public ?? false),
|
||||||
|
"default_level": _zeitbild.value_object.access_level.from_string(calendar_raw.access.default_level),
|
||||||
|
"attributed": lib_plankton.map.hashmap.implementation_map(
|
||||||
|
lib_plankton.map.hashmap.make(
|
||||||
|
x => x.toFixed(0),
|
||||||
|
{
|
||||||
|
"pairs": (
|
||||||
|
calendar_raw.access.attributed
|
||||||
|
.map(
|
||||||
|
(entry) => ({
|
||||||
|
"key": track.user[entry.user_id],
|
||||||
|
"value": _zeitbild.value_object.access_level.from_string(entry.level),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"resource_id": resource_id,
|
||||||
|
};
|
||||||
|
const calendar_id : _zeitbild.type_calendar_id = await _zeitbild.service.calendar.add(
|
||||||
|
calendar_object
|
||||||
|
);
|
||||||
|
track.calendar[calendar_raw.id] = calendar_id;
|
||||||
}
|
}
|
||||||
return Promise.resolve<void>(undefined);
|
return Promise.resolve<void>(undefined);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,24 +23,41 @@ namespace _zeitbild.service.calendar
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async function get_access_level(
|
function get_access_level(
|
||||||
calendar_object : _zeitbild.type_calendar_object,
|
calendar_object : _zeitbild.type_calendar_object,
|
||||||
user_id : (null | _zeitbild.type_user_id)
|
user_id : (null | _zeitbild.type_user_id)
|
||||||
)
|
) : _zeitbild.enum_access_level
|
||||||
: Promise<_zeitbild.enum_access_level>
|
|
||||||
{
|
{
|
||||||
return _zeitbild.access_level_determine(
|
return (
|
||||||
calendar_object,
|
lib_plankton.list.max<_zeitbild.enum_access_level, _zeitbild.enum_access_level>(
|
||||||
(
|
[
|
||||||
(user_id === null)
|
(
|
||||||
?
|
calendar_object.access.public
|
||||||
null
|
?
|
||||||
:
|
_zeitbild.enum_access_level.view
|
||||||
|
:
|
||||||
|
_zeitbild.enum_access_level.none
|
||||||
|
),
|
||||||
|
(
|
||||||
|
(user_id === null)
|
||||||
|
?
|
||||||
|
_zeitbild.enum_access_level.none
|
||||||
|
:
|
||||||
|
calendar_object.access.attributed.get(
|
||||||
|
user_id,
|
||||||
|
lib_plankton.pod.make_filled<_zeitbild.enum_access_level>(
|
||||||
|
calendar_object.access.default_level
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
],
|
||||||
|
x => x,
|
||||||
{
|
{
|
||||||
"id": user_id,
|
"compare_value": _zeitbild.value_object.access_level.order,
|
||||||
"object": (await _zeitbild.service.user.get(user_id)),
|
|
||||||
}
|
}
|
||||||
)
|
)?.value
|
||||||
|
??
|
||||||
|
_zeitbild.enum_access_level.none
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,7 +65,7 @@ namespace _zeitbild.service.calendar
|
||||||
/**
|
/**
|
||||||
* checks if a user has a sufficient access level
|
* checks if a user has a sufficient access level
|
||||||
*/
|
*/
|
||||||
async function wrap_check_access_level<type_result>(
|
function wrap_check_access_level<type_result>(
|
||||||
calendar_object : _zeitbild.type_calendar_object,
|
calendar_object : _zeitbild.type_calendar_object,
|
||||||
user_id : (null | _zeitbild.type_user_id),
|
user_id : (null | _zeitbild.type_user_id),
|
||||||
threshold : _zeitbild.enum_access_level,
|
threshold : _zeitbild.enum_access_level,
|
||||||
|
|
@ -57,29 +74,26 @@ namespace _zeitbild.service.calendar
|
||||||
=>
|
=>
|
||||||
Promise<type_result>
|
Promise<type_result>
|
||||||
)
|
)
|
||||||
)
|
) : Promise<type_result>
|
||||||
: Promise<type_result>
|
|
||||||
{
|
{
|
||||||
const access_level : _zeitbild.enum_access_level = await get_access_level(
|
const access_level : _zeitbild.enum_access_level = get_access_level(
|
||||||
calendar_object,
|
calendar_object,
|
||||||
user_id
|
user_id
|
||||||
);
|
);
|
||||||
if (! _zeitbild.access_level_order(threshold, access_level))
|
if (! _zeitbild.value_object.access_level.order(threshold, access_level)) {
|
||||||
{
|
|
||||||
return Promise.reject<type_result>(
|
return Promise.reject<type_result>(
|
||||||
new Error(
|
new Error(
|
||||||
lib_plankton.string.coin(
|
lib_plankton.string.coin(
|
||||||
"insufficient access level; at least required: {{threshold}}, actual: {{actual}}",
|
"insufficient access level; at least required: {{threshold}}, actual: {{actual}}",
|
||||||
{
|
{
|
||||||
"threshold": _zeitbild.access_level_to_string(threshold),
|
"threshold": _zeitbild.value_object.access_level.to_string(threshold),
|
||||||
"actual": _zeitbild.access_level_to_string(access_level),
|
"actual": _zeitbild.value_object.access_level.to_string(access_level),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
return success_handler(access_level);
|
return success_handler(access_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -565,7 +579,7 @@ namespace _zeitbild.service.calendar
|
||||||
const calendar_object : _zeitbild.type_calendar_object = await _zeitbild.repository.calendar.read(
|
const calendar_object : _zeitbild.type_calendar_object = await _zeitbild.repository.calendar.read(
|
||||||
calendar_id
|
calendar_id
|
||||||
);
|
);
|
||||||
const access_level : _zeitbild.enum_access_level = await get_access_level(
|
const access_level : _zeitbild.enum_access_level = get_access_level(
|
||||||
calendar_object,
|
calendar_object,
|
||||||
user_id
|
user_id
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
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.service.group
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export function list(
|
|
||||||
)
|
|
||||||
: Promise<
|
|
||||||
Array<
|
|
||||||
{
|
|
||||||
id : _zeitbild.type_group_id;
|
|
||||||
object : _zeitbild.type_group_object;
|
|
||||||
}
|
|
||||||
>
|
|
||||||
>
|
|
||||||
{
|
|
||||||
return _zeitbild.repository.group.list();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export function add(
|
|
||||||
group_object : _zeitbild.type_group_object
|
|
||||||
)
|
|
||||||
: Promise<_zeitbild.type_group_id>
|
|
||||||
{
|
|
||||||
return _zeitbild.repository.group.create(group_object);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export function change(
|
|
||||||
group_id : _zeitbild.type_group_id,
|
|
||||||
group_object : _zeitbild.type_group_object
|
|
||||||
)
|
|
||||||
: Promise<void>
|
|
||||||
{
|
|
||||||
return _zeitbild.repository.group.update(group_id, group_object);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -33,19 +33,6 @@ namespace _zeitbild
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export type type_group_id = int;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export type type_group_object = {
|
|
||||||
name : string;
|
|
||||||
label : string;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
export type type_user_id = int;
|
export type type_user_id = int;
|
||||||
|
|
@ -55,9 +42,6 @@ namespace _zeitbild
|
||||||
*/
|
*/
|
||||||
export type type_user_object = {
|
export type type_user_object = {
|
||||||
name : string;
|
name : string;
|
||||||
groups : Array<
|
|
||||||
type_group_id
|
|
||||||
>;
|
|
||||||
email_address : (
|
email_address : (
|
||||||
null
|
null
|
||||||
|
|
|
|
||||||
|
|
@ -147,11 +131,7 @@ namespace _zeitbild
|
||||||
access : {
|
access : {
|
||||||
public : boolean;
|
public : boolean;
|
||||||
default_level : enum_access_level;
|
default_level : enum_access_level;
|
||||||
attributed_group : lib_plankton.map.type_map<
|
attributed : lib_plankton.map.type_map<
|
||||||
type_group_id,
|
|
||||||
enum_access_level
|
|
||||||
>;
|
|
||||||
attributed_user : lib_plankton.map.type_map<
|
|
||||||
type_user_id,
|
type_user_id,
|
||||||
enum_access_level
|
enum_access_level
|
||||||
>;
|
>;
|
||||||
|
|
|
||||||
74
source/value_objects/access_level.ts
Normal file
74
source/value_objects/access_level.ts
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
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.value_object.access_level
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export function to_string(
|
||||||
|
access_level : _zeitbild.enum_access_level
|
||||||
|
) : string
|
||||||
|
{
|
||||||
|
switch (access_level) {
|
||||||
|
case _zeitbild.enum_access_level.none: {return "none";}
|
||||||
|
case _zeitbild.enum_access_level.view: {return "view";}
|
||||||
|
case _zeitbild.enum_access_level.edit: {return "edit";}
|
||||||
|
case _zeitbild.enum_access_level.admin: {return "admin";}
|
||||||
|
default: {throw (new Error("invalid access level: " + String(access_level)));}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export function from_string(
|
||||||
|
access_level_ : string
|
||||||
|
) : _zeitbild.enum_access_level
|
||||||
|
{
|
||||||
|
switch (access_level_) {
|
||||||
|
case "none": {return _zeitbild.enum_access_level.none;}
|
||||||
|
case "view": {return _zeitbild.enum_access_level.view;}
|
||||||
|
case "edit": {return _zeitbild.enum_access_level.edit;}
|
||||||
|
case "admin": {return _zeitbild.enum_access_level.admin;}
|
||||||
|
default: {throw (new Error("invalid encoded access level: " + String(access_level_)));}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export function order(
|
||||||
|
x : _zeitbild.enum_access_level,
|
||||||
|
y : _zeitbild.enum_access_level
|
||||||
|
) : boolean
|
||||||
|
{
|
||||||
|
const list : Array<_zeitbild.enum_access_level> = [
|
||||||
|
_zeitbild.enum_access_level.none,
|
||||||
|
_zeitbild.enum_access_level.view,
|
||||||
|
_zeitbild.enum_access_level.edit,
|
||||||
|
_zeitbild.enum_access_level.admin,
|
||||||
|
];
|
||||||
|
return (list.indexOf(x) <= list.indexOf(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -47,14 +47,12 @@ ${dir_temp}/zeitbild-unlinked.js: \
|
||||||
${dir_source}/database.ts \
|
${dir_source}/database.ts \
|
||||||
${dir_source}/auth.ts \
|
${dir_source}/auth.ts \
|
||||||
${dir_source}/types.ts \
|
${dir_source}/types.ts \
|
||||||
${dir_source}/logic.ts \
|
${dir_source}/value_objects/access_level.ts \
|
||||||
${dir_source}/repositories/auth_internal.ts \
|
${dir_source}/repositories/auth_internal.ts \
|
||||||
${dir_source}/repositories/group.ts \
|
|
||||||
${dir_source}/repositories/user.ts \
|
${dir_source}/repositories/user.ts \
|
||||||
${dir_source}/repositories/resource.ts \
|
${dir_source}/repositories/resource.ts \
|
||||||
${dir_source}/repositories/calendar.ts \
|
${dir_source}/repositories/calendar.ts \
|
||||||
${dir_source}/services/auth_internal.ts \
|
${dir_source}/services/auth_internal.ts \
|
||||||
${dir_source}/services/group.ts \
|
|
||||||
${dir_source}/services/user.ts \
|
${dir_source}/services/user.ts \
|
||||||
${dir_source}/services/resource.ts \
|
${dir_source}/services/resource.ts \
|
||||||
${dir_source}/services/calendar.ts \
|
${dir_source}/services/calendar.ts \
|
||||||
|
|
@ -67,7 +65,6 @@ ${dir_temp}/zeitbild-unlinked.js: \
|
||||||
${dir_source}/api/actions/session_oidc.ts \
|
${dir_source}/api/actions/session_oidc.ts \
|
||||||
${dir_source}/api/actions/session_end.ts \
|
${dir_source}/api/actions/session_end.ts \
|
||||||
${dir_source}/api/actions/session_status.ts \
|
${dir_source}/api/actions/session_status.ts \
|
||||||
${dir_source}/api/actions/group_list.ts \
|
|
||||||
${dir_source}/api/actions/users.ts \
|
${dir_source}/api/actions/users.ts \
|
||||||
${dir_source}/api/actions/user_dav_conf.ts \
|
${dir_source}/api/actions/user_dav_conf.ts \
|
||||||
${dir_source}/api/actions/user_dav_token.ts \
|
${dir_source}/api/actions/user_dav_token.ts \
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue