diff --git a/docs/redirects.json b/docs/redirects.json index b5985c1..d9604aa 100644 --- a/docs/redirects.json +++ b/docs/redirects.json @@ -2213,6 +2213,9 @@ "services-forgejo-options-shb.forgejo.ldap.userGroup": [ "services-forgejo.html#services-forgejo-options-shb.forgejo.ldap.userGroup" ], + "services-forgejo-options-shb.forgejo.ldap.waitForSystemdServices": [ + "services-forgejo.html#services-forgejo-options-shb.forgejo.ldap.waitForSystemdServices" + ], "services-forgejo-options-shb.forgejo.localActionRunner": [ "services-forgejo.html#services-forgejo-options-shb.forgejo.localActionRunner" ], diff --git a/modules/blocks/lldap.nix b/modules/blocks/lldap.nix index 01445af..3c3e231 100644 --- a/modules/blocks/lldap.nix +++ b/modules/blocks/lldap.nix @@ -360,7 +360,7 @@ in inherit (cfg) ensureGroups ensureUserFields ensureGroupFields; ensureUsers = lib.mapAttrs (n: v: (lib.removeAttrs v [ "password" ]) // { - "password_file" = v.password.result.path; + "password_file" = toString v.password.result.path; }) cfg.ensureUsers; }; }; diff --git a/modules/services/forgejo.nix b/modules/services/forgejo.nix index 0b44f95..17739fa 100644 --- a/modules/services/forgejo.nix +++ b/modules/services/forgejo.nix @@ -108,6 +108,16 @@ in description = "Group users must belong to be admins."; default = "forgejo_admin"; }; + + waitForSystemdServices = mkOption { + type = listOf str; + default = []; + description = '' + List of systemd services to wait on before starting. + This is needed because forgejo will try a lookup on the LDAP instance + and will abort setting up LDAP if it can't reach it. + ''; + }; }; }); }; @@ -392,6 +402,8 @@ in # For cli info: https://docs.gitea.com/usage/command-line # Security protocols in: https://codeberg.org/forgejo/forgejo/src/branch/forgejo/services/auth/source/ldap/security_protocol.go#L27-L31 (mkIf (cfg.enable && cfg.ldap.enable != false) { + systemd.services.forgejo.wants = cfg.ldap.waitForSystemdServices; + systemd.services.forgejo.after = cfg.ldap.waitForSystemdServices; # The delimiter in the `cut` command is a TAB! systemd.services.forgejo.preStart = let provider = "SHB-${cfg.ldap.provider}"; diff --git a/test/common.nix b/test/common.nix index 86eb5f1..eec536e 100644 --- a/test/common.nix +++ b/test/common.nix @@ -120,22 +120,22 @@ let + (optionalString (hasAttr "test" nodes.server && hasAttr "login" nodes.server.test) '' with subtest("Login from server"): code, logs = server.execute("login_playwright") + print(logs) try: server.copy_from_vm("trace") except: print("No trace found on server") - print(logs) if code != 0: raise Exception("login_playwright did not succeed") '') + (optionalString (hasAttr "test" nodes.client && hasAttr "login" nodes.client.test) '' with subtest("Login from client"): code, logs = client.execute("login_playwright") + print(logs) try: - server.copy_from_vm("trace") + client.copy_from_vm("trace") except: print("No trace found on client") - print(logs) if code != 0: raise Exception("login_playwright did not succeed") '') @@ -319,6 +319,7 @@ in print(f"Page has title: {page.title()}") exec(line) finally: + print(f'Saving trace at trace/{i}.zip') context.tracing.stop(path=f"trace/{i}.zip") browser.close() @@ -401,6 +402,24 @@ in dcdomain = "dc=example,dc=com"; ldapUserPassword.result = config.shb.hardcodedsecret.ldapUserPassword.result; jwtSecret.result = config.shb.hardcodedsecret.jwtSecret.result; + + ensureUsers = { + alice = { + email = "alice@example.com"; + groups = [ "user_group" ]; + password.result.path = pkgs.writeText "alicePassword" "AlicePassword"; + }; + bob = { + email = "bob@example.com"; + groups = [ "user_group" "admin_group" ]; + password.result.path = pkgs.writeText "bobPassword" "BobPassword"; + }; + }; + + ensureGroups = { + user_group = {}; + admin_group = {}; + }; }; }; diff --git a/test/services/forgejo.nix b/test/services/forgejo.nix index 9d7ce7b..72b9b58 100644 --- a/test/services/forgejo.nix +++ b/test/services/forgejo.nix @@ -118,6 +118,9 @@ let port = config.shb.lldap.ldapPort; dcdomain = config.shb.lldap.dcdomain; adminPassword.result = config.shb.hardcodedsecret.forgejoLdapUserPassword.result; + waitForSystemdServices = [ "lldap.service" ]; + + userGroup = "user_group"; }; }; @@ -200,6 +203,8 @@ in ldap = pkgs.testers.runNixOSTest { name = "forgejo_ldap"; + interactive.sshBackdoor.enable = true; + nodes.server = { imports = [ basic @@ -208,7 +213,45 @@ in ]; }; - nodes.client = {}; + nodes.client = { + imports = [ + ({ config, ... }: { + imports = [ + testLib.baseModule + testLib.clientLoginModule + ]; + + test = { + subdomain = "f"; + }; + + test.login = { + startUrl = "http://${config.test.fqdn}/user/login"; + usernameFieldLabelRegex = "Username or email address"; + passwordFieldLabelRegex = "Password"; + loginButtonNameRegex = "[sS]ign [iI]n"; + testLoginWith = [ + { username = "alice"; password = "NotAlicePassword"; nextPageExpect = [ + "expect(page.get_by_text('Username or password is incorrect.')).to_be_visible()" + ]; } + { username = "alice"; password = "AlicePassword"; 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'))" + ]; } + { username = "bob"; password = "NotBobPassword"; nextPageExpect = [ + "expect(page.get_by_text('Username or password is incorrect.')).to_be_visible()" + ]; } + { username = "bob"; password = "BobPassword"; 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'))" + ]; } + ]; + }; + }) + ]; + }; testScript = commonTestScript.access; };