feat: enhance project and scenario management with role-based access control
- Implemented role-based access control for project and scenario routes. - Added authorization checks to ensure users have appropriate roles for viewing and managing projects and scenarios. - Introduced utility functions for ensuring project and scenario access based on user roles. - Refactored project and scenario routes to utilize new authorization helpers. - Created initial data seeding script to set up default roles and an admin user. - Added tests for authorization helpers and initial data seeding functionality. - Updated exception handling to include authorization errors.
This commit is contained in:
@@ -6,7 +6,7 @@ from typing import cast
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from fastapi import FastAPI
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import ValidationError
|
||||
from sqlalchemy import create_engine
|
||||
@@ -15,13 +15,14 @@ from sqlalchemy.engine import Engine
|
||||
from sqlalchemy.pool import StaticPool
|
||||
|
||||
from config.database import Base
|
||||
from dependencies import get_unit_of_work
|
||||
from dependencies import get_auth_session, get_unit_of_work
|
||||
from models import (
|
||||
MiningOperationType,
|
||||
Project,
|
||||
ResourceType,
|
||||
Scenario,
|
||||
ScenarioStatus,
|
||||
User,
|
||||
)
|
||||
from schemas.scenario import (
|
||||
ScenarioComparisonRequest,
|
||||
@@ -30,6 +31,7 @@ from schemas.scenario import (
|
||||
from services.exceptions import ScenarioValidationError
|
||||
from services.scenario_validation import ScenarioComparisonValidator
|
||||
from services.unit_of_work import UnitOfWork
|
||||
from services.session import AuthSession, SessionTokens
|
||||
from routes.scenarios import router as scenarios_router
|
||||
|
||||
|
||||
@@ -159,6 +161,28 @@ def api_client(session_factory) -> Iterator[TestClient]:
|
||||
yield uow
|
||||
|
||||
app.dependency_overrides[get_unit_of_work] = _override_uow
|
||||
|
||||
with UnitOfWork(session_factory=session_factory) as uow:
|
||||
assert uow.users is not None
|
||||
uow.ensure_default_roles()
|
||||
user = User(
|
||||
email="test-scenarios@example.com",
|
||||
username="scenario-tester",
|
||||
password_hash=User.hash_password("password"),
|
||||
is_active=True,
|
||||
is_superuser=True,
|
||||
)
|
||||
uow.users.create(user)
|
||||
user = uow.users.get(user.id, with_roles=True)
|
||||
|
||||
def _override_auth_session(request: Request) -> AuthSession:
|
||||
session = AuthSession(tokens=SessionTokens(
|
||||
access_token="test", refresh_token="test"))
|
||||
session.user = user
|
||||
request.state.auth_session = session
|
||||
return session
|
||||
|
||||
app.dependency_overrides[get_auth_session] = _override_auth_session
|
||||
client = TestClient(app)
|
||||
try:
|
||||
yield client
|
||||
@@ -171,6 +195,8 @@ def _create_project_with_scenarios(
|
||||
scenario_overrides: list[dict[str, object]],
|
||||
) -> tuple[int, list[int]]:
|
||||
with UnitOfWork(session_factory=session_factory) as uow:
|
||||
assert uow.projects is not None
|
||||
assert uow.scenarios is not None
|
||||
project_name = f"Project {uuid4()}"
|
||||
project = Project(name=project_name,
|
||||
operation_type=MiningOperationType.OPEN_PIT)
|
||||
|
||||
Reference in New Issue
Block a user