add backend for join form #308 #438
No reviewers
Labels
No labels
bug
duplicate
enhancement
help wanted
high priority
invalid
L
low priority
M
medium priority
needs refinement
optional
question
S
UX research
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: local-it/mitgliederverwaltung#438
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feature/concept-web-form-308"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Description of the implemented changes
The changes were:
Backend for public join requests (onboarding flow, Issue #308 – Subtask 1). Introduces the
JoinRequestresource and persistence so that a confirmation flow can create records after email confirmation. No UI, no emails, no pre-confirmation logic in this PR. Security-focused: no public read on JoinRequest; idempotent confirm via unique constraint. Refactoring applies review feedback (narrow public API, server-set metadata only).What has been changed?
Concept & docs
docs/onboarding-join-concept.md(design, data model, implementation plan for public join and later approval).docs/development-progress-log.md.JoinRequest resource (
lib/membership/join_request.ex)email,confirmation_token_hash,status,submitted_at,source,schema_version,payload, and audit fields (approved_at,rejected_at,reviewed_by_user_id).admin_read(primary); requires permission (e.g. admin). No public read – unauthenticated callers cannot list or read JoinRequests.create(for admins) andconfirm(public,actor: nil).confirmaccepts onlyemail,confirmation_token_hash,payload; server setsstatus,submitted_at,source,schema_versionvia change module.confirmallowed withactor_absent();admin_read,create,update,destroyrequireHasPermission.confirmation_token_hashfor idempotency.Change module (
lib/membership/join_request/changes/set_confirm_server_metadata.ex)confirmso clients cannot setstatus,source, etc.Domain (
lib/membership/membership.ex)confirm_join_request/2: builds and runsconfirmcreate; on unique-constraint violation (duplicate token) returns{:ok, nil}(idempotent, no record returned).list_join_requestsandget_join_requestuseadmin_read.Authorization
lib/mv/authorization/permission_sets.ex: JoinRequest added to admin permission set (read/create/update/destroy, scope :all).Migrations
20260220120000_add_join_requests.exs: tablejoin_requestswith unique index onconfirmation_token_hash.20260220120001_alter_join_requests_schema_version_to_integer.exs:schema_versionfrom bigint to integer.Tests (
test/mv/membership/join_request_test.exs)actor: nil; no public read (actor nil cannot read by id or list); genericcreatewith actor nil forbidden; idempotency (second confirm with same token returns{:ok, nil}, single record); minimal attributes and required email. Count vialist_join_requests(actor: system_actor)(noauthorize?: false).Gettext
Definition of Done
Code Quality
Accessibility
(N/A – no UI or HTML in this PR; backend only.)
Testing
(N/A – no frontend; axe not applicable.)
Additional Notes
docs/onboarding-join-concept.md. Follow-up work (separate PRs): pre-confirmation store + confirmation email + route/confirm_join/:token(Subtask 2); admin join-form settings (Subtask 3); public/joinpage + anti-abuse (Subtask 4).confirmation_token_hashand returning{:ok, nil}instead of exposing the existing record.confirmaccepts only client payload (email,confirmation_token_hash,payload); server metadata set in change;schema_versionaligned to integer in DB; tests no longer useauthorize?: falsefor counting (admin list used instead); Credo addressed (aliases for nested modules).{:ok, nil}fromconfirm_join_request/2as “already confirmed” and show the same success outcome as the first confirmation.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.