Compare commits

...

9 Commits

Author SHA1 Message Date
310950de42 Update littlelink
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
2025-09-15 12:08:07 +01:00
d418acb16a Make gitea two-factor
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
2025-09-15 12:08:07 +01:00
8f2cea6abf Add blog
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
2025-09-15 12:08:07 +01:00
43b6159feb Add gitea runner image
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
2025-09-15 12:08:07 +01:00
6b38429bac 80TiB
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
2025-09-15 12:08:07 +01:00
615524070b Update grafana dashboards
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
2025-09-15 12:08:06 +01:00
1727785180 Add declarative attic cache
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
2025-09-15 12:08:06 +01:00
ffafc81ed1 Add authelia consent duration
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
2025-09-15 12:07:54 +01:00
367d65e1ba Add comentario
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
2025-09-15 12:07:53 +01:00
40 changed files with 1669 additions and 2018 deletions

8
flake.lock generated
View File

@@ -511,11 +511,11 @@
"secrets": {
"flake": false,
"locked": {
"lastModified": 1757519344,
"narHash": "sha256-wLwVbKDPkFCPh9UYLDqCPb62hp6mHBAgjn3Dech54YU=",
"lastModified": 1757873556,
"narHash": "sha256-WYrV46if1XsiQKOQEMNtHdAPeFDeu7YBdcoNSXc3sf8=",
"ref": "refs/heads/main",
"rev": "8ae051ad0936cb8fbf10b3ab2130f09a07ca1ce6",
"revCount": 39,
"rev": "21ab0b0a59264b1da501f90725bf2c03e07ae941",
"revCount": 43,
"type": "git",
"url": "ssh://git@karaolidis.com/karaolidis/nix-secrets.git"
},

View File

@@ -200,13 +200,17 @@
)
((pkgs.lib.filterAttrs (_: config: config.pkgs.system == system)) inputs.self.nixosConfigurations);
packages = pkgs.lib.mapAttrs' (n: pkgs.lib.nameValuePair "package-${n}") inputs.self.packages;
packages = pkgs.lib.mapAttrs' (
name: pkgs.lib.nameValuePair "package-${name}"
) inputs.self.packages.${system};
overlayPackages = pkgs.lib.mapAttrs' (n: pkgs.lib.nameValuePair "overlayPackage-${n}") (
import ./overlays/packages.nix { inherit pkgs; }
);
devShells = pkgs.lib.mapAttrs' (n: pkgs.lib.nameValuePair "devShell-${n}") inputs.self.devShells;
devShells = pkgs.lib.mapAttrs' (
name: pkgs.lib.nameValuePair "devShell-${name}"
) inputs.self.devShells.${system};
formatter.formatting = treefmt.config.build.check inputs.self;
in

View File

@@ -43,7 +43,9 @@
];
download-buffer-size = 524288000;
substituters = lib.mkBefore [ "https://nix.karaolidis.com/main" ];
trusted-public-keys = lib.mkBefore [ "main:nJVRBnv73MDkwuV5sgm52m4E2ImOhWHvY12qzjPegAk=" ];
trusted-public-keys = lib.mkBefore [
"nix.karaolidis.com:1yz1tIVLGDEOFC1p/uYtR4Sx+nIbdYDqsDv4kkV0uyk="
];
netrc-file = config.sops.templates.nix-netrc.path;
};

View File

@@ -17,13 +17,13 @@ Remember to update [format.nix](format.nix).
### Adding a new drive
Create a `format.nix` containing the new disk layout. Do not include already existing disks in this file, nor the global pool.
```
parted /dev/sdd -- mklabel gpt
parted /dev/sdd -- mkpart primary 0% 100%
cryptsetup luksFormat /dev/sdd
cryptsetup open /dev/sdd storage2
disko -m "destroy" --yes-wipe-all-disks format.nix
disko -m "format" --yes-wipe-all-disks format.nix
btrfs device add /dev/mapper/storage2 /mnt/storage
btrfs balance start -dconvert=raid1 -mconvert=raid1 /mnt/storage
btrfs balance start -dconvert=raid1 -mconvert=raid1 /mnt/storage --bg
```
### Removing an old drive

View File

@@ -59,6 +59,8 @@
main.keyFile = "/usb/keyfile";
storage0.keyFile = "/usb/keyfile";
storage1.keyFile = "/usb/keyfile";
storage2.keyFile = "/usb/keyfile";
storage3.keyFile = "/usb/keyfile";
};
systemd.contents."/etc/fstab".text = ''

View File

@@ -123,10 +123,66 @@
settings = {
allowDiscards = true;
};
};
};
};
};
};
storage2 = {
device = "/dev/disk/by-id/ata-TOSHIBA_MG11ACA24TE_7512A15XF6AL";
type = "disk";
content = {
type = "gpt";
partitions = {
root = {
name = "root";
size = "100%";
content = {
name = "storage2";
type = "luks";
passwordFile = "/tmp/keyfile";
settings = {
allowDiscards = true;
};
};
};
};
};
};
storage3 = {
device = "/dev/disk/by-id/ata-TOSHIBA_MG11ACA24TE_7512A192F6AL";
type = "disk";
content = {
type = "gpt";
partitions = {
root = {
name = "root";
size = "100%";
content = {
name = "storage3";
type = "luks";
passwordFile = "/tmp/keyfile";
settings = {
allowDiscards = true;
};
content = {
type = "btrfs";
extraArgs = [ "-f -L storage -m raid1 -d raid1 /dev/mapper/storage0" ];
extraArgs = [
"-f"
"-L"
"storage"
"-m"
"raid1"
"-d"
"raid1"
"/dev/mapper/storage0"
"/dev/mapper/storage1"
"/dev/mapper/storage2"
# Implicit /dev/mapper/storage3
];
subvolumes =
let
mountOptions = [

View File

@@ -16,6 +16,7 @@ in
"attic/postgresql".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml";
"attic/rs256".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml";
"attic/admin".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml";
"attic/keypairs/main".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml";
};
templates = {
@@ -94,6 +95,7 @@ in
[
"/mnt/storage/private/storm/containers/storage/volumes/attic/_data:/var/lib/attic"
"${hmConfig.sops.templates.attic-server.path}:/etc/attic/server.toml:ro"
"${hmConfig.sops.secrets."attic/keypairs/main".path}:/etc/attic/keypairs/main:ro"
"${postStart}:/etc/attic/post-start.sh:ro"
];
environmentFiles = [ hmConfig.sops.templates.attic-env.path ];

View File

@@ -11,9 +11,11 @@ while true; do
set -o errexit
if [ $status -eq 0 ]; then
attic cache configure "$CACHE_NAME" --keypair-path "/etc/attic/keypairs/$CACHE_NAME"
break
elif echo "$out" | grep -q "NoSuchCache"; then
attic cache create "$CACHE_NAME"
attic cache create "$CACHE_NAME" --keypair-path "/etc/attic/keypairs/$CACHE_NAME"
break
elif echo "$out" | grep -q "404"; then
sleep 0.1
else

View File

@@ -136,6 +136,7 @@ in
"gitea"
"outline"
"shlink"
"comentario"
];
};
}

View File

@@ -0,0 +1,62 @@
{ user, home }:
{
config,
inputs,
lib,
pkgs,
...
}:
let
hmConfig = config.home-manager.users.${user};
inherit (hmConfig.virtualisation.quadlet) volumes networks;
in
{
home-manager.users.${user} = {
sops = {
secrets."blog/apiKey".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml";
templates.blog-receiver-env.content = ''
AUTH_KEY=${hmConfig.sops.placeholder."blog/apiKey"}
'';
};
virtualisation.quadlet = {
volumes.blog = { };
containers = {
blog.containerConfig = {
image = "docker-archive:${pkgs.dockerImages.nginx}";
networks = [ networks.traefik.ref ];
volumes = [ "${volumes.blog.ref}:/var/www/nginx:ro" ];
labels = [
"traefik.enable=true"
"traefik.http.routers.blog.rule=Host(`blog.karaolidis.com`)"
];
};
blog-receiver = {
containerConfig = {
image = "docker-archive:${pkgs.dockerImages.nginx-receiver}";
networks = [ networks.traefik.ref ];
volumes = [ "${volumes.blog.ref}:/var/www/nginx" ];
environments = {
TARGET_DIR = "/var/www/nginx";
SUBPATH = "/upload";
};
environmentFiles = [ hmConfig.sops.templates.blog-receiver-env.path ];
labels = [
"traefik.enable=true"
"traefik.http.routers.blog-receiver.rule=Host(`blog.karaolidis.com`) && PathPrefix(`/upload`)"
"traefik.http.middlewares.redirect-root-to-blog.redirectregex.regex=^https://(www\.)?karaolidis\.com(/.*)?$"
"traefik.http.middlewares.redirect-root-to-blog.redirectregex.replacement=https://blog.karaolidis.com$${2}"
"traefik.http.middlewares.redirect-root-to-blog.redirectregex.permanent=false"
];
};
unitConfig.After = [ "sops-nix.service" ];
};
};
};
};
}

View File

@@ -0,0 +1,159 @@
{ user, home }:
{
config,
inputs,
pkgs,
lib,
...
}:
let
hmConfig = config.home-manager.users.${user};
inherit (hmConfig.virtualisation.quadlet) containers volumes networks;
autheliaClientId = "d16NArYYcTbDU0YTQEwmlvzWAzJKhbIbe4s8wGENSRTK40gvAwGbYO0fCSq4rh6pjNxI0ZuH1cM8XnADCgSV9SHRzgX9MqcFre5r";
in
{
home-manager.users.${user} = {
sops = {
secrets = {
"comentario/postgresql".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml";
"comentario/authelia/password".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml";
"comentario/authelia/digest".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml";
"comentario/smtp".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml";
};
templates = {
comentario-postgresql-env.content = ''
POSTGRES_PASSWORD=${hmConfig.sops.placeholder."comentario/postgresql"}
'';
comentario.content = builtins.readFile (
(pkgs.formats.yaml { }).generate "secrets.yaml" {
postgres = {
host = "comentario-postgresql";
port = 5432;
database = "comentario";
username = "comentario";
password = hmConfig.sops.placeholder."comentario/postgresql";
};
smtpServer = {
host = "smtp.protonmail.ch";
port = 587;
username = "jupiter@karaolidis.com";
password = hmConfig.sops.placeholder."comentario/smtp";
};
idp.oidc = [
{
id = "authelia";
name = "Authelia";
url = "https://id.karaolidis.com";
scopes = [
"openid"
"profile"
"email"
"is_admin"
];
key = autheliaClientId;
secret = hmConfig.sops.placeholder."comentario/authelia/password";
}
];
}
);
authelia-comentario.content = builtins.readFile (
(pkgs.formats.yaml { }).generate "comentario.yaml" {
identity_providers.oidc = {
authorization_policies.comentario = {
default_policy = "deny";
rules = [
{
policy = "one_factor";
subject = "group:comentario";
}
];
};
clients = [
{
client_id = autheliaClientId;
client_name = "Comentario";
client_secret = hmConfig.sops.placeholder."comentario/authelia/digest";
redirect_uris = [ "https://comments.karaolidis.com/api/oauth/oidc:authelia/callback" ];
authorization_policy = "comentario";
claims_policy = "is_admin";
scopes = [
"openid"
"profile"
"email"
"is_admin"
];
pre_configured_consent_duration = "1 month";
}
];
};
}
);
};
};
virtualisation.quadlet = {
networks.comentario = { };
volumes.comentario-postgresql = { };
containers = {
comentario = {
containerConfig = {
image = "docker-archive:${pkgs.dockerImages.comentario}";
networks = [
networks.comentario.ref
networks.traefik.ref
];
environments = {
BASE_URL = "https://comments.karaolidis.com";
NO_COLOR = "true";
SUPERUSER_CLAIM = "is_admin";
DYN_DEFAULT_AUTH_EMAILUPDATE_ENABLED = "true";
DYN_DEFAULT_AUTH_SIGNUP_CONFIRM_COMMENTER = "false";
DYN_DEFAULT_AUTH_SIGNUP_ENABLED = "false";
DYN_DEFAULT_AUTH_SIGNUP_SSO_ENABLED = "true";
};
volumes = [ "${hmConfig.sops.templates.comentario.path}:/etc/comentario/secrets.yaml:ro" ];
labels = [
"traefik.enable=true"
"traefik.http.routers.comentario.rule=Host(`comments.karaolidis.com`)"
];
};
unitConfig = {
After = [
"${containers.comentario-postgresql._serviceName}.service"
"sops-nix.service"
];
Requires = [ "${containers.comentario-postgresql._serviceName}.service" ];
};
};
comentario-postgresql = {
containerConfig = {
image = "docker-archive:${pkgs.dockerImages.postgresql}";
networks = [ networks.comentario.ref ];
volumes = [ "${volumes.comentario-postgresql.ref}:/var/lib/postgresql/data" ];
environments = {
POSTGRES_DB = "comentario";
POSTGRES_USER = "comentario";
};
environmentFiles = [ hmConfig.sops.templates.comentario-postgresql-env.path ];
};
unitConfig.After = [ "sops-nix.service" ];
};
authelia.containerConfig.volumes = [
"${hmConfig.sops.templates.authelia-comentario.path}:/etc/authelia/conf.d/comentario.yaml:ro"
];
};
};
};
}

View File

@@ -12,6 +12,8 @@ in
imports = [
(import ./attic { inherit user home; })
(import ./authelia { inherit user home; })
(import ./blog { inherit user home; })
(import ./comentario { inherit user home; })
(import ./gitea { inherit user home; })
(import ./grafana { inherit user home; })
(import ./littlelink { inherit user home; })

View File

@@ -61,7 +61,12 @@ in
home-manager.users.${user} =
let
autheliaClientId = "I2ZYDFGWP1bzfiauXe94IaiReZF6SqoEskSp6phoL2L8l16Cq7YX3Vr4pkQOSYfNDOwuFjTRIpqQ8eAqK0M93NeEgpr8YoPhKHyR";
inherit (hmConfig.virtualisation.quadlet) containers volumes networks;
inherit (hmConfig.virtualisation.quadlet)
containers
volumes
networks
images
;
in
{
sops = {
@@ -178,7 +183,7 @@ in
default_policy = "deny";
rules = [
{
policy = "one_factor";
policy = "two_factor";
subject = "group:gitea";
}
];
@@ -191,6 +196,7 @@ in
client_secret = hmConfig.sops.placeholder."gitea/authelia/digest";
redirect_uris = [ "https://git.karaolidis.com/user/oauth2/authelia/callback" ];
authorization_policy = "gitea";
pre_configured_consent_duration = "1 month";
}
];
};
@@ -213,6 +219,16 @@ in
gitea-act-runner-cache = { };
};
images.gitea-act-runner-worker.imageConfig = {
image = "docker-archive:${pkgs.dockerImages.gitea-act-runner-worker}";
tag =
let
name = pkgs.dockerImages.gitea-act-runner-worker.passthru.buildArgs.name;
tag = pkgs.dockerImages.gitea-act-runner-worker.passthru.imageTag;
in
"localhost/${name}:${tag}";
};
containers = {
gitea = {
containerConfig = {
@@ -277,8 +293,22 @@ in
volumes =
let
uid = builtins.toString config.users.users.${user}.uid;
runnerConfig = (pkgs.formats.yaml { }).generate "config.yaml" {
runner = {
file = "/var/lib/gitea-act-runner/registration";
capacity = 4;
labels = [ "nix:docker://${images.gitea-act-runner-worker.imageConfig.tag}" ];
};
cache.dir = "/tmp/gitea-act-runner/";
container = {
privileged = true;
docker_host = "-";
};
};
in
[
"${runnerConfig}:/etc/gitea-act-runner/config.yaml:ro"
"/run/user/${uid}/podman/podman.sock:/var/run/docker.sock"
"${volumes.gitea-act-runner-data.ref}:/var/lib/gitea-act-runner"
"${volumes.gitea-act-runner-cache.ref}:/tmp/gitea-act-runner"

View File

@@ -867,6 +867,6 @@
"timepicker": {},
"timezone": "browser",
"title": "Traefik",
"uid": "9789120c-ed69-448a-9ef8-77e73b5a25e2",
"version": 7
"uid": "traefik",
"version": 1
}

View File

@@ -32,6 +32,7 @@ in
authorization_policy = "admin_one_factor";
require_pkce = true;
pkce_challenge_method = "S256";
pre_configured_consent_duration = "1 month";
}
];
}

View File

@@ -38,7 +38,7 @@ in
AVATAR_ALT = "Nick Karaolidis Profile Picture";
BUTTON_ORDER = lib.strings.concatStringsSep "," [
"GHOST"
"BLOG"
"EMAIL"
"LINKED_IN"
"GITEA"
@@ -50,7 +50,14 @@ in
"STEAM"
];
GHOST = "https://blog.karaolidis.com/";
CUSTOM_BUTTON_TEXT = "Blog";
CUSTOM_BUTTON_URL = "https://blog.karaolidis.com";
CUSTOM_BUTTON_COLOR = "#000000";
CUSTOM_BUTTON_TEXT_COLOR = "#ffffff";
CUSTOM_BUTTON_ALT_TEXT = "Blog";
CUSTOM_BUTTON_NAME = "BLOG";
CUSTOM_BUTTON_ICON = "fas fa-pen-nib";
EMAIL = "nick@karaolidis.com";
EMAIL_TEXT = "E-mail";
LINKED_IN = "https://www.linkedin.com/in/nikolaos-karaolidis";

View File

@@ -8,8 +8,7 @@
let
hmConfig = config.home-manager.users.${user};
inherit (hmConfig.virtualisation.quadlet) volumes networks;
jellyfinAutheliaClientId = "59TRpNutxEeRRCAZbDsK7rsnrA5NC69HAdAO45CEfc740xl4hgIacDy2u03oiFc89Exb67udBQvmfwxgeAQtJPiNAJxA5OzGmdQf";
autheliaClientId = "59TRpNutxEeRRCAZbDsK7rsnrA5NC69HAdAO45CEfc740xl4hgIacDy2u03oiFc89Exb67udBQvmfwxgeAQtJPiNAJxA5OzGmdQf";
in
{
home-manager.users.${user} = {
@@ -45,7 +44,7 @@ in
clients = [
{
client_id = jellyfinAutheliaClientId;
client_id = autheliaClientId;
client_name = "Jellyfin";
client_secret = hmConfig.sops.placeholder."jellyfin/authelia/digest";
redirect_uris = [ "https://media.karaolidis.com/sso/OID/redirect/authelia" ];
@@ -58,6 +57,7 @@ in
"groups"
];
token_endpoint_auth_method = "client_secret_post";
pre_configured_consent_duration = "1 month";
}
];
};
@@ -105,7 +105,7 @@ in
"${volumes.jellyfin-log.ref}:/var/log/jellyfin"
"${volumes.jellyfin-cache.ref}:/tmp/jellyfin"
];
environments.JELLYFIN_OIDC_CLIENT_ID = jellyfinAutheliaClientId;
environments.JELLYFIN_OIDC_CLIENT_ID = autheliaClientId;
environmentFiles = [ hmConfig.sops.templates.jellyfin-env.path ];
labels = [
"traefik.enable=true"

View File

@@ -14,9 +14,8 @@
let
hmConfig = config.home-manager.users.${user};
inherit (hmConfig.virtualisation.quadlet) containers volumes networks;
arrs = radarrs ++ sonarrs;
jellyseerrAutheliaClientId = "s8QyVqBdiEStH5WXeEYNSrEh8ls2xHif0qyTGbC7V8nHNcqHi5NhqHUapCHuVFT4kEtngqgLry2SKOKepQl3AiqCWlhTjlIxr7LI";
autheliaClientId = "s8QyVqBdiEStH5WXeEYNSrEh8ls2xHif0qyTGbC7V8nHNcqHi5NhqHUapCHuVFT4kEtngqgLry2SKOKepQl3AiqCWlhTjlIxr7LI";
in
{
home-manager.users.${user} = {
@@ -64,7 +63,7 @@ in
slug = "authelia";
name = "Authelia";
issuerUrl = "https://id.karaolidis.com";
clientId = jellyseerrAutheliaClientId;
clientId = autheliaClientId;
clientSecret = hmConfig.sops.placeholder."jellyseerr/authelia/password";
scopes = lib.strings.concatStringsSep " " [
"openid"
@@ -113,12 +112,13 @@ in
clients = [
{
client_id = jellyseerrAutheliaClientId;
client_id = autheliaClientId;
client_name = "jellyseerr";
client_secret = hmConfig.sops.placeholder."jellyseerr/authelia/digest";
redirect_uris = [ "https://request.karaolidis.com/login?provider=authelia&callback=true" ];
authorization_policy = "jellyseerr";
token_endpoint_auth_method = "client_secret_post";
pre_configured_consent_duration = "1 month";
}
];
};

View File

@@ -137,6 +137,7 @@ in
"groups"
"is_admin"
];
pre_configured_consent_duration = "1 month";
}
];
};
@@ -169,14 +170,14 @@ in
];
volumes =
let
post-setup = pkgs.writeTextFile {
postSetup = pkgs.writeTextFile {
name = "post-setup.sh";
executable = true;
text = builtins.readFile ./post-setup.sh;
};
in
[
"${post-setup}:/etc/nextcloud/post-setup.sh:ro"
"${postSetup}:/etc/nextcloud/post-setup.sh:ro"
"/mnt/storage/private/storm/containers/storage/volumes/nextcloud-data/_data:/var/lib/nextcloud"
"${volumes.nextcloud-log.ref}:/var/log/nextcloud"
"${volumes.nextcloud-config.ref}:/var/www/nextcloud/config"

View File

@@ -65,6 +65,7 @@ in
];
response_types = [ "code" ];
token_endpoint_auth_method = "client_secret_post";
pre_configured_consent_duration = "1 month";
}
];
};

View File

@@ -64,6 +64,7 @@ in
"offline_access"
];
response_types = [ "code" ];
pre_configured_consent_duration = "1 month";
}
];
};

View File

@@ -0,0 +1,162 @@
diff --git a/client/src/cli.rs b/client/src/cli.rs
index ee86783..e96b1b6 100644
--- a/client/src/cli.rs
+++ b/client/src/cli.rs
@@ -9,6 +9,7 @@ use enum_as_inner::EnumAsInner;
use crate::command::cache::{self, Cache};
use crate::command::get_closure::{self, GetClosure};
+use crate::command::key::{self, Key};
use crate::command::login::{self, Login};
use crate::command::push::{self, Push};
use crate::command::r#use::{self, Use};
@@ -30,6 +31,7 @@ pub enum Command {
Push(Push),
Cache(Cache),
WatchStore(WatchStore),
+ Key(Key),
#[clap(hide = true)]
GetClosure(GetClosure),
@@ -57,6 +59,7 @@ pub async fn run() -> Result<()> {
Command::Cache(_) => cache::run(opts).await,
Command::WatchStore(_) => watch_store::run(opts).await,
Command::GetClosure(_) => get_closure::run(opts).await,
+ Command::Key(_) => key::run(opts).await,
}
}
diff --git a/client/src/command/cache.rs b/client/src/command/cache.rs
index af01378..af24d8c 100644
--- a/client/src/command/cache.rs
+++ b/client/src/command/cache.rs
@@ -7,8 +7,11 @@ use crate::api::ApiClient;
use crate::cache::CacheRef;
use crate::cli::Opts;
use crate::config::Config;
-use attic::api::v1::cache_config::{
- CacheConfig, CreateCacheRequest, KeypairConfig, RetentionPeriodConfig,
+use attic::{
+ api::v1::cache_config::{
+ CacheConfig, CreateCacheRequest, KeypairConfig, RetentionPeriodConfig,
+ },
+ signing::NixKeypair,
};
/// Manage caches on an Attic server.
@@ -72,6 +75,12 @@ struct Create {
default_value = "cache.nixos.org-1"
)]
upstream_cache_key_names: Vec<String>,
+
+ /// The signing keypair to use for the cache.
+ ///
+ /// If not specified, a new keypair will be generated.
+ #[clap(long)]
+ keypair_path: Option<String>,
}
/// Configure a cache.
@@ -91,6 +100,14 @@ struct Configure {
#[clap(long)]
regenerate_keypair: bool,
+ /// Set a keypair for the cache.
+ ///
+ /// The server-side signing key will be set to the
+ /// specified keypair. This is useful for setting up
+ /// a cache with a pre-existing keypair.
+ #[clap(long, conflicts_with = "regenerate_keypair")]
+ keypair_path: Option<String>,
+
/// Make the cache public.
///
/// Use `--private` to make it private.
@@ -179,9 +196,15 @@ async fn create_cache(sub: Create) -> Result<()> {
let (server_name, server, cache) = config.resolve_cache(&sub.cache)?;
let api = ApiClient::from_server_config(server.clone())?;
+ let keypair = if let Some(keypair_path) = &sub.keypair_path {
+ let contents = std::fs::read_to_string(keypair_path)?;
+ KeypairConfig::Keypair(NixKeypair::from_str(&contents)?)
+ } else {
+ KeypairConfig::Generate
+ };
+
let request = CreateCacheRequest {
- // TODO: Make this configurable?
- keypair: KeypairConfig::Generate,
+ keypair,
is_public: sub.public,
priority: sub.priority,
store_dir: sub.store_dir,
@@ -230,6 +253,10 @@ async fn configure_cache(sub: Configure) -> Result<()> {
if sub.regenerate_keypair {
patch.keypair = Some(KeypairConfig::Generate);
+ } else if let Some(keypair_path) = &sub.keypair_path {
+ let contents = std::fs::read_to_string(keypair_path)?;
+ let keypair = KeypairConfig::Keypair(NixKeypair::from_str(&contents)?);
+ patch.keypair = Some(keypair);
}
patch.store_dir = sub.store_dir;
diff --git a/client/src/command/key.rs b/client/src/command/key.rs
new file mode 100644
index 0000000..807d8a7
--- /dev/null
+++ b/client/src/command/key.rs
@@ -0,0 +1,42 @@
+use anyhow::Result;
+use clap::{Parser, Subcommand};
+
+use crate::cli::Opts;
+use attic::signing::NixKeypair;
+
+/// Manage signing keys.
+#[derive(Debug, Parser)]
+pub struct Key {
+ #[clap(subcommand)]
+ command: KeyCommand,
+}
+
+#[derive(Debug, Subcommand)]
+enum KeyCommand {
+ Generate(Generate),
+}
+
+/// Generate a key.
+#[derive(Debug, Clone, Parser)]
+pub struct Generate {
+ /// Name of the key (must not contain colons).
+ name: String,
+}
+
+pub async fn run(opts: Opts) -> Result<()> {
+ let sub = opts.command.as_key().unwrap();
+ match &sub.command {
+ KeyCommand::Generate(sub) => generate_key(sub).await,
+ }
+}
+
+async fn generate_key(sub: &Generate) -> Result<()> {
+ let keypair = NixKeypair::generate(&sub.name)?;
+
+ println!("🔑 Generated keypair \"{}\"", sub.name);
+ println!();
+ println!(" Private key: {}", keypair.export_keypair());
+ println!(" Public key: {}", keypair.export_public_key());
+
+ Ok(())
+}
diff --git a/client/src/command/mod.rs b/client/src/command/mod.rs
index cca423f..26b105a 100644
--- a/client/src/command/mod.rs
+++ b/client/src/command/mod.rs
@@ -1,5 +1,6 @@
pub mod cache;
pub mod get_closure;
+pub mod key;
pub mod login;
pub mod push;
pub mod r#use;

View File

@@ -1,5 +1,11 @@
final: prev:
# FIXME: https://github.com/zhaofengli/attic/pull/280
prev.attic-client.overrideAttrs (oldAttrs: {
patches = oldAttrs.patches or [ ] ++ [ ./stdout-logging.patch ];
patches = oldAttrs.patches or [ ] ++ [
# fix: log non-errors to stdout
(builtins.fetchurl {
url = "https://github.com/zhaofengli/attic/pull/280.patch";
sha256 = "sha256:0j6ay6d9is7053sq5njakjmlpwk24db296rma694jggpl19ibxjv";
})
./declarative-key-pair.patch
];
})

View File

@@ -1,321 +0,0 @@
diff --git a/client/src/command/cache.rs b/client/src/command/cache.rs
index af01378..0602b3b 100644
--- a/client/src/command/cache.rs
+++ b/client/src/command/cache.rs
@@ -189,7 +189,7 @@ async fn create_cache(sub: Create) -> Result<()> {
};
api.create_cache(cache, request).await?;
- eprintln!(
+ println!(
"✨ Created cache \"{}\" on \"{}\"",
cache.as_str(),
server_name.as_str()
@@ -239,7 +239,7 @@ async fn configure_cache(sub: Configure) -> Result<()> {
let api = ApiClient::from_server_config(server.clone())?;
api.configure_cache(cache, &patch).await?;
- eprintln!(
+ println!(
"✅ Configured \"{}\" on \"{}\"",
cache.as_str(),
server_name.as_str()
@@ -254,12 +254,12 @@ async fn destroy_cache(sub: Destroy) -> Result<()> {
let (server_name, server, cache) = config.resolve_cache(&sub.cache)?;
if !sub.no_confirm {
- eprintln!("When you destory a cache:");
- eprintln!();
- eprintln!("1. Everyone will lose access.");
- eprintln!("2. The underlying data won't be deleted immediately.");
- eprintln!("3. You may not be able to create a cache of the same name.");
- eprintln!();
+ println!("When you destory a cache:");
+ println!();
+ println!("1. Everyone will lose access.");
+ println!("2. The underlying data won't be deleted immediately.");
+ println!("3. You may not be able to create a cache of the same name.");
+ println!();
let answer: String = Input::new()
.with_prompt(format!(
@@ -278,7 +278,7 @@ async fn destroy_cache(sub: Destroy) -> Result<()> {
let api = ApiClient::from_server_config(server.clone())?;
api.destroy_cache(cache).await?;
- eprintln!("🗑️ The cache was destroyed.");
+ println!("🗑️ The cache was destroyed.");
Ok(())
}
@@ -291,40 +291,40 @@ async fn show_cache_config(sub: Info) -> Result<()> {
let cache_config = api.get_cache_config(cache).await?;
if let Some(is_public) = cache_config.is_public {
- eprintln!(" Public: {}", is_public);
+ println!(" Public: {}", is_public);
}
if let Some(public_key) = cache_config.public_key {
- eprintln!(" Public Key: {}", public_key);
+ println!(" Public Key: {}", public_key);
}
if let Some(substituter_endpoint) = cache_config.substituter_endpoint {
- eprintln!("Binary Cache Endpoint: {}", substituter_endpoint);
+ println!("Binary Cache Endpoint: {}", substituter_endpoint);
}
if let Some(api_endpoint) = cache_config.api_endpoint {
- eprintln!(" API Endpoint: {}", api_endpoint);
+ println!(" API Endpoint: {}", api_endpoint);
}
if let Some(store_dir) = cache_config.store_dir {
- eprintln!(" Store Directory: {}", store_dir);
+ println!(" Store Directory: {}", store_dir);
}
if let Some(priority) = cache_config.priority {
- eprintln!(" Priority: {}", priority);
+ println!(" Priority: {}", priority);
}
if let Some(upstream_cache_key_names) = cache_config.upstream_cache_key_names {
- eprintln!(" Upstream Cache Keys: {:?}", upstream_cache_key_names);
+ println!(" Upstream Cache Keys: {:?}", upstream_cache_key_names);
}
if let Some(retention_period) = cache_config.retention_period {
match retention_period {
RetentionPeriodConfig::Period(period) => {
- eprintln!(" Retention Period: {:?}", period);
+ println!(" Retention Period: {:?}", period);
}
RetentionPeriodConfig::Global => {
- eprintln!(" Retention Period: Global Default");
+ println!(" Retention Period: Global Default");
}
}
}
diff --git a/client/src/command/login.rs b/client/src/command/login.rs
index 9abcea7..6cadd59 100644
--- a/client/src/command/login.rs
+++ b/client/src/command/login.rs
@@ -28,7 +28,7 @@ pub async fn run(opts: Opts) -> Result<()> {
let mut config_m = config.as_mut();
if let Some(server) = config_m.servers.get_mut(&sub.name) {
- eprintln!("✍️ Overwriting server \"{}\"", sub.name.as_str());
+ println!("✍️ Overwriting server \"{}\"", sub.name.as_str());
server.endpoint = sub.endpoint.to_owned();
@@ -38,7 +38,7 @@ pub async fn run(opts: Opts) -> Result<()> {
});
}
} else {
- eprintln!("✍️ Configuring server \"{}\"", sub.name.as_str());
+ println!("✍️ Configuring server \"{}\"", sub.name.as_str());
config_m.servers.insert(
sub.name.to_owned(),
diff --git a/client/src/command/push.rs b/client/src/command/push.rs
index b2bb661..5d39549 100644
--- a/client/src/command/push.rs
+++ b/client/src/command/push.rs
@@ -91,7 +91,7 @@ impl PushContext {
return Ok(());
} else {
- eprintln!("⚙️ Pushing {num_missing_paths} paths to \"{cache}\" on \"{server}\" ({num_already_cached} already cached, {num_upstream} in upstream)...",
+ println!("⚙️ Pushing {num_missing_paths} paths to \"{cache}\" on \"{server}\" ({num_already_cached} already cached, {num_upstream} in upstream)...",
cache = self.cache_name.as_str(),
server = self.server_name.as_str(),
num_missing_paths = plan.store_path_map.len(),
diff --git a/client/src/command/use.rs b/client/src/command/use.rs
index 37d8cd6..d87f65e 100644
--- a/client/src/command/use.rs
+++ b/client/src/command/use.rs
@@ -34,15 +34,15 @@ pub async fn run(opts: Opts) -> Result<()> {
let public_key = cache_config.public_key
.ok_or_else(|| anyhow!("The server did not tell us which public key it uses. Is signing managed by the client?"))?;
- eprintln!(
+ println!(
"Configuring Nix to use \"{cache}\" on \"{server_name}\":",
cache = cache.as_str(),
server_name = server_name.as_str(),
);
// Modify nix.conf
- eprintln!("+ Substituter: {}", substituter);
- eprintln!("+ Trusted Public Key: {}", public_key);
+ println!("+ Substituter: {}", substituter);
+ println!("+ Trusted Public Key: {}", public_key);
let mut nix_config = NixConfig::load().await?;
nix_config.add_substituter(&substituter);
@@ -50,7 +50,7 @@ pub async fn run(opts: Opts) -> Result<()> {
// Modify netrc
if let Some(token) = server.token()? {
- eprintln!("+ Access Token");
+ println!("+ Access Token");
let mut nix_netrc = NixNetrc::load().await?;
let host = Url::parse(&substituter)?
diff --git a/client/src/command/watch_store.rs b/client/src/command/watch_store.rs
index 24eaf7a..aec0c33 100644
--- a/client/src/command/watch_store.rs
+++ b/client/src/command/watch_store.rs
@@ -91,7 +91,7 @@ pub async fn run(opts: Opts) -> Result<()> {
watcher.watch(&store_dir, RecursiveMode::NonRecursive)?;
- eprintln!(
+ println!(
"👀 Pushing new store paths to \"{cache}\" on \"{server}\"",
cache = cache.as_str(),
server = server_name.as_str(),
diff --git a/client/src/push.rs b/client/src/push.rs
index 309bd4b..2fea414 100644
--- a/client/src/push.rs
+++ b/client/src/push.rs
@@ -595,7 +595,7 @@ pub async fn upload_path(
};
mp.suspend(|| {
- eprintln!(
+ println!(
"✅ {} ({})",
path.as_os_str().to_string_lossy(),
info_string
diff --git a/server/src/database/migration/m20230112_000004_migrate_nar_remote_files_to_chunks.rs b/server/src/database/migration/m20230112_000004_migrate_nar_remote_files_to_chunks.rs
index 42d70a6..6bbe585 100644
--- a/server/src/database/migration/m20230112_000004_migrate_nar_remote_files_to_chunks.rs
+++ b/server/src/database/migration/m20230112_000004_migrate_nar_remote_files_to_chunks.rs
@@ -24,7 +24,7 @@ impl MigrationTrait for Migration {
// When this migration is run, we assume that there are no
// preexisting chunks.
- eprintln!("* Migrating NARs to chunks...");
+ println!("* Migrating NARs to chunks...");
// Add a temporary column into `chunk` to store the related `nar_id`.
manager
diff --git a/server/src/database/migration/m20230112_000005_drop_old_nar_columns.rs b/server/src/database/migration/m20230112_000005_drop_old_nar_columns.rs
index 9d29b66..7436b4a 100644
--- a/server/src/database/migration/m20230112_000005_drop_old_nar_columns.rs
+++ b/server/src/database/migration/m20230112_000005_drop_old_nar_columns.rs
@@ -16,7 +16,7 @@ impl MigrationName for Migration {
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
- eprintln!("* Migrating NAR schema...");
+ println!("* Migrating NAR schema...");
if manager.get_database_backend() == DatabaseBackend::Sqlite {
// Just copy all data to a new table
diff --git a/server/src/lib.rs b/server/src/lib.rs
index 0314e69..89644e1 100644
--- a/server/src/lib.rs
+++ b/server/src/lib.rs
@@ -217,7 +217,7 @@ async fn fallback(_: Uri) -> ServerResult<()> {
/// Runs the API server.
pub async fn run_api_server(cli_listen: Option<SocketAddr>, config: Config) -> Result<()> {
- eprintln!("Starting API server...");
+ println!("Starting API server...");
let state = StateInner::new(config).await;
@@ -239,7 +239,7 @@ pub async fn run_api_server(cli_listen: Option<SocketAddr>, config: Config) -> R
.layer(TraceLayer::new_for_http())
.layer(CatchPanicLayer::new());
- eprintln!("Listening on {:?}...", listen);
+ println!("Listening on {:?}...", listen);
let listener = TcpListener::bind(&listen).await?;
@@ -256,7 +256,7 @@ pub async fn run_api_server(cli_listen: Option<SocketAddr>, config: Config) -> R
/// Runs database migrations.
pub async fn run_migrations(config: Config) -> Result<()> {
- eprintln!("Running migrations...");
+ println!("Running migrations...");
let state = StateInner::new(config).await;
let db = state.database().await?;
diff --git a/server/src/main.rs b/server/src/main.rs
index c5f08df..3a37c23 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -121,14 +121,14 @@ fn init_logging(tokio_console: bool) {
.init();
if tokio_console {
- eprintln!("Note: tokio-console is enabled");
+ println!("Note: tokio-console is enabled");
}
}
fn dump_version() {
#[cfg(debug_assertions)]
- eprintln!("Attic Server {} (debug)", env!("CARGO_PKG_VERSION"));
+ println!("Attic Server {} (debug)", env!("CARGO_PKG_VERSION"));
#[cfg(not(debug_assertions))]
- eprintln!("Attic Server {} (release)", env!("CARGO_PKG_VERSION"));
+ println!("Attic Server {} (release)", env!("CARGO_PKG_VERSION"));
}
diff --git a/server/src/oobe.rs b/server/src/oobe.rs
index d3d912d..98ef88c 100644
--- a/server/src/oobe.rs
+++ b/server/src/oobe.rs
@@ -77,25 +77,25 @@ pub async fn run_oobe() -> Result<()> {
token.encode(&SignatureType::RS256(key), &None, &None)?
};
- eprintln!();
- eprintln!("-----------------");
- eprintln!("Welcome to Attic!");
- eprintln!();
- eprintln!("A simple setup using SQLite and local storage has been configured for you in:");
- eprintln!();
- eprintln!(" {}", config_path.to_str().unwrap());
- eprintln!();
- eprintln!("Run the following command to log into this server:");
- eprintln!();
- eprintln!(" attic login local http://localhost:8080 {root_token}");
- eprintln!();
- eprintln!("Documentations and guides:");
- eprintln!();
- eprintln!(" https://docs.attic.rs");
- eprintln!();
- eprintln!("Enjoy!");
- eprintln!("-----------------");
- eprintln!();
+ println!();
+ println!("-----------------");
+ println!("Welcome to Attic!");
+ println!();
+ println!("A simple setup using SQLite and local storage has been configured for you in:");
+ println!();
+ println!(" {}", config_path.to_str().unwrap());
+ println!();
+ println!("Run the following command to log into this server:");
+ println!();
+ println!(" attic login local http://localhost:8080 {root_token}");
+ println!();
+ println!("Documentations and guides:");
+ println!();
+ println!(" https://docs.attic.rs");
+ println!();
+ println!("Enjoy!");
+ println!("-----------------");
+ println!();
Ok(())
}

View File

@@ -20,6 +20,7 @@ final: prev:
flaresolverr = final.docker-image-flaresolverr;
gitea = final.docker-image-gitea;
gitea-act-runner = final.docker-image-gitea-act-runner;
gitea-act-runner-worker = final.docker-image-gitea-act-runner-worker;
grafana = final.docker-image-grafana;
grafana-image-renderer = final.docker-image-grafana-image-renderer;
jellyfin = final.docker-image-jellyfin;

View File

@@ -1,10 +1,15 @@
final: prev:
prev.tea.overrideAttrs (oldAttrs: {
patches = oldAttrs.patches or [ ] ++ [
# feat: add user auth via env
(builtins.fetchurl {
url = "https://gitea.com/gitea/tea/pulls/639.patch";
sha256 = "sha256:0c5gpi6aajd3h0wp7lrvj5qk9wsqhgbap7ijvl0x117v0g8mgzvs";
})
./instance-ssh-host-env.patch
# fix: evaluate env login in repo context
(builtins.fetchurl {
url = "https://gitea.com/gitea/tea/pulls/809.patch";
sha256 = "sha256:1mmsnzabcdy5lihs51kbx8r1vcr51rfj9a8gl5894jm7qvng7c5d";
})
];
})

View File

@@ -1,174 +0,0 @@
diff --git a/modules/config/login.go b/modules/config/login.go
index 3b77fb9..94de9cd 100644
--- a/modules/config/login.go
+++ b/modules/config/login.go
@@ -13,6 +13,7 @@ import (
"net/http/cookiejar"
"net/url"
"os"
+ "strconv"
"strings"
"time"
@@ -200,6 +201,63 @@ func UpdateLogin(login *Login) error {
return saveConfig()
}
+// CreateLoginFromEnvVars returns a login based on environment variables, or nil if no login can be created
+func CreateLoginFromEnvVars() (*Login, error) {
+ var token string
+
+ giteaToken := os.Getenv("GITEA_TOKEN")
+ githubToken := os.Getenv("GH_TOKEN")
+ giteaInstanceURL := os.Getenv("GITEA_INSTANCE_URL")
+ instanceInsecure := os.Getenv("GITEA_INSTANCE_INSECURE")
+ giteaInstanceSSHHost := os.Getenv("GITEA_INSTANCE_SSH_HOST")
+ insecure := false
+ if len(instanceInsecure) > 0 {
+ insecure, _ = strconv.ParseBool(instanceInsecure)
+ }
+
+ // if no tokens are set, or no instance url for gitea fail fast
+ if len(giteaInstanceURL) == 0 || (len(giteaToken) == 0 && len(githubToken) == 0) {
+ return nil, nil
+ }
+
+ token = giteaToken
+ if len(giteaToken) == 0 {
+ token = githubToken
+ }
+
+ login := &Login{
+ Name: "GITEA_LOGIN_VIA_ENV",
+ URL: giteaInstanceURL,
+ Token: token,
+ SSHHost: giteaInstanceSSHHost,
+ Insecure: insecure,
+ SSHKey: "",
+ SSHCertPrincipal: "",
+ SSHKeyFingerprint: "",
+ SSHAgent: false,
+ VersionCheck: true,
+ Created: time.Now().Unix(),
+ }
+
+ client := login.Client()
+ u, _, err := client.GetMyUserInfo()
+ if err != nil {
+ return nil, fmt.Errorf("failed to validate token: %s", err)
+ }
+
+ login.User = u.UserName
+
+ if login.SSHHost == "" {
+ parsedURL, err := url.Parse(giteaInstanceURL)
+ if err != nil {
+ return nil, err
+ }
+ login.SSHHost = parsedURL.Host
+ }
+
+ return login, nil
+}
+
// Client returns a client to operate Gitea API. You may provide additional modifiers
// for the client like gitea.SetBasicAuth() for customization
func (l *Login) Client(options ...gitea.ClientOption) *gitea.Client {
diff --git a/modules/context/context.go b/modules/context/context.go
index aec5592..636eeec 100644
--- a/modules/context/context.go
+++ b/modules/context/context.go
@@ -9,9 +9,7 @@ import (
"log"
"os"
"path"
- "strconv"
"strings"
- "time"
"code.gitea.io/tea/modules/config"
"code.gitea.io/tea/modules/git"
@@ -108,16 +106,6 @@ func InitCommand(cmd *cli.Command) *TeaContext {
c.RepoSlug = repoFlag
}
- // override config user with env variable
- envLogin := GetLoginByEnvVar()
- if envLogin != nil {
- _, err := utils.ValidateAuthenticationMethod(envLogin.URL, envLogin.Token, "", "", false, "", "")
- if err != nil {
- log.Fatal(err.Error())
- }
- c.Login = envLogin
- }
-
// override login from flag, or use default login if repo based detection failed
if len(loginFlag) != 0 {
c.Login = config.GetLoginByName(loginFlag)
@@ -196,10 +184,25 @@ func contextFromLocalRepo(repoPath, remoteValue string) (*git.TeaRepo, *config.L
return repo, nil, "", fmt.Errorf("Remote '%s' not found in this Git repository", remoteValue)
}
+ envLogin, err := config.CreateLoginFromEnvVars()
+ if err != nil {
+ log.Fatal(err.Error())
+ }
+
logins, err := config.GetLogins()
if err != nil {
return repo, nil, "", err
}
+
+ if envLogin != nil {
+ _, err := utils.ValidateAuthenticationMethod(envLogin.URL, envLogin.Token, "", "", false, "", "")
+ if err != nil {
+ log.Fatal(err.Error())
+ }
+
+ logins = append([]config.Login{*envLogin}, logins...)
+ }
+
for _, l := range logins {
sshHost := l.GetSSHHost()
for _, u := range remoteConfig.URLs {
@@ -223,40 +226,3 @@ func contextFromLocalRepo(repoPath, remoteValue string) (*git.TeaRepo, *config.L
return repo, nil, "", errNotAGiteaRepo
}
-
-// GetLoginByEnvVar returns a login based on environment variables, or nil if no login can be created
-func GetLoginByEnvVar() *config.Login {
- var token string
-
- giteaToken := os.Getenv("GITEA_TOKEN")
- githubToken := os.Getenv("GH_TOKEN")
- giteaInstanceURL := os.Getenv("GITEA_INSTANCE_URL")
- instanceInsecure := os.Getenv("GITEA_INSTANCE_INSECURE")
- insecure := false
- if len(instanceInsecure) > 0 {
- insecure, _ = strconv.ParseBool(instanceInsecure)
- }
-
- // if no tokens are set, or no instance url for gitea fail fast
- if len(giteaInstanceURL) == 0 || (len(giteaToken) == 0 && len(githubToken) == 0) {
- return nil
- }
-
- token = giteaToken
- if len(giteaToken) == 0 {
- token = githubToken
- }
-
- return &config.Login{
- Name: "GITEA_LOGIN_VIA_ENV",
- URL: giteaInstanceURL,
- Token: token,
- Insecure: insecure,
- SSHKey: "",
- SSHCertPrincipal: "",
- SSHKeyFingerprint: "",
- SSHAgent: false,
- Created: time.Now().Unix(),
- VersionCheck: false,
- }
-}

View File

@@ -1,23 +1,27 @@
{ pkgs, ... }:
# AUTO-UPDATE: nix-update --flake comentario --version=branch=dev --subpackage frontend
pkgs.buildGoModule (finalAttrs: {
pkgs.buildGo125Module (finalAttrs: {
pname = "comentario";
version = "3.14.0-unstable-2025-08-29";
version = "3.14.0-unstable-2025-09-15";
src = pkgs.fetchFromGitLab {
owner = "comentario";
repo = "comentario";
# FIXME: Stable rev once type error is fixed
rev = "90773f976366318389f9d5aa457e6303e6159740";
hash = "sha256-f0Y+OdbsG8eA2kD17b4QWaL0hAuoF476XtYm/aFOmLY=";
rev = "d79035b41a912a432b74eb7fb0240b79cabff6bf";
hash = "sha256-nTOojxYBDeA5Z+rh+C+SbFJ4fzmr8sT2oZmO+chiXJM=";
};
patches = [
# FIXME: https://gitlab.com/comentario/comentario/-/merge_requests/23
./dynamic-config-env-vars.patch
# fe: dynamic configuration env vars
(builtins.fetchurl {
url = "https://gitlab.com/comentario/comentario/-/merge_requests/23.patch";
sha256 = "sha256:0ih5hwadjkh47vvji4jygpfxcfpjcarhcwazc7asxpfxc87g04pv";
})
./superuser-claim.patch
];
vendorHash = "sha256-IYo1Z7BVTGafsN4gC554S33r7X9Urb1uS4RkOqMYlP0=";
vendorHash = "sha256-AOI/WnVkrSgJlT2FtYOTuifOPw8sfc4C0g/prVkvJlA=";
nativeBuildInputs = with pkgs; [
go-swagger
@@ -37,7 +41,7 @@ pkgs.buildGoModule (finalAttrs: {
missingHashes = ./missing-hashes.json;
offlineCache = pkgs.yarn-berry.fetchYarnBerryDeps {
inherit (finalFrontendAttrs) src patches missingHashes;
hash = "sha256-bn/PNgk7ZjCzGSj7BQQCB+5RY+ivJGYZa2/GC4eRjPY=";
hash = "sha256-dYk85+e9C0yHZ9jYgsefStZfyQFZZku+Z4Kn7bN4Qjw=";
};
nativeBuildInputs = with pkgs; [

View File

@@ -1,312 +0,0 @@
From 2ef5994a21d694bdf50d1d9d4c524c9584368917 Mon Sep 17 00:00:00 2001
From: Nikolaos Karaolidis <nick@karaolidis.com>
Date: Mon, 28 Jul 2025 15:33:55 +0100
Subject: [PATCH] fe: dynamic configuration env vars
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
---
.../dynamic/auth.emailupdate.enabled.en.md | 1 +
.../auth.login.local.maxattempts.en.md | 2 ++
.../auth.signup.confirm.commenter.en.md | 2 ++
.../dynamic/auth.signup.confirm.user.en.md | 2 ++
.../backend/dynamic/auth.signup.enabled.en.md | 2 ++
...in.defaults.comments.deletion.author.en.md | 2 ++
...defaults.comments.deletion.moderator.en.md | 2 ++
...ain.defaults.comments.editing.author.en.md | 2 ++
....defaults.comments.editing.moderator.en.md | 2 ++
...omain.defaults.comments.enablevoting.en.md | 2 ++
...domain.defaults.comments.rss.enabled.en.md | 2 ++
...domain.defaults.comments.showdeleted.en.md | 2 ++
...ain.defaults.comments.text.maxlength.en.md | 2 ++
.../domain.defaults.login.showforunauth.en.md | 2 ++
...ain.defaults.markdown.images.enabled.en.md | 2 ++
...main.defaults.markdown.links.enabled.en.md | 2 ++
...ain.defaults.markdown.tables.enabled.en.md | 4 ++-
...main.defaults.signup.enablefederated.en.md | 2 ++
.../domain.defaults.signup.enablelocal.en.md | 2 ++
.../domain.defaults.signup.enablesso.en.md | 2 ++
.../dynamic/integrations.usegravatar.en.md | 1 +
.../dynamic/operation.newowner.enabled.en.md | 2 ++
internal/data/dyn_config.go | 28 +++++++++++++++++--
23 files changed, 69 insertions(+), 3 deletions(-)
diff --git a/docs/content/configuration/backend/dynamic/auth.emailupdate.enabled.en.md b/docs/content/configuration/backend/dynamic/auth.emailupdate.enabled.en.md
index 5b9c5716..a139c953 100644
--- a/docs/content/configuration/backend/dynamic/auth.emailupdate.enabled.en.md
+++ b/docs/content/configuration/backend/dynamic/auth.emailupdate.enabled.en.md
@@ -20,3 +20,4 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter defines w
* If no operational mailer is configured, the email will be updated right away, without intermediate confirmation.
* If set to `Off`, users cannot change their emails themselves. Email can only be updated by a [superuser](/kb/permissions/superuser) (for example, at a user's request).
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_AUTH_EMAILUPDATE_ENABLED`.
diff --git a/docs/content/configuration/backend/dynamic/auth.login.local.maxattempts.en.md b/docs/content/configuration/backend/dynamic/auth.login.local.maxattempts.en.md
index bada14ec..5a3993a8 100644
--- a/docs/content/configuration/backend/dynamic/auth.login.local.maxattempts.en.md
+++ b/docs/content/configuration/backend/dynamic/auth.login.local.maxattempts.en.md
@@ -20,3 +20,5 @@ Comentario keeps a counter of failed login attempts for each user.
* The failed login attempt counter gets reset to zero as soon as the user has successfully logged in.
This mechanism is mostly intended to safeguard users against brute-force attacks on their passwords. In order to disable it, set the value to `0`.
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_AUTH_LOGIN_LOCAL_MAXATTEMPTS`.
diff --git a/docs/content/configuration/backend/dynamic/auth.signup.confirm.commenter.en.md b/docs/content/configuration/backend/dynamic/auth.signup.confirm.commenter.en.md
index 6ad25e5a..fbb38b3b 100644
--- a/docs/content/configuration/backend/dynamic/auth.signup.confirm.commenter.en.md
+++ b/docs/content/configuration/backend/dynamic/auth.signup.confirm.commenter.en.md
@@ -17,3 +17,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter configure
* If set to `Off`, commenters will be logged in immediately upon registration. This is not recommended due to security considerations; it may also render the user account unusable in the future if they misspelled their email address.
This setting applies only to websites embedding Comentario. For the Administration UI there's a [separate configuration item](auth.signup.confirm.user).
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_AUTH_SIGNUP_CONFIRM_COMMENTER`.
diff --git a/docs/content/configuration/backend/dynamic/auth.signup.confirm.user.en.md b/docs/content/configuration/backend/dynamic/auth.signup.confirm.user.en.md
index 6a14a1d3..3aee4ae6 100644
--- a/docs/content/configuration/backend/dynamic/auth.signup.confirm.user.en.md
+++ b/docs/content/configuration/backend/dynamic/auth.signup.confirm.user.en.md
@@ -17,3 +17,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter configure
* If set to `Off`, users can log in immediately upon registration. This is not recommended due to security considerations; it may also render the user account unusable in the future if they misspelled their email address.
This setting applies only to the Administration UI. For websites embedding Comentario there's a [separate configuration item](auth.signup.confirm.commenter).
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_AUTH_SIGNUP_CONFIRM_USER`.
diff --git a/docs/content/configuration/backend/dynamic/auth.signup.enabled.en.md b/docs/content/configuration/backend/dynamic/auth.signup.enabled.en.md
index 35acc2ba..d8a38804 100644
--- a/docs/content/configuration/backend/dynamic/auth.signup.enabled.en.md
+++ b/docs/content/configuration/backend/dynamic/auth.signup.enabled.en.md
@@ -20,3 +20,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter controls
* If set to `Off`, new user registrations are forbidden.
This setting applies only to the Administration UI. It can be useful for (temporarily) preventing new sign-ups.
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_AUTH_SIGNUP_ENABLED`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.comments.deletion.author.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.comments.deletion.author.en.md
index 9fef72b4..93f280cf 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.comments.deletion.author.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.comments.deletion.author.en.md
@@ -18,3 +18,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter can be us
* When set to `On`, comment authors will see a *trashcan* button on their comments, which allows them to delete a written comment.
* If set to `Off`, comments cannot be removed by their authors once submitted (but possibly can [by domain moderators](domain.defaults.comments.deletion.moderator) if enabled).
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_COMMENTS_DELETION_AUTHOR`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.comments.deletion.moderator.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.comments.deletion.moderator.en.md
index 97c3b3e0..f1c002f8 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.comments.deletion.moderator.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.comments.deletion.moderator.en.md
@@ -18,3 +18,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter can be us
* When set to `On`, users with the moderator or owner [role](/kb/permissions/roles) and [superusers](/kb/permissions/superuser) will see a *trashcan* button on every comment, allowing them to delete any comment on the domain's pages.
* If set to `Off`, comments cannot be removed by moderators (but possibly can [by their authors](domain.defaults.comments.deletion.author) if enabled).
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_COMMENTS_DELETION_MODERATOR`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.comments.editing.author.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.comments.editing.author.en.md
index 346a93b6..de989f59 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.comments.editing.author.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.comments.editing.author.en.md
@@ -17,3 +17,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter can be us
* When set to `On`, comment authors will see a *pencil* button on their comments, which allows them to edit a written comment.
* If set to `Off`, comments cannot be changed by their authors once submitted (but possibly can [by domain moderators](domain.defaults.comments.editing.moderator) if enabled).
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_COMMENTS_EDITING_AUTHOR`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.comments.editing.moderator.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.comments.editing.moderator.en.md
index 0b35d1e3..25bfcbf1 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.comments.editing.moderator.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.comments.editing.moderator.en.md
@@ -17,3 +17,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter can be us
* When set to `On`, users with the moderator or owner [role](/kb/permissions/roles) and [superusers](/kb/permissions/superuser) will see a *pencil* button on every comment, allowing them to edit any comment on the domain's pages.
* If set to `Off`, comments cannot be changed by moderators (but possibly can [by their authors](domain.defaults.comments.editing.author) if enabled).
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_COMMENTS_EDITING_MODERATOR`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.comments.enablevoting.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.comments.enablevoting.en.md
index a2e72f5b..17ec769e 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.comments.enablevoting.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.comments.enablevoting.en.md
@@ -13,3 +13,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter can be us
* When set to `On`, every comment card will contain a score and a set of upvote/downvote buttons. Also, any commenter will be able to upvote or downvote others' comments (bot not those they authored self).
* If set to `Off`, the score and the voting buttons will be hidden. It will also disable sorting comments by votes.
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_COMMENTS_ENABLEVOTING`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.comments.rss.enabled.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.comments.rss.enabled.en.md
index 3981741e..4108ed90 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.comments.rss.enabled.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.comments.rss.enabled.en.md
@@ -21,3 +21,5 @@ When RSS is enabled, the users will be able to subscribe to comment feeds using:
* `RSS` dropdown button under the [comment editor](/kb/comment-editor) (left of the sorting buttons).
* `Comment RSS feed` links in Domain properties and Domain page properties.
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_COMMENTS_RSS_ENABLED`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.comments.showdeleted.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.comments.showdeleted.en.md
index 89b26859..f2293dba 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.comments.showdeleted.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.comments.showdeleted.en.md
@@ -18,3 +18,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter controls
* If set to `Off`, deleted comments will be hidden in the comment tree immediately, as well as all its child comments.
This setting doesn't affect comment display in the Administration UI (it has a separate switch for hiding deleted comments).
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_COMMENTS_SHOWDELETED`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.comments.text.maxlength.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.comments.text.maxlength.en.md
index a87b2fff..9e068c5a 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.comments.text.maxlength.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.comments.text.maxlength.en.md
@@ -21,3 +21,5 @@ It defines how long comment texts can be on a specific domain, representing the
* The lowest possible value for this setting is the "Twitter limit" of `140` characters.
* The top (physical) limit is `1048576` (1 MiB).
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_COMMENTS_TEXT_MAXLENGTH`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.login.showforunauth.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.login.showforunauth.en.md
index 85b264e6..65a29ea4 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.login.showforunauth.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.login.showforunauth.en.md
@@ -19,3 +19,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter allows to
* If set to `Off`, the login dialog will be skipped if [commenting without registration](/configuration/frontend/domain/authentication) is enabled for this domain. Otherwise the dialog will be shown and user will be requested to log in or sign up.
When this setting is `Off`, the user can still authenticate explicitly using the `Sign in` button above the comment editor.
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_LOGIN_SHOWFORUNAUTH`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.markdown.images.enabled.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.markdown.images.enabled.en.md
index f229294c..6af7d884 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.markdown.images.enabled.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.markdown.images.enabled.en.md
@@ -18,3 +18,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter configure
* If set to `Off`, commenters won't be able to insert images, and the corresponding markup will be removed from the resulting text.
This setting only applies to newly written comments and does not affect images in existing comments.
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_MARKDOWN_IMAGES_ENABLED`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.markdown.links.enabled.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.markdown.links.enabled.en.md
index cfaaddcb..bb171b1e 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.markdown.links.enabled.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.markdown.links.enabled.en.md
@@ -18,3 +18,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter configure
* If set to `Off`, commenters won't be able to insert links, and the corresponding string will be rendered as plain, non-clickable text.
This setting only applies to newly written comments and does not affect links in existing comments.
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_MARKDOWN_LINKS_ENABLED`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.markdown.tables.enabled.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.markdown.tables.enabled.en.md
index 243affed..f38c097e 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.markdown.tables.enabled.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.markdown.tables.enabled.en.md
@@ -16,5 +16,7 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter configure
* If set to `On`, commenters can insert [tables](/kb/markdown#tables) in comments.
* If set to `Off`, commenters won't be able to insert tables, and the corresponding markup will be removed from the resulting text.
-
+
This setting only applies to newly written comments and does not affect tables in existing comments.
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_MARKDOWN_TABLES_ENABLED`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.signup.enablefederated.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.signup.enablefederated.en.md
index 7a5d92a9..c6015fdb 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.signup.enablefederated.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.signup.enablefederated.en.md
@@ -21,3 +21,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter controls
This setting doesn't apply to the Administration UI, which uses a [separate configuration item](auth.signup.enabled) for that.
It also doesn't affect *existing users*, i.e. those already registered. They will be able to log in even when this setting is disabled. To disable federated login completely, switch off undesirable providers in the domain's [authentication settings](/configuration/frontend/domain/authentication).
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_SIGNUP_ENABLEFEDERATED`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.signup.enablelocal.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.signup.enablelocal.en.md
index 874d6dc4..f2dff20e 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.signup.enablelocal.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.signup.enablelocal.en.md
@@ -23,3 +23,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter controls
This setting doesn't apply to the Administration UI, which uses a [separate configuration item](auth.signup.enabled) for that.
It also doesn't affect *existing users*. They will be able to log in even when this setting is disabled. To disable login with email/password completely, switch it off in the domain's [authentication settings](/configuration/frontend/domain/authentication).
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_SIGNUP_ENABLELOCAL`.
diff --git a/docs/content/configuration/backend/dynamic/domain.defaults.signup.enablesso.en.md b/docs/content/configuration/backend/dynamic/domain.defaults.signup.enablesso.en.md
index 6da28064..86bc6826 100644
--- a/docs/content/configuration/backend/dynamic/domain.defaults.signup.enablesso.en.md
+++ b/docs/content/configuration/backend/dynamic/domain.defaults.signup.enablesso.en.md
@@ -22,3 +22,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter controls
* If set to `Off`, SSO registration on websites embedding comments will be forbidden.
This setting doesn't affect *SSO users who are already registered*. They will be able to log in even when this setting is disabled. To disable SSO login completely, switch it off in the domain's [authentication settings](/configuration/frontend/domain/authentication).
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_DOMAIN_DEFAULTS_SIGNUP_ENABLESSO`.
diff --git a/docs/content/configuration/backend/dynamic/integrations.usegravatar.en.md b/docs/content/configuration/backend/dynamic/integrations.usegravatar.en.md
index 8509944d..b81d1766 100644
--- a/docs/content/configuration/backend/dynamic/integrations.usegravatar.en.md
+++ b/docs/content/configuration/backend/dynamic/integrations.usegravatar.en.md
@@ -16,3 +16,4 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter configure
It also enables the use of Gravatar during import (e.g. from [Commento](/installation/migration/commento) or [WordPress](/installation/migration/wordpress)).
* If set to `Off`, Gravatar won't be contacted.
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_INTEGRATIONS_USEGRAVATAR`.
diff --git a/docs/content/configuration/backend/dynamic/operation.newowner.enabled.en.md b/docs/content/configuration/backend/dynamic/operation.newowner.enabled.en.md
index a3025d96..d2a27b15 100644
--- a/docs/content/configuration/backend/dynamic/operation.newowner.enabled.en.md
+++ b/docs/content/configuration/backend/dynamic/operation.newowner.enabled.en.md
@@ -15,3 +15,5 @@ This [dynamic configuration](/configuration/backend/dynamic) parameter configure
* If set to `Off`, users without domains (for example, commenters) won't be able to register their own domains in Comentario, and thus become domain owners. Most likely, this is what you want, therefore `Off` is the default.
This setting doesn't affect users who already own at least one domain.
+
+This default value of this setting can be overridden at startup using the environment variable `DYN_DEFAULT_OPERATION_NEWOWNER_ENABLED`.
diff --git a/internal/data/dyn_config.go b/internal/data/dyn_config.go
index 8595ea2a..ad5b9894 100644
--- a/internal/data/dyn_config.go
+++ b/internal/data/dyn_config.go
@@ -2,14 +2,21 @@ package data
import (
"fmt"
+ "os"
+ "strconv"
+ "strings"
+ "time"
+
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/google/uuid"
+ "github.com/op/go-logging"
"gitlab.com/comentario/comentario/internal/api/models"
- "strconv"
- "time"
)
+// logger represents a package-wide logger instance
+var logger = logging.MustGetLogger("data")
+
// DynConfigItemSectionKey is a key of dynamic configuration item section
type DynConfigItemSectionKey string
@@ -196,6 +203,11 @@ const (
// ConfigKeyDomainDefaultsPrefix is a prefix given to domain setting keys that turn them into global domain defaults keys
const ConfigKeyDomainDefaultsPrefix = "domain.defaults."
+func getInitialDynConfigItemEnvVar(key DynConfigItemKey) (string, bool) {
+ name := "DYN_DEFAULT_" + strings.ToUpper(strings.ReplaceAll(string(key), ".", "_"))
+ return os.LookupEnv(name)
+}
+
// DefaultDynInstanceConfig is the default dynamic instance configuration
var DefaultDynInstanceConfig = DynConfigMap{
ConfigKeyAuthEmailUpdateEnabled: {DefaultValue: "false", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionAuth},
@@ -221,3 +233,15 @@ var DefaultDynInstanceConfig = DynConfigMap{
ConfigKeyDomainDefaultsPrefix + DomainConfigKeyFederatedSignupEnabled: {DefaultValue: "true", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionAuth},
ConfigKeyDomainDefaultsPrefix + DomainConfigKeySsoSignupEnabled: {DefaultValue: "true", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionAuth},
}
+
+func init() {
+ for key, item := range DefaultDynInstanceConfig {
+ value, override := getInitialDynConfigItemEnvVar(key)
+ if override {
+ if err := item.ValidateValue(value); err != nil {
+ logger.Fatalf("bad override for %q: %v", key, err)
+ }
+ item.DefaultValue = value
+ }
+ }
+}
--
GitLab

View File

@@ -1,84 +1,86 @@
{
"@esbuild/aix-ppc64@npm:0.25.5": "fb872b34a2843293dc60e809968fedf93e0d8f7174b062decffae6ba861eb56aaea0cd0aba87ba99162ceb2a690f0cde4fc29c000b52c035e40c91ec7861d43e",
"@esbuild/aix-ppc64@npm:0.25.8": "37fc14b17214c1f6bf41175029b62a43664a6a5a5b802614fe1d837bbf7abf5eaf2f6b735b6a446ebcfabb632e038c8ad9cccd87a259c45a1846689f8527874a",
"@esbuild/android-arm64@npm:0.25.5": "c818e799b19b5587466bf68a27b578ccaaf866c1d144573fbde7659e3fd3f555422ec3e67f5bd186a87648957d1b6e74df4f847edea7219c16979c9916f36e91",
"@esbuild/aix-ppc64@npm:0.25.9": "b5c49f119424bb3f7be30b652ef87bf881824ace02cc2327ba6f7e0f86d04d2afe2087086985f4220dfdbb816acb67e6dfcf00da9eb8b028babfac43df3adac8",
"@esbuild/android-arm64@npm:0.25.8": "e367e989238292ccee72013511dde1aef2d2160d8d5d669a12272f693cf9a0970fac9d7835178b3c46ed6936a0c4b29d21d58ed11851a3697bf98b4320be4b74",
"@esbuild/android-arm@npm:0.25.5": "a5384933f9f2ffcadce2be49da6ff43249fe42f32a04071316434e9f633fc20c8d4029072e9a53555620c3531045786297607b852579eee30b6dbc3bc9d98cd9",
"@esbuild/android-arm64@npm:0.25.9": "afe76da072b16e355f546d1d9023b814ead0487d9fa5e393eeb4bb3f6f76e5542e14b82396ca37c38e868ed64deef6b25f1c47e2564141fe5ecfe0eb7543f3f8",
"@esbuild/android-arm@npm:0.25.8": "cbfa2c802d8931e5f4d06582f20573cb34774ab713b4712c37eb15bfab6f90b693878b661de2a3bb9c81eecf45b37e0ddf2e9c79ef4ff932bbc37da588c40183",
"@esbuild/android-x64@npm:0.25.5": "8ce115dc7e1e6735f23b4aadb2dfca29c0abd8577ce34802ea3d017a64e388928949134fe225dfe190babdc5ec01be5fc7794eca84738cdefc12c5e3789ce43b",
"@esbuild/android-arm@npm:0.25.9": "0d4c724b84043db6597736865a4fe86640c88f21dc0ebe93a2298b4a0e0f0a5d1530a821dd1c18a2b39a6ca9abe8ff714b8ed5de496045a67150ea47c86a39d7",
"@esbuild/android-x64@npm:0.25.8": "1d4b900dd2f43790415745d20ae6cadb53e9412911578aaf43462277169c22800eca1f49a9f8ce9c37236e1691279494f91967d28310720707911910ec765013",
"@esbuild/darwin-arm64@npm:0.25.5": "a009eab62f2bd284a6f2001d5e08217059186ffc16907bbe873e1de40fe9b5ed92c0db2f4c4d0dc41545838850a430c8f2f35d7bdb9cd01a1a04293acd97afca",
"@esbuild/android-x64@npm:0.25.9": "9da8b1ede5670c2c9e644e0fedf1dd0747081272b296d3f80b53b44b637744d836efee00dc767b81940eb285524a5e3149d8045787f6281ee2bd53f61a9c8717",
"@esbuild/darwin-arm64@npm:0.25.8": "a8a50e303056e668e99370a88d1744de4a83e62e2f3f7fcf2ff611142346505229568b0ec5edda93ec96e33e842a585880a312790553202750f123d9636fa97d",
"@esbuild/darwin-x64@npm:0.25.5": "cac8021a7a0c549263e076913346b35a5bb81f76ffbc1abfad5e7b67303f013ac0c76f111bf624ea8447b327ec86c18a60c6ff307d743a2269f5d47313f5b2de",
"@esbuild/darwin-arm64@npm:0.25.9": "84a88a8f72fcc66381518d5821e4ed276aeea17c76559bee4fcb472b19456da630ad84d8d74b3e4c297ef7b1ec5bd5037d55ac6ef5c515a77fb94a1bd891dece",
"@esbuild/darwin-x64@npm:0.25.8": "9806fe9d54f3228a01f535e7c51aea26bd1bab3c5d64d5f77f4606de44f361f049222776d32bfd262d45991b7aecca645ed576ea338edbf4f8044b22b3e331ad",
"@esbuild/freebsd-arm64@npm:0.25.5": "d248e7103b7094eb4288db7c9a78b2905a25b4a957f2b945531ca88d3394f45ceca2343a7c84954734534af6159bc741eb3d5c1ed9df990f7395337a1b14192c",
"@esbuild/darwin-x64@npm:0.25.9": "c500bcd0c1a8f66d19cf575299a7da7f29dbdb56beac95bb6ddc570291e3e9da4e7d31db6453fc19ea5ac7f85662f40c9a3965c3e1f49657efeb292a6f601a26",
"@esbuild/freebsd-arm64@npm:0.25.8": "8e6cbdd45819390ecdb62a70a4f119a9269a90895f3e1237788b36a512248a756233ef59f55f9033658af372a196f0edc3567f078f1387e150238d2bd51f733b",
"@esbuild/freebsd-x64@npm:0.25.5": "8a7be0740f07f5dbb3e24bf782ca6ef518a8ce9b53e5d864221722045713586d41774cbd531df97dc868b291b3b303c12e50ca8611c3cb7b5fe09a30b38285eb",
"@esbuild/freebsd-arm64@npm:0.25.9": "fb4951968ad62e5316ffd08c037bb2396e8119a0c2289e968421bb277bdbffe23d89c92dcd2d7eb680f31be2b05e36406211b141b9b89378b424e4b5193c3d7f",
"@esbuild/freebsd-x64@npm:0.25.8": "3f920c686037f825859a2fe82104085f4b254b77821cc71a71db512ef0679dd01481c136c3f7057ba7250daff2458aa3ffd101cc28cb5fff2d55270ba5930ec8",
"@esbuild/linux-arm64@npm:0.25.5": "ce3c8fca47cf0a92148fb288eb35a5c4a4dcf7a700730b3a48fdd63c13e17c719eb6b350378203fba773477eb5be637f47a6d52c5d4ce5bdc0075ee917156006",
"@esbuild/freebsd-x64@npm:0.25.9": "0c71856891d5cea255f9bcb4482c70347a39198da2769a273afbd16bc9db7176bc1d28c41dd569b8b8f98cfd14b10a728c79f54311037d702bb7dffd95f27740",
"@esbuild/linux-arm64@npm:0.25.8": "234edc9f815cdc74d21c6a90a3542c941deeaf3a24b408c74a4651616bd270383ba5a15eaef837ab347a374032c7028fc29e4f1da0becb33f0b8dd8f744934d7",
"@esbuild/linux-arm@npm:0.25.5": "cc81ea76ab86ed2a837c9da329f7c63412d288dc0aa608c8dcdf51705dc93d5b7f966a429be4896babe611074e5898c7e6c8e07ad7f50123a05478975294fbb4",
"@esbuild/linux-arm64@npm:0.25.9": "6c64bf50dfb709d4000b022558293764a20ff8ba0b6638e8abb3bd0806cab25ac971f1910eaf2a4d73f92080afdb296d57175b2199647de019c2f419365f839d",
"@esbuild/linux-arm@npm:0.25.8": "dc6dc225ae278cb3383e11d9829d22f301e1b79f2ed4efde1a01896ae67e45efde98caa61f10cb425a809e9b61e9a4651b60d2b6a3e9ad6174519e8ce74bc02a",
"@esbuild/linux-ia32@npm:0.25.5": "bfed6750923afd56148f658f6ec8995479f5115116dc212ecb9e4c556064422e22eda855177e7c02cbc945494e4db1167101918c5fa932278115db2c7025a3f6",
"@esbuild/linux-arm@npm:0.25.9": "b9a473988dadbe98f1c6ade2597e5967371d929ac83bb9f888d726d4f0e5cc4b8fe5020332adb26d61748619bf3e62c831d9c80b3bf815a6dd90dab76283d533",
"@esbuild/linux-ia32@npm:0.25.8": "1c780012035552e27adea34d11f959a3ddd4a4d576cddd03d320b1db18110e777c1adca2c6d10affd587a4454900d3ffcad9371956855e56739babdc2e4edcd3",
"@esbuild/linux-loong64@npm:0.25.5": "e5c20140bbbdba53f0d86dd72961ed73e6255d2ada2d3a626f390b352170605644822ad7592f695b6e520edcefe0c5f6ba19d10694b5d11d725745d9792bde01",
"@esbuild/linux-ia32@npm:0.25.9": "51f458a7038e2ee014b994f7f216821194b00716ae5abe78fe828d9cefd47575dc0ff703f95c18017e59b7bcb63c13ac6d551e8ab64522cce8af89bc33a689d6",
"@esbuild/linux-loong64@npm:0.25.8": "d3d39691d301d144c7d61f52163a2fe64caaf928f4117d906707dc1456f3d88d1a7a3b16fb988ccfc0b0bc203f4bcd56665a9c7405dc380b3165a26ab195b9ec",
"@esbuild/linux-mips64el@npm:0.25.5": "6b3559517efd0dd1301debc7af7e275b055859c26facdda2e229b1aaab6ebea4c480a1da151c46211ee4035d95bfa7f0cdacf735b57ee99d41b69c77357310b9",
"@esbuild/linux-loong64@npm:0.25.9": "81478bff0f6d54e06fa96ec120c2dc92e47c3a1392397a121cf50a83496156f9abebd46f93e35a496f4f305c8af7cd430e4fe723474a2420cc21d39257852210",
"@esbuild/linux-mips64el@npm:0.25.8": "437e51b2be977cf7774114e04c141e3c0f1ceb7f12b961b7b3ac7f99c4e203afdd74c41e072ecdc4bab3cde4f14feedd78653727d1b2013ed3611bd89117ee8c",
"@esbuild/linux-ppc64@npm:0.25.5": "a1a1af99d758efce928335637924dcd8ddec4201af51014e1f831b012d53a0a673b1e0c31036ec9e8c5a0311439283419ec8abdfc67ecb245fa7f7b653006ed0",
"@esbuild/linux-mips64el@npm:0.25.9": "78709795d663461c54168719517c4c38b2a51861af0f97a91003ea6fe2c2b67dca77f57c2a2c4eb2c6481a8660b5fe477c72e46e90154cb72f1f235e683b2d0f",
"@esbuild/linux-ppc64@npm:0.25.8": "29d2e344b1c8b767518d25b23eb9e98d85deae1f2def2e01c1939536ac7d1fc9e92749a8d29b29277b3340d3613e4b0f96213c6aa2de7e06885a19d3d269870a",
"@esbuild/linux-riscv64@npm:0.25.5": "6cd8dce6723b73e0f89898ab6cd52e0d009afdacdfc0d5529134de7b832c92c2e0421fbb5cbfc0e0c0b2b00a9b1ff2c4cdb9695b2c535ebc174960e986c727a7",
"@esbuild/linux-ppc64@npm:0.25.9": "4a43e167f7f9659a5ca34678cb6fee53fbdba8b14a9a45f323abf33d9e141fd268984b0a18445db84cbada5ed2ac211ef318d5c44af0fbc0c7eea31c0c82321f",
"@esbuild/linux-riscv64@npm:0.25.8": "82b2ef7fd5a00b465da97bd797246269d7460ed710c0533517a1f8ad8e32527f405509b2ce27e29f8f3df1affa04e45cf5d1a71205f69dab5c1a27118cf10fb8",
"@esbuild/linux-s390x@npm:0.25.5": "31b86dbc93d19eb362bad3353e65d6da771118346e723582d06c05f1b6ffad1c3765001b5215ef1e8f0c2bb29130d98815359bbc88e5c08304354d5a92e6ea94",
"@esbuild/linux-riscv64@npm:0.25.9": "e71027660a884b5bbcb6e9e84ed439b3ef19466cd9f6d16c1bdfe2db6dbe9a40e8fc19ad429749102d1c15f015372f7f9f8ab7f82d506efffbd143fe8ab28aa9",
"@esbuild/linux-s390x@npm:0.25.8": "74168a6e8927d12c883dba56006f5277f8888c7b1b5e4d132a3c235b8629c3015b4715968ba128a79ff55c9f08a23df84fe44047e8cda4366b9699c5c45f27a4",
"@esbuild/linux-x64@npm:0.25.5": "f878a3e40edfd8a50de94bf982a9eaf03e636a0332af163a6c905490063aae652384fb392d4765c4338fb6f991034949c92ec768ee65c3b2fceeb494b89fe8b3",
"@esbuild/linux-s390x@npm:0.25.9": "7004c5852a3cbd1bd1d727e13b2f2be0747861ceab840ab8492ddff80b3d34dd41398681016cda3748c697e1b384bf4d4c1ad588538df38eba599ba935ecbd09",
"@esbuild/linux-x64@npm:0.25.8": "d531002ac2ead0bdb293ec1a4eceea687d37815e298196af2471107cdd4c1f76ef7d12417052b51852b80f66111abfb5ad8375c58b97da92306b975e9a8f0649",
"@esbuild/netbsd-arm64@npm:0.25.5": "941c5e28a63a93f19122271b5490e196db12815702c2266c6d66401b6909a4364ab889611ba81c5359624e3ce61f0505a680a1179ed9a555d1415fa1c485d75d",
"@esbuild/linux-x64@npm:0.25.9": "3bab69aa63d5ef65e9eaa229963ee3a3c868a06badf019277af06d4f7c52ea3a30abafad361e5bcce71032abd8b6fb666607977a627fa2def8db6756cf99b2ee",
"@esbuild/netbsd-arm64@npm:0.25.8": "55626924ae946a6225707062648aabb79c70d61e7e094b067338ea1adf72493b502e99e59440fe0d3abfe20eb36c33f78115815d63e72fa99f5e90146c2ee5d9",
"@esbuild/netbsd-x64@npm:0.25.5": "edbefdd88ca24a373497a7c8d1fdab418827ff89c6eee1c574159dbb4d9174552aa87753f35525a894964b77c14b012164ec5582b9f19dd4d6c1f5d45df411c7",
"@esbuild/netbsd-arm64@npm:0.25.9": "02b82c6773ad09082e3b18f01dbf4b9f72519a9e93995b479e4bd4bb28c8a4088972fd0e9304881d09775429dc388a3625249096426349dc3adc2208ee408a4a",
"@esbuild/netbsd-x64@npm:0.25.8": "d03122aaa3e9a8bda686bc4120820805b5d9701099458a2c928ee1a292fabcc47df0cb178c8c428edb78a058e75cf7c0d80fa25b71fb91db43d73fe6e4062c41",
"@esbuild/openbsd-arm64@npm:0.25.5": "d44633a374c109d2fb9c678882016e3ec3d79f0c5f21a6e6fb0114ea709bc539200b037a4e3ec52304eea2f8c5957bf16c6f0a7af5cfde41b652c4bac604bba6",
"@esbuild/netbsd-x64@npm:0.25.9": "51a576cb8ad7f43e43f76b25273735646eefa0d2a5bdaa3bd6387ab89512940bee49e91f7051b3d08d143d5cd6b4501f72a9462f30e242f0dff931c4ebe40363",
"@esbuild/openbsd-arm64@npm:0.25.8": "113ed8722788986b5b703c791bb9c954e80a861b92f453c66c79318d71cc6eac509c1dc79d20671b4af92165eee05a28eb7b3122537d8701447d30f58c428942",
"@esbuild/openbsd-x64@npm:0.25.5": "efc4641ea653dedc9886f0603c2e7cfc6fbe94c34d4cdaee9b060a8b9d8143d1192c45da93b3e802af2c26f72ab1ad3a3fad0e0cb297d06de55814fe83ccd32c",
"@esbuild/openbsd-arm64@npm:0.25.9": "9bf0e7a535304f0d3c700d6e4ef536fe94b17e05bf5f9a4cc308ffc8c3d3cd642ee7debcf7f649a845610b1c706675af903f785ef14f320ee918faa61bf79bb5",
"@esbuild/openbsd-x64@npm:0.25.8": "dfa68d80d68ae825de85aeccc118724ced6b232dcf25da6d862ba03abda2f55e75483dccbf8cb3a7338e7882a05e5425fcf5a902b7dced72c9f1a9c2650912bd",
"@esbuild/openbsd-x64@npm:0.25.9": "bb9bb4c5f095575f267d30c9e65f8e64c3f425d24904f6e22112c305ee5f1503aea750f510252e4b862f366e5efac678b71cc848cda72c587be8af4119d28f80",
"@esbuild/openharmony-arm64@npm:0.25.8": "8dab5710d93ad4a78a34a0016f6ea0bf2e16489845f9895ecaf354c1c3db209bed8f05a31309b95c358bfeaea53829605f4e315e9a53dae4d9fdb58e31ca4688",
"@esbuild/sunos-x64@npm:0.25.5": "29860663381b6098c0fda6f69235407654dfad953e83b3f9f06a270950d5c37da4ca60a4b5915b8e2606d468b560be6179870f64a22d5b046e8a930c31a7b554",
"@esbuild/openharmony-arm64@npm:0.25.9": "130f08d72a018aceef14b8534b9910bd2c0852fc074467ad0adf54d339584277326c7ffc8cd8126be08a530184c51d8de11d06971d1cc44545162bfb8428bcc3",
"@esbuild/sunos-x64@npm:0.25.8": "ccc940bd687d1f6d320d2538ac594b7fe5e291e194380a8b392dd2348d738cf8d322f9f62bcea82b3809f98796a0a004cd02ba9c4d563e5e336665e1ec8e1e1d",
"@esbuild/win32-arm64@npm:0.25.5": "a77d395251c8a62ab0cec07d5230222823fa02fbf3ef008d94b5213a335c9f949872c3f1c2f947abaa28098b669018e429af42f59616e049860a0072f3b006de",
"@esbuild/sunos-x64@npm:0.25.9": "a86fca2baaaffcaed419bdc6569cf4a88b4ae830034f8deb4d83ba781b989e25b03696cfe05a482e24710191abc53479b70491f3f157eff37ed2b486d88c897b",
"@esbuild/win32-arm64@npm:0.25.8": "b0a9a86548d4a62e68b12a89e21aaadda3d6d3e96541a2714b74df370cc344e1a2d91604998a26951da28c2f932bd2ee033adc9346bb232622c3ac419107136a",
"@esbuild/win32-ia32@npm:0.25.5": "ff1b6cbe835082aef5b93c3e2012d51be431d05c6ae5f90a5bc89687c687e8e2340c262dedddd124b27b511616bbc4088b5a4a949d3147f677084dc6ec572629",
"@esbuild/win32-arm64@npm:0.25.9": "cd32c8fe88511e413f6161480ea3b6fc2ed7cb4bd2febb455e7bc45842880c752ba71772f289908ded50d8cfd3207e6730c8fdec2e811af1f65e97d1ee53b4ef",
"@esbuild/win32-ia32@npm:0.25.8": "5880e933c8fb8dc1de1225128c171ea64f4b27fe52fc11ed9cfe6b0ca8ae091c2703d4cb629f08c06731810c46f48cf881516d0d54b3ac408dec34586ea84d27",
"@esbuild/win32-x64@npm:0.25.5": "266e69e8d37bd4deb77443588e49472e4e9791178cb39e1692eabb67cf65d8e85a932ac468e7ebb2072c8a9ee23ad413c8f0f7d954c474f643cedbbf7aad952a",
"@esbuild/win32-ia32@npm:0.25.9": "c374576d857dfa3c8dc5bdeef598ffc0e3adfcb8b7986a2b78ce61d2aa3c3d1f1cd15cb685f52b88411403d974f657c3fd44cf9b4fadb94e8ed69d75e9e3e0ef",
"@esbuild/win32-x64@npm:0.25.8": "9e98fe0e7eef7a0e774ab761c59d520ea1c997a7a6e4c7f9cbc967471a4a7ffb14bc27c60d2aa10796c4e945c3da2613fcc297054566fe3f5191e1250691d622",
"@lmdb/lmdb-darwin-arm64@npm:3.4.1": "2ef08ba9fbefcef1b8623c2892021fa4e7c7a148b7b50c0cdb824e1f3579806bcd73fab50ffad0deaa8fa9e3f7aa98db81a2db84dc22c48ae6cc4e68d48c672d",
"@lmdb/lmdb-darwin-x64@npm:3.4.1": "fd60bdb8198f17914efb8a51b198fe5e44e111a3b6b1082ec1f76aaaf02ac58b70b34950cc3ff5c289db779820908fdad0edb7f76addddc0ef841d0f2c8a084a",
"@lmdb/lmdb-linux-arm64@npm:3.4.1": "45c496e8784e82ff19a87cf54c9e988fec9c7e160558e9b3d4cdf9de9ee3c80def506303cfeb70226f2a614f898f9b062c462bde220209ba559f152cdfff1601",
"@lmdb/lmdb-linux-arm@npm:3.4.1": "6542a3c7a389d5e43955f2a25314b1aea619156b6fd7b6f46e27dcd24949ef68d91fb88cbbbf41de96e83856c44fc392fcf0f98d3c1b43b8ab65f67eb70fc3f8",
"@lmdb/lmdb-linux-x64@npm:3.4.1": "c432e8e30b7895eb5ad05dae1bc0d5ad59c1f220c717d68ac8c34201fbc380500e1cdbee33bcf2d21bb10aa9f32aa42234816205740f4e12e737fae8466c0028",
"@lmdb/lmdb-win32-arm64@npm:3.4.1": "95148c68e73fd25914e65ae129ce822679d8ffb952de771fced47364c42f36909d3c3f3ae66457450a6eaae03428ecf9f689d68674d335c663444f6e9eca07c4",
"@lmdb/lmdb-win32-x64@npm:3.4.1": "6b25b8caaa41e817bb9e278d26947e49b8669ef1c6d60595b9258fd067bc49f47ed7890b82acbcfcca79bf98661d3cc00eaf26f852c5e8f89db9346c69b2f6f6",
"@esbuild/win32-x64@npm:0.25.9": "41f2ba9101f4a9a28e3287026a32a05e8fdffcb4a4e41cfaf9f94b41093c6882f46ef80f12854b67b7ad78e47d1df492f3e8a71d41813a61500ace4a574af851",
"@lmdb/lmdb-darwin-arm64@npm:3.4.2": "318710007b94270701e8fb8321a1629e12f4628b943e017d1acab1896774b3974397f0972d9d603ffd3e129a68dc1ac0031f99538923e314ad6f4c8c480f4972",
"@lmdb/lmdb-darwin-x64@npm:3.4.2": "52b1afeffa796dd0d520c21662f428da39b29f76370d014581805cde274912e3e752bd80444e253bf1aee65c75238a3d2a98588f9d22842aa7ecfaa82ae3e3d9",
"@lmdb/lmdb-linux-arm64@npm:3.4.2": "2d938b6a07710714f25a29d4285230e2f4999b6d5206b74250ce65deae7514dd9dfafd86481f8ac5c5e2baaea56413558279f0b093e4a83e2f98063c8ebe75ed",
"@lmdb/lmdb-linux-arm@npm:3.4.2": "5b21eda51f3b993a9b35ed0e6093d3240c8faf4c1090a500ae01c7437d5a94d0db8f3d58f2db05a9b8236e2629d1d54ce35533c0c9fba473b40ffea4bf19a7c3",
"@lmdb/lmdb-linux-x64@npm:3.4.2": "da1ccac62a108b7db7d719a14d5ba5f81285b4ec1e3f841400477ef98428940f33fe6a175b442df3a97206fec9dc1d611d4b23f03ac5ef0db0161b8de4629d77",
"@lmdb/lmdb-win32-arm64@npm:3.4.2": "cc300aeca06ac55de7eb24c2047b920cbce0a6f646f1aba1ed5ecc8cc2bebc92f9f82975e7ecf80977db30636ab7c869108e79b91c4b5c59b771055b09cf9e12",
"@lmdb/lmdb-win32-x64@npm:3.4.2": "8fae43fa379018653c307f28c6064099e4f8e19439f4cc895d7f29d11dfe1969e99d0da32b167820304154758a23b30b2dc2c86f71b3590e33bf837cf64ae46d",
"@msgpackr-extract/msgpackr-extract-darwin-arm64@npm:3.0.3": "f8d48613de17e5356d273745042bbc7c0d345e1e4e5e88ed1132a3ed9ca65db9f8b908a708383d7a58ede276c105e7c9a2887fad00d5e47892010466e5312b47",
"@msgpackr-extract/msgpackr-extract-darwin-x64@npm:3.0.3": "270f8831d7f6d61ff36e7118e09ec13baa633bb22dd57fa3a9e6af67f7036a3fd1beec4c8aad1c72639522300364cef98bc5ba2cddf67a3832f8a35b7fc45502",
"@msgpackr-extract/msgpackr-extract-linux-arm64@npm:3.0.3": "326c19865ead39017326dd8066cde30adaf87a62b968a22d5e5369691817086f681fc291be80b7c61c5496fe915f6df546f41e14ee18b896c54de5099cf147ac",
"@msgpackr-extract/msgpackr-extract-linux-arm@npm:3.0.3": "115f627bcd7c290ddfa1d16405cc1ce388be0b295a26adb1ee2d774133a77809aa0bae83775d3c11f220544e77d34c01d607037bf9dfc6aaac67329cb5fe2818",
"@msgpackr-extract/msgpackr-extract-linux-x64@npm:3.0.3": "ab74755aa2afd27ad8f5277c7cb7a0c721028ba63c3e3109458689340d76ed4c901aa2c71ae5950f3a2149ae9e835e711a12842db219864107cc0c5c1fbdc0da",
"@msgpackr-extract/msgpackr-extract-win32-x64@npm:3.0.3": "edfea4f5455f71f608c15163467b98245d46fbd6078019347418e193968431afe632a11e8729ec39755a54563d86940899e2fe8f3d124393f91855956bd1d745",
"@napi-rs/nice-android-arm-eabi@npm:1.0.4": "45b448e131164f3a8cbb31a2a5f55bebb7a3d5f5331d29e18f7aafc55b0b0153f19cee4176095a37d3b2bf64073cb1a3e82840d73171fed0282ea22fd167b556",
"@napi-rs/nice-android-arm64@npm:1.0.4": "d32f04cd8028da9fded9dc0f85f39280097b8fe47ad13c80924be4a41a4f85426c97f9928ad3e7532d1dd976ce4ffca46db1d41c4f938ed1e0419963225b2d13",
"@napi-rs/nice-darwin-arm64@npm:1.0.4": "6599fac84bf0f11a1e3cd290d182bc7cf9d44ca437e8db8a5f68cdd127f8003626527ca3a9a4246bef2def8450dc0675b60f919d8d613631b63ead3dcfd1b4e5",
"@napi-rs/nice-darwin-x64@npm:1.0.4": "fa86938095b1b26add66e844d5c890a23a36f52eef3dfa26cfc4f96e085a43e3a9f3cd21a340aee5824f3c0745291474822a4f16fdf4ddfa11bf59e2fc2ad1f9",
"@napi-rs/nice-freebsd-x64@npm:1.0.4": "18ffc677b3e38686954dfe46974bb796203f98e604d8a611ce86e1a73135b46a1ae031cb96df64e07fa3c68772465f15a7cc3146d22399dd0428022ce16131b8",
"@napi-rs/nice-linux-arm-gnueabihf@npm:1.0.4": "08691179d26f4f7f9f12221f40aa16051a945b52e58b6bc8f243f0fe8f17390a1b75ecc5da3b6bf0ccc3cc1b429703852a2398f60227024481602a8090be9eb9",
"@napi-rs/nice-linux-arm64-gnu@npm:1.0.4": "82a0503b880fa72f8921a81ff22a5257a8a7782ad30e097cbbbcccfe5021559d29c01ec06235ba1d549a18ef1b2ace6af94b5ba6d55aeb39afae237ae57b4f21",
"@napi-rs/nice-linux-arm64-musl@npm:1.0.4": "26d52ea8cdedb140f594813c8d8d6c513511759298a1fdaf1cc1adee3c562b0be41fd8f5ae98666f023ed20d80d6d37ce3f71a7ef372bc30e6fbbf4f5805a2e3",
"@napi-rs/nice-linux-ppc64-gnu@npm:1.0.4": "037cd5d190f71c867fd370e76d2721c12ba124392d71f52773a7668dc1f61d642b05c3b9045ce759571af7251c9b33627177b3dcb8f0f49cd71c0e4a64510ee1",
"@napi-rs/nice-linux-riscv64-gnu@npm:1.0.4": "f34a91d10e9799d9b944c1ad33306d93e4f4c0182ccbac945b2326d5e533e987762bbba12a05ad0b2cbb7651ff004cc16187a9b87fc0e0c0745d6045552c4957",
"@napi-rs/nice-linux-s390x-gnu@npm:1.0.4": "1cddeeae3b28bb773cd17b43df08612fa33cd9ef35d9ce77ca59f45912d676da2900585c05c74fce504ce25771fb7828b109910f9b2e621b56aca9c0ff9a69ee",
"@napi-rs/nice-linux-x64-gnu@npm:1.0.4": "658a8e6ac405f9ac56cc39e356561d41dd2681f982aa2f873b30fc8ac375518f8aa428f3ff6634a82183deac9f556ebc333abb34f4612cd7d115e05e1e78bd12",
"@napi-rs/nice-linux-x64-musl@npm:1.0.4": "21e2a6d6bb927fc2dab2aa9bc80c1546c68b7b2f97831467ba3f716f27289d2cd0643697cd616e61ea708b09b424087a55161d18f350c6a3b00435f7fb719e1b",
"@napi-rs/nice-win32-arm64-msvc@npm:1.0.4": "004988d067b404d74ff3cb87de9e3bd6dfeb19c1156ea46dda361753daa91671e634ecd58d97e3137f81a969bf268c0551b86dc4f10708c285de9c8de71b0566",
"@napi-rs/nice-win32-ia32-msvc@npm:1.0.4": "a5e5ef142b4c361d665bb39ce82b4f8fdc685a59dca0696436fed60a2ad65f399451afddf57d82a4b82050a457c1802c04c826407e6e902f4907b5e53745cd05",
"@napi-rs/nice-win32-x64-msvc@npm:1.0.4": "fbd1ccc22daf769b179656cab2cbcffe0612dc859181ae057509d50e4f10787d00c90277ba949084ce7c01caf9251f8cde8a198694bc8b5aba57e83c49ff8cf8",
"@napi-rs/nice-android-arm-eabi@npm:1.1.1": "a1f8caf7bba36f2131303d7bee53e98f46521e499f4b1ba25f5ab770d8acea36abc1792c53e5c6db4235ff1873ee7c94d2ab2f38c8d492ddbdf47fbc6e92c423",
"@napi-rs/nice-android-arm64@npm:1.1.1": "5f623438ee64b9e9df5fa8f7b6533776e9774e8edd2aca6945f85869a4f3232c2f30d3a69ad1ce54e775e4747085e57ab473c8421551bda65d809ab65332a8bd",
"@napi-rs/nice-darwin-arm64@npm:1.1.1": "733a2d0b606efb52d5532c9a00c54e8c664ecb794fba302c14055d0145baa02b5a50459ef07c171416a5f941e2779cef7406181df7e7969f978ee1d1fdcf2b5f",
"@napi-rs/nice-darwin-x64@npm:1.1.1": "f99af3768f04db9fb91d54e460e4e315242d3d8ff3ab0d013c56f4bdf62497d223459cf41554dc0914d11e97f39c2b154c517c3d5996c0ef0297d18702c51b29",
"@napi-rs/nice-freebsd-x64@npm:1.1.1": "0d317f65d4d07ae3c8d5d6a424b6b10c599728eef8d58f89ceef2491dffb849bf5744b0eb59c0feeea461b1fd4959db676dc471cdff10ce1304d06246178ce0e",
"@napi-rs/nice-linux-arm-gnueabihf@npm:1.1.1": "ed67fd70224048f84401cc1167210d2ab306eac252a83eed96357c49499029205b83e1cfdc606427c46edafb113c0c17613a5de7f122947d4ed6bf3cd7663287",
"@napi-rs/nice-linux-arm64-gnu@npm:1.1.1": "9477d397afb1df69647adb449c0d05300a99abf6038a3e2eb63307908375b9a6fa271fe5f7ed211b1b55e87dd9c6ce25f41a6f0f270fa45af13a3a84f546be72",
"@napi-rs/nice-linux-arm64-musl@npm:1.1.1": "a754ae5275a306f70eb621e855f234318c9b4db323e10dac3d180c1e66953cb5505e8a1ef13677492839f160c28cc14583b22b3953a061d5b42a7cb7b0dcf42e",
"@napi-rs/nice-linux-ppc64-gnu@npm:1.1.1": "91c96752d3b0c57156dfe0885b8124e933197a3a84d4f312986721b37abc1f129f9f071b73142c2074d7e848bab8b8a16e6d246e8c355fda9ed6817ea6450330",
"@napi-rs/nice-linux-riscv64-gnu@npm:1.1.1": "e898401c486a5b637426562bb93b12609349119812273b5c19ebc565e516c1246043888ee2c5d24c6178c93288a761284813e495c026c74466f832ef5d63d906",
"@napi-rs/nice-linux-s390x-gnu@npm:1.1.1": "0ef13c6beca52613a76c38f70e60ac4959ad08f9d898f64036be8d45ad8266e1f4fc64cf1ba669e55a5869c64a3c2c9a9ea4d4d3836a5b6941fb147a7ee0abd7",
"@napi-rs/nice-linux-x64-gnu@npm:1.1.1": "d5ce16822498a12d29c59d5aaa5af4346bb9394d45342706392c2e27915dea9cb37692f0c7fc69dab8c65d31556dec851d631a8d557598bc32d57c3788835dc6",
"@napi-rs/nice-linux-x64-musl@npm:1.1.1": "debb8a7067c1d20ce4c29c897e470ef84fa8f66014c0c8e7fe66d6676d6e9199a0936ec3cf3098f89ca1fa1f2628c27d32991f933a7a33da304f1baa45af0eb9",
"@napi-rs/nice-openharmony-arm64@npm:1.1.1": "086899cc30d453380399afea4e827cca1428f9cdfc7e253289b0fd41a84c76850315f0070432a00c3c9f80608ac42d638ad836fcad742f437c1fd9465d8a83c4",
"@napi-rs/nice-win32-arm64-msvc@npm:1.1.1": "653a7b04d9caa311d793f12d2c2323830a0863737fa4e0cf4ceb5adbb85d30b29d02fb59e5d513e5375273054a965777c83732b25592e80a574f15114bdf96c2",
"@napi-rs/nice-win32-ia32-msvc@npm:1.1.1": "f32fcebde27d2e8022e6ea2c8a4fad0676b59c24373c8f7e6fafe3711932a743798909122937278f94c42cba952f5403ed1dc1879544e508299af88ecbbbd68c",
"@napi-rs/nice-win32-x64-msvc@npm:1.1.1": "657bf5caa5b07b16f39b3fca7d7f99a0609a01ffbb620ff167652145c0e5c3ee1bbc19f4ed09b9e4373da8a1f84870b58152bb6c44288a3e9cb46ca8a236cec8",
"@parcel/watcher-android-arm64@npm:2.5.1": "f99d569e4f6cf78a1b0097fb9d4682cb201a74370ae440c531da4e1d5021e46141bfcdf8ef708b51a5b9cb1c30f78eea933ce75216d5eeb7b969a2ad27c68e4a",
"@parcel/watcher-darwin-arm64@npm:2.5.1": "973c7ef3c94608da9cd1b20b18b9a7de2fb46fe44553731fe372b640de524491976150d0845f3d5953b74ed8ea469cb8d18a48651d0e5fb82f549a6b46b54f79",
"@parcel/watcher-darwin-x64@npm:2.5.1": "848c5516aed9c36e14751200dbbf57e83c0bd46cdab0932df33db120e66b9596de18eeb98980e319efde84014f67d9e7924d7555383d8ffcefe35c501166b84b",
@@ -92,45 +94,39 @@
"@parcel/watcher-win32-arm64@npm:2.5.1": "e015314d6b9b727cbe25eedf963ca8b23bf6d4e78d3c28008bd0d2657940ad54a271330486df3a93a5f1a30f2b8d052d14415b85cc7e7b747c6c73b5dc055628",
"@parcel/watcher-win32-ia32@npm:2.5.1": "920b6ad6a2095aeb9c2d329c5118472a3c14669fa93eaa99aa8050c76c5c2d3d76d92677167ed748c2ac5487c568d5df16d5d94f4bc7c354094fccd8e0d6350c",
"@parcel/watcher-win32-x64@npm:2.5.1": "8f1c8e41ec9f86e4dcd0d4db0a077742d5dcc853f15ea888387183e34e2efcff09fd1cc9ec46fc1121b9ad4ddc0e221283f2ffb23cfd7dbcbb8b03060b461963",
"@rollup/rollup-android-arm-eabi@npm:4.44.1": "ec8b655e2930312fe94eded1cfe439901bbd442a891494a512259caa0bd936c29b9d06debb061bece88f5d41f619ccb4d0d77d0fe190f1a5c25a3a1a724d255f",
"@rolldown/binding-android-arm64@npm:1.0.0-beta.32": "f683651ca6732c155432bf11ecf88d45231ff1a81c8b51697efaad11f02b00fa2af14d042099d8caf5053ff9741680f4b476d63e93cbad155af067ab51218239",
"@rolldown/binding-darwin-arm64@npm:1.0.0-beta.32": "4ac2ecafab76c25edbfa0fd70fe46647d0b9385b985265be8208a3dc9d65910ab8c352a328e58b41c2d981f26d9d1b48e08ea087d986707bf37891736d5b5d57",
"@rolldown/binding-darwin-x64@npm:1.0.0-beta.32": "877ad1cd46fb411598a11cefd86c5557dc32037d1d757869dd520c05ada993424364012c0d0b65b221a15b65569fea1bb997140272e5886d1f0332d29de22cdc",
"@rolldown/binding-freebsd-x64@npm:1.0.0-beta.32": "a441aaaed1ca4954d7ec1c23c42d57faf926a93028cbc8e212392f15dd545e86916f8ae814dcc24f667225259bd6b7ea69e3ff1921f30b430f48050a026a8995",
"@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-beta.32": "60a7a54ed4271e4ae24ce74f1d91f7f75122036374d8d3aca276ffae31de5b06b4c700226143d7463e24a8fb19c0d9a4cc48b14a8b53d1c03cb5555037e27899",
"@rolldown/binding-linux-arm64-gnu@npm:1.0.0-beta.32": "280bed83133d9d055156aec07fd212a5f804583b2f7a50fe6282c3e51f82fd643aa4affa17f8b6f9040bc3f0b5d8de5c3bf0b73f2471cbe3c80e413a32731663",
"@rolldown/binding-linux-arm64-musl@npm:1.0.0-beta.32": "e13ada56d9168b07d9c30d35e52e66d94b882e872fb92c65cf7da25ecb80c2b776e35a47cf0a739d6352fb386952dcb0918f5ff4b823e88aae8728d3b4201df5",
"@rolldown/binding-linux-x64-gnu@npm:1.0.0-beta.32": "452b5d9826aad34b593f83249e8de3a7078f79837de7aae9e08865342b4142ea6acb4c506fbf637b355e4f9c38d92acace1bb7d9389fe9be8a7cd5a40e58953e",
"@rolldown/binding-linux-x64-musl@npm:1.0.0-beta.32": "06fd13ea6ed94bd92a00dac8f4a7856e6d2058b52cbf8f43743f50a245bb3c0aadc571092233a4914e7772f0f8fa538b1eb66395c88e44610f4509676c87706e",
"@rolldown/binding-openharmony-arm64@npm:1.0.0-beta.32": "fc927ae8f8a6209a463d55c09782ff15759960a69af5fbd45273899fbf9792be5266c5a799d8d5561cca29e0c2a9648ad6060cad99c76b89f3773fda63078725",
"@rolldown/binding-wasm32-wasi@npm:1.0.0-beta.32": "f6b61a2b1ce791aa63144f361bca382d94fbcd8b42166960adaaddbe82cbfa255621ddd846c823a388b2eaa9a524f82873754e5ce63f80125b6ac2b601ff4196",
"@rolldown/binding-win32-arm64-msvc@npm:1.0.0-beta.32": "ca0fafbfaaf1104663417ef52459def1f173beb4afaef86254ce69e0686a6038fc41eef9cac0bce62e2b7d4ecb3b16c4a9a4d460e2d256bff359e6959a9a3b69",
"@rolldown/binding-win32-ia32-msvc@npm:1.0.0-beta.32": "4e365b3f5bb753aefe9a5e1841b1239073598dc738d1cdb2700a984fcb11b2eb5c623a3a3bb348cbfe9b354da15144244bb0875503a0d64603565c19213e5697",
"@rolldown/binding-win32-x64-msvc@npm:1.0.0-beta.32": "48bd1895a5a6111d28ecb5492632e2410aec9dc8502de75fa8617b22892e8138a59e9c543da0c393243b9d5f5a585daa59cdbf76f94724c0e9c78f60f1ab677f",
"@rollup/rollup-android-arm-eabi@npm:4.46.2": "d7d021a87cd3504c8d71b00a94199e13c4e07c14fe20ed7300cf1e6436a5f3fe8496c9e5f206e023b15f9b6f8991b2d95a48b47fa41d5c00b44f37fe5f4d5eb8",
"@rollup/rollup-android-arm64@npm:4.44.1": "5eb5c7de31f435afb97feebd06feefb93c2cb272002240b8530c1f274436ea578d8320d67fa49eb1409ddb20a47219efff59a09b22a426584b881d36adac7bea",
"@rollup/rollup-android-arm64@npm:4.46.2": "ca901edbf95bbdd2505c979f777e2a01e2e885a597b6daeed5362dac523ea2a1eb9c0c0d22b9b436f3613c22abdd442bd2764491948890930333a9e40ade35be",
"@rollup/rollup-darwin-arm64@npm:4.44.1": "93cef94c44d1baabc5346148d59ebb5d640948b2895bbc5de6804908999857f331c388eb449f98eba98d2b239492e91211accee7eaf4b579ae3c007705d76246",
"@rollup/rollup-darwin-arm64@npm:4.46.2": "ed2b07c4803915d46ff642abd659e179fae524dcd3cb88c810a5b71290d16b498e0371dcb91fe98f6301b8c6600d579a099be1e9450278326281002df4a80019",
"@rollup/rollup-darwin-x64@npm:4.44.1": "d235e7f40080cc19295d45935b83a0238cb66962e7d6d4af0eb261012d80bc344fe073ec9dcc3d39092138a66e7a69c4e79cbac7c6ee49b8329b80d12d52968f",
"@rollup/rollup-darwin-x64@npm:4.46.2": "c53e31df756cb8d44e179c167db1ec5d321225561a1aff2b320091c226c2dfafd080a98a1466f2dc697ff0173b52c41d89c60cae97f73b41fbd128d4c87fde66",
"@rollup/rollup-freebsd-arm64@npm:4.44.1": "e26f6bf6914e190d72f74da4c8e47c27661fc99f6310f80e664acfcd6262f4981ff043ff53ccc06dc6a232d481f9f0055e32dba3b65442259316b18fc0ea9087",
"@rollup/rollup-freebsd-arm64@npm:4.46.2": "9495d87e670bbea87e43d06df53ae83fcd46e2c82a80927556f3516ac76613b8b7739bbd4b43c3f264bbab57a50a3b6cd2dfa6c1b2741bd3acdeba8af7c47018",
"@rollup/rollup-freebsd-x64@npm:4.44.1": "d06455bfbe8bf71996864879b8b9b4f95617adda959a5a143be0df9a5bf749cd52740a9a3b2548e67be00eef9ccb99ef04368a052afceae2011e2a817baf4156",
"@rollup/rollup-freebsd-x64@npm:4.46.2": "890a965b45f4c4b9beb4696912ee30472180a040dafb24ce32f8811aed4d0d0ee90bf675d234abc6d8e66266d2966a72483fff7e6f1dbd116424b23e18fe38a9",
"@rollup/rollup-linux-arm-gnueabihf@npm:4.44.1": "1bb6818627de1434f889c8a6bfc13a0205f25055bcc9f39483e445411c753111c7d082cfca2affdeeaad46c3711e3ece140fabb7173ef3cd19446d3682863854",
"@rollup/rollup-linux-arm-gnueabihf@npm:4.46.2": "ce9720f61b4f7d9a791ba78e13cbbea67ef5f46c465e054c08f009cd06de8c1e4518df8e8578366a27cc9ae4280d37528dd0762906a19e820ca1a95158b47090",
"@rollup/rollup-linux-arm-musleabihf@npm:4.44.1": "6e9eff8ad332d9923a7cadc0ce1911c4e0a2f8457a8131485f0bce241bb7c223dc811b976ffb9ca08d4930630c647219dbfcdab639c3a8bef075b68285c01960",
"@rollup/rollup-linux-arm-musleabihf@npm:4.46.2": "b884f568a681d8c13ffdfa77ad6183ed6f7f9fe5bc952b1c82dc21e36b4bc8eb7ee292168929a2575ff5ff14582060d7d73c583aef7edf04fd0bddd67140f4b0",
"@rollup/rollup-linux-arm64-gnu@npm:4.44.1": "a5382c59bf531afd774b7de82d1600bfb5915a0708ad6c7099ffd1af657b813a525de18902178120b247c95e21487f0c96a8eecc8d9ae9163da12ecb4a5ed3d3",
"@rollup/rollup-linux-arm64-gnu@npm:4.46.2": "519477372d8358a4d3f1f1245bc2b5b57b65960f9a7d02bc5795ba68aed471fe87b20391a63c334bf0abb94085ad8c89d8d3b2e4d79ca0fed702537e9a0949eb",
"@rollup/rollup-linux-arm64-musl@npm:4.44.1": "44944da3785383b8cdb5f8b4eb627737edc10e206ec66ec6a762f75f2dcc12dff7bfaae864d37941d5d30c50c8fee5f5a2b12c19627b356e0aea3186f80e2d48",
"@rollup/rollup-linux-arm64-musl@npm:4.46.2": "a5dec7799dd832b5374171a73a6b57cffef8be317482dd9ea4e6554db6fc8afb4bdb91ec725502f1b378aa9cb9a1333684056d55c9120262cb7744a33b961a76",
"@rollup/rollup-linux-loongarch64-gnu@npm:4.44.1": "1f7502f1777622abb717a3109bf69907ba46a277a6ea33b99d6cea8e33f74b6d8a979ac5bfa33398f31211687adf7458ef9680b7f2e3523d82088a3d59857c8f",
"@rollup/rollup-linux-loongarch64-gnu@npm:4.46.2": "76ebbf40535f68c6922edf7d866dad00608cd475c8436d199653341ea09124cb4478f67c12d32b5363634f3f811926acb14a086eb146a1fe6b310fdbde01f2c8",
"@rollup/rollup-linux-powerpc64le-gnu@npm:4.44.1": "535c564216655518831098e5481f06b62452fad69209409776f4508e9c73265dfe531983a64b47c9090b244668b4c023c906061eee5a4c3c29c1c9822f1d1209",
"@rollup/rollup-linux-ppc64-gnu@npm:4.46.2": "31b62a51393e0f2608e1133701523e894ff5d04038e3d9af95abf595ab7fbe827167a651b200e9975d0e76904699cde3428aa1afbf46bf939f836f8ef90b1d88",
"@rollup/rollup-linux-riscv64-gnu@npm:4.44.1": "423cb7d6578052d23374fe2ec3b996be9a420785fe324a0d1aa38e9e9d3f4b34ba3673f4ce5f622c7ed99bf82c4e24f55469b6e75deb5f27eb67369c052d8a9b",
"@rollup/rollup-linux-riscv64-gnu@npm:4.46.2": "4f22bc5fe58730026085d1a5372b51d9ed933b314cde2d3dec1d73ad76106406915c313d331f094176ed917863c0041667e63184d9730da7107b11266dad477f",
"@rollup/rollup-linux-riscv64-musl@npm:4.44.1": "03a0530b45b554363296e938493e263aa26c342080aea72c9e2b673fc42d5ed2d9267d283ef136c71da64bc85a03fd360988aedbfc68029bd948567afafe71a6",
"@rollup/rollup-linux-riscv64-musl@npm:4.46.2": "1bc37b77ac38d7e82e7d661b67fc043a1db01272a0566e5432c61e3c7a5e6c11b5ecb4a49547da2de33a8e0a7b0d685f3c7341572fa77c90e9b71e515f753e86",
"@rollup/rollup-linux-s390x-gnu@npm:4.44.1": "93fecf841caf9621a99b8f0938d21a261ccc1ee7dced2ff47de659662a3bbbc0e3cc45ef38d3aca84918ecaeff51188a68a109db337892518ccfa393c305fafc",
"@rollup/rollup-linux-s390x-gnu@npm:4.46.2": "1b1821a848d8bf86fa5e01ae57f60ebe5566cbcb0c605b5d05050821e94b8b45a72515ef302a3021196018b289aaffade5c41a5f89b3f8324d509a25d28dcfc4",
"@rollup/rollup-linux-x64-gnu@npm:4.44.1": "b401ab19f21fb0f8ff50662a9fbe823d4c7904fdf0f8de17c3338107e3974ac89ba1189b7c6f0f2ff8734cfd07325bcb5e5dc6a5d53df076fe34757233063a72",
"@rollup/rollup-linux-x64-gnu@npm:4.46.2": "66231802689c1ac1d6ecec6fd65d14c01c900537e588808e0a2c92ba34e322665bb6df3853500717cf600f40a93de4c490838290e21bb10eed4249f587a08109",
"@rollup/rollup-linux-x64-musl@npm:4.44.1": "87ef16e6ca9ae5d398f5b7e1b58033cf1b5f87efb0ab7c4b16dc7dd213a1b3a9305c2624b11e89539d75d146912eb7a41a139270464fc617fd1c2917e391fc56",
"@rollup/rollup-linux-x64-musl@npm:4.46.2": "064ed54e9ddb05eec1b5da5ac8366f3290b7b65e63959a76a26d6940ce44d741c30488e39ce94c51a2679b2c56217c2e0aaf74e123a1c0928503712c115d6047",
"@rollup/rollup-win32-arm64-msvc@npm:4.44.1": "5f4fe05f1c778d839ce22c2b1a1419d8c511fd10793326dab5a033978f259733b6d042519a26ad7df3f5b2cce75bfc2d2600d9c43ec9cf16d6acf105bedf00e7",
"@rollup/rollup-win32-arm64-msvc@npm:4.46.2": "b59089cddf652e3da278744f6b8b2105360d1219833e54791380322913d40073ed4197ccd06d6091e83e1e12a5290d7a2e4aeae7947ff20c45943d07d1f0af0c",
"@rollup/rollup-win32-ia32-msvc@npm:4.44.1": "5639edf6114f38055489c35f03f5d039b4719ae50309db235dc176c026fb8eb5bb028e0db2769ed4faec34722200f6a31df62c23a0f8c90a13568685a6f00140",
"@rollup/rollup-win32-ia32-msvc@npm:4.46.2": "d0aae1f80a64d9148426a7ff25b9df7f3abf7aca912c358a952f4b3bc541e030b5959f52e0b67abe01b9c8c8fb6567d1bbd30e31daabb7e2c4dc0488faf875f7",
"@rollup/rollup-win32-x64-msvc@npm:4.44.1": "d23d4b88a0a96965ba20e75bb9f5bea6e22cab53b9658a54317634363a64aa43dd1ff66f569d0e4fecc34d60d554a64ae905fd85cbc436f78544d6f9d550ebe2",
"@rollup/rollup-win32-x64-msvc@npm:4.46.2": "740ca3c1d07f5af76fc9c2db917edbf6d0c1cf3eeee8330a0c571db4990ec44f0b272696a215ab118e8a32d7529f84bd47225e85dfab458a989b4b18d0bbea49",
"@unrs/resolver-binding-android-arm-eabi@npm:1.11.1": "04dd38b694c1680bfec192b499e188700398a414886a08a8a7c72815db56ac147df03d88c73ff6fff7ac3e0a01dc41978054b3622b49463e0d684c5168557fcc",
"@unrs/resolver-binding-android-arm64@npm:1.11.1": "763626adc34dd2b4af677b5ced6493e7b2b1935351a5c9137f1c9561d11faf97b94015e6876e57e85c33ff563564314c92c0882a4780a57f2225cbbd779a695d",

View File

@@ -0,0 +1,209 @@
diff --git a/cypress/e2e/frontend/manage/config/config-manager.cy.ts b/cypress/e2e/frontend/manage/config/config-manager.cy.ts
index b4e3d94b..4ecccf7b 100644
--- a/cypress/e2e/frontend/manage/config/config-manager.cy.ts
+++ b/cypress/e2e/frontend/manage/config/config-manager.cy.ts
@@ -143,6 +143,7 @@ context('Config Manager', () => {
['New commenters must confirm their email', ''],
['New users must confirm their email', '✔'],
['Enable registration of new users', '✔'],
+ ['Enable registration of new users via SSO', '✔'],
['Show login dialog for unauthenticated users', '✔'],
['Enable commenter registration via external provider', '✔'],
['Enable local commenter registration', '✔'],
@@ -182,6 +183,7 @@ context('Config Manager', () => {
cy.get('@configEdit').find('#auth_signup_confirm_commenter') .should('not.be.checked').clickLabel().should('be.checked');
cy.get('@configEdit').find('#auth_signup_confirm_user') .should('be.checked') .clickLabel().should('not.be.checked');
cy.get('@configEdit').find('#auth_signup_enabled') .should('be.checked') .clickLabel().should('not.be.checked');
+ cy.get('@configEdit').find('#auth_signup_sso_enabled') .should('be.checked') .clickLabel().should('not.be.checked');
cy.get('@configEdit').find('#domain_defaults_comments_deletion_author') .should('be.checked') .clickLabel().should('not.be.checked');
cy.get('@configEdit').find('#domain_defaults_comments_deletion_moderator').should('be.checked') .clickLabel().should('not.be.checked');
cy.get('@configEdit').find('#domain_defaults_comments_editing_author') .should('be.checked') .clickLabel().should('not.be.checked');
@@ -219,6 +221,7 @@ context('Config Manager', () => {
['New commenters must confirm their email', '✔'],
['New users must confirm their email', ''],
['Enable registration of new users', ''],
+ ['Enable registration of new users via SSO', ''],
['Show login dialog for unauthenticated users', ''],
['Enable commenter registration via external provider', ''],
['Enable local commenter registration', '✔'],
@@ -283,6 +286,7 @@ context('Config Manager', () => {
[InstanceConfigKey.authSignupConfirmCommenter]: false,
[InstanceConfigKey.authSignupConfirmUser]: false,
[InstanceConfigKey.authSignupEnabled]: false,
+ [InstanceConfigKey.authSsoSignupEnabled]: false,
[InstanceConfigKey.domainDefaultsCommentDeletionAuthor]: false,
[InstanceConfigKey.domainDefaultsCommentDeletionModerator]: true,
[InstanceConfigKey.domainDefaultsCommentEditingAuthor]: true,
@@ -311,6 +315,7 @@ context('Config Manager', () => {
['New commenters must confirm their email', ''],
['New users must confirm their email', ''],
['Enable registration of new users', ''],
+ ['Enable registration of new users via SSO', ''],
['Show login dialog for unauthenticated users', ''],
['Enable commenter registration via external provider', ''],
['Enable local commenter registration', ''],
diff --git a/cypress/support/cy-utils.ts b/cypress/support/cy-utils.ts
index 4775dce0..c0a87913 100644
--- a/cypress/support/cy-utils.ts
+++ b/cypress/support/cy-utils.ts
@@ -199,6 +199,7 @@ export enum InstanceConfigKey {
authSignupConfirmCommenter = 'auth.signup.confirm.commenter',
authSignupConfirmUser = 'auth.signup.confirm.user',
authSignupEnabled = 'auth.signup.enabled',
+ authSsoSignupEnabled = 'auth.signup.sso.enabled',
integrationsUseGravatar = 'integrations.useGravatar',
operationNewOwnerEnabled = 'operation.newOwner.enabled',
// Domain defaults
diff --git a/docs/content/configuration/backend/dynamic/auth.signup.enabled.en.md b/docs/content/configuration/backend/dynamic/auth.signup.enabled.en.md
index 35acc2ba..9427c016 100644
--- a/docs/content/configuration/backend/dynamic/auth.signup.enabled.en.md
+++ b/docs/content/configuration/backend/dynamic/auth.signup.enabled.en.md
@@ -7,6 +7,7 @@ tags:
- administration
- Administration UI
seeAlso:
+ - auth.signup.sso.enabled
- domain.defaults.signup.enablefederated
- domain.defaults.signup.enablelocal
- domain.defaults.signup.enablesso
diff --git a/docs/content/configuration/backend/dynamic/auth.signup.sso.enabled.en.md b/docs/content/configuration/backend/dynamic/auth.signup.sso.enabled.en.md
new file mode 100644
index 00000000..66748b51
--- /dev/null
+++ b/docs/content/configuration/backend/dynamic/auth.signup.sso.enabled.en.md
@@ -0,0 +1,23 @@
+---
+title: Enable registration of new users via SSO
+description: auth.signup.sso.enabled
+tags:
+ - configuration
+ - dynamic configuration
+ - administration
+ - Administration UI
+seeAlso:
+ - auth.signup.enabled
+ - domain.defaults.signup.enablefederated
+ - domain.defaults.signup.enablelocal
+ - domain.defaults.signup.enablesso
+---
+
+This [dynamic configuration](/configuration/backend/dynamic) parameter controls whether new users are allowed to register in the Administration UI of Comentario via SSO.
+
+<!--more-->
+
+* If set to `On`, new users can register in the Administration UI via SSO.
+* If set to `Off`, new user registrations via SSO are forbidden.
+
+This setting applies only to the Administration UI.
diff --git a/e2e/plugin/db-seed.sql b/e2e/plugin/db-seed.sql
index 1e02e554..69aaec98 100644
--- a/e2e/plugin/db-seed.sql
+++ b/e2e/plugin/db-seed.sql
@@ -5,6 +5,7 @@ values
('auth.signup.confirm.commenter', 'false', '0001-01-01 00:00:00.000000'),
('auth.signup.confirm.user', 'true', '0001-01-01 00:00:00.000000'),
('auth.signup.enabled', 'true', '0001-01-01 00:00:00.000000'),
+ ('auth.signup.sso.enabled', 'true', '0001-01-01 00:00:00.000000'),
('domain.defaults.comments.deletion.author', 'true', '0001-01-01 00:00:00.000000'),
('domain.defaults.comments.deletion.moderator', 'true', '0001-01-01 00:00:00.000000'),
('domain.defaults.comments.editing.author', 'true', '0001-01-01 00:00:00.000000'),
diff --git a/frontend/app/_models/config.ts b/frontend/app/_models/config.ts
index 11ddd516..0ded8049 100644
--- a/frontend/app/_models/config.ts
+++ b/frontend/app/_models/config.ts
@@ -30,6 +30,7 @@ export enum InstanceConfigItemKey {
authSignupConfirmCommenter = 'auth.signup.confirm.commenter',
authSignupConfirmUser = 'auth.signup.confirm.user',
authSignupEnabled = 'auth.signup.enabled',
+ authSsoSignupEnabled = 'auth.signup.sso.enabled',
integrationsUseGravatar = 'integrations.useGravatar',
operationNewOwnerEnabled = 'operation.newOwner.enabled',
// Domain defaults
diff --git a/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.spec.ts b/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.spec.ts
index b282586c..1eaf1085 100644
--- a/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.spec.ts
+++ b/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.spec.ts
@@ -21,6 +21,7 @@ describe('DynConfigItemNamePipe', () => {
{in: 'auth.signup.confirm.commenter', want: 'New commenters must confirm their email'},
{in: 'auth.signup.confirm.user', want: 'New users must confirm their email'},
{in: 'auth.signup.enabled', want: 'Enable registration of new users'},
+ {in: 'auth.signup.sso.enabled', want: 'Enable registration of new users via SSO' },
{in: 'integrations.useGravatar', want: 'Use Gravatar for user avatars'},
{in: 'operation.newOwner.enabled', want: 'Non-owner users can add domains'},
// Domain defaults
diff --git a/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.ts b/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.ts
index 7d3dc792..723e8149 100644
--- a/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.ts
+++ b/frontend/app/_modules/manage/_pipes/dyn-config-item-name.pipe.ts
@@ -12,6 +12,7 @@ export class DynConfigItemNamePipe implements PipeTransform {
[InstanceConfigItemKey.authSignupConfirmCommenter]: $localize`New commenters must confirm their email`,
[InstanceConfigItemKey.authSignupConfirmUser]: $localize`New users must confirm their email`,
[InstanceConfigItemKey.authSignupEnabled]: $localize`Enable registration of new users`,
+ [InstanceConfigItemKey.authSsoSignupEnabled]: $localize`Enable registration of new users via SSO`,
[InstanceConfigItemKey.integrationsUseGravatar]: $localize`Use Gravatar for user avatars`,
[InstanceConfigItemKey.operationNewOwnerEnabled]: $localize`Non-owner users can add domains`,
// Domain defaults
diff --git a/internal/api/restapi/handlers/oauth.go b/internal/api/restapi/handlers/oauth.go
index 0d8cd282..01324302 100644
--- a/internal/api/restapi/handlers/oauth.go
+++ b/internal/api/restapi/handlers/oauth.go
@@ -220,7 +220,7 @@ func AuthOauthCallback(params api_general.AuthOauthCallbackParams) middleware.Re
var cfgItem *data.DynConfigItem
if domain == nil {
// Frontend signup
- cfgItem, err = svc.Services.DynConfigService().Get(data.ConfigKeyAuthSignupEnabled)
+ cfgItem, err = svc.Services.DynConfigService().Get(data.ConfigKeyAuthSsoSignupEnabled)
} else if sso {
// SSO embed signup
@@ -248,9 +248,18 @@ func AuthOauthCallback(params api_general.AuthOauthCallbackParams) middleware.Re
return errors.New(errMessage)
}
+ // Check if the superuser claim is set
+ superuser := false
+ if raw, ok := fedUser.RawData[config.ServerConfig.SuperuserClaim]; ok {
+ if isAdmin, ok := raw.(bool); ok && isAdmin {
+ superuser = true
+ }
+ }
+
// Insert a new user
user = data.NewUser(fedUser.Email, fedUserName).
WithConfirmed(true). // Confirm the user right away as we trust the IdP
+ WithSuperuser(superuser).
WithLangFromReq(params.HTTPRequest).
WithSignup(params.HTTPRequest, authSession.Host, !config.ServerConfig.LogFullIPs).
WithFederated(fedUser.UserID, idpID).
diff --git a/internal/config/config.go b/internal/config/config.go
index e1292447..1715a7f6 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -36,6 +36,7 @@ type ServerConfiguration struct {
TemplatePath string `long:"template-path" description:"Path to template files" default:"./templates" env:"TEMPLATE_PATH"`
SecretsFile string `long:"secrets" description:"Path to YAML file with secrets" default:"secrets.yaml" env:"SECRETS_FILE"`
Superuser string `long:"superuser" description:"ID or email of user to be made superuser" default:"" env:"SUPERUSER"`
+ SuperuserClaim string `long:"superuser-claim" description:"Name of the OIDC claim for superusers" default:"is_superuser" env:"SUPERUSER_CLAIM"`
LogFullIPs bool `long:"log-full-ips" description:"Log IP addresses in full" env:"LOG_FULL_IPS"`
HomeContentURL string `long:"home-content-url" description:"URL of a HTML page to display on homepage" env:"HOME_CONTENT_URL"`
GitLabURL string `long:"gitlab-url" description:"Custom GitLab URL for authentication" default:"" env:"GITLAB_URL"`
diff --git a/internal/data/dyn_config.go b/internal/data/dyn_config.go
index 8595ea2a..621fd132 100644
--- a/internal/data/dyn_config.go
+++ b/internal/data/dyn_config.go
@@ -170,6 +170,7 @@ const (
ConfigKeyAuthSignupConfirmCommenter DynConfigItemKey = "auth.signup.confirm.commenter"
ConfigKeyAuthSignupConfirmUser DynConfigItemKey = "auth.signup.confirm.user"
ConfigKeyAuthSignupEnabled DynConfigItemKey = "auth.signup.enabled"
+ ConfigKeyAuthSsoSignupEnabled DynConfigItemKey = "auth.signup.sso.enabled"
ConfigKeyIntegrationsUseGravatar DynConfigItemKey = "integrations.useGravatar"
ConfigKeyOperationNewOwnerEnabled DynConfigItemKey = "operation.newOwner.enabled"
)
@@ -203,6 +204,7 @@ var DefaultDynInstanceConfig = DynConfigMap{
ConfigKeyAuthSignupConfirmCommenter: {DefaultValue: "true", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionAuth},
ConfigKeyAuthSignupConfirmUser: {DefaultValue: "true", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionAuth},
ConfigKeyAuthSignupEnabled: {DefaultValue: "true", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionAuth},
+ ConfigKeyAuthSsoSignupEnabled: {DefaultValue: "true", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionAuth},
ConfigKeyIntegrationsUseGravatar: {DefaultValue: "true", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionIntegrations},
ConfigKeyOperationNewOwnerEnabled: {DefaultValue: "false", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionMisc},
ConfigKeyDomainDefaultsPrefix + DomainConfigKeyCommentDeletionAuthor: {DefaultValue: "true", Datatype: ConfigDatatypeBool, Section: DynConfigItemSectionComments},

View File

@@ -13,6 +13,7 @@
docker-image-flaresolverr = import ./docker/flaresolverr { inherit pkgs; };
docker-image-gitea = import ./docker/gitea { inherit pkgs; };
docker-image-gitea-act-runner = import ./docker/gitea-act-runner { inherit pkgs; };
docker-image-gitea-act-runner-worker = import ./docker/gitea-act-runner-worker { inherit pkgs; };
docker-image-grafana = import ./docker/grafana { inherit pkgs; };
docker-image-grafana-image-renderer = import ./docker/grafana-image-renderer { inherit pkgs; };
docker-image-jellyfin = import ./docker/jellyfin { inherit pkgs; };

View File

@@ -0,0 +1,38 @@
{ pkgs, ... }:
let
containerPolicy = pkgs.writeTextDir "/etc/containers/policy.json" (
builtins.readFile (
(pkgs.formats.json { }).generate "policy.json" {
default = [ { type = "insecureAcceptAnything"; } ];
transports.docker-daemon."" = [ { type = "insecureAcceptAnything"; } ];
}
)
);
in
pkgs.dockerTools.buildImage {
name = "gitea-act-runner-worker";
fromImage = pkgs.docker-image-base;
copyToRoot = pkgs.buildEnv {
name = "root";
paths = with pkgs; [
git
git-lfs
curl
jq
nix
nodejs
buildah
skopeo
containerPolicy
];
pathsToLink = [
"/bin"
"/etc"
];
};
runAsRoot = ''
mkdir -p /var/tmp
'';
}

View File

@@ -10,16 +10,7 @@ let
runnerConfig = pkgs.writeTextDir "/etc/gitea-act-runner/config.yaml" (
builtins.readFile (
(pkgs.formats.yaml { }).generate "config.yaml" {
runner = {
file = "/var/lib/gitea-act-runner/registration";
capacity = 4;
labels = [
"ubuntu-latest:docker://catthehacker/ubuntu:act-latest"
"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04"
"ubuntu-20.04:docker://catthehacker/ubuntu:act-20.04"
"ubuntu-18.04:docker://catthehacker/ubuntu:act-18.04"
];
};
runner.file = "/var/lib/gitea-act-runner/registration";
cache.dir = "/tmp/gitea-act-runner/";
# https://gitea.com/gitea/act_runner/issues/223#issuecomment-743748
container.docker_host = "-";

View File

@@ -27,11 +27,14 @@ var (
maxUploadSize int64 = 1 << 30 // 1GB
deployLock sync.Mutex
infoLog = log.New(os.Stdout, "", log.LstdFlags)
errorLog = log.New(os.Stderr, "", log.LstdFlags)
)
func main() {
if authenticationKey == "" || targetDirectory == "" {
log.Fatal("AUTH_KEY and TARGET_DIR must be set")
errorLog.Fatal("AUTH_KEY and TARGET_DIR must be set")
}
if port == "" {
@@ -43,15 +46,15 @@ func main() {
basePath = "/" + subPath
}
log.Printf("starting server on :%s, endpoint %q, target directory %q", port, basePath, targetDirectory)
infoLog.Printf("starting server on :%s, endpoint %q, target directory %q", port, basePath, targetDirectory)
http.HandleFunc(basePath, withRecovery(handle))
log.Fatal(http.ListenAndServe(":"+port, nil))
errorLog.Fatal(http.ListenAndServe(":"+port, nil))
}
func handle(w http.ResponseWriter, r *http.Request) {
remoteIP := realIP(r)
log.Printf("incoming %q request on %q from %s", r.Method, r.URL.Path, remoteIP)
infoLog.Printf("incoming %q request on %q from %s", r.Method, r.URL.Path, remoteIP)
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
@@ -60,7 +63,7 @@ func handle(w http.ResponseWriter, r *http.Request) {
auth := r.Header.Get("Authorization")
if subtle.ConstantTimeCompare([]byte(auth), []byte(authenticationKey)) != 1 {
log.Printf("unauthorized request from %s", remoteIP)
errorLog.Printf("unauthorized request from %s", remoteIP)
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
@@ -112,7 +115,7 @@ func handle(w http.ResponseWriter, r *http.Request) {
defer os.RemoveAll(extractDir)
if err := extractor.Extract(ctx, archiveStream, extract(extractDir)); err != nil {
log.Printf("failed to extract archive: %v", err)
errorLog.Printf("failed to extract archive: %v", err)
http.Error(w, "bad archive", http.StatusBadRequest)
return
}
@@ -131,7 +134,7 @@ func handle(w http.ResponseWriter, r *http.Request) {
}
w.WriteHeader(http.StatusOK)
log.Printf("upload successful from %s", remoteIP)
infoLog.Printf("upload successful from %s", remoteIP)
}
func realIP(r *http.Request) string {
@@ -235,7 +238,7 @@ func withRecovery(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
defer func() {
if v := recover(); v != nil {
log.Printf("panic: %v", v)
errorLog.Printf("panic: %v", v)
http.Error(w, "internal error", http.StatusInternalServerError)
}
}()

View File

@@ -12,8 +12,12 @@ pkgs.stdenv.mkDerivation (finalAttrs: {
};
patches = [
# Fix variety typo
(builtins.fetchurl {
url = "https://patch-diff.githubusercontent.com/raw/Clemens-E/obsidian-languagetool-plugin/pull/132.patch";
sha256 = "sha256:13lzp0920h1kc9yl3r04r505zb417hlciyiwii0fm5b12g35av8v";
})
./settings-notification.patch
./variety-typo.patch
];
offlineCache = pkgs.fetchYarnDeps {

View File

@@ -1,149 +0,0 @@
diff --git a/src/SettingsTab.ts b/src/SettingsTab.ts
index d0d65bb..2a211b0 100644
--- a/src/SettingsTab.ts
+++ b/src/SettingsTab.ts
@@ -33,10 +33,10 @@ export interface LanguageToolPluginSettings {
staticLanguage?: string;
motherTongue?: string;
- englishVeriety?: undefined | 'en-US' | 'en-GB' | 'en-CA' | 'en-AU' | 'en-ZA' | 'en-NZ';
- germanVeriety?: undefined | 'de-DE' | 'de-AT' | 'de-CH';
- portugueseVeriety?: undefined | 'pt-BR' | 'pt-PT' | 'pt-AO' | 'pt-MZ';
- catalanVeriety?: undefined | 'ca-ES' | 'ca-ES-valencia';
+ englishVariety?: undefined | 'en-US' | 'en-GB' | 'en-CA' | 'en-AU' | 'en-ZA' | 'en-NZ';
+ germanVariety?: undefined | 'de-DE' | 'de-AT' | 'de-CH';
+ portugueseVariety?: undefined | 'pt-BR' | 'pt-PT' | 'pt-AO' | 'pt-MZ';
+ catalanVariety?: undefined | 'ca-ES' | 'ca-ES-valencia';
pickyMode: boolean;
@@ -286,13 +286,13 @@ export class LanguageToolSettingsTab extends PluginSettingTab {
component.onChange(async value => {
this.plugin.settings.staticLanguage = value;
if (value !== 'auto') {
- this.plugin.settings.englishVeriety = undefined;
+ this.plugin.settings.englishVariety = undefined;
englishVarietyDropdown?.setValue('default');
- this.plugin.settings.germanVeriety = undefined;
+ this.plugin.settings.germanVariety = undefined;
germanVarietyDropdown?.setValue('default');
- this.plugin.settings.portugueseVeriety = undefined;
+ this.plugin.settings.portugueseVariety = undefined;
portugueseVarietyDropdown?.setValue('default');
- this.plugin.settings.catalanVeriety = undefined;
+ this.plugin.settings.catalanVariety = undefined;
catalanVarietyDropdown?.setValue('default');
}
await this.plugin.saveSettings();
@@ -338,14 +338,14 @@ export class LanguageToolSettingsTab extends PluginSettingTab {
'en-ZA': 'English (South Africa)',
'en-NZ': 'English (New Zealand)',
})
- .setValue(this.plugin.settings.englishVeriety ?? 'default')
+ .setValue(this.plugin.settings.englishVariety ?? 'default')
.onChange(async value => {
if (value === 'default') {
- this.plugin.settings.englishVeriety = undefined;
+ this.plugin.settings.englishVariety = undefined;
} else {
this.plugin.settings.staticLanguage = 'auto';
staticLanguageComponent?.setValue('auto');
- this.plugin.settings.englishVeriety = value as 'en-US' | 'en-GB' | 'en-CA' | 'en-AU' | 'en-ZA' | 'en-NZ';
+ this.plugin.settings.englishVariety = value as 'en-US' | 'en-GB' | 'en-CA' | 'en-AU' | 'en-ZA' | 'en-NZ';
}
await this.plugin.saveSettings();
});
@@ -360,14 +360,14 @@ export class LanguageToolSettingsTab extends PluginSettingTab {
'de-CH': 'German (Switzerland)',
'de-AT': 'German (Austria)',
})
- .setValue(this.plugin.settings.germanVeriety ?? 'default')
+ .setValue(this.plugin.settings.germanVariety ?? 'default')
.onChange(async value => {
if (value === 'default') {
- this.plugin.settings.germanVeriety = undefined;
+ this.plugin.settings.germanVariety = undefined;
} else {
this.plugin.settings.staticLanguage = 'auto';
staticLanguageComponent?.setValue('auto');
- this.plugin.settings.germanVeriety = value as 'de-DE' | 'de-CH' | 'de-AT';
+ this.plugin.settings.germanVariety = value as 'de-DE' | 'de-CH' | 'de-AT';
}
await this.plugin.saveSettings();
});
@@ -383,14 +383,14 @@ export class LanguageToolSettingsTab extends PluginSettingTab {
'pt-AO': 'Portuguese (Angola)',
'pt-MZ': 'Portuguese (Mozambique)',
})
- .setValue(this.plugin.settings.portugueseVeriety ?? 'default')
+ .setValue(this.plugin.settings.portugueseVariety ?? 'default')
.onChange(async value => {
if (value === 'default') {
- this.plugin.settings.portugueseVeriety = undefined;
+ this.plugin.settings.portugueseVariety = undefined;
} else {
this.plugin.settings.staticLanguage = 'auto';
staticLanguageComponent?.setValue('auto');
- this.plugin.settings.portugueseVeriety = value as 'pt-BR' | 'pt-PT' | 'pt-AO' | 'pt-MZ';
+ this.plugin.settings.portugueseVariety = value as 'pt-BR' | 'pt-PT' | 'pt-AO' | 'pt-MZ';
}
await this.plugin.saveSettings();
});
@@ -404,14 +404,14 @@ export class LanguageToolSettingsTab extends PluginSettingTab {
'ca-ES': 'Catalan',
'ca-ES-valencia': 'Catalan (Valencian)',
})
- .setValue(this.plugin.settings.catalanVeriety ?? 'default')
+ .setValue(this.plugin.settings.catalanVariety ?? 'default')
.onChange(async value => {
if (value === 'default') {
- this.plugin.settings.catalanVeriety = undefined;
+ this.plugin.settings.catalanVariety = undefined;
} else {
this.plugin.settings.staticLanguage = 'auto';
staticLanguageComponent?.setValue('auto');
- this.plugin.settings.catalanVeriety = value as 'ca-ES' | 'ca-ES-valencia';
+ this.plugin.settings.catalanVariety = value as 'ca-ES' | 'ca-ES-valencia';
}
await this.plugin.saveSettings();
});
diff --git a/src/api.ts b/src/api.ts
index 109984c..4cd1700 100644
--- a/src/api.ts
+++ b/src/api.ts
@@ -58,27 +58,27 @@ export async function getDetectionResult(
params.disabledRules = settings.ruleOtherDisabledRules;
}
- if (settings.englishVeriety) {
+ if (settings.englishVariety) {
params.preferredVariants = `${params.preferredVariants ? `${params.preferredVariants},` : ''}${
- settings.englishVeriety
+ settings.englishVariety
}`;
}
- if (settings.germanVeriety) {
+ if (settings.germanVariety) {
params.preferredVariants = `${params.preferredVariants ? `${params.preferredVariants},` : ''}${
- settings.germanVeriety
+ settings.germanVariety
}`;
}
- if (settings.portugueseVeriety) {
+ if (settings.portugueseVariety) {
params.preferredVariants = `${params.preferredVariants ? `${params.preferredVariants},` : ''}${
- settings.portugueseVeriety
+ settings.portugueseVariety
}`;
}
- if (settings.catalanVeriety) {
+ if (settings.catalanVariety) {
params.preferredVariants = `${params.preferredVariants ? `${params.preferredVariants},` : ''}${
- settings.catalanVeriety
+ settings.catalanVariety
}`;
}

View File

@@ -1 +1,10 @@
{ patcher, ... }: { }
{ patcher, ... }:
{
quadlet-nix.patches = [
(patcher.fetchpatch {
name = "feat: supports images";
url = "https://github.com/SEIAROTg/quadlet-nix/compare/main...karaolidis:quadlet-nix:image.diff";
hash = "sha256-XLdOrSJ/gyLARGI0psBejtpX9Z2NSRTaUbFtBi8BxPw=";
})
];
}