import { chromium } from "@playwright/test"; import { GenericContainer } from "testcontainers"; import { describe, expect, test } from "vitest"; import { OnboardingActions } from "./shared/actions/onboarding-actions"; import { createHomarrContainer, withLogs } from "./shared/create-homarr-container"; import { createSqliteDbFileAsync } from "./shared/e2e-db"; const defaultCredentials = { username: "admin", password: "password", email: "admin@homarr.dev", group: "lldap_admin", }; const ldapBase = "dc=example,dc=com"; describe("LLDAP authorization", () => { test("Authorize with LLDAP successfully", async () => { // Arrange const lldapContainer = await createLldapContainer().start(); const { db, localMountPath } = await createSqliteDbFileAsync(); const homarrContainer = await createHomarrContainer({ environment: { AUTH_PROVIDERS: "ldap", AUTH_LDAP_URI: `ldap://host.docker.internal:${lldapContainer.getMappedPort(3890)}`, AUTH_LDAP_BASE: ldapBase, AUTH_LDAP_BIND_DN: `uid=${defaultCredentials.username},ou=People,${ldapBase}`, AUTH_LDAP_BIND_PASSWORD: defaultCredentials.password, }, mounts: { "/appdata": localMountPath, }, }).start(); const browser = await chromium.launch(); const context = await browser.newContext(); const page = await context.newPage(); try { const onboardingActions = new OnboardingActions(page, db); await onboardingActions.skipOnboardingAsync({ group: defaultCredentials.group, }); // Act const baseUrl = `http://${homarrContainer.getHost()}:${homarrContainer.getMappedPort(7575)}`; await page.goto(`${baseUrl}/auth/login`); await page.getByLabel("Username").fill(defaultCredentials.username); await page.locator("#password").fill(defaultCredentials.password); await page.locator("css=button[type='submit']").click(); // Assert await page.waitForURL(baseUrl, { timeout: 60_000 }); const users = await db.query.users.findMany({ with: { groups: { with: { group: true, }, }, }, }); expect(users).toHaveLength(1); const user = users[0]; if (!user) { throw new Error("Expected LDAP login to create one user"); } expect(user).toEqual( expect.objectContaining({ name: defaultCredentials.username, email: defaultCredentials.email, provider: "ldap", }), ); const groups = user.groups.map((g) => g.group.name); expect(groups).toContain(defaultCredentials.group); } finally { await Promise.all([browser.close(), homarrContainer.stop(), lldapContainer.stop()]); } }, 120_000); }); const createLldapContainer = () => { return withLogs( new GenericContainer("lldap/lldap:stable").withExposedPorts(3890).withEnvironment({ LLDAP_JWT_SECRET: "REPLACE_WITH_RANDOM", LLDAP_KEY_SEED: "REPLACE_WITH_RANDOM", LLDAP_LDAP_BASE_DN: ldapBase, LLDAP_LDAP_USER_PASS: defaultCredentials.password, LLDAP_LDAP_USER_EMAIL: defaultCredentials.email, }), ); };