add playwright test with ldap for forgejo

This commit is contained in:
ibizaman 2025-07-24 22:44:34 +02:00 committed by Pierre Penninckx
parent 12f2b4f49e
commit 91580421be
5 changed files with 82 additions and 5 deletions

View file

@ -2213,6 +2213,9 @@
"services-forgejo-options-shb.forgejo.ldap.userGroup": [ "services-forgejo-options-shb.forgejo.ldap.userGroup": [
"services-forgejo.html#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-options-shb.forgejo.localActionRunner": [
"services-forgejo.html#services-forgejo-options-shb.forgejo.localActionRunner" "services-forgejo.html#services-forgejo-options-shb.forgejo.localActionRunner"
], ],

View file

@ -360,7 +360,7 @@ in
inherit (cfg) ensureGroups ensureUserFields ensureGroupFields; inherit (cfg) ensureGroups ensureUserFields ensureGroupFields;
ensureUsers = lib.mapAttrs (n: v: (lib.removeAttrs v [ "password" ]) // { ensureUsers = lib.mapAttrs (n: v: (lib.removeAttrs v [ "password" ]) // {
"password_file" = v.password.result.path; "password_file" = toString v.password.result.path;
}) cfg.ensureUsers; }) cfg.ensureUsers;
}; };
}; };

View file

@ -108,6 +108,16 @@ in
description = "Group users must belong to be admins."; description = "Group users must belong to be admins.";
default = "forgejo_admin"; 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 # 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 # 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) { (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! # The delimiter in the `cut` command is a TAB!
systemd.services.forgejo.preStart = let systemd.services.forgejo.preStart = let
provider = "SHB-${cfg.ldap.provider}"; provider = "SHB-${cfg.ldap.provider}";

View file

@ -120,22 +120,22 @@ let
+ (optionalString (hasAttr "test" nodes.server && hasAttr "login" nodes.server.test) '' + (optionalString (hasAttr "test" nodes.server && hasAttr "login" nodes.server.test) ''
with subtest("Login from server"): with subtest("Login from server"):
code, logs = server.execute("login_playwright") code, logs = server.execute("login_playwright")
print(logs)
try: try:
server.copy_from_vm("trace") server.copy_from_vm("trace")
except: except:
print("No trace found on server") print("No trace found on server")
print(logs)
if code != 0: if code != 0:
raise Exception("login_playwright did not succeed") raise Exception("login_playwright did not succeed")
'') '')
+ (optionalString (hasAttr "test" nodes.client && hasAttr "login" nodes.client.test) '' + (optionalString (hasAttr "test" nodes.client && hasAttr "login" nodes.client.test) ''
with subtest("Login from client"): with subtest("Login from client"):
code, logs = client.execute("login_playwright") code, logs = client.execute("login_playwright")
print(logs)
try: try:
server.copy_from_vm("trace") client.copy_from_vm("trace")
except: except:
print("No trace found on client") print("No trace found on client")
print(logs)
if code != 0: if code != 0:
raise Exception("login_playwright did not succeed") raise Exception("login_playwright did not succeed")
'') '')
@ -319,6 +319,7 @@ in
print(f"Page has title: {page.title()}") print(f"Page has title: {page.title()}")
exec(line) exec(line)
finally: finally:
print(f'Saving trace at trace/{i}.zip')
context.tracing.stop(path=f"trace/{i}.zip") context.tracing.stop(path=f"trace/{i}.zip")
browser.close() browser.close()
@ -401,6 +402,24 @@ in
dcdomain = "dc=example,dc=com"; dcdomain = "dc=example,dc=com";
ldapUserPassword.result = config.shb.hardcodedsecret.ldapUserPassword.result; ldapUserPassword.result = config.shb.hardcodedsecret.ldapUserPassword.result;
jwtSecret.result = config.shb.hardcodedsecret.jwtSecret.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 = {};
};
}; };
}; };

View file

@ -118,6 +118,9 @@ let
port = config.shb.lldap.ldapPort; port = config.shb.lldap.ldapPort;
dcdomain = config.shb.lldap.dcdomain; dcdomain = config.shb.lldap.dcdomain;
adminPassword.result = config.shb.hardcodedsecret.forgejoLdapUserPassword.result; adminPassword.result = config.shb.hardcodedsecret.forgejoLdapUserPassword.result;
waitForSystemdServices = [ "lldap.service" ];
userGroup = "user_group";
}; };
}; };
@ -200,6 +203,8 @@ in
ldap = pkgs.testers.runNixOSTest { ldap = pkgs.testers.runNixOSTest {
name = "forgejo_ldap"; name = "forgejo_ldap";
interactive.sshBackdoor.enable = true;
nodes.server = { nodes.server = {
imports = [ imports = [
basic 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; testScript = commonTestScript.access;
}; };