4 Commits

Author SHA1 Message Date
d59ec55999 Remove persistent LDAP volumes so bootstrap.ldif always applies on startup
All checks were successful
linter / quality (pull_request) Successful in 1m45s
security / Dependency Audit (pull_request) Successful in 1m21s
security / Static Analysis (pull_request) Successful in 2m11s
tests / ci (8.4) (pull_request) Successful in 1m27s
tests / ci (8.5) (pull_request) Successful in 2m21s
The osixia/openldap image only runs bootstrap LDIF when the database is
empty. Named volumes (sail-ldap-data, sail-ldap-config) caused changes
to bootstrap.ldif to be ignored after the first run. Removing these
volumes ensures the test LDAP directory is always seeded fresh from the
bootstrap file on each sail up.
2026-03-06 04:02:18 +00:00
9f47e6e2c8 Seed OpenLDAP with bootstrap users including email addresses
All checks were successful
linter / quality (pull_request) Successful in 1m20s
security / Dependency Audit (pull_request) Successful in 2m22s
security / Static Analysis (pull_request) Successful in 1m42s
tests / ci (8.4) (pull_request) Successful in 1m25s
tests / ci (8.5) (pull_request) Successful in 1m24s
Add docker/openldap/bootstrap.ldif which creates an ou=people OU and
three test users (admin, approver, staff) each with a mail attribute,
matching the database seeder. Mount the LDIF into the openldap container
and add --copy-service so it is loaded on first boot.
2026-03-06 02:47:54 +00:00
fd53a28f03 Merge pull request 'Fix LDAP authentication failures' (#7) from worktree-ldap-issues into master
Some checks failed
linter / quality (push) Successful in 1m23s
security / Dependency Audit (push) Successful in 1m29s
security / Static Analysis (push) Successful in 1m42s
tests / ci (8.5) (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
Reviewed-on: #7
2026-03-06 10:35:45 +08:00
bbcffe64b7 Fix LDAP authentication failures
All checks were successful
linter / quality (pull_request) Successful in 1m35s
security / Dependency Audit (pull_request) Successful in 1m19s
security / Static Analysis (pull_request) Successful in 1m32s
tests / ci (8.4) (pull_request) Successful in 2m36s
tests / ci (8.5) (pull_request) Successful in 1m37s
- Add missing LDAP env vars to .env.example (host, base DN, bind credentials)
- Use 'uid' instead of 'username' as the LDAP lookup attribute in Auth::attempt
- Override getLdapGuidColumn/getLdapDomainColumn in User model to match
  migration column names (ldap_guid/ldap_domain vs default guid/domain)
2026-03-06 02:34:46 +00:00
5 changed files with 66 additions and 7 deletions

View File

@@ -63,3 +63,10 @@ AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
VITE_APP_NAME="${APP_NAME}"
LDAP_HOST=openldap
LDAP_USERNAME="cn=admin,dc=travel,dc=local"
LDAP_PASSWORD=adminpassword
LDAP_PORT=389
LDAP_BASE_DN="dc=travel,dc=local"
LDAP_LOGGING=true

View File

@@ -64,6 +64,16 @@ class User extends Authenticatable implements FilamentUser, LdapAuthenticatable
return $this->hasRole('administrator');
}
public function getLdapGuidColumn(): string
{
return 'ldap_guid';
}
public function getLdapDomainColumn(): string
{
return 'ldap_domain';
}
public function emergencyContacts(): HasMany
{
return $this->hasMany(EmergencyContact::class);

View File

@@ -84,6 +84,7 @@ services:
- sail
openldap:
image: 'osixia/openldap:1.5.0'
command: '--copy-service'
ports:
- '${FORWARD_LDAP_PORT:-389}:389'
- '${FORWARD_LDAPS_PORT:-636}:636'
@@ -96,8 +97,7 @@ services:
LDAP_READONLY_USER_USERNAME: '${LDAP_READONLY_USERNAME:-readonly}'
LDAP_READONLY_USER_PASSWORD: '${LDAP_READONLY_PASSWORD:-readonly}'
volumes:
- 'sail-ldap-data:/var/lib/ldap'
- 'sail-ldap-config:/etc/ldap/slapd.d'
- './docker/openldap/bootstrap.ldif:/container/service/slapd/assets/config/bootstrap/ldif/custom/bootstrap.ldif'
networks:
- sail
healthcheck:
@@ -134,7 +134,3 @@ volumes:
driver: local
sail-redis:
driver: local
sail-ldap-data:
driver: local
sail-ldap-config:
driver: local

View File

@@ -0,0 +1,46 @@
# People OU
dn: ou=people,dc=travel,dc=local
objectClass: organizationalUnit
ou: people
# Administrator
dn: uid=admin,ou=people,dc=travel,dc=local
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
cn: Administrator
sn: Administrator
uid: admin
mail: admin@travel.local
uidNumber: 1000
gidNumber: 1000
homeDirectory: /home/admin
userPassword: password
# Travel Approver
dn: uid=approver,ou=people,dc=travel,dc=local
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
cn: Travel Approver
sn: Approver
uid: approver
mail: approver@travel.local
uidNumber: 1001
gidNumber: 1000
homeDirectory: /home/approver
userPassword: password
# Staff Member
dn: uid=staff,ou=people,dc=travel,dc=local
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
cn: Staff Member
sn: Member
uid: staff
mail: staff@travel.local
uidNumber: 1002
gidNumber: 1000
homeDirectory: /home/staff
userPassword: password

View File

@@ -18,7 +18,7 @@ new #[Layout('components.layouts.guest')] class extends Component {
{
$this->validate();
if (Auth::attempt(['username' => $this->username, 'password' => $this->password], $this->rememberMe)) {
if (Auth::attempt(['uid' => $this->username, 'password' => $this->password], $this->rememberMe)) {
session()->regenerate();
$this->redirectIntended(route('dashboard'), navigate: true);
return;