[FEATURE]: PermissionSets Elixir Module (Hardcoded Permissions) #323

Closed
opened 2026-01-06 19:33:51 +01:00 by moritz · 0 comments
Owner

Description:

Create the core PermissionSets module that defines all four permission sets with their resource and page permissions. This is the heart of the MVP's authorization logic.

Tasks:

  1. Create lib/mv/authorization/permission_sets.ex
  2. Define module with @moduledoc explaining the 4 permission sets
  3. Define types:
    @type scope :: :own | :linked | :all
    @type action :: :read | :create | :update | :destroy
    @type resource_permission :: %{
      resource: String.t(),
      action: action(),
      scope: scope(),
      granted: boolean()
    }
    @type permission_set :: %{
      resources: [resource_permission()],
      pages: [String.t()]
    }
    
  4. Implement get_permissions/1 for each of the 4 permission sets
  5. Implement all_permission_sets/0 returning [:own_data, :read_only, :normal_user, :admin]
  6. Implement valid_permission_set?/1 checking if name is in the list
  7. Implement permission_set_name_to_atom/1 with error handling
  8. Add comprehensive @doc examples for each function

Permission Set Details:

1. own_data (Mitglied):

  • Resources:
    • User: read/update :own
    • Member: read/update :linked
    • CustomFieldValue: read/update :linked
    • CustomField read :all
  • Pages: ["/", "/profile", "/members/:id"]

2. read_only (Vorstand, Buchhaltung):

  • Resources:
    • User: read :own, update :own
    • Member: read :all
    • CustomFieldValue: read :all
    • CustomField: read :all
  • Pages: ["/", "/members", "/members/:id", "/properties"]

3. normal_user (Kassenwart):

  • Resources:
    • User: read/update :own
    • Member: read/create/update :all (no destroy for safety)
    • CustomFieldValue: read/create/update/destroy :all
    • CustomField: read :all
  • Pages: ["/", "/members", "/members/new", "/members/:id", "/members/:id/edit", "/properties", "/properties/new", "/properties/:id/edit"]

4. admin:

  • Resources:
    • User: read/update/destroy :all
    • Member: read/create/update/destroy :all
    • CustomFieldValue read/create/update/destroy :all
    • CustomField: read/create/update/destroy :all
    • Role: read/create/update/destroy :all
  • Pages: ["*"] (wildcard = all pages)

Acceptance Criteria:

  • Module created with all 4 permission sets
  • get_permissions/1 returns correct structure for each set
  • valid_permission_set?/1 works for atoms and strings
  • permission_set_name_to_atom/1 handles errors gracefully
  • All functions have @doc and @spec
  • Code is readable and well-commented

Test Strategy (TDD):

Structure Tests:

  • get_permissions(:own_data) returns map with :resources and :pages keys
  • Each permission set returns list of resource permissions
  • Each resource permission has required keys: :resource, :action, :scope, :granted
  • Pages lists are non-empty (except potentially for restricted roles)

Permission Content Tests:

  • :own_data allows User read/update with scope :own
  • :own_data allows Member/Property read/update with scope :linked
  • :read_only allows Member/Property read with scope :all
  • :read_only does NOT allow Member/Property create/update/destroy
  • :normal_user allows Member/Property full CRUD with scope :all
  • :admin allows everything with scope :all
  • :admin has wildcard page permission "*"

Validation Tests:

  • valid_permission_set?("own_data") returns true
  • valid_permission_set?(:admin) returns true
  • valid_permission_set?("invalid") returns false
  • permission_set_name_to_atom("own_data") returns {:ok, :own_data}
  • permission_set_name_to_atom("invalid") returns {:error, :invalid_permission_set}

Edge Cases:

  • All 4 sets defined in all_permission_sets/0
  • Function doesn't crash on nil input (returns false/error tuple)

Test File: test/mv/authorization/permission_sets_test.exs

**Description:** Create the core `PermissionSets` module that defines all four permission sets with their resource and page permissions. This is the heart of the MVP's authorization logic. **Tasks:** 1. Create `lib/mv/authorization/permission_sets.ex` 2. Define module with `@moduledoc` explaining the 4 permission sets 3. Define types: ```elixir @type scope :: :own | :linked | :all @type action :: :read | :create | :update | :destroy @type resource_permission :: %{ resource: String.t(), action: action(), scope: scope(), granted: boolean() } @type permission_set :: %{ resources: [resource_permission()], pages: [String.t()] } ``` 4. Implement `get_permissions/1` for each of the 4 permission sets 5. Implement `all_permission_sets/0` returning `[:own_data, :read_only, :normal_user, :admin]` 6. Implement `valid_permission_set?/1` checking if name is in the list 7. Implement `permission_set_name_to_atom/1` with error handling 8. Add comprehensive `@doc` examples for each function **Permission Set Details:** **1. own_data (Mitglied):** - Resources: - User: read/update :own - Member: read/update :linked - CustomFieldValue: read/update :linked - CustomField read :all - Pages: `["/", "/profile", "/members/:id"]` **2. read_only (Vorstand, Buchhaltung):** - Resources: - User: read :own, update :own - Member: read :all - CustomFieldValue: read :all - CustomField: read :all - Pages: `["/", "/members", "/members/:id", "/properties"]` **3. normal_user (Kassenwart):** - Resources: - User: read/update :own - Member: read/create/update :all (no destroy for safety) - CustomFieldValue: read/create/update/destroy :all - CustomField: read :all - Pages: `["/", "/members", "/members/new", "/members/:id", "/members/:id/edit", "/properties", "/properties/new", "/properties/:id/edit"]` **4. admin:** - Resources: - User: read/update/destroy :all - Member: read/create/update/destroy :all - CustomFieldValue read/create/update/destroy :all - CustomField: read/create/update/destroy :all - Role: read/create/update/destroy :all - Pages: `["*"]` (wildcard = all pages) **Acceptance Criteria:** - [ ] Module created with all 4 permission sets - [ ] `get_permissions/1` returns correct structure for each set - [ ] `valid_permission_set?/1` works for atoms and strings - [ ] `permission_set_name_to_atom/1` handles errors gracefully - [ ] All functions have `@doc` and `@spec` - [ ] Code is readable and well-commented **Test Strategy (TDD):** **Structure Tests:** - `get_permissions(:own_data)` returns map with `:resources` and `:pages` keys - Each permission set returns list of resource permissions - Each resource permission has required keys: `:resource`, `:action`, `:scope`, `:granted` - Pages lists are non-empty (except potentially for restricted roles) **Permission Content Tests:** - `:own_data` allows User read/update with scope :own - `:own_data` allows Member/Property read/update with scope :linked - `:read_only` allows Member/Property read with scope :all - `:read_only` does NOT allow Member/Property create/update/destroy - `:normal_user` allows Member/Property full CRUD with scope :all - `:admin` allows everything with scope :all - `:admin` has wildcard page permission "*" **Validation Tests:** - `valid_permission_set?("own_data")` returns true - `valid_permission_set?(:admin)` returns true - `valid_permission_set?("invalid")` returns false - `permission_set_name_to_atom("own_data")` returns `{:ok, :own_data}` - `permission_set_name_to_atom("invalid")` returns `{:error, :invalid_permission_set}` **Edge Cases:** - All 4 sets defined in `all_permission_sets/0` - Function doesn't crash on nil input (returns false/error tuple) **Test File:** `test/mv/authorization/permission_sets_test.exs`
moritz added the
M
label 2026-01-06 19:33:51 +01:00
moritz self-assigned this 2026-01-06 19:33:51 +01:00
moritz added this to the Sprint 10: 11.12-08.01 project 2026-01-06 19:33:51 +01:00
moritz added this to the Accounts & Logins milestone 2026-01-08 17:14:49 +01:00
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
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#323
No description provided.