Concept for Groups #354

Closed
simon wants to merge 118 commits from feature/concept-groups into main
Owner

closes #307

Description of the implemented changes

The changes were:

  • Bugfixing
  • New Feature
  • Breaking Change
  • Refactoring

What has been changed?

Definition of Done

Code Quality

  • No new technical depths
  • Linting passed
  • Documentation is added were needed

Accessibility

  • New elements are properly defined with html-tags
  • Colour contrast follows WCAG criteria
  • Aria labels are added when needed
  • Everything is accessible by keyboard
  • Tab-Order is comprehensible
  • All interactive elements have a visible focus

Testing

  • Tests for new code are written
  • All tests pass
  • axe-core dev tools show no critical or major issues

Additional Notes

closes #307 ## Description of the implemented changes The changes were: - [ ] Bugfixing - [ ] New Feature - [ ] Breaking Change - [ ] Refactoring <!--- Describe the goal of the PR in a few words --> ## What has been changed? <!--- List the things you changed --> ## Definition of Done ### Code Quality - [ ] No new technical depths - [ ] Linting passed - [ ] Documentation is added were needed ### Accessibility - [ ] New elements are properly defined with html-tags - [ ] Colour contrast follows WCAG criteria - [ ] Aria labels are added when needed - [ ] Everything is accessible by keyboard - [ ] Tab-Order is comprehensible - [ ] All interactive elements have a visible focus ### Testing - [ ] Tests for new code are written - [ ] All tests pass - [ ] axe-core dev tools show no critical or major issues ## Additional Notes <!--- Add any additional information for the reviewers here -->
simon added 1 commit 2026-01-16 14:56:19 +01:00
simon added 1 commit 2026-01-16 18:11:00 +01:00
requested reviews from moritz, carla 2026-01-16 18:13:23 +01:00
carla reviewed 2026-01-19 10:43:08 +01:00
@ -0,0 +1132,4 @@
assert %{name: ["has already been taken"]} = errors_on(changeset)
end
test "name uniqueness is case-sensitive" do
Owner

Do we want this to be case sensitive?

Do we want this to be case sensitive?
Author
Owner

I guess not - i'll change it!

I guess not - i'll change it!
simon marked this conversation as resolved
carla approved these changes 2026-01-19 11:11:19 +01:00
carla left a comment
Owner

Looks good to me :) Nice!!

Looks good to me :) Nice!!
@ -0,0 +276,4 @@
### Search Integration
**Member Search Enhancement:**
- Include group names in member search vector
Owner

Do you think full text in groups is neccessary if we have th efilter or has it consequences for the performance so just a filter is enough as well?

Do you think full text in groups is neccessary if we have th efilter or has it consequences for the performance so just a filter is enough as well?
Author
Owner

I think I expect a fuzzy-fulltext search to match everything that can be found related to a member, including groups. Do you disagree?

I think I expect a fuzzy-fulltext search to match everything that can be found related to a member, including groups. Do you disagree?
Owner

No I expect the same, I just thought it might affect th eperformance depending on the amount of groups...but let's start with it :)

No I expect the same, I just thought it might affect th eperformance depending on the amount of groups...but let's start with it :)
simon marked this conversation as resolved
@ -0,0 +299,4 @@
- Edit group (inline or modal)
- Delete group with confirmation modal
- Show member count per group
Owner

Add to sidebar settings -> groups?

Add to sidebar settings -> groups?
simon marked this conversation as resolved
@ -0,0 +357,4 @@
### Accessibility (A11y) Considerations
**Requirements:**
- All UI elements must be keyboard accessible
Owner

<3

<3
simon marked this conversation as resolved
@ -0,0 +374,4 @@
</span>
```
**Clickable Group Badge (for filtering):**
Owner

Maybe the dropdown is even enough fo the first start?

Maybe the dropdown is even enough fo the first start?
simon marked this conversation as resolved
@ -0,0 +718,4 @@
- ❌ Rollen/Positionen in Gruppen
- ❌ Erweiterte Gruppenattribute (Datum, Status, etc.)
- ❌ Gruppen-spezifische Berechtigungen
- ❌ Gruppen in Mitgliedersuche (kann später kommen)
Owner

I think thats also part of MVP right? :)

I think thats also part of MVP right? :)
Author
Owner

the search yes, the aspects above I'd leave out for the mvp

think that also matches what we decided in the planning meeting?
grafik

the search yes, the aspects above I'd leave out for the mvp think that also matches what we decided in the planning meeting? ![grafik](/attachments/95724d2a-44e4-49d4-8f8c-c68fcb14a679)
Owner

Yeah, I just meant the last line :)

Yeah, I just meant the last line :)
simon marked this conversation as resolved
simon added 1 commit 2026-01-19 11:53:58 +01:00
simon added 1 commit 2026-01-19 12:00:07 +01:00
simon added spent time 2026-01-19 12:01:09 +01:00
30 minutes
simon added 114 commits 2026-01-27 10:55:04 +01:00
- Remove CustomFieldValueLive (Index, Form, Show)
- Remove ContributionTypeLive.Index
- Remove ContributionPeriodLive.Show
- Remove corresponding routes from router
- Remove references in CustomFieldValueLive.Index
- Add comprehensive tests for UserLive.Show
- Add comprehensive tests for RoleLive.Show
- Cover mount, display, navigation, and error handling
Replace expensive length/1 calls with direct list comparison
to fix Credo warnings about performance
- Extract helper functions from process_chunk to reduce nesting
- Extract format_error_message from extract_changeset_error
- Split extract_error_message into smaller functions to reduce complexity
- Fixes Credo refactoring opportunities
- Add translations for validation error messages
- Add translations for save failure messages
Auto-assignment of default membership fee type is already implemented
via SetDefaultMembershipFeeType change. Test assertion is now active.
Introduce Mv.Helpers.SystemActor module with lazy loading
for operations that must always run regardless of user permissions.
System actor has admin role and auto-creates in test environment.
Add system@mila.local user with admin role for systemic operations.
This user is used by SystemActor helper for mandatory side effects.
Update email sync loader and changes to use system actor instead of user actor.
This ensures email sync always works regardless of user permissions.
Update email validation modules to use system actor for queries.
This ensures data integrity checks always run regardless of user permissions.
Update cycle generator, member hooks, and job to use system actor.
Remove actor parameters as cycle generation is a mandatory side effect.
Test system actor retrieval, caching, fallback behavior,
and auto-creation in test environment.
Add section explaining when and how to use system actor for systemic operations.
Include examples and distinction between user mode and system mode.
Add type specifications for all private functions to improve
static analysis with Dialyzer and documentation quality.
Extract setup code into reusable helper functions to reduce
duplication and improve maintainability.
Use Application config instead of Mix.env() to prevent
runtime crashes in production releases where Mix is not available
Pass actor_opts to delete_cycles/1 to ensure proper authorization
when MembershipFeeCycle policies are enforced
Log warnings when query errors occur in email uniqueness checks
to improve visibility of data integrity issues
Allow system user email to be configured via environment variable
with fallback to default 'system@mila.local'
Restrict UI access to cycle regeneration to administrators only
to prevent policy bypass via user interface
Move require Logger statements from function/case level to module level
for better code organization and consistency with Elixir best practices
Implement bypass for READ + HasPermission for UPDATE pattern
Extend HasPermission check to support User resource scope :own
31 tests covering all 4 permission sets and bypass scenarios
Update HasPermission tests to expect false for scope :own without record
Add bypass vs HasPermission pattern documentation
Update architecture and implementation plan docs
Add Mix.env() check to match?/3 for defense in depth.
Document NoActor pattern in CODE_GUIDELINES.md.
Extract ash_resource? helper to reduce nesting depth.
Add ensure_role_loaded fallback for unloaded actor roles.
Add explicit comments explaining why all permission sets
grant User.update with scope :own for password changes.
Move why explanations to documentation files.
Keep policy comments concise and focused.
Add ensure_user_role_loaded to global live_view quote block.
Remove redundant on_mount calls from individual LiveViews.
Fix Credo parsing error by removing for comprehension.
Duplicate tests for own_data, read_only, normal_user sets.
Encapsulate two-tier policy pattern (bypass + HasPermission).
Promote consistency across resource policy definitions.
Enforce User.update :own across all permission sets.
Verify READ bypass + UPDATE HasPermission pattern.
Clarify that User.update :own is handled by HasPermission.
Fix file path references from lib/mv/accounts to lib/accounts.
Use Application.compile_env for release-safety.
Config only set in test.exs (defaults to false).
Consolidate role loading logic from HasPermission and LiveHelpers.
Use Ash.Resource.Info.resource? for reliable Ash detection.
Dead code - macro was never used in codebase.
PolicyConsistency test will be replaced with better implementation.
SECURITY: Skip authorization for role loading to avoid circular dependency.
Actor loads their OWN role, needed for authorization itself.
Documented why this is safe.
Test removed - JWT flow tested via AshAuthentication integration.
Direct test would require JWT mocking without value.
Replace Mix.env example with config-based approach.
Remove outdated runtime guard documentation.
Remove mentions of runtime guards - only compile-time config is used.
Clarify that production safety comes from config defaults.
Pattern match on %Mv.Accounts.User{} instead of generic actor.
Clearer intention, prevents accidental authorization bypasses.
Non-User actors are returned as-is (no-op).
- Add authorize?: false to all bootstrap operations in seeds.exs
- Fix user-linking validation to respect authorize? context flag
- Prevents authorization errors during initial setup when no actor exists yet
- Add SystemActor to Ash.read_one() calls in OidcEmailCollision validation
- Prevents authorization failures during OIDC registration when no actor is logged in
- Enables proper email collision detection and account linking flow
- Add SystemActor to all Ash operations in LinkOidcAccountLive
- Enables user lookup, reload, and oidc_id linking during OIDC flow
- User is not yet logged in during linking, so SystemActor provides authorization
Document the three authorization bypass mechanisms and when to use each:
- NoActor (test-only bypass)
- system_actor (systemic operations)
- authorize?: false (bootstrap scenarios)
This removes the NoActor bypass that was masking authorization bugs in tests.
All operations now require an explicit actor for authorization.
- Role lookup and creation (find_admin_role, create_admin_role)
- System user creation and role assignment
- Role loading during initialization
This commit adds actor: system_actor to all Ash operations in tests that
require authorization.
- Add get_mitglied_role/0 helper to avoid code duplication
- Add create_role_with_system_flag action for seeds/migrations
- Allows setting is_system_role flag (required for 'Mitglied' role)
- Assigns 'Mitglied' role to new users if no role is set
Replace action-level changes with attribute default function to ensure
all users get the 'Mitglied' role regardless of creation path.
Make migration more robust by creating the 'Mitglied' role if it doesn't
exist, ensuring it works regardless of seed execution order.
Avoid macro pinning issues by binding role_data.name to role_name
before using it in the filter query.
The attribute-level default solution makes this change module obsolete.
All role assignment is now handled via the role_id attribute's default
function, which is more robust and works for all creation paths.
- Add database-level NOT NULL constraint for users.role_id
- Update SystemActor tests to verify NOT NULL constraint enforcement
- Add process dictionary caching for default_role_id/0 to reduce DB queries
- Only cache non-nil role_id values to allow retry after role creation
- Prevents processes from being permanently stuck with nil if first call
  happens before the 'Mitglied' role exists
- Update documentation to explain bootstrap safety mechanism
Remove fallback to system_actor in process_chunk to prevent
unauthorized access. Actor must now be explicitly provided.
Handle consume_uploaded_entries returning [content] directly
instead of [{:ok, content}]. Add locale support for translations
in background tasks.
Include email address in duplicate email error messages.
Add German translation for email uniqueness errors.
Ensure locale is set for translations in async tasks.
Fix missing max_errors assign in GlobalSettingsLive
Some checks failed
continuous-integration/drone/push Build is failing
2d1ddfa654
Set max_errors as socket assign in mount/3 to make it
available in templates. Fixes KeyError in CSV import UI.
simon closed this pull request 2026-01-27 13:13:36 +01:00
moritz deleted branch feature/concept-groups 2026-01-27 13:22:45 +01:00
Some checks are pending
continuous-integration/drone/push Build is failing
continuous-integration/drone/promote/production
Required

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Total time spent: 30 minutes
simon
30 minutes
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: local-it/mitgliederverwaltung#354
No description provided.