[mod]
This commit is contained in:
parent
aea08efed6
commit
9e077fe362
23 changed files with 4156 additions and 5361 deletions
|
@ -2,5 +2,8 @@
|
|||
"version": 1,
|
||||
"log": [
|
||||
{"kind": "stdout", "data": {"threshold": "info"}}
|
||||
]
|
||||
],
|
||||
"session_management": {
|
||||
"in_memory": false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,120 +2,51 @@
|
|||
"users": [
|
||||
{
|
||||
"id": 1,
|
||||
"object": {
|
||||
"name": "christian.frass"
|
||||
}
|
||||
"name": "alice",
|
||||
"email_address": "alice@example.org",
|
||||
"password": "alice"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"object": {
|
||||
"name": "andre.weichert"
|
||||
}
|
||||
"name": "bob",
|
||||
"email_address": "bob@example.org",
|
||||
"password": "bob"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"object": {
|
||||
"name": "steffen.doegnitz"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"object": {
|
||||
"name": "frank.dietrich"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"object": {
|
||||
"name": "michael.berger"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"object": {
|
||||
"name": "roland.schroeder"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"object": {
|
||||
"name": "rene.hahn"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"object": {
|
||||
"name": "max.meierhof"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"object": {
|
||||
"name": "klaus.kleba"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"object": {
|
||||
"name": "tim.detzner"
|
||||
}
|
||||
"name": "charlie",
|
||||
"email_address": "charlie@example.org",
|
||||
"password": "charlie"
|
||||
}
|
||||
],
|
||||
"calendars": [
|
||||
{
|
||||
"id": 1,
|
||||
"object": {
|
||||
"kind": "concrete",
|
||||
"data": {
|
||||
"name": "BV",
|
||||
"private": false,
|
||||
"hue": 0.0000000000000000,
|
||||
"users": [
|
||||
"name": "house",
|
||||
"public": false,
|
||||
"members": [
|
||||
{
|
||||
"user_id": 1,
|
||||
"role": "editor"
|
||||
}
|
||||
],
|
||||
"resource": {
|
||||
"kind": "local",
|
||||
"data": {
|
||||
"events": [
|
||||
{
|
||||
"name": "9. Bundesparteitag | 1. Sitzung | Tag 1",
|
||||
"name": "clean floors",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 10, "day": 18},
|
||||
"date": {"year": 2024, "month": 9, "day": 21},
|
||||
"time": {"hour": 10, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 10, "day": 18},
|
||||
"time": {"hour": 18, "minute": 0, "second": 0}
|
||||
"date": {"year": 2024, "month": 9, "day": 21},
|
||||
"time": {"hour": 11, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": "Halle",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"name": "9. Bundesparteitag | 1. Sitzung | Tag 2",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 10, "day": 19},
|
||||
"time": {"hour": 10, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 10, "day": 19},
|
||||
"time": {"hour": 18, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": "Halle",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"name": "9. Bundesparteitag | 1. Sitzung | Tag 3",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 10, "day": 20},
|
||||
"time": {"hour": 10, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 10, "day": 20},
|
||||
"time": {"hour": 18, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": "Halle",
|
||||
"location": "1st floor",
|
||||
"description": null
|
||||
}
|
||||
]
|
||||
|
@ -124,73 +55,35 @@
|
|||
},
|
||||
{
|
||||
"id": 2,
|
||||
"object": {
|
||||
"kind": "concrete",
|
||||
"data": {
|
||||
"name": "LV Sachsen",
|
||||
"private": false,
|
||||
"hue": 0.6180339887498949,
|
||||
"users": [
|
||||
"name": "turf",
|
||||
"public": false,
|
||||
"members": [
|
||||
{
|
||||
"id": 9,
|
||||
"user_id": 1,
|
||||
"role": "viewer"
|
||||
},
|
||||
{
|
||||
"user_id": 2,
|
||||
"role": "editor"
|
||||
}
|
||||
],
|
||||
"resource": {
|
||||
"kind": "local",
|
||||
"data": {
|
||||
"events": [
|
||||
{
|
||||
"name": "Sören Pellmann zu den Landtagswahlen im Osten",
|
||||
"name": "garden party",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 11},
|
||||
"date": {"year": 2024, "month": 9, "day": 21},
|
||||
"time": {"hour": 18, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": null,
|
||||
"location": "online: https://v2202002113208108062.supersrv.de/b/har-jbu-lxy-rx1",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"name": "Erinnern versammeln. Praktiken für die Zukünfte einer Gesellschaft der Vielen.",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 13},
|
||||
"time": {"hour": 17, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 15},
|
||||
"time": null
|
||||
"date": {"year": 2024, "month": 9, "day": 21},
|
||||
"time": {"hour": 23, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": "Weltecho, Annaberger Straße 24, 09111 Chemnitz",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"name": "Parteikonvent zur Auswertung des Wahljahres",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 14},
|
||||
"time": {"hour": 10, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 14},
|
||||
"time": {"hour": 16, "minute": 30, "second": 0}
|
||||
},
|
||||
"location": "Veranstaltungs- und Kulturforum STADTPARK | Hammertal 3 | 09669 Frankenberg/Sachsen",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"name": "Ist die extreme Rechte noch zu stoppen?",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 19},
|
||||
"time": {"hour": 19, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 19},
|
||||
"time": {"hour": 21, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": "online: https://www.dielinke-sachsen.de/termine/?termin_ort=digital-internet-stream",
|
||||
"location": "bob's garden",
|
||||
"description": null
|
||||
}
|
||||
]
|
||||
|
@ -199,149 +92,44 @@
|
|||
},
|
||||
{
|
||||
"id": 3,
|
||||
"object": {
|
||||
"kind": "concrete",
|
||||
"data": {
|
||||
"name": "KV Zwickau",
|
||||
"private": false,
|
||||
"hue": 0.4721359549995796,
|
||||
"events": [
|
||||
"name": "town",
|
||||
"public": true,
|
||||
"members": [
|
||||
{
|
||||
"name": "Vorstands-Sitzung",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 5},
|
||||
"time": {"hour": 18, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 5},
|
||||
"time": {"hour": 21, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": "Zwickau, Innere Schneeberger Straße 17",
|
||||
"description": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
"user_id": 1,
|
||||
"role": "viewer"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"object": {
|
||||
"kind": "concrete",
|
||||
"data": {
|
||||
"name": "OV Glauchau",
|
||||
"private": false,
|
||||
"users": [
|
||||
{
|
||||
"id": 1,
|
||||
"role": "editor"
|
||||
"user_id": 2,
|
||||
"role": "viewer"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"role": "editor"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"user_id": 3,
|
||||
"role": "editor"
|
||||
}
|
||||
],
|
||||
"hue": 0.09016994374947451,
|
||||
"resource": {
|
||||
"kind": "local",
|
||||
"data": {
|
||||
"events": [
|
||||
{
|
||||
"name": "Kinderspieletag",
|
||||
"name": "ting",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 8},
|
||||
"time": {"hour": 12, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 8},
|
||||
"date": {"year": 2024, "month": 9, "day": 23},
|
||||
"time": {"hour": 16, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": null,
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"name": "Mitglieder-Sitzung",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 19},
|
||||
"time": {"hour": 17, "minute": 30, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 19},
|
||||
"time": {"hour": 19, "minute": 0, "second": 0}
|
||||
"date": {"year": 2024, "month": 9, "day": 23},
|
||||
"time": {"hour": 18, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": null,
|
||||
"location": "market square",
|
||||
"description": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"object": {
|
||||
"kind": "concrete",
|
||||
"data": {
|
||||
"name": "OV Zwickau",
|
||||
"private": false,
|
||||
"hue": 0.09016994374947451,
|
||||
"users": [
|
||||
{
|
||||
"id": 7,
|
||||
"role": "editor"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"role": "viewer"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"name": "4ter Christopher Street Day",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 8, "day": 31},
|
||||
"time": {"hour": 10, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 8, "day": 31},
|
||||
"time": {"hour": 17, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": "Zwickau",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"name": "Regionaltreffen Westsachsen: Schule ohne Rassismus – Schule mit Courage",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 19},
|
||||
"time": {"hour": 9, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": null,
|
||||
"location": null,
|
||||
"description": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"object": {
|
||||
"kind": "caldav",
|
||||
"data": {
|
||||
"name": "Lixer",
|
||||
"private": true,
|
||||
"url": "https://export.kalender.digital/ics/0/3e10dae66950379d4cc8/gesamterkalender.ics?past_months=3&future_months=36",
|
||||
"read_only": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
347
data/linke.json
Normal file
347
data/linke.json
Normal file
|
@ -0,0 +1,347 @@
|
|||
{
|
||||
"users": [
|
||||
{
|
||||
"id": 1,
|
||||
"object": {
|
||||
"name": "christian.frass"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"object": {
|
||||
"name": "andre.weichert"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"object": {
|
||||
"name": "steffen.doegnitz"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"object": {
|
||||
"name": "frank.dietrich"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"object": {
|
||||
"name": "michael.berger"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"object": {
|
||||
"name": "roland.schroeder"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"object": {
|
||||
"name": "rene.hahn"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"object": {
|
||||
"name": "max.meierhof"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"object": {
|
||||
"name": "klaus.kleba"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"object": {
|
||||
"name": "tim.detzner"
|
||||
}
|
||||
}
|
||||
],
|
||||
"calendars": [
|
||||
{
|
||||
"id": 1,
|
||||
"object": {
|
||||
"kind": "concrete",
|
||||
"data": {
|
||||
"name": "BV",
|
||||
"private": false,
|
||||
"hue": 0.0000000000000000,
|
||||
"users": [
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"name": "9. Bundesparteitag | 1. Sitzung | Tag 1",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 10, "day": 18},
|
||||
"time": {"hour": 10, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 10, "day": 18},
|
||||
"time": {"hour": 18, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": "Halle",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"name": "9. Bundesparteitag | 1. Sitzung | Tag 2",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 10, "day": 19},
|
||||
"time": {"hour": 10, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 10, "day": 19},
|
||||
"time": {"hour": 18, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": "Halle",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"name": "9. Bundesparteitag | 1. Sitzung | Tag 3",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 10, "day": 20},
|
||||
"time": {"hour": 10, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 10, "day": 20},
|
||||
"time": {"hour": 18, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": "Halle",
|
||||
"description": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"object": {
|
||||
"kind": "concrete",
|
||||
"data": {
|
||||
"name": "LV Sachsen",
|
||||
"private": false,
|
||||
"hue": 0.6180339887498949,
|
||||
"users": [
|
||||
{
|
||||
"id": 9,
|
||||
"role": "editor"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"name": "Sören Pellmann zu den Landtagswahlen im Osten",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 11},
|
||||
"time": {"hour": 18, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": null,
|
||||
"location": "online: https://v2202002113208108062.supersrv.de/b/har-jbu-lxy-rx1",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"name": "Erinnern versammeln. Praktiken für die Zukünfte einer Gesellschaft der Vielen.",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 13},
|
||||
"time": {"hour": 17, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 15},
|
||||
"time": null
|
||||
},
|
||||
"location": "Weltecho, Annaberger Straße 24, 09111 Chemnitz",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"name": "Parteikonvent zur Auswertung des Wahljahres",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 14},
|
||||
"time": {"hour": 10, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 14},
|
||||
"time": {"hour": 16, "minute": 30, "second": 0}
|
||||
},
|
||||
"location": "Veranstaltungs- und Kulturforum STADTPARK | Hammertal 3 | 09669 Frankenberg/Sachsen",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"name": "Ist die extreme Rechte noch zu stoppen?",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 19},
|
||||
"time": {"hour": 19, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 19},
|
||||
"time": {"hour": 21, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": "online: https://www.dielinke-sachsen.de/termine/?termin_ort=digital-internet-stream",
|
||||
"description": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"object": {
|
||||
"kind": "concrete",
|
||||
"data": {
|
||||
"name": "KV Zwickau",
|
||||
"private": false,
|
||||
"hue": 0.4721359549995796,
|
||||
"events": [
|
||||
{
|
||||
"name": "Vorstands-Sitzung",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 5},
|
||||
"time": {"hour": 18, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 5},
|
||||
"time": {"hour": 21, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": "Zwickau, Innere Schneeberger Straße 17",
|
||||
"description": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"object": {
|
||||
"kind": "concrete",
|
||||
"data": {
|
||||
"name": "OV Glauchau",
|
||||
"private": false,
|
||||
"users": [
|
||||
{
|
||||
"id": 1,
|
||||
"role": "editor"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"role": "editor"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"role": "editor"
|
||||
}
|
||||
],
|
||||
"hue": 0.09016994374947451,
|
||||
"events": [
|
||||
{
|
||||
"name": "Kinderspieletag",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 8},
|
||||
"time": {"hour": 12, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 8},
|
||||
"time": {"hour": 16, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": null,
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"name": "Mitglieder-Sitzung",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 19},
|
||||
"time": {"hour": 17, "minute": 30, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 19},
|
||||
"time": {"hour": 19, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": null,
|
||||
"description": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"object": {
|
||||
"kind": "concrete",
|
||||
"data": {
|
||||
"name": "OV Zwickau",
|
||||
"private": false,
|
||||
"hue": 0.09016994374947451,
|
||||
"users": [
|
||||
{
|
||||
"id": 7,
|
||||
"role": "editor"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"role": "viewer"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"name": "4ter Christopher Street Day",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 8, "day": 31},
|
||||
"time": {"hour": 10, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 8, "day": 31},
|
||||
"time": {"hour": 17, "minute": 0, "second": 0}
|
||||
},
|
||||
"location": "Zwickau",
|
||||
"description": null
|
||||
},
|
||||
{
|
||||
"name": "Regionaltreffen Westsachsen: Schule ohne Rassismus – Schule mit Courage",
|
||||
"begin": {
|
||||
"timezone_shift": 2,
|
||||
"date": {"year": 2024, "month": 9, "day": 19},
|
||||
"time": {"hour": 9, "minute": 0, "second": 0}
|
||||
},
|
||||
"end": null,
|
||||
"location": null,
|
||||
"description": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"object": {
|
||||
"kind": "caldav",
|
||||
"data": {
|
||||
"name": "Lixer",
|
||||
"private": true,
|
||||
"url": "https://export.kalender.digital/ics/0/3e10dae66950379d4cc8/gesamterkalender.ics?past_months=3&future_months=36",
|
||||
"read_only": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
2014
lib/plankton/plankton.d.ts
vendored
2014
lib/plankton/plankton.d.ts
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -58,16 +58,21 @@ namespace _zeitbild.api
|
|||
],
|
||||
}
|
||||
}),
|
||||
"restriction": restriction_none, // TODO
|
||||
"execution": () => (
|
||||
_zeitbild.service.calendar.overview(2) // TODO: user_id
|
||||
"restriction": restriction_logged_in,
|
||||
"execution": async (stuff) => {
|
||||
const session : {key : string; value : lib_plankton.session.type_session;} = await session_from_stuff(stuff);
|
||||
const user_id : _zeitbild.type.user_id = await _zeitbild.service.user.identify(session.value.name);
|
||||
|
||||
return (
|
||||
_zeitbild.service.calendar.overview(user_id)
|
||||
.then(
|
||||
data => Promise.resolve({
|
||||
"status_code": 200,
|
||||
"data": data,
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -102,6 +102,9 @@ namespace _zeitbild.api
|
|||
}),
|
||||
"restriction": restriction_none, // TODO
|
||||
"execution": async (stuff) => {
|
||||
const session : {key : string; value : lib_plankton.session.type_session;} = await session_from_stuff(stuff);
|
||||
const user_id : _zeitbild.type.user_id = await _zeitbild.service.user.identify(session.value.name);
|
||||
|
||||
const from : _zeitbild.helpers.type_pit = parseInt(stuff.query_parameters["from"]);
|
||||
const to : _zeitbild.helpers.type_pit = parseInt(stuff.query_parameters["to"]);
|
||||
const calendar_ids_wanted : Array<_zeitbild.type.calendar_id> = (
|
||||
|
@ -123,7 +126,7 @@ namespace _zeitbild.api
|
|||
null
|
||||
);
|
||||
const calendar_ids_allowed : Array<_zeitbild.type.calendar_id> = (
|
||||
(await _zeitbild.service.calendar.overview(0)) // TODO: user_id
|
||||
(await _zeitbild.service.calendar.overview(user_id))
|
||||
.map((x : any) => x.id)
|
||||
);
|
||||
const calendar_ids : Array<_zeitbild.type.calendar_id> = (
|
||||
|
|
|
@ -50,15 +50,15 @@ namespace _zeitbild.api
|
|||
return Promise.reject(new Error("impossible"));
|
||||
}
|
||||
else {
|
||||
const admin : (null | _zeitbild.service.admin.type_value) = await _zeitbild.service.admin.login(input.name, input.password);
|
||||
if (admin === null) {
|
||||
const passed : boolean = await _zeitbild.service.auth_internal.check(input.name, input.password);
|
||||
if (! passed) {
|
||||
return Promise.resolve({
|
||||
"status_code": 403,
|
||||
"data": null,
|
||||
});
|
||||
}
|
||||
else {
|
||||
const session_key : string = await lib_plankton.session.begin(admin.name);
|
||||
const session_key : string = await lib_plankton.session.begin(input.name);
|
||||
return Promise.resolve({
|
||||
"status_code": 201,
|
||||
"data": session_key,
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace _zeitbild.api
|
|||
lib_plankton.http.enum_method.delete,
|
||||
"/session/oidc",
|
||||
{
|
||||
"description": "beendet eine Sitzung",
|
||||
"description": "verarbeitet einen OIDC login callback",
|
||||
"input_schema": () => ({
|
||||
"type": "null",
|
||||
}),
|
||||
|
@ -22,8 +22,15 @@ namespace _zeitbild.api
|
|||
}),
|
||||
"restriction": restriction_logged_in,
|
||||
"execution": async (stuff) => {
|
||||
const session : {key : string; value : lib_plankton.session.type_session} = await session_from_stuff(stuff);
|
||||
await lib_plankton.session.end(session.key);
|
||||
// do NOT wait
|
||||
_zeitbild.auth.control(
|
||||
{
|
||||
"kind": "authorization_callback",
|
||||
"data": {
|
||||
"http_request": http_request
|
||||
}
|
||||
}
|
||||
);
|
||||
return Promise.resolve({
|
||||
"status_code": 200,
|
||||
"data": null,
|
||||
|
|
|
@ -13,11 +13,10 @@ namespace _zeitbild.api
|
|||
name : string;
|
||||
password : string;
|
||||
},
|
||||
(
|
||||
null
|
||||
|
|
||||
string
|
||||
)
|
||||
{
|
||||
kind : string;
|
||||
data : any;
|
||||
}
|
||||
>(
|
||||
rest_subject,
|
||||
lib_plankton.http.enum_method.get,
|
||||
|
@ -28,25 +27,15 @@ namespace _zeitbild.api
|
|||
"nullable": true,
|
||||
}),
|
||||
"output_schema": () => ({
|
||||
"type": "string",
|
||||
"description": "der Sitzungs-Schlüssel, der als Header 'X-Session-Key' gesetzt werden muss um Erlaubnis zur Ausführung geschützter Aktionen zu erhalten",
|
||||
"nullable": false
|
||||
}),
|
||||
"restriction": restriction_none,
|
||||
"execution": async () => {
|
||||
const admin : (null | _zeitbild.service.admin.type_value) = await _zeitbild.service.admin.login(input.name, input.password);
|
||||
if (admin === null) {
|
||||
const preparation = await _zeitbild.auth.prepare();
|
||||
return Promise.resolve({
|
||||
"status_code": 403,
|
||||
"data": null,
|
||||
"status_code": 200,
|
||||
"data": preparation,
|
||||
});
|
||||
}
|
||||
else {
|
||||
const session_key : string = await lib_plankton.session.begin(admin.name);
|
||||
return Promise.resolve({
|
||||
"status_code": 201,
|
||||
"data": session_key,
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
|
|
@ -26,8 +26,10 @@ namespace _zeitbild.api
|
|||
}
|
||||
// session
|
||||
{
|
||||
// _zeitbild.api.register_session_prepare(rest_subject);
|
||||
_zeitbild.api.register_session_begin(rest_subject);
|
||||
_zeitbild.api.register_session_end(rest_subject);
|
||||
// _zeitbild.api.register_session_oidc(rest_subject);
|
||||
}
|
||||
// calendar
|
||||
{
|
||||
|
|
93
source/auth.ts
Normal file
93
source/auth.ts
Normal file
|
@ -0,0 +1,93 @@
|
|||
|
||||
namespace _zeitbild.auth
|
||||
{
|
||||
|
||||
/**
|
||||
let _subject : (
|
||||
null
|
||||
|
|
||||
lib_plankton.auth.type_auth<any, any>
|
||||
) = null;
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export function init(
|
||||
) : Promise<void>
|
||||
{
|
||||
/*
|
||||
switch (_zeitbild.conf.get().auth.kind) {
|
||||
case "internal": {
|
||||
_subject = lib_plankton.auth.internal.implementation_auth(
|
||||
{
|
||||
// "password_image_chest": password_image_chest,
|
||||
// "check_password": (image, input) => Promise.resolve<boolean>(image === get_password_image(input)),
|
||||
}
|
||||
);
|
||||
}
|
||||
case "oidc": {
|
||||
_subject = lib_plankton.auth.oidc.implementation_auth(
|
||||
{
|
||||
"url_authorization": _zeitbild.conf.get().auth.data.url_authorization,
|
||||
"url_token": _zeitbild.conf.get().auth.data.url_token,
|
||||
"url_userinfo": _zeitbild.conf.get().auth.data.url_userinfo,
|
||||
"client_id": _zeitbild.conf.get().auth.data.client_id,
|
||||
"client_secret": _zeitbild.conf.get().auth.data.client_secret,
|
||||
"url_redirect": "/session/begin",
|
||||
"scopes": [
|
||||
"openid",
|
||||
"profile",
|
||||
"email",
|
||||
],
|
||||
"login_url_mode": "open",
|
||||
}
|
||||
);
|
||||
}
|
||||
default: {
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
return Promise.resolve<void>(undefined);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
export function prepare(
|
||||
) : Promise<{kind : string; data : any;}>
|
||||
{
|
||||
return (
|
||||
_subject.prepare()
|
||||
.then(
|
||||
(data) => ({
|
||||
"kind": _zeitbild.conf.get().auth.kind,
|
||||
"data": data,
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
export function execute(
|
||||
input : any
|
||||
) : Promise<string>
|
||||
{
|
||||
return _subject.execute(input);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
export function control(
|
||||
input : any
|
||||
) : Promise<void>
|
||||
{
|
||||
return _subject.control(input);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
411
source/conf.ts
411
source/conf.ts
|
@ -4,245 +4,214 @@ namespace _zeitbild.conf
|
|||
|
||||
/**
|
||||
*/
|
||||
type type_log_threshold = (
|
||||
"debug"
|
||||
|
|
||||
"info"
|
||||
|
|
||||
"notice"
|
||||
|
|
||||
"warning"
|
||||
|
|
||||
const _schema : lib_plankton.conf.type_schema = {
|
||||
"nullable": false,
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"version": {
|
||||
"nullable": false,
|
||||
"type": "integer",
|
||||
"enum": [1]
|
||||
},
|
||||
"log": {
|
||||
"nullable": false,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kind": {
|
||||
"nullable": false,
|
||||
"type": "string",
|
||||
"enum": ["stdout"]
|
||||
},
|
||||
"data": {
|
||||
"nullable": false,
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"threshold": {
|
||||
"nullable": false,
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"debug",
|
||||
"info",
|
||||
"notice",
|
||||
"warning",
|
||||
"error"
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
type type_log_format = (
|
||||
"jsonl"
|
||||
|
|
||||
"human_readable"
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export type type_conf = {
|
||||
general : {
|
||||
language : (null | string);
|
||||
};
|
||||
log : Array<
|
||||
{
|
||||
kind : "stdout";
|
||||
data : {
|
||||
threshold : type_log_threshold;
|
||||
};
|
||||
],
|
||||
"default": "info"
|
||||
}
|
||||
|
|
||||
{
|
||||
kind : "file";
|
||||
data : {
|
||||
threshold : type_log_threshold;
|
||||
path : string;
|
||||
};
|
||||
},
|
||||
"required": [
|
||||
]
|
||||
}
|
||||
|
|
||||
{
|
||||
kind : "email";
|
||||
data : {
|
||||
threshold : type_log_threshold;
|
||||
smtp_credentials : {
|
||||
host : string;
|
||||
port : int;
|
||||
username : string;
|
||||
password : string;
|
||||
};
|
||||
sender : string;
|
||||
receivers : Array<string>;
|
||||
};
|
||||
}
|
||||
>;
|
||||
server : {
|
||||
host : string;
|
||||
port : int;
|
||||
path_base : string;
|
||||
};
|
||||
database : (
|
||||
{
|
||||
kind : "sqlite";
|
||||
data : {
|
||||
path : string;
|
||||
};
|
||||
}
|
||||
|
|
||||
{
|
||||
kind : "postgresql";
|
||||
data : {
|
||||
host : string;
|
||||
port ?: int;
|
||||
username : string;
|
||||
password : string;
|
||||
schema : string;
|
||||
};
|
||||
}
|
||||
);
|
||||
authentication : (
|
||||
{
|
||||
kind : "internal";
|
||||
data : {
|
||||
};
|
||||
}
|
||||
|
|
||||
{
|
||||
kind : "oidc";
|
||||
data : {
|
||||
client_id : string;
|
||||
client_secret : string;
|
||||
url_authorization : string;
|
||||
url_token : string;
|
||||
url_userinfo : string;
|
||||
};
|
||||
}
|
||||
);
|
||||
session_management : {
|
||||
in_memory : boolean;
|
||||
drop_all_at_start : boolean;
|
||||
lifetime : int;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
var _data : (null | type_conf) = null;
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export function inject(
|
||||
conf_raw : any
|
||||
) : void
|
||||
{
|
||||
const version : int = (conf_raw["version"] ?? 1);
|
||||
_data = {
|
||||
"general": (
|
||||
((node_general) => ({
|
||||
"language": (node_general["language"] ?? null),
|
||||
})) (conf_raw["general"] ?? {})
|
||||
),
|
||||
"log": (
|
||||
(() => {
|
||||
const node_log = (
|
||||
conf_raw["log"]
|
||||
??
|
||||
[
|
||||
]
|
||||
},
|
||||
"default": [
|
||||
{
|
||||
"kind": "stdout",
|
||||
"data": {
|
||||
"threshold": "info"
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
);
|
||||
return (
|
||||
node_log.map(
|
||||
(node_log_entry : any) => ({
|
||||
"kind": node_log_entry["kind"],
|
||||
"data": Object.assign(
|
||||
{
|
||||
"format": "human_readable",
|
||||
"threshold": "notice",
|
||||
},
|
||||
(node_log_entry["data"] ?? {})
|
||||
)
|
||||
})
|
||||
)
|
||||
);
|
||||
}) ()
|
||||
),
|
||||
"server": (
|
||||
((node_server) => ({
|
||||
"host": (() => {
|
||||
return (node_server["host"] ?? "::");
|
||||
}) (),
|
||||
"port": (node_server["port"] ?? 7845),
|
||||
"path_base": (node_server["path_base"] ?? ""),
|
||||
})) (conf_raw["server"] ?? {})
|
||||
),
|
||||
"database": (
|
||||
((node_database) => {
|
||||
const kind : string = (node_database["kind"] ?? "sqlite");
|
||||
const node_database_data_raw = (node_database["data"] ?? {});
|
||||
switch (kind) {
|
||||
case "sqlite": {
|
||||
return {
|
||||
"kind": kind,
|
||||
"server": {
|
||||
"nullable": false,
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"nullable": false,
|
||||
"type": "string",
|
||||
"default": "::"
|
||||
},
|
||||
"port": {
|
||||
"nullable": false,
|
||||
"type": "integer",
|
||||
"default": 7845
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
],
|
||||
"additionalProperties": false,
|
||||
"default": {
|
||||
}
|
||||
},
|
||||
"database": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kind": {
|
||||
"nullable": false,
|
||||
"type": "string",
|
||||
"enum": ["sqlite"]
|
||||
},
|
||||
"data": {
|
||||
"path": (node_database_data_raw["path"] ?? "data.sqlite"),
|
||||
"nullable": false,
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"nullable": false,
|
||||
"type": "string",
|
||||
"default": "data.sqlite"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
],
|
||||
"default": {}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kind": {
|
||||
"nullable": false,
|
||||
"type": "string",
|
||||
"enum": ["postgresql"]
|
||||
},
|
||||
"data": {
|
||||
"nullable": false,
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"host": {
|
||||
"nullable": false,
|
||||
"type": "string"
|
||||
},
|
||||
"port": {
|
||||
"nullable": false,
|
||||
"type": "integer",
|
||||
"default": 5432
|
||||
},
|
||||
"username": {
|
||||
"nullable": false,
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"nullable": false,
|
||||
"type": "string"
|
||||
},
|
||||
"scheme": {
|
||||
"nullable": false,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"host",
|
||||
"username",
|
||||
"password",
|
||||
"scheme"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind",
|
||||
"data"
|
||||
]
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"kind": "sqlite"
|
||||
}
|
||||
},
|
||||
"session_management": {
|
||||
"nullable": false,
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"in_memory": {
|
||||
"nullable": false,
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"drop_all_at_start": {
|
||||
"nullable": false,
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"lifetime": {
|
||||
"nullable": false,
|
||||
"type": "integer",
|
||||
"default": 900
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
],
|
||||
"additionalProperties": false,
|
||||
"default": {}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"version"
|
||||
],
|
||||
"additionalProperties": false
|
||||
};
|
||||
break;
|
||||
}
|
||||
case "postgresql": {
|
||||
return {
|
||||
"kind": kind,
|
||||
"data": node_database_data_raw,
|
||||
};
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw (new Error("unhandled"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}) (conf_raw["database"] ?? {})
|
||||
),
|
||||
"session_management": (
|
||||
((node_session_management) => ({
|
||||
"in_memory": (node_session_management["in_memory"] ?? true),
|
||||
"drop_all_at_start": (node_session_management["drop_all_at_start"] ?? true),
|
||||
"lifetime": (node_session_management["lifetime"] ?? 900),
|
||||
})) (conf_raw["session_management"] ?? {})
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @todo mandatory fields
|
||||
*/
|
||||
export async function load(
|
||||
path : string
|
||||
) : Promise<void>
|
||||
var _data : (null | any) = null;
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export function schema(
|
||||
) : lib_plankton.conf.type_schema
|
||||
{
|
||||
let conf_raw : any;
|
||||
if (! (await lib_plankton.file.exists(path))) {
|
||||
// return Promise.reject<void>(new Error("configuration file not found: " + path + "; using fallback"));
|
||||
conf_raw = {};
|
||||
}
|
||||
else {
|
||||
try {
|
||||
conf_raw = lib_plankton.json.decode(await lib_plankton.file.read(path));
|
||||
}
|
||||
catch (error) {
|
||||
conf_raw = null;
|
||||
}
|
||||
}
|
||||
if (conf_raw === null) {
|
||||
return Promise.reject<void>("configuration file could not be read");
|
||||
}
|
||||
else {
|
||||
inject(conf_raw);
|
||||
// process.stderr.write(JSON.stringify(_data, undefined, "\t"));
|
||||
return Promise.resolve<void>(undefined);
|
||||
}
|
||||
return _schema;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export function get(
|
||||
) : type_conf
|
||||
) : any
|
||||
{
|
||||
if (_data === null) {
|
||||
throw (new Error("conf not loaded yet"));
|
||||
|
@ -252,4 +221,18 @@ namespace _zeitbild.conf
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export async function init(
|
||||
path : string
|
||||
) : Promise<void>
|
||||
{
|
||||
_data = await lib_plankton.conf.load(
|
||||
_schema,
|
||||
path
|
||||
);
|
||||
return Promise.resolve<void>(undefined);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
136
source/main.ts
136
source/main.ts
|
@ -1,4 +1,90 @@
|
|||
|
||||
/**
|
||||
*/
|
||||
type type_data = {
|
||||
users : Array<
|
||||
{
|
||||
id : int;
|
||||
name : string;
|
||||
email_address : string;
|
||||
password : string;
|
||||
}
|
||||
>;
|
||||
calendars : Array<
|
||||
{
|
||||
id : int;
|
||||
name : string;
|
||||
public : boolean;
|
||||
members : Array<
|
||||
{
|
||||
user_id : int;
|
||||
role : _zeitbild.type.role;
|
||||
}
|
||||
>;
|
||||
resource : _zeitbild.type.resource_object;
|
||||
}
|
||||
>;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
async function data_init(
|
||||
data : type_data
|
||||
) : Promise<void>
|
||||
{
|
||||
let track : {
|
||||
user : Record<
|
||||
int,
|
||||
_zeitbild.type.user_id
|
||||
>;
|
||||
calendar : Record<
|
||||
int,
|
||||
_zeitbild.type.user_id
|
||||
>;
|
||||
} = {
|
||||
"user": {},
|
||||
"calendar": {},
|
||||
};
|
||||
for await (const user_raw of data.users) {
|
||||
const user_id : _zeitbild.type.user_id = await _zeitbild.service.user.add(
|
||||
{
|
||||
"name": user_raw.name,
|
||||
"email_address": user_raw.email_address,
|
||||
}
|
||||
);
|
||||
await _zeitbild.service.auth_internal.set(
|
||||
user_raw.name,
|
||||
user_raw.password
|
||||
);
|
||||
track.user[user_raw.id] = user_id;
|
||||
}
|
||||
for await (const calendar_raw of data.calendars) {
|
||||
const resource_id : _zeitbild.type.resource_id = await _zeitbild.service.resource.add(
|
||||
calendar_raw.resource
|
||||
);
|
||||
const calendar_id : _zeitbild.type.calendar_id = await _zeitbild.service.calendar.add(
|
||||
{
|
||||
"name": calendar_raw.name,
|
||||
"public": calendar_raw.public,
|
||||
"members": (
|
||||
calendar_raw.members
|
||||
.map(
|
||||
(member_raw) => ({
|
||||
"user_id": track.user[member_raw.user_id],
|
||||
"role": member_raw.role,
|
||||
})
|
||||
)
|
||||
),
|
||||
"resource_id": resource_id,
|
||||
}
|
||||
);
|
||||
track.calendar[calendar_raw.id] = calendar_id;
|
||||
}
|
||||
return Promise.resolve<void>(undefined);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
async function main(
|
||||
|
@ -35,8 +121,16 @@ async function main(
|
|||
"description": "api-doc"
|
||||
},
|
||||
{
|
||||
"name": "expose-conf",
|
||||
"description": "expose-conf"
|
||||
"name": "conf-schema",
|
||||
"description": "conf-schema"
|
||||
},
|
||||
{
|
||||
"name": "conf-expose",
|
||||
"description": "conf-expose"
|
||||
},
|
||||
{
|
||||
"name": "fill",
|
||||
"description": "fill"
|
||||
},
|
||||
{
|
||||
"name": "help",
|
||||
|
@ -88,10 +182,12 @@ async function main(
|
|||
const args : Record<string, any> = arg_handler.read(lib_plankton.args.enum_environment.cli, args_raw.join(" "));
|
||||
|
||||
// init2
|
||||
await _zeitbild.conf.load(args["conf_path"]);
|
||||
await _zeitbild.conf.init(
|
||||
args["conf_path"]
|
||||
);
|
||||
lib_plankton.log.conf_push(
|
||||
_zeitbild.conf.get().log.map(
|
||||
log_output => lib_plankton.log.channel_make(
|
||||
(log_output : any) => lib_plankton.log.channel_make(
|
||||
{
|
||||
"kind": log_output.kind,
|
||||
"data": log_output.data
|
||||
|
@ -125,7 +221,19 @@ async function main(
|
|||
);
|
||||
break;
|
||||
}
|
||||
case "expose-conf": {
|
||||
case "conf-schema": {
|
||||
process.stdout.write(
|
||||
JSON.stringify(
|
||||
_zeitbild.conf.schema(),
|
||||
undefined,
|
||||
"\t"
|
||||
)
|
||||
+
|
||||
"\n"
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "conf-expose": {
|
||||
process.stdout.write(
|
||||
JSON.stringify(
|
||||
_zeitbild.conf.get(),
|
||||
|
@ -150,6 +258,15 @@ async function main(
|
|||
);
|
||||
break;
|
||||
}
|
||||
case "fill": {
|
||||
await data_init(
|
||||
lib_plankton.json.decode(
|
||||
await lib_plankton.file.read(args.data_path)
|
||||
)
|
||||
);
|
||||
process.stdout.write("-- done\n");
|
||||
break;
|
||||
}
|
||||
case "serve": {
|
||||
// prepare database
|
||||
await _zeitbild.database.check();
|
||||
|
@ -184,6 +301,8 @@ async function main(
|
|||
}
|
||||
);
|
||||
|
||||
await _zeitbild.auth.init();
|
||||
|
||||
const rest_subject : lib_plankton.rest.type_rest = _zeitbild.api.make();
|
||||
const server : lib_plankton.server.type_subject = lib_plankton.server.make(
|
||||
async (input, metadata) => {
|
||||
|
@ -219,9 +338,12 @@ async function main(
|
|||
(
|
||||
main(process.argv.slice(2))
|
||||
.then(
|
||||
() => {}
|
||||
() => {
|
||||
}
|
||||
)
|
||||
.catch(
|
||||
(error) => {process.stderr.write(String(error) + "\n");}
|
||||
(error) => {
|
||||
process.stderr.write(String(error) + "\n");
|
||||
}
|
||||
)
|
||||
);
|
||||
|
|
77
source/repositories/auth_internal.ts
Normal file
77
source/repositories/auth_internal.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
|
||||
namespace _zeitbild.repository.auth_internal
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
var _chest : (
|
||||
null
|
||||
|
|
||||
lib_plankton.storage.type_chest<
|
||||
Array<string>,
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function get_chest(
|
||||
) : lib_plankton.storage.type_chest<
|
||||
Array<string>,
|
||||
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 (_chest === null) {
|
||||
_chest = lib_plankton.storage.sql_table_common.chest(
|
||||
{
|
||||
"database_implementation": _zeitbild.database.get_implementation(),
|
||||
"table_name": "auth_internal",
|
||||
"key_names": ["name"],
|
||||
}
|
||||
);
|
||||
}
|
||||
else {
|
||||
// do nothing
|
||||
}
|
||||
return _chest;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export function read(
|
||||
name : string
|
||||
) : Promise<string>
|
||||
{
|
||||
return (
|
||||
get_chest().read([name])
|
||||
.then(
|
||||
(row) => Promise.resolve<string>(row["password_image"])
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export function write(
|
||||
name : string,
|
||||
password_image : string
|
||||
) : Promise<void>
|
||||
{
|
||||
return (
|
||||
get_chest().write([name], {"password_image": password_image})
|
||||
.then(
|
||||
() => Promise.resolve<void>(undefined)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -210,6 +210,92 @@ namespace _zeitbild.repository.resource
|
|||
*/
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function encode_event(
|
||||
event : _zeitbild.type.event_object,
|
||||
local_resource_id : int
|
||||
) : Record<string, any>
|
||||
{
|
||||
/*
|
||||
const decode_datetime : ((datetime_raw : string) => _zeitbild.helpers.type_datetime) = ((datetime_raw) => {
|
||||
const parts : Array<string> = datetime_raw.split("|");
|
||||
const timezone_shift : int = parseInt(parts[0]);
|
||||
if (parts[1].length <= 10) {
|
||||
return {
|
||||
"timezone_shift": timezone_shift,
|
||||
"date": {
|
||||
"year": parseInt(parts[1].slice(0, 4)),
|
||||
"month": parseInt(parts[1].slice(5, 7)),
|
||||
"day": parseInt(parts[1].slice(8, 10)),
|
||||
},
|
||||
"time": null
|
||||
};
|
||||
}
|
||||
else {
|
||||
return {
|
||||
"timezone_shift": timezone_shift,
|
||||
"date": {
|
||||
"year": parseInt(parts[1].slice(0, 4)),
|
||||
"month": parseInt(parts[1].slice(5, 7)),
|
||||
"day": parseInt(parts[1].slice(8, 10)),
|
||||
},
|
||||
"time": {
|
||||
"hour": parseInt(parts[1].slice(11, 13)),
|
||||
"minute": parseInt(parts[1].slice(14, 16)),
|
||||
"second": parseInt(parts[1].slice(17, 19)),
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
*/
|
||||
const encode_datetime : ((datetime : _zeitbild.helpers.type_datetime) => string) = ((datetime) => {
|
||||
return lib_plankton.string.coin(
|
||||
"{{timezone_shift}}|{{date}}{{macro_time}}",
|
||||
{
|
||||
"timezone_shift": datetime.timezone_shift.toFixed(0).padStart(2, "0"),
|
||||
"date": lib_plankton.string.coin(
|
||||
"{{year}}-{{month}}-{{day}}",
|
||||
{
|
||||
"year": datetime.date.year.toFixed(0).padStart(4, "0"),
|
||||
"month": datetime.date.month.toFixed(0).padStart(2, "0"),
|
||||
"day": datetime.date.day.toFixed(0).padStart(2, "0"),
|
||||
}
|
||||
),
|
||||
"macro_time": (
|
||||
(datetime.time === null)
|
||||
?
|
||||
""
|
||||
:
|
||||
lib_plankton.string.coin(
|
||||
"T{{hour}}:{{minute}}:{{second}}",
|
||||
{
|
||||
"hour": datetime.time.hour.toFixed(0).padStart(2, "0"),
|
||||
"minute": datetime.time.minute.toFixed(0).padStart(2, "0"),
|
||||
"second": datetime.time.second.toFixed(0).padStart(2, "0"),
|
||||
}
|
||||
)
|
||||
),
|
||||
}
|
||||
);
|
||||
});
|
||||
return {
|
||||
"local_resource_id": local_resource_id,
|
||||
"name": event.name,
|
||||
"begin": encode_datetime(event.begin),
|
||||
"end": (
|
||||
(event.end === null)
|
||||
?
|
||||
null
|
||||
:
|
||||
encode_datetime(event.end)
|
||||
),
|
||||
"location": event.location,
|
||||
"description": event.description,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function decode_event(
|
||||
|
@ -311,4 +397,58 @@ namespace _zeitbild.repository.resource
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export async function create(
|
||||
resource_object : _zeitbild.type.resource_object
|
||||
) : Promise<_zeitbild.type.resource_id>
|
||||
{
|
||||
switch (resource_object.kind) {
|
||||
case "local": {
|
||||
const local_resource_id : int = await get_local_resource_core_store().create(
|
||||
{
|
||||
"_dummy": null,
|
||||
}
|
||||
);
|
||||
for await (const event of resource_object.data.events) {
|
||||
get_local_resource_event_store().create(
|
||||
encode_event(
|
||||
event,
|
||||
local_resource_id
|
||||
)
|
||||
)
|
||||
}
|
||||
const resource_id : _zeitbild.type.resource_id = await get_resource_core_store().create(
|
||||
{
|
||||
"kind": "local",
|
||||
"sub_id": local_resource_id,
|
||||
}
|
||||
);
|
||||
return Promise.resolve<_zeitbild.type.resource_id>(resource_id);
|
||||
break;
|
||||
}
|
||||
case "caldav": {
|
||||
const caldav_resource_id : int = await get_caldav_resource_store().create(
|
||||
{
|
||||
"url": resource_object.data.url,
|
||||
"read_only": resource_object.data.read_only,
|
||||
}
|
||||
);
|
||||
const resource_id : _zeitbild.type.resource_id = await get_local_resource_core_store().create(
|
||||
{
|
||||
"kind": "caldav",
|
||||
"sub_id": caldav_resource_id,
|
||||
}
|
||||
);
|
||||
return Promise.resolve<_zeitbild.type.resource_id>(resource_id);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw (new Error("not implemended"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
119
source/repositories/user.ts
Normal file
119
source/repositories/user.ts
Normal file
|
@ -0,0 +1,119 @@
|
|||
|
||||
namespace _zeitbild.repository.user
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
var _store : (
|
||||
null
|
||||
|
|
||||
lib_plankton.storage.type_store<
|
||||
_zeitbild.type.user_id,
|
||||
Record<string, any>,
|
||||
{},
|
||||
lib_plankton.storage.type_sql_table_autokey_search_term,
|
||||
Record<string, any>
|
||||
>
|
||||
) = null;
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function get_store(
|
||||
) : lib_plankton.storage.type_store<
|
||||
_zeitbild.type.user_id,
|
||||
Record<string, any>,
|
||||
{},
|
||||
lib_plankton.storage.type_sql_table_autokey_search_term,
|
||||
Record<string, any>
|
||||
>
|
||||
{
|
||||
if (_store === null) {
|
||||
_store = lib_plankton.storage.sql_table_autokey_store(
|
||||
{
|
||||
"database_implementation": _zeitbild.database.get_implementation(),
|
||||
"table_name": "users",
|
||||
"key_name": "id",
|
||||
}
|
||||
);
|
||||
}
|
||||
else {
|
||||
// do nothing
|
||||
}
|
||||
return _store;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function encode(
|
||||
user_object : _zeitbild.type.user_object
|
||||
) : Record<string, any>
|
||||
{
|
||||
return {
|
||||
"name": user_object.name,
|
||||
"email_address": user_object.email_address,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function decode(
|
||||
row : Record<string, any>
|
||||
) : _zeitbild.type.user_object
|
||||
{
|
||||
return {
|
||||
"name": row["name"],
|
||||
"email_address": row["email_address"],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export async function read(
|
||||
user_id : _zeitbild.type.user_id
|
||||
) : Promise<_zeitbild.type.user_object>
|
||||
{
|
||||
const row : Record<string, any> = await get_store().read(user_id);
|
||||
const user_object : _zeitbild.type.user_object = decode(row);
|
||||
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 row : Record<string, any> = encode(user_object);
|
||||
const user_id : _zeitbild.type.user_id = await get_store().create(row);
|
||||
return Promise.resolve<_zeitbild.type.user_id>(user_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export async function identify(
|
||||
name : string
|
||||
) : Promise<_zeitbild.type.user_id>
|
||||
{
|
||||
const hits : Array<{key : _zeitbild.type.user_id; preview : any;}> = await get_store().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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
40
source/services/auth_internal.ts
Normal file
40
source/services/auth_internal.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
|
||||
namespace _zeitbild.service.auth_internal
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
export function set(
|
||||
name : string,
|
||||
password : string
|
||||
) : Promise<void>
|
||||
{
|
||||
return (
|
||||
lib_plankton.bcrypt.compute(password)
|
||||
.then<void>(
|
||||
(password_image) => _zeitbild.repository.auth_internal.write(name, password_image)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export async function check(
|
||||
name : string,
|
||||
password : string
|
||||
) : Promise<boolean>
|
||||
{
|
||||
try {
|
||||
const password_image : string = await _zeitbild.repository.auth_internal.read(name);
|
||||
return lib_plankton.bcrypt.compare(
|
||||
password_image,
|
||||
password
|
||||
);
|
||||
}
|
||||
catch (error) {
|
||||
return Promise.resolve<boolean>(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -2,6 +2,16 @@
|
|||
namespace _zeitbild.service.calendar
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
export function add(
|
||||
calendar_object : _zeitbild.type.calendar_object
|
||||
) : Promise<_zeitbild.type.calendar_id>
|
||||
{
|
||||
return _zeitbild.repository.calendar.create(calendar_object);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export async function list(
|
||||
|
|
14
source/services/resource.ts
Normal file
14
source/services/resource.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
namespace _zeitbild.service.resource
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
export function add(
|
||||
resource_object : _zeitbild.type.resource_object
|
||||
) : Promise<_zeitbild.type.resource_id>
|
||||
{
|
||||
return _zeitbild.repository.resource.create(resource_object);
|
||||
}
|
||||
|
||||
}
|
24
source/services/user.ts
Normal file
24
source/services/user.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
namespace _zeitbild.service.user
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
export function add(
|
||||
user_object : _zeitbild.type.user_object
|
||||
) : Promise<_zeitbild.type.user_id>
|
||||
{
|
||||
return _zeitbild.repository.user.create(user_object);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export function identify(
|
||||
name : string
|
||||
) : Promise<_zeitbild.type.user_id>
|
||||
{
|
||||
return _zeitbild.repository.user.identify(name);
|
||||
}
|
||||
|
||||
}
|
|
@ -18,16 +18,32 @@ cmd_tsc := ${dir_tools}/typescript/node_modules/.bin/tsc
|
|||
## rules
|
||||
|
||||
.PHONY: default
|
||||
default: ${dir_build}/zeitbild
|
||||
default: ${dir_build}/zeitbild node_modules
|
||||
|
||||
.PHONY: node_modules
|
||||
node_modules:
|
||||
@ cd ${dir_build} && npm install sqlite3 bcrypt
|
||||
|
||||
${dir_temp}/conf.ts: \
|
||||
${dir_source}/conf.ts.tpl \
|
||||
${dir_source}/conf.schema.json
|
||||
@ ${cmd_mkdir} $(dir $@)
|
||||
${dir_tools}/coin $@
|
||||
|
||||
${dir_temp}/zeitbild-unlinked.js: \
|
||||
${dir_lib}/plankton/plankton.d.ts \
|
||||
${dir_source}/helpers.ts \
|
||||
${dir_source}/conf.ts \
|
||||
${dir_source}/database.ts \
|
||||
${dir_source}/auth.ts \
|
||||
${dir_source}/types.ts \
|
||||
${dir_source}/repositories/auth_internal.ts \
|
||||
${dir_source}/repositories/user.ts \
|
||||
${dir_source}/repositories/resource.ts \
|
||||
${dir_source}/repositories/calendar.ts \
|
||||
${dir_source}/services/auth_internal.ts \
|
||||
${dir_source}/services/user.ts \
|
||||
${dir_source}/services/resource.ts \
|
||||
${dir_source}/services/calendar.ts \
|
||||
${dir_source}/api/base.ts \
|
||||
${dir_source}/api/actions/meta_ping.ts \
|
||||
|
|
|
@ -8,21 +8,23 @@ modules=""
|
|||
modules="${modules} base"
|
||||
modules="${modules} call"
|
||||
modules="${modules} log"
|
||||
modules="${modules} conf"
|
||||
modules="${modules} storage"
|
||||
modules="${modules} database"
|
||||
modules="${modules} session"
|
||||
modules="${modules} file"
|
||||
modules="${modules} string"
|
||||
modules="${modules} structures"
|
||||
modules="${modules} json"
|
||||
modules="${modules} ical"
|
||||
modules="${modules} url"
|
||||
modules="${modules} http"
|
||||
modules="${modules} api"
|
||||
modules="${modules} rest"
|
||||
modules="${modules} rest"
|
||||
modules="${modules} server"
|
||||
modules="${modules} args"
|
||||
modules="${modules} auth"
|
||||
# modules="${modules} auth"
|
||||
modules="${modules} bcrypt"
|
||||
|
||||
|
||||
## exec
|
||||
|
|
Loading…
Add table
Reference in a new issue