KolektivComputer / KolektivComputer/kalendee
LDAP M2: auto-provisioning, user_identities, and admin visibility
- Dominant language
- Kotlin
- Stars
- 0
- Forks
- 0
- Avg merge
- 11h 20m
- Merged PRs (30d)
- 23
Description
## Context
M2 turns a successful directory bind into a local Kalendee user on first login and records where the account came from. A shared `user_identities` table maps (`source`, `subject`) to a user and is also the natural home for OAuth identity links, and admins need to see the account source. Directory-backed accounts must not pretend they can change local passwords.
## Tasks
- [ ] Migration: `user_identities` (`user_id`, `source`, `subject`, `email`, timestamps; `UNIQUE(source, subject)`) — design alongside the OAuth identity storage from `feat/oauth-foundation`
- [ ] First-login provisioning: create the user with a random unguessable password hash, verified email from the directory, collision-safe username generation
- [ ] Repeat logins resolve to the existing user via `user_identities` (no duplicates, case-normalized)
- [ ] `authSource` (`local` | `ldap` | `google` | `microsoft`) surfaced in admin user list/detail
- [ ] Hide/disable password change and reset fields for directory accounts (UI + server guard)
- [ ] Account deletion cascades through `user_identities`
- [ ] Tests: first/repeat login, username collision, admin source display, password-field guard
## References
- #9 (LDAP M1) — `UserDirectory` seam
- `server/src/main/kotlin/dev/kolektiv/kalendee/auth/AuthService.kt`
- `server/src/main/kotlin/dev/kolektiv/kalendee/organizations/OrganizationService.kt` — member identity shape
- `server/pack/src/pages/kalendee/admin/+page.svelte`
- `server/src/main/resources/db/migration/V17__external_calendars.sql` — OAuth connection model
- `docs/external-calendars.md` — identity edge cases (unverified email, duplicate usernames, first-user admin)
## Dependencies
- **Depends on #9 (LDAP M1).**
- Identity table coordinates with the OAuth foundation on `feat/oauth-foundation` (currently being restored) so both sources share one model.
- #11 (M3) builds on provisioning.
Contributor guide
Assessment
This issue has not been assessed yet.