SUBTASK #86: Roles and permissions (2.1)

Open
#88 0 comments 0 reactions 1 assignee View on GitHub

Maintainers usually reply within 1 day

@Titus0341 is already working on this.

Since Nov 2, 2026.

Assessment

Difficulty
3/5
Estimated time
Half a day
Newbie friendliness
42/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
python

Research direction

Start with backend/records/enums.py for UserRole and AccountStatus, then backend/records/user.py for where has_role goes. The role-to-permission table is not in the payload; it must come from the team's agreed decision on #86 before ROLE_PERMISSIONS can be written. Done when tests/services/access_control/test_permissions.py passes without a database and permissions.py imports no Flask, database or network code.

Written by the indexing model from the issue text.

Description

backend Low Priority subtask

What to do

One table that says which role may do what, and a pure function that answers "may this user do this?" with a reason when the answer is no. Everything else (the Application Controller, the screens) asks this function and never compares role names itself.

Background

  • Spec SEC-03 (access by role), POL-01 and SEC-09 (refuse everything else), SEC-10 (backup only for authorized users)
  • OOD: AccessControlService.authorizeAction(), verifyRole(), User.hasRole(role)
  • UserRole (admin, editor, viewer) and AccountStatus (active, disabled) are in backend/records/enums.py
  • The table is the "What each role may do" decision on #PARENT. Use the version the team agreed.

Steps

  • backend/services/access_control/permissions.py:
    • Permission enum: VIEW_DATA, EXPORT, START_SCAN, EDIT_DEVICES, EDIT_REFERENCE_DATA, MANAGE_ALERTS, BACKUP_RESTORE, MANAGE_USERS, VIEW_AUDIT_LOG
    • ROLE_PERMISSIONS: dict[UserRole, frozenset[Permission]]: the agreed table, and the only place it's written
    • AccessDecision(allowed: bool, reason: str | None), frozen
    • authorize(user: User | None, permission: Permission) -> AccessDecision:
      • No user: refused, "Sign in to continue."
      • Disabled account: refused, "This account is disabled."
      • Role without the permission: refused in plain words, e.g. "Your role (viewer) can't start scans."
    • permissions_for(user: User) -> list[str]: the user's permissions by name, sorted, so the UI can hide what the user can't use (subtask 5)
  • User.has_role(role: UserRole) -> bool in backend/records/user.py (OOD hasRole)
  • Unit tests:
    • Every UserRole has a row (a new role without one fails the test)
    • The table equals the agreed one exactly, written out in the test, so changing a permission is a visible change in the PR
    • A viewer may VIEW_DATA but not START_SCAN; an editor may EDIT_DEVICES but not MANAGE_USERS or BACKUP_RESTORE; an admin may do everything
    • A disabled admin may do nothing
    • No user gives "Sign in to continue."
    • Each refusal has a reason; each permission granted has none

Where

  • backend/services/access_control/permissions.py
  • backend/records/user.py (add has_role)
  • tests/services/access_control/test_permissions.py

Done when

  • All the tests above pass without a database
  • permissions.py imports no Flask, database or network code

Depends on

  • The role table decision on #86
Dominant language
Python
Stars
1
Forks
1
Avg merge
9h 31m
Merged PRs (30d)
36

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Bearkat-Professionals/Software-Engineering-Project

All issues in Bearkat-Professionals/Software-Engineering-Project

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.