From d5293825e99400aee2df0b27a6a1adb5f653082f Mon Sep 17 00:00:00 2001 From: ibizaman Date: Sun, 26 Jan 2025 22:27:22 +0100 Subject: [PATCH] add option to create forgejo users declaratively --- CHANGELOG.md | 2 +- docs/redirects.json | 42 ++++++++++++++----------- modules/services/forgejo.nix | 61 +++++++++++++++++++++++------------- test/services/forgejo.nix | 28 +++++++++++++++-- 4 files changed, 90 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c9e72e..2846975 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ Template: ## New Features -- Add option to select name of admin user for Forgejo. +- Add `shb.forgejo.users` option to create users declaratively. ## Fixes diff --git a/docs/redirects.json b/docs/redirects.json index 6fc54b3..ef13980 100644 --- a/docs/redirects.json +++ b/docs/redirects.json @@ -968,32 +968,38 @@ "services-forgejo-options": [ "services-forgejo.html#services-forgejo-options" ], - "services-forgejo-options-shb.forgejo.adminUsername": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.adminUsername" + "services-forgejo-options-shb.forgejo.users": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.users" ], - "services-forgejo-options-shb.forgejo.adminPassword": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.adminPassword" + "services-forgejo-options-shb.forgejo.users._name_.email": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.users._name_.email" ], - "services-forgejo-options-shb.forgejo.adminPassword.request": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.adminPassword.request" + "services-forgejo-options-shb.forgejo.users._name_.isAdmin": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.users._name_.isAdmin" ], - "services-forgejo-options-shb.forgejo.adminPassword.request.group": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.adminPassword.request.group" + "services-forgejo-options-shb.forgejo.users._name_.password": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.users._name_.password" ], - "services-forgejo-options-shb.forgejo.adminPassword.request.mode": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.adminPassword.request.mode" + "services-forgejo-options-shb.forgejo.users._name_.password.request": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.users._name_.password.request" ], - "services-forgejo-options-shb.forgejo.adminPassword.request.owner": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.adminPassword.request.owner" + "services-forgejo-options-shb.forgejo.users._name_.password.request.group": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.users._name_.password.request.group" ], - "services-forgejo-options-shb.forgejo.adminPassword.request.restartUnits": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.adminPassword.request.restartUnits" + "services-forgejo-options-shb.forgejo.users._name_.password.request.mode": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.users._name_.password.request.mode" ], - "services-forgejo-options-shb.forgejo.adminPassword.result": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.adminPassword.result" + "services-forgejo-options-shb.forgejo.users._name_.password.request.owner": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.users._name_.password.request.owner" ], - "services-forgejo-options-shb.forgejo.adminPassword.result.path": [ - "services-forgejo.html#services-forgejo-options-shb.forgejo.adminPassword.result.path" + "services-forgejo-options-shb.forgejo.users._name_.password.request.restartUnits": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.users._name_.password.request.restartUnits" + ], + "services-forgejo-options-shb.forgejo.users._name_.password.result": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.users._name_.password.result" + ], + "services-forgejo-options-shb.forgejo.users._name_.password.result.path": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.users._name_.password.result.path" ], "services-forgejo-options-shb.forgejo.backup": [ "services-forgejo.html#services-forgejo-options-shb.forgejo.backup" diff --git a/modules/services/forgejo.nix b/modules/services/forgejo.nix index fa98340..0b44f95 100644 --- a/modules/services/forgejo.nix +++ b/modules/services/forgejo.nix @@ -5,8 +5,8 @@ let contracts = pkgs.callPackage ../contracts {}; - inherit (lib) getExe lists literalExpression mkBefore mkEnableOption mkForce mkIf mkMerge mkOption mkOverride optionals; - inherit (lib.types) bool enum listOf nullOr package port submodule str; + inherit (lib) all attrNames concatMapStringsSep getExe lists literalExpression mapAttrsToList mkBefore mkEnableOption mkForce mkIf mkMerge mkOption mkOverride nameValuePair optionalString optionals; + inherit (lib.types) attrsOf bool enum listOf nullOr package port submodule str; in { options.shb.forgejo = { @@ -170,22 +170,37 @@ in }; }; - adminUsername = mkOption { - type = str; - description = "Forgejo admin user name."; - default = "admin"; - }; + users = mkOption { + description = "Users managed declaratively."; + type = attrsOf (submodule { + options = { + isAdmin = mkOption { + description = "Set user as admin or not."; + type = bool; + default = false; + }; - adminPassword = mkOption { - description = "Forgejo admin user password."; - type = submodule { - options = contracts.secret.mkRequester { - mode = "0440"; - owner = "forgejo"; - group = "forgejo"; - restartUnits = [ "forgejo.service" ]; + email = mkOption { + description = ''Email of user. + + This is only set when the user is created, changing this later on will have no effect. + ''; + type = str; + }; + + password = mkOption { + description = "Forgejo admin user password."; + type = submodule { + options = contracts.secret.mkRequester { + mode = "0440"; + owner = "forgejo"; + group = "forgejo"; + restartUnits = [ "forgejo.service" ]; + }; + }; + }; }; - }; + }); }; databasePassword = mkOption { @@ -503,16 +518,20 @@ in (mkIf cfg.enable { assertions = [ { - assertion = cfg.adminUsername != "admin"; - message = "Admin username cannot be 'admin'."; + assertion = all (u: u != "admin") (attrNames cfg.users); + message = "Username cannot be 'admin'."; } ]; systemd.services.forgejo.preStart = '' admin="${getExe config.services.forgejo.package} admin user" - $admin create --admin --must-change-password=false --email "root@localhost" --username "${cfg.adminUsername}" --password "$(tr -d '\n' < ${cfg.adminPassword.result.path})" || true - $admin change-password --must-change-password=false --username "${cfg.adminUsername}" --password "$(tr -d '\n' < ${cfg.adminPassword.result.path})" || true -''; + '' + concatMapStringsSep "\n" (u: '' + if ! $admin list | grep "${u.name}"; then + $admin create ${optionalString u.value.isAdmin "--admin"} --email "${u.value.email}" --must-change-password=false --username "${u.name}" --password "$(tr -d '\n' < ${u.value.password.result.path})" + else + $admin change-password --must-change-password=false --username "${u.name}" --password "$(tr -d '\n' < ${u.value.password.result.path})" + fi +'') (mapAttrsToList nameValuePair cfg.users); }) (mkIf (cfg.enable && cfg.smtp != null) { diff --git a/test/services/forgejo.nix b/test/services/forgejo.nix index ec535df..4467e10 100644 --- a/test/services/forgejo.nix +++ b/test/services/forgejo.nix @@ -34,8 +34,17 @@ let enable = true; inherit (config.test) subdomain domain; - adminUsername = "theadmin"; - adminPassword.result = config.shb.hardcodedsecret.forgejoAdminPassword.result; + users = { + "theadmin" = { + isAdmin = true; + email = "theadmin@example.com"; + password.result = config.shb.hardcodedsecret.forgejoAdminPassword.result; + }; + "theuser" = { + email = "theuser@example.com"; + password.result = config.shb.hardcodedsecret.forgejoUserPassword.result; + }; + }; databasePassword.result = config.shb.hardcodedsecret.forgejoDatabasePassword.result; }; @@ -45,10 +54,15 @@ let }; shb.hardcodedsecret.forgejoAdminPassword = { - request = config.shb.forgejo.adminPassword.request; + request = config.shb.forgejo.users."theadmin".password.request; settings.content = adminPassword; }; + shb.hardcodedsecret.forgejoUserPassword = { + request = config.shb.forgejo.users."theuser".password.request; + settings.content = "userPassword"; + }; + shb.hardcodedsecret.forgejoDatabasePassword = { request = config.shb.forgejo.databasePassword.request; settings.content = "databasePassword"; @@ -78,6 +92,14 @@ let "expect(page.get_by_role('button', name=re.compile('Sign In'))).not_to_be_visible()" "expect(page).to_have_title(re.compile('Dashboard'))" ]; } + { username = "theuser"; password = "userPasswordOops"; nextPageExpect = [ + "expect(page.get_by_text('Username or password is incorrect.')).to_be_visible()" + ]; } + { username = "theuser"; password = "userPassword"; nextPageExpect = [ + "expect(page.get_by_text('Username or password is incorrect.')).not_to_be_visible()" + "expect(page.get_by_role('button', name=re.compile('Sign In'))).not_to_be_visible()" + "expect(page).to_have_title(re.compile('Dashboard'))" + ]; } ]; }; };