Commit graph

205 commits

Author SHA1 Message Date
8edbbac95f
feat: OIDC configuration in global Settings (ENV or DB)
- Add oidc_* attributes to Setting, migration and Config helpers
- Secrets and OidcRoleSyncConfig read from Config (ENV overrides DB)
- GlobalSettingsLive: OIDC section with disabled fields when ENV set
- OIDC role sync tests use DataCase for DB access
2026-02-24 13:58:24 +01:00
f29bbb02a2
feat: add Vereinfacht connection test button to settings 2026-02-24 13:09:34 +01:00
12419c5237
docs: fix remaining rauthy references after oidc rename
Update action names (register_with_rauthy → register_with_oidc,
sign_in_with_rauthy → sign_in_with_oidc) and strategy name
(:rauthy → :oidc) in docs, code comments and guidelines.
2026-02-24 11:51:01 +01:00
339d37937a
Rename OIDC strategy from :rauthy to :oidc, update callback path
- Rename AshAuthentication strategy from :oidc :rauthy to :oidc :oidc;
  generated actions are now register_with_oidc / sign_in_with_oidc.
- Update config keys (:rauthy → :oidc) in dev.exs and runtime.exs.
- Update default_redirect_uri to /auth/user/oidc/callback everywhere.
- Rename Mv.Accounts helper functions accordingly.
- Update Mv.Secrets, AuthController, link_oidc_account_live and all tests.
- Update docker-compose.prod.yml, .env.example, README and docs.

IMPORTANT: OIDC providers must be updated to use the new redirect URI
/auth/user/oidc/callback instead of /auth/user/rauthy/callback.
2026-02-24 11:51:00 +01:00
1c8c5ae83b
fix: include Fee Type in export when Start Date not in fields
Append membership_fee_type to column list when it is visible but
membership_fee_start_date was not in the selection (MemberExport,
export_column_order, build_export_member_fields_list).
2026-02-24 09:30:11 +01:00
94bcb5dc8c
fix: sort Fee Type by name in LiveView and exports
Use Ash related-field sort (membership_fee_type.name) instead of
membership_fee_type_id so column order is alphabetical. Load
membership_fee_type when sorting by it even if column is hidden.
In-memory re-sort (Build) uses loaded fee type name.
2026-02-24 09:30:04 +01:00
e86c78a0dc
feat(export): include Fee Type and groups in PDF export
MemberExport allowlist and insert_fee_type; Build load/sort/cell_value;
MemberPdfExportController allow membership_fee_type and groups.
2026-02-24 00:20:29 +01:00
f3b213ecec
feat(export): include Fee Type in CSV export
Payload and column_order when visible; allowlist, load, sort;
MembersCSV cell for :membership_fee_type.
2026-02-23 23:55:08 +01:00
fec2f7b6f6
Constants: add vereinfacht_required_member_fields
Defines first_name, last_name, street, postal_code, city as required
when Vereinfacht integration is active.
2026-02-23 22:13:16 +01:00
daaa4dc345
Vereinfacht: filter blank vereinfacht_contact_id in sync_members
Include members with empty string; use expr with ref for Ash filter.
2026-02-23 20:49:30 +01:00
8ffd842c38
Vereinfacht client: receipt allowlist, find_contact pagination, flatten nesting
- Receipt attrs: allowlist only (no String.to_atom on API input / DoS)
- find_contact_by_email: paginate through all pages (page[size]=100)
- Extract helpers to satisfy Credo max nesting depth
2026-02-23 20:49:19 +01:00
ede3df12ef
SyncFlash: document :public ETS table option 2026-02-23 19:54:44 +01:00
6c22d889a1
Vereinfacht client: receipts API, fetch_contact refactor, isExternal
- get_contact_with_receipts(contact_id) with ?include=receipts
- fetch_contact/2, build_url_with_params, extract_receipts_from_response
- Filter external contacts by isExternal in find_contact_id_by_email
- Send isExternal: true in create/update payloads
2026-02-23 19:54:44 +01:00
140e4a9054
SyncContact: only run when relevant attributes changed
- Sync on create; on update only when synced attrs changed or no contact_id yet
- Reduces unnecessary API calls on unrelated member updates
2026-02-23 19:54:43 +01:00
1188320844
Restrict set_vereinfacht_contact_id to system actor
- Add ActorIsSystemUser policy check
- Member set_vereinfacht_contact_id only allowed for system user
2026-02-23 19:54:43 +01:00
9d3c72acff
Add Vereinfacht app URL setting and contact view URL
- Setting attribute vereinfacht_app_url, migration, .env.example
- Config: vereinfacht_app_url() from env/setting or derived from API URL
- Contact view URL uses app URL with /en/admin/finances/contacts/{id}
- Global settings: App URL field, read-only when VEREINFACHT_APP_URL set
- Tests: update contact view URL expectations
2026-02-23 19:54:43 +01:00
124857cc9c
Vereinfacht: update existing contact when found by email
Before saving contact_id to member, sync current data to the
existing contact so Vereinfacht stays up to date.
2026-02-23 19:54:42 +01:00
bc2d91f9e7
Vereinfacht client: find by email in response, no retries in test
API does not allow filter[email]; fetch list and match client-side.
Disable Req retries in test for fast failure and less log noise.
2026-02-23 19:54:42 +01:00
f2bcf68da2
Config: per-field Vereinfacht ENV helpers
vereinfacht_api_url_env_set?, vereinfacht_api_key_env_set?,
vereinfacht_club_id_env_set? for read-only Settings fields when set.
2026-02-23 19:54:41 +01:00
a94c0c0b14
Vereinfacht: sync linked member only when email or member changed
Run SyncLinkedMemberAfterUserChange only when email or member
relationship changed to avoid unnecessary API calls.
2026-02-23 19:54:41 +01:00
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