Commit graph

185 commits

Author SHA1 Message Date
a008cf381a
feat(vereinfacht): add client, sync flash and SyncContact change
- Application: create SyncFlash ETS table on start
- Vereinfacht: Client, SyncFlash, sync_member, format_error, sync_members_without_contact
- SyncContact change on Member create_member and update_member
- Member: attribute vereinfacht_contact_id, internal action set_vereinfacht_contact_id
2026-02-23 19:51:31 +01:00
a5a4d66655
feat(vereinfacht): add DB schema, config and setting attributes
- Migrations: vereinfacht_contact_id on members, vereinfacht_* on settings
- Mv.Config: Vereinfacht ENV/Settings helpers, vereinfacht_configured?, contact_view_url
- Setting: vereinfacht_api_url, api_key, club_id
2026-02-23 19:51:31 +01:00
397f7a7975 fix linting
Some checks failed
continuous-integration/drone/push Build is failing
2026-02-20 09:16:38 +01:00
cb932ad6ef feat: respects sorting groups for export
Some checks failed
continuous-integration/drone/push Build is failing
2026-02-20 08:45:55 +01:00
01f62297fc feat: add groups to export 2026-02-19 14:36:35 +01:00
b18f895939 chore: rename ImportExport module to Import
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/promote/production Build is passing
2026-02-17 18:59:18 +01:00
22458cd52b Merge branch 'main' into feature/286_export_pdf
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/promote/production Build is passing
2026-02-13 17:40:39 +01:00
baa288bff3 refactor 2026-02-13 17:21:14 +01:00
b416944321 Statistics: log Ash errors instead of returning 0/nil silently 2026-02-12 19:35:48 +01:00
490dced8c8 Statistics: member stats independent of fee type 2026-02-12 19:35:48 +01:00
a263cb4954 Pass actor through CycleGenerator so seeds can use admin
- get_actor(opts): use opts[:actor] or system actor
- load_member, do_generate_cycles, create_cycles pass opts
- Seeds pass admin_user_with_role for Ash.load! and cycle updates
2026-02-12 19:35:48 +01:00
919a8e4ebd Add statistics route, permissions, and sidebar entry
- /statistics route and PagePaths.statistics
- Permission sets: viewer and admin can access /statistics
- Sidebar link with can_access_page check
- Plug and sidebar tests updated
2026-02-12 19:35:48 +01:00
fd10fe5cf6 Add Statistics module for member and cycle aggregates
- first_join_year, active/inactive counts, joins/exits by year
- cycle_totals_by_year, open_amount_total
- Unit tests for Statistics
2026-02-12 19:35:48 +01:00
fd1f4d02d5 style: fix styling 2026-02-11 13:55:02 +01:00
f6b35f03a5 feat: adds pdf export with imprintor
Some checks failed
continuous-integration/drone/push Build is failing
2026-02-11 11:47:26 +01:00
e68a7cf8c7 fix linting
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/promote/production Build is passing
2026-02-09 14:08:12 +01:00
e1266944b1 feat: add membership fee status to columns and dropdown 2026-02-09 13:34:38 +01:00
36e57b24be Merge branch 'main' into feature/export_csv
Some checks failed
continuous-integration/drone/push Build is failing
2026-02-06 08:02:05 +01:00
9b9e7ec995 fix: sorting and filter for export 2026-02-05 15:03:25 +01:00
ad54b0c462 Release.seed_admin: ensure app started when run via bin/mv eval
Some checks reported errors
continuous-integration/drone/push Build was killed
continuous-integration/drone/promote/production Build is passing
Application.ensure_all_started(:mv) so Ash/Telemetry work (ETS table exists).
Fixes Unknown Error / telemetry_handler_table in production entrypoint.
2026-02-04 21:33:41 +01:00
ad42a53919 OIDC sign-in: robust after_action for get? result, non-bang role sync
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/promote/production Build is passing
- sign_in_with_rauthy after_action normalizes result (nil/struct/list) to list before Enum.each.
- OidcRoleSync.do_set_role uses Ash.update and swallows errors so auth is not blocked; skip update if role already correct.
2026-02-04 20:25:54 +01:00
c5f1fdce0a Code-review follow-ups: policy, docs, seed_admin behaviour
All checks were successful
continuous-integration/drone/push Build is passing
- Use OidcRoleSyncContext for set_role_from_oidc_sync; document JWT peek risk.
- seed_admin without password sets Admin role on existing user (OIDC-only); update docs and test.
- Fix DE translation for 'access this page'; add get? true comment in User.
2026-02-04 19:44:43 +01:00
d441009c8a Refactor: remove debug instrumentation from OidcRoleSync
Drop temporary logging used to diagnose OIDC groups sync in dev.
2026-02-04 18:13:30 +01:00
99722dee26 Add OidcRoleSync: apply Admin/Mitglied from OIDC groups
Register and sign-in call apply_admin_role_from_user_info; users in configured
admin group get Admin role, others get Mitglied. Internal User action + bypass policy.
2026-02-04 18:13:30 +01:00
a6e35da0f7 Add OIDC role sync config (OIDC_ADMIN_GROUP_NAME, OIDC_GROUPS_CLAIM)
Mv.OidcRoleSyncConfig reads from config; runtime.exs overrides from ENV in prod.
2026-02-04 18:13:30 +01:00
e065b39ed4 Add Mv.Release.seed_admin for admin bootstrap from ENV
Creates/updates admin user from ADMIN_EMAIL and ADMIN_PASSWORD or ADMIN_PASSWORD_FILE.
Idempotent; no fallback password in production. Called from docker entrypoint and seeds.
2026-02-04 18:13:30 +01:00
b177e41882 Add Role.get_admin_role for Release.seed_admin
Used by Mv.Release to resolve Admin role when creating/updating admin user from ENV.
2026-02-04 18:13:30 +01:00
c82f4b7fd7 feat: add csv export
Some checks failed
continuous-integration/drone/push Build is failing
2026-02-04 16:40:41 +01:00
5194b20b5c
Fix unlink-by-omission: on_missing :ignore, test, doc, string-key
Some checks failed
continuous-integration/drone/push Build is failing
- Member update_member: on_missing :unrelate → :ignore (no unlink when :user omitted)
- Test: normal_user update linked member without :user keeps link
- Doc: unlink only explicit (user: nil), admin-only; Actor.admin?(nil) note
- Check: defense-in-depth for "user" string key
2026-02-04 14:07:39 +01:00
543fded102
Harden member user-link check: argument presence, nil actor, policy scope
- Forbid on :user argument presence (not value) to block unlink via nil/empty
- Defensive nil actor handling; policy restricted to create/update only
- Test: Ash.load with actor; test non-admin cannot unlink via user: nil
- Docs: unlink behaviour and policy split
2026-02-04 14:07:39 +01:00
26fbafdd9d
Restrict member user link to admins (forbid policy)
Add ForbidMemberUserLinkUnlessAdmin check; forbid_if on Member create/update.
Fix member user-link tests: pass :user in params, assert via reload.
2026-02-04 14:07:38 +01:00
4d3a64c177
Add Role resource policies (defense-in-depth)
- PermissionSets: Role read :all for own_data, read_only, normal_user; admin keeps full CRUD
- Role resource: authorizers and policies with HasPermission
- Tests: role_policies_test.exs (read all, create/update/destroy admin only)
- Fix existing tests to pass actor or authorize?: false for Role operations
2026-02-04 14:07:38 +01:00
40e75f4066 refactor: reduce nesting in HasPermission.strict_check_with_permissions
Some checks reported errors
continuous-integration/drone/push Build was killed
continuous-integration/drone/promote/production Build is passing
Extract strict_check_filter_scope/4 to satisfy Credo max depth 2.
2026-02-04 13:29:41 +01:00
f7ba98c36b
refactor: reduce nesting in SyncUserEmailToMember.sync_email
Some checks failed
continuous-integration/drone/push Build is failing
Extract apply_sync/1 and sync_by_record_type/4 to satisfy Credo max depth 2.
2026-02-04 13:03:36 +01:00
178f5a01c7 MembershipFeeCycle: own_data read :linked via bypass and HasPermission scope
- own_data gets read scope :linked; apply_scope in HasPermission; bypass check for own_data.
- PermissionSetsTest expects own_data :linked, others :all for MFC read.
2026-02-04 09:20:10 +01:00
890a4d3752 MemberGroup: restrict bypass to own_data via MemberGroupReadLinkedForOwnData
- ActorPermissionSetIs check; bypass policy filters by member_id for own_data only.
- Admin with member_id still gets :all via HasPermission. Tests added.
2026-02-04 09:19:57 +01:00
e799f0271c Refactor PermissionSets: define admin permissions via perm_all()
Use perm/3 helper for admin resource permissions (DRY). MemberGroup
keeps read/create/destroy only (no update in domain).
2026-02-04 00:33:58 +01:00
5ed41555e9 Member/Setting/validations: domain, actor, and seeds
- setting.ex: domain/authorize for default_membership_fee_type_id check
- validate_same_interval: require membership_fee_type (no None)
- set_membership_fee_start_date: domain/actor for fee type lookup
- Validations: domain/authorize for cross-resource checks
- helpers.ex, email_sync change, seeds.exs actor/authorize fixes
- Update related tests
2026-02-03 23:52:16 +01:00
893f9453bd Add PermissionSets for Group, MemberGroup, MembershipFeeType, MembershipFeeCycle
- Extend permission_sets.ex with resources and pages for new domains
- Adjust HasPermission check for resource/action/scope
- Update roles-and-permissions and implementation-plan docs
- Add permission_sets_test.exs coverage
2026-02-03 23:52:09 +01:00
47b6a16177
Doc: Actor maybe_load_role comment; ActorIsAdmin system user = admin 2026-02-03 16:07:39 +01:00
60a4181255
Validation: error message admin or linked user; resolve_actor fallback 2026-02-03 16:07:26 +01:00
4e6b7305b6
Doc: Loader auth-independent for link checks; email-sync rule rationale 2026-02-03 16:07:13 +01:00
4ea31f0f37 Add email-change permission validation for linked members
All checks were successful
continuous-integration/drone/push Build is passing
Only admins or the linked user may change a linked member's email.
- New validation EmailChangePermission (uses Actor.admin?, Loader.get_linked_user).
- Register on Member update_member; docs and gettext.
2026-02-03 14:35:32 +01:00
ad02f8914f Use EmailSync.Loader.get_linked_user in EmailNotUsedByOtherUser
Remove duplicate get_linked_user_id; reuse Loader for linked user lookup.
2026-02-03 14:35:08 +01:00
3d46ba655f Add Actor.permission_set_name/1 and admin?/1 for consistent capability checks
- Actor.permission_set_name(actor) returns role's permission set (supports nil role load).
- Actor.admin?(actor) returns true for system user or admin permission set.
- ActorIsAdmin policy check delegates to Actor.admin?/1.
2026-02-03 14:34:24 +01:00
960506d16a refactoring
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/promote/production Build is passing
2026-02-02 16:56:07 +01:00
b21c3df7ef refactoring 2026-02-02 14:34:12 +01:00
9e27de84cb Merge branch 'main' into feature/338_import_custom_fields
Some checks failed
continuous-integration/drone/push Build is failing
2026-02-02 13:46:05 +01:00
12715f3d85 refactoring 2026-02-02 13:07:08 +01:00
3f8797c356 feat: import custom fields via CSV 2026-02-02 11:42:07 +01:00