User Roles and Permissions
Relevant source files
The following files were used as context for generating this wiki page:The QA-Dashboard application employs a role-based access control (RBAC) system to manage user capabilities. The system is designed to be simple, distinguishing between two primary roles: Admin and Regular User. There is also a concept of an Anonymous or guest user with read-only access to some features. This distinction governs what actions a user can perform, particularly concerning content management and question status updates.
Permissions are enforced on the backend through FastAPI dependencies that verify a user's role before allowing access to protected API endpoints. The frontend UI dynamically adapts based on the authenticated user's role, showing or hiding administrative controls accordingly. The core of this system is the is_admin boolean flag in the users database table.
Sources: README.md, backend/security.py, backend/database.py
User Data Model
The user's role is defined directly within the User model in the database. The is_admin column is a boolean that determines if a user has elevated privileges.
Sources: backend/database.py:32-41
users Table Schema
The diagram below illustrates the schema for the users table, which is central to defining user roles.
This ER diagram shows the structure of the users table, highlighting the is_admin field.
Sources: backend/database.py:32-41
The table below details the fields of the User model.
| Column | Type | Constraints | Description |
|---|---|---|---|
id | UUID | Primary Key, Default: uuid4 | Unique identifier for the user. |
username | String | Unique, Not Null | The user's chosen username. |
email | String | Unique, Not Null | The user's email, used for login. |
password | String | Not Null | The user's hashed password. |
is_admin | Boolean | Default: false | Determines if the user has administrative rights. |
created_at | DateTime | Default: datetime.utcnow | The timestamp when the user account was created. |
Sources: backend/database.py:32-41, backend/schemas.py:17-25
Role Definitions and Capabilities
The application defines three levels of access: Admin, Regular User (authenticated), and Anonymous User (guest).
| Role | Description | Key Permissions -
| Admin | A user with is_admin: true. Has full control over all content. | - Create/Read Questions & Answers
- Update question status (Pending, Escalated, Answered)
- Delete any answer -
| Regular User | An authenticated user with is_admin: false. Can create and view content. | - Create/Read Questions & Answers
- Cannot update question status
- Cannot delete answers (not even their own) -
| Anonymous User | A non-authenticated guest user. | - Read Questions
- Cannot create questions or answers
- Cannot update status or delete content
- Can view the forum page as a guest -
Sources: README.md, backend/api/questions.py:145-149, backend/api/answers.py:73-79, web/src/app/login/page.js:97-99
Anonymous User
The system includes a special "Anonymous" user account, which is created on application startup if it doesn't already exist. This user has a hardcoded UUID. This allows for guest functionality, where unauthenticated visitors can view content without needing to log in.
Sources: backend/main.py:19-35, backend/security.py:79-87
Permission Enforcement
Permissions are enforced at the API level using FastAPI's dependency injection system. Key functions in backend/security.py are responsible for validating a user's identity and role.
Sources: backend/security.py
Key Security Dependencies
get_current_user: This dependency decodes the JWT token from theAuthorizationheader to identify the user making the request. It fetches the user record from the database. If the token is invalid or the user doesn't exist, it raises a401 Unauthorizederror.get_admin_user: This dependency relies onget_current_userto get the authenticated user, and then performs an additional check to ensure the user'sis_adminflag isTrue. If not, it raises a403 Forbiddenerror.
Sources: backend/security.py:59-93, backend/security.py:96-102
Admin-Only Action Flow
The following sequence diagram illustrates how a request to delete an answer is handled, showcasing the admin permission check.
This diagram shows the successful flow for an admin deleting an answer. An equivalent flow for a non-admin user would result in a 403 Forbidden error from the get_admin_user dependency.
Sources: backend/api/answers.py:70-89, backend/security.py:96-102
Example: Admin-Only Endpoint
The endpoint for deleting an answer explicitly requires an admin user by depending on get_admin_user.
# backend/api/answers.py:70-76
@router.delete("/{answer_id}")
async def delete_answer(
answer_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Delete an answer (only by admin)"""
The implementation then checks the is_admin flag on the current_user object provided by the dependency.
# backend/api/answers.py:78-82
if not current_user.is_admin:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Not authorized to delete this answer",
)
Sources: backend/api/answers.py:70-82
UI Representation of Roles
The frontend dynamically adjusts the user interface based on the is_admin property of the logged-in user. This data is available through the useAuth context.
Admin Controls on Question Cards
For administrators, the QuestionCard component displays a dropdown menu to change a question's status. This control is not rendered for regular users.
// web/src/components/QuestionCard.js:80-89
{user?.is_admin && (
<select
value={question.status}
onChange={(e) => handleStatusChange(e.target.value)}
className="px-2 py-1 text-xs border border-gray-300 rounded bg-white cursor-pointer hover:border-indigo-500 text-black"
>
<option value="Pending">Mark Pending</option>
<option value="Escalated">Mark Escalated</option>
<option value="Answered">Mark Answered</option>
</select>
)}
Sources: web/src/components/QuestionCard.js:80-89
Admin Controls in Answer Lists
Similarly, the "Delete" button for an answer is only visible to admin users.
// web/src/components/AnswerList.js:21-26
{user && user.is_admin && (
<button
onClick={() => handleDeleteAnswer(answer.id)}
className="text-xs text-red-600 hover:text-red-700 font-medium"
>
Delete
</button>
)}
Sources: web/src/components/AnswerList.js:21-26
Admin Badge
The header component displays a prominent "Admin" badge next to the username if the user has administrative privileges.
Sources: web/src/components/Header.js:18-22
Summary
The user role and permission system in the QA-Dashboard is straightforward yet effective. It leverages a single is_admin flag in the users database model as the source of truth. Backend API endpoints are protected using FastAPI dependencies that check this flag, ensuring that unauthorized actions are blocked with appropriate HTTP error codes. The frontend provides a clean user experience by conditionally rendering administrative controls, clearly separating the capabilities of regular users and administrators.