chore(koi): kanidm -> zitadel
This commit is contained in:
parent
7832342642
commit
6f3fb407cb
17 changed files with 208 additions and 325 deletions
|
@ -33,13 +33,15 @@
|
||||||
./containers/navidrome
|
./containers/navidrome
|
||||||
./containers/conduwuit
|
./containers/conduwuit
|
||||||
./containers/zond
|
./containers/zond
|
||||||
./containers/kanidm
|
./containers/zitadel
|
||||||
./containers/siyuan
|
./containers/siyuan
|
||||||
./containers/memos
|
./containers/memos
|
||||||
./containers/wakapi
|
./containers/wakapi
|
||||||
|
./containers/outline
|
||||||
./containers/teisu.nix
|
./containers/teisu.nix
|
||||||
./containers/bots/pcre-sub-bot.nix
|
./containers/bots/pcre-sub-bot.nix
|
||||||
./containers/bots/channel-logger-bot.nix
|
./containers/bots/channel-logger-bot.nix
|
||||||
|
./containers/bots/bsky-crossposter
|
||||||
./vms/hass.nix
|
./vms/hass.nix
|
||||||
./vms/bnuuy.nix
|
./vms/bnuuy.nix
|
||||||
# ./vms/windows.nix
|
# ./vms/windows.nix
|
||||||
|
@ -80,6 +82,8 @@
|
||||||
"8.8.8.8"
|
"8.8.8.8"
|
||||||
"8.8.4.4"
|
"8.8.4.4"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
firewall.logRefusedConnections = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtualisation.libvirtd = {
|
virtualisation.libvirtd = {
|
||||||
|
@ -102,7 +106,7 @@
|
||||||
}];
|
}];
|
||||||
|
|
||||||
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
|
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
|
||||||
boot.kernelParams = [ "panic=5" "mitigations=off" ];
|
boot.kernelParams = [ "panic=5" "panic_on_oops=1" "mitigations=off" ];
|
||||||
boot.kernelPackages = pkgs.linuxPackages_latest;
|
boot.kernelPackages = pkgs.linuxPackages_latest;
|
||||||
|
|
||||||
services.desu-deploy = {
|
services.desu-deploy = {
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
{ config, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
UID = 1111;
|
|
||||||
in {
|
|
||||||
imports = [
|
|
||||||
./proxy.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
desu.secrets.kanidm-tls-key.owner = "kanidm";
|
|
||||||
desu.secrets.kanidm-tls-cert.owner = "kanidm";
|
|
||||||
|
|
||||||
users.users.kanidm = {
|
|
||||||
isNormalUser = true;
|
|
||||||
uid = UID;
|
|
||||||
};
|
|
||||||
|
|
||||||
virtualisation.oci-containers.containers.kanidm = {
|
|
||||||
image = "kanidm/server:1.4.2";
|
|
||||||
volumes = [
|
|
||||||
# "/srv/kanidm/data:/data/db"
|
|
||||||
"${./server.toml}:/data/server.toml"
|
|
||||||
"${./style.css}:/hpkg/style.css"
|
|
||||||
"${./fish.png}:/hpkg/img/fish.png"
|
|
||||||
];
|
|
||||||
|
|
||||||
user = "${builtins.toString UID}";
|
|
||||||
|
|
||||||
extraOptions = [
|
|
||||||
"--mount=type=bind,source=/srv/kanidm/data,target=/data/db"
|
|
||||||
"--mount=type=bind,source=${config.desu.secrets.kanidm-tls-key.path},target=/data/key.pem,readonly"
|
|
||||||
"--mount=type=bind,source=${config.desu.secrets.kanidm-tls-cert.path},target=/data/chain.pem,readonly"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
|
||||||
"d /srv/kanidm/data 0700 ${builtins.toString UID} ${builtins.toString UID} -"
|
|
||||||
];
|
|
||||||
|
|
||||||
services.nginx.virtualHosts."id.stupid.fish" = {
|
|
||||||
forceSSL = true;
|
|
||||||
useACMEHost = "stupid.fish";
|
|
||||||
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "https://kanidm.docker:8443$request_uri";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 86 KiB |
|
@ -1,22 +0,0 @@
|
||||||
notes for self:
|
|
||||||
|
|
||||||
## creating an oauth2 app:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
kanidm system oauth2 create myapp myapp_display_name https://url.to.app
|
|
||||||
kanidm system oauth2 warning-insecure-client-disable-pkce myapp # optional, for oauth2-proxy
|
|
||||||
kanidm system oauth2 prefer-short-username myapp # optional
|
|
||||||
kanidm system oauth2 show-basic-secret myapp
|
|
||||||
kanidm system oauth2 add-redirect-url myapp https://url.to.app/oauth2/callback # the default path for oauth2-proxy
|
|
||||||
|
|
||||||
# adding users to the app
|
|
||||||
kanidm group create myapp_users
|
|
||||||
kanidm group add-members myapp_users teidesu
|
|
||||||
kanidm system oauth2 update-scope-map myapp myapp_users email openid profile
|
|
||||||
```
|
|
||||||
|
|
||||||
## oauth2 proxy env:
|
|
||||||
```bash
|
|
||||||
OAUTH2_PROXY_COOKIE_SECRET=...
|
|
||||||
OAUTH2_PROXY_CLIENT_SECRET=...
|
|
||||||
```
|
|
|
@ -1,9 +0,0 @@
|
||||||
bindaddress = "0.0.0.0:8443"
|
|
||||||
adminbindpath = "/tmp/kanidm.sock"
|
|
||||||
trust_x_forward_for = true
|
|
||||||
db_path = "/data/db/kanidm.db"
|
|
||||||
tls_chain = "/data/chain.pem"
|
|
||||||
tls_key = "/data/key.pem"
|
|
||||||
|
|
||||||
domain = "id.stupid.fish"
|
|
||||||
origin = "https://id.stupid.fish"
|
|
|
@ -1,239 +0,0 @@
|
||||||
:root {
|
|
||||||
--totp-width-and-height: 30px;
|
|
||||||
--totp-stroke-width: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-cred-reset-body {
|
|
||||||
max-width: 500px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#settings-window .form-cred-reset-body {
|
|
||||||
max-width: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-signin {
|
|
||||||
max-width: 680px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sidebar
|
|
||||||
*/
|
|
||||||
|
|
||||||
.side-menu {
|
|
||||||
min-width: 180px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.side-menu-item {
|
|
||||||
--icon-size: 24px;
|
|
||||||
padding: .4rem .7rem;
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&.active {
|
|
||||||
background-color: var(--bs-gray-300);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-container img {
|
|
||||||
filter: invert(40%);
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Personal Settings sidemenu
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Navbar
|
|
||||||
*/
|
|
||||||
|
|
||||||
.kanidm_logo {
|
|
||||||
width: 12em;
|
|
||||||
height: 12em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.identity-verification-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
max-width: fit-content;
|
|
||||||
align-items: center;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.totp-display-container {
|
|
||||||
padding: 5px 10px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
max-width: fit-content;
|
|
||||||
align-items: center;
|
|
||||||
margin: auto;
|
|
||||||
border-radius: 15px;
|
|
||||||
background: #21252915;
|
|
||||||
box-shadow: -5px -5px 11px #ededed, 5px 5px 11px #ffffff;
|
|
||||||
margin: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.totp-display {
|
|
||||||
font-size: 35px;
|
|
||||||
margin: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.totp-timer {
|
|
||||||
margin: 10px;
|
|
||||||
position: relative;
|
|
||||||
height: var(--totp-width-and-height);
|
|
||||||
width: var(--totp-width-and-height);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Removes SVG styling that would hide the time label */
|
|
||||||
.totp-timer__circle {
|
|
||||||
fill: none;
|
|
||||||
stroke: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.totp-timer__path-remaining {
|
|
||||||
stroke-width: var(--totp-stroke-width);
|
|
||||||
|
|
||||||
/* Makes sure the animation starts at the top of the circle */
|
|
||||||
transform: rotate(90deg);
|
|
||||||
transform-origin: center;
|
|
||||||
|
|
||||||
/* One second aligns with the speed of the countdown timer */
|
|
||||||
transition: 1s linear all;
|
|
||||||
|
|
||||||
stroke: currentColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
.totp-timer__svg {
|
|
||||||
transform: scaleX(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.totp-timer__path-remaining.green {
|
|
||||||
color: rgb(65, 184, 131);
|
|
||||||
}
|
|
||||||
|
|
||||||
.totp-timer__path-remaining.orange {
|
|
||||||
color: orange;
|
|
||||||
}
|
|
||||||
|
|
||||||
.totp-timer__path-remaining.red {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.totp-timer__path-remaining.no-transition {
|
|
||||||
-webkit-transition: none !important;
|
|
||||||
-moz-transition: none !important;
|
|
||||||
-o-transition: none !important;
|
|
||||||
transition: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card>a {
|
|
||||||
height: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.oauth2-img {
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 90%;
|
|
||||||
padding: 10px;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-tiny {
|
|
||||||
--bs-btn-padding-y: .05rem;
|
|
||||||
--bs-btn-padding-x: .4rem;
|
|
||||||
--bs-btn-font-size: .75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#cred-update-commit-bar {
|
|
||||||
display: block;
|
|
||||||
/*
|
|
||||||
position: fixed;
|
|
||||||
bottom: .5rem;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
*/
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-container {
|
|
||||||
padding: 2px;
|
|
||||||
width: var(--icon-size);
|
|
||||||
height: var(--icon-size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* stupid.fish customizations */
|
|
||||||
.kanidm_logo {
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
background: url(/pkg/img/fish.png) no-repeat;
|
|
||||||
background-size: contain;
|
|
||||||
padding: 4em 8em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer .text-muted::after {
|
|
||||||
content: ' and some stupidity';
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-signin h3 {
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ayu mirage */
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
body {
|
|
||||||
background: #242936;
|
|
||||||
color: #cccac2;
|
|
||||||
--bs-body-bg: #242936;
|
|
||||||
--bs-body-color: #cccac2;
|
|
||||||
--bs-border-color: #707a8c45;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-control {
|
|
||||||
background-color: #1f2430;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-light,
|
|
||||||
.bg-dark {
|
|
||||||
background-color: #1f2430 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-muted {
|
|
||||||
color: #b8cfe680 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-dark {
|
|
||||||
--bs-btn-color: #cccac2;
|
|
||||||
--bs-btn-bg: #1f2430;
|
|
||||||
--bs-btn-border-color: #1f2430;
|
|
||||||
--bs-btn-hover-color: #cccac2;
|
|
||||||
--bs-btn-hover-bg: #2e3037;
|
|
||||||
--bs-btn-hover-border-color: #2e3037;
|
|
||||||
--bs-btn-focus-shadow-rgb: 66, 70, 73;
|
|
||||||
--bs-btn-active-color: #cccac2;
|
|
||||||
--bs-btn-active-bg: #2e3037;
|
|
||||||
--bs-btn-active-border-color: #2e3037;
|
|
||||||
--bs-btn-active-shadow: none;
|
|
||||||
--bs-btn-disabled-color: #b8cfe680;
|
|
||||||
--bs-btn-disabled-bg: #1f2430;
|
|
||||||
--bs-btn-disabled-border-color: #1f2430;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert-light {
|
|
||||||
--bs-alert-color: #cccac2;
|
|
||||||
--bs-alert-bg: #1f2430;
|
|
||||||
--bs-alert-border-color: transparent;
|
|
||||||
--bs-alert-link-color: #cccac2;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -33,7 +33,7 @@ in {
|
||||||
|
|
||||||
desu.secrets.siyuan-teidesu-proxy-env.owner = "siyuan-teidesu";
|
desu.secrets.siyuan-teidesu-proxy-env.owner = "siyuan-teidesu";
|
||||||
desu.openid-proxy.services.siyuan-teidesu = {
|
desu.openid-proxy.services.siyuan-teidesu = {
|
||||||
clientId = "teidesu-siyuan";
|
clientId = "299749237216837638";
|
||||||
domain = "siyuan.tei.su";
|
domain = "siyuan.tei.su";
|
||||||
upstream = "http://siyuan-teidesu.docker:6806";
|
upstream = "http://siyuan-teidesu.docker:6806";
|
||||||
envSecret = "siyuan-teidesu-proxy-env";
|
envSecret = "siyuan-teidesu-proxy-env";
|
||||||
|
|
|
@ -76,7 +76,7 @@ in
|
||||||
];
|
];
|
||||||
|
|
||||||
desu.openid-proxy.services.torrent = {
|
desu.openid-proxy.services.torrent = {
|
||||||
clientId = "torrent";
|
clientId = "299749111337385990";
|
||||||
domain = "torrent.stupid.fish";
|
domain = "torrent.stupid.fish";
|
||||||
upstream = "http://torrent.containers";
|
upstream = "http://torrent.containers";
|
||||||
envSecret = "torrent-proxy-env";
|
envSecret = "torrent-proxy-env";
|
||||||
|
|
55
hosts/koi/containers/zitadel/default.nix
Normal file
55
hosts/koi/containers/zitadel/default.nix
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
{ pkgs, config, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
UID = 1122;
|
||||||
|
in {
|
||||||
|
imports = [
|
||||||
|
./proxy.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
users.users.zitadel = {
|
||||||
|
isNormalUser = true;
|
||||||
|
uid = UID;
|
||||||
|
};
|
||||||
|
|
||||||
|
services.postgresql.ensureUsers = [
|
||||||
|
{ name = "zitadel"; ensureDBOwnership = true; }
|
||||||
|
];
|
||||||
|
services.postgresql.ensureDatabases = [ "zitadel" ];
|
||||||
|
desu.postgresql.ensurePasswords.zitadel = "zitadel";
|
||||||
|
|
||||||
|
desu.secrets.zitadel-env.owner = "zitadel";
|
||||||
|
|
||||||
|
virtualisation.oci-containers.containers.zitadel = {
|
||||||
|
image = "ghcr.io/zitadel/zitadel:v2.66.1";
|
||||||
|
cmd = [ "start-from-setup" "--masterkeyFromEnv" "--tlsMode" "external" ];
|
||||||
|
environment = {
|
||||||
|
"ZITADEL_DATABASE_POSTGRES_HOST" = "172.17.0.1";
|
||||||
|
"ZITADEL_DATABASE_POSTGRES_PORT" = "5432";
|
||||||
|
"ZITADEL_DATABASE_POSTGRES_DATABASE" = "zitadel";
|
||||||
|
"ZITADEL_DATABASE_POSTGRES_USER_USERNAME" = "zitadel";
|
||||||
|
"ZITADEL_DATABASE_POSTGRES_USER_PASSWORD" = "zitadel";
|
||||||
|
"ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE" = "disable";
|
||||||
|
"ZITADEL_EXTERNALSECURE" = "true";
|
||||||
|
"ZITADEL_EXTERNALDOMAIN" = "id.stupid.fish";
|
||||||
|
"ZITADEL_EXTERNALPORT" = "443";
|
||||||
|
"ZITADEL_TLS_ENABLED" = "false";
|
||||||
|
"ZITADEL_WEBAUTHNNAME" = "stupid.fish";
|
||||||
|
};
|
||||||
|
environmentFiles = [
|
||||||
|
config.desu.secrets.zitadel-env.path
|
||||||
|
];
|
||||||
|
user = builtins.toString UID;
|
||||||
|
};
|
||||||
|
systemd.services.docker-zitadel.requires = [ "postgresql.service" ];
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."id.stupid.fish" = {
|
||||||
|
forceSSL = true;
|
||||||
|
useACMEHost = "stupid.fish";
|
||||||
|
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://zitadel.docker:8080$request_uri";
|
||||||
|
proxyWebsockets = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
137
hosts/koi/containers/zitadel/init.sql
Normal file
137
hosts/koi/containers/zitadel/init.sql
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
CREATE SCHEMA IF NOT EXISTS eventstore;
|
||||||
|
CREATE SCHEMA IF NOT EXISTS projections;
|
||||||
|
CREATE SCHEMA IF NOT EXISTS system;
|
||||||
|
CREATE TABLE IF NOT EXISTS system.encryption_keys (
|
||||||
|
id TEXT NOT NULL
|
||||||
|
, key TEXT NOT NULL
|
||||||
|
|
||||||
|
, PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
CREATE TABLE IF NOT EXISTS eventstore.events2 (
|
||||||
|
instance_id TEXT NOT NULL
|
||||||
|
, aggregate_type TEXT NOT NULL
|
||||||
|
, aggregate_id TEXT NOT NULL
|
||||||
|
|
||||||
|
, event_type TEXT NOT NULL
|
||||||
|
, "sequence" BIGINT NOT NULL
|
||||||
|
, revision SMALLINT NOT NULL
|
||||||
|
, created_at TIMESTAMPTZ NOT NULL
|
||||||
|
, payload JSONB
|
||||||
|
, creator TEXT NOT NULL
|
||||||
|
, "owner" TEXT NOT NULL
|
||||||
|
|
||||||
|
, "position" DECIMAL NOT NULL
|
||||||
|
, in_tx_order INTEGER NOT NULL
|
||||||
|
|
||||||
|
, PRIMARY KEY (instance_id, aggregate_type, aggregate_id, "sequence")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS es_active_instances ON eventstore.events2 (created_at DESC, instance_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS es_wm ON eventstore.events2 (aggregate_id, instance_id, aggregate_type, event_type);
|
||||||
|
CREATE INDEX IF NOT EXISTS es_projection ON eventstore.events2 (instance_id, aggregate_type, event_type, "position");
|
||||||
|
|
||||||
|
-- represents an event to be created.
|
||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE eventstore.command AS (
|
||||||
|
instance_id TEXT
|
||||||
|
, aggregate_type TEXT
|
||||||
|
, aggregate_id TEXT
|
||||||
|
, command_type TEXT
|
||||||
|
, revision INT2
|
||||||
|
, payload JSONB
|
||||||
|
, creator TEXT
|
||||||
|
, owner TEXT
|
||||||
|
);
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION eventstore.commands_to_events(commands eventstore.command[]) RETURNS SETOF eventstore.events2 VOLATILE AS $$
|
||||||
|
SELECT
|
||||||
|
c.instance_id
|
||||||
|
, c.aggregate_type
|
||||||
|
, c.aggregate_id
|
||||||
|
, c.command_type AS event_type
|
||||||
|
, cs.sequence + ROW_NUMBER() OVER (PARTITION BY c.instance_id, c.aggregate_type, c.aggregate_id ORDER BY c.in_tx_order) AS sequence
|
||||||
|
, c.revision
|
||||||
|
, NOW() AS created_at
|
||||||
|
, c.payload
|
||||||
|
, c.creator
|
||||||
|
, cs.owner
|
||||||
|
, EXTRACT(EPOCH FROM NOW()) AS position
|
||||||
|
, c.in_tx_order
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
c.instance_id
|
||||||
|
, c.aggregate_type
|
||||||
|
, c.aggregate_id
|
||||||
|
, c.command_type
|
||||||
|
, c.revision
|
||||||
|
, c.payload
|
||||||
|
, c.creator
|
||||||
|
, c.owner
|
||||||
|
, ROW_NUMBER() OVER () AS in_tx_order
|
||||||
|
FROM
|
||||||
|
UNNEST(commands) AS c
|
||||||
|
) AS c
|
||||||
|
JOIN (
|
||||||
|
SELECT
|
||||||
|
cmds.instance_id
|
||||||
|
, cmds.aggregate_type
|
||||||
|
, cmds.aggregate_id
|
||||||
|
, CASE WHEN (e.owner IS NOT NULL OR e.owner <> '') THEN e.owner ELSE command_owners.owner END AS owner
|
||||||
|
, COALESCE(MAX(e.sequence), 0) AS sequence
|
||||||
|
FROM (
|
||||||
|
SELECT DISTINCT
|
||||||
|
instance_id
|
||||||
|
, aggregate_type
|
||||||
|
, aggregate_id
|
||||||
|
, owner
|
||||||
|
FROM UNNEST(commands)
|
||||||
|
) AS cmds
|
||||||
|
LEFT JOIN eventstore.events2 AS e
|
||||||
|
ON cmds.instance_id = e.instance_id
|
||||||
|
AND cmds.aggregate_type = e.aggregate_type
|
||||||
|
AND cmds.aggregate_id = e.aggregate_id
|
||||||
|
JOIN (
|
||||||
|
SELECT
|
||||||
|
DISTINCT ON (
|
||||||
|
instance_id
|
||||||
|
, aggregate_type
|
||||||
|
, aggregate_id
|
||||||
|
)
|
||||||
|
instance_id
|
||||||
|
, aggregate_type
|
||||||
|
, aggregate_id
|
||||||
|
, owner
|
||||||
|
FROM
|
||||||
|
UNNEST(commands)
|
||||||
|
) AS command_owners ON
|
||||||
|
cmds.instance_id = command_owners.instance_id
|
||||||
|
AND cmds.aggregate_type = command_owners.aggregate_type
|
||||||
|
AND cmds.aggregate_id = command_owners.aggregate_id
|
||||||
|
GROUP BY
|
||||||
|
cmds.instance_id
|
||||||
|
, cmds.aggregate_type
|
||||||
|
, cmds.aggregate_id
|
||||||
|
, 4 -- owner
|
||||||
|
) AS cs
|
||||||
|
ON c.instance_id = cs.instance_id
|
||||||
|
AND c.aggregate_type = cs.aggregate_type
|
||||||
|
AND c.aggregate_id = cs.aggregate_id
|
||||||
|
ORDER BY
|
||||||
|
in_tx_order;
|
||||||
|
$$ LANGUAGE SQL;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION eventstore.push(commands eventstore.command[]) RETURNS SETOF eventstore.events2 VOLATILE AS $$
|
||||||
|
INSERT INTO eventstore.events2
|
||||||
|
SELECT * FROM eventstore.commands_to_events(commands)
|
||||||
|
RETURNING *
|
||||||
|
$$ LANGUAGE SQL;
|
||||||
|
CREATE SEQUENCE IF NOT EXISTS eventstore.system_seq;
|
||||||
|
CREATE TABLE IF NOT EXISTS eventstore.unique_constraints (
|
||||||
|
instance_id TEXT,
|
||||||
|
unique_type TEXT,
|
||||||
|
unique_field TEXT,
|
||||||
|
PRIMARY KEY (instance_id, unique_type, unique_field)
|
||||||
|
);
|
|
@ -61,7 +61,7 @@ in {
|
||||||
"--client-id=${service.clientId}"
|
"--client-id=${service.clientId}"
|
||||||
"--upstream=${service.upstream}"
|
"--upstream=${service.upstream}"
|
||||||
"--redirect-url=https://${service.domain}/oauth2/callback"
|
"--redirect-url=https://${service.domain}/oauth2/callback"
|
||||||
"--oidc-issuer-url=https://id.stupid.fish/oauth2/openid/${service.clientId}"
|
"--oidc-issuer-url=https://id.stupid.fish"
|
||||||
] ++ service.extra;
|
] ++ service.extra;
|
||||||
};
|
};
|
||||||
}) (builtins.attrNames cfg.services)
|
}) (builtins.attrNames cfg.services)
|
|
@ -24,7 +24,7 @@ in
|
||||||
|
|
||||||
desu.secrets.hass-proxy-env = {};
|
desu.secrets.hass-proxy-env = {};
|
||||||
desu.openid-proxy.services.hass = {
|
desu.openid-proxy.services.hass = {
|
||||||
clientId = "hass";
|
clientId = "299748893099360262";
|
||||||
domain = "hass.stupid.fish";
|
domain = "hass.stupid.fish";
|
||||||
upstream = "http://10.42.0.3:8123";
|
upstream = "http://10.42.0.3:8123";
|
||||||
envSecret = "hass-proxy-env";
|
envSecret = "hass-proxy-env";
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
6
secrets/zitadel-env.age
Normal file
6
secrets/zitadel-env.age
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
age-encryption.org/v1
|
||||||
|
-> ssh-ed25519 sj88Xw KHqbr2MMzik5ygZw4RC65UAX6QB8/y8m761UtWLaLFo
|
||||||
|
WWW15wcaj1HDWy/T9TQyp+MAR+pzfX41sCWq4Rj6THs
|
||||||
|
--- MJrS0sFAtch6GH83x5r1yJ9ogvYti0drZR8Pdx1Y60U
|
||||||
|
s4ÊAÉ°w›ìÐ «wLæEžî'¿ç >\<5C>Ð.×öoªpT6~<7E>©Ûº¦<1D>¼qMzô:ÞÐÃö‡ìÕ)iS‹š%œÿ"<œñÿæ_¥ÍcýäÆ<C3A4>ßcr¯;µœÌ@Mu Öä%U^0À€¡µ¡ƒò4µ£ºÂQNe”¨Q¡ßÉ+ù)N=â+AÐÕþrfbWœážÚr»
|
||||||
|
+‹}e'©9¤Çâ¿!9„JÚÚ<C39A> …0tl½•½^î¦S†=ÊUܳ¥r"âÑ_7
|
Loading…
Reference in a new issue