feat(roles): add admin store roles page, permission i18n, and menu integration
Some checks failed
Some checks failed
- Add admin store roles page with merchant→store cascading for superadmin and store-only selection for platform admin - Add permission catalog API with translated labels/descriptions (en/fr/de/lb) - Add permission translations to all 15 module locale files (60 files total) - Add info icon tooltips for permission descriptions in role editor - Add store roles menu item and admin menu item in module definition - Fix store-selector.js URL construction bug when apiEndpoint has query params - Add admin store roles API (CRUD + platform scoping) - Add integration tests for admin store roles and permission catalog Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,14 @@ from app.modules.tenancy.exceptions import (
|
||||
InvalidRoleException,
|
||||
UserNotFoundException,
|
||||
)
|
||||
from app.modules.tenancy.models import Role, Store, StoreUser, User
|
||||
from app.modules.tenancy.models import (
|
||||
Platform,
|
||||
Role,
|
||||
Store,
|
||||
StorePlatform,
|
||||
StoreUser,
|
||||
User,
|
||||
)
|
||||
from app.modules.tenancy.services.store_team_service import store_team_service
|
||||
|
||||
# =============================================================================
|
||||
@@ -728,3 +735,80 @@ class TestStoreTeamServiceDeleteRole:
|
||||
store_id=team_store.id,
|
||||
role_id=role.id,
|
||||
)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# ADMIN STORE ACCESS VALIDATION
|
||||
# =============================================================================
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.tenancy
|
||||
class TestValidateAdminStoreAccess:
|
||||
"""Tests for validate_admin_store_access()."""
|
||||
|
||||
def test_super_admin_can_access_any_store(self, db, team_store):
|
||||
"""Super admin (accessible_platform_ids=None) can access any store."""
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
user_ctx = MagicMock()
|
||||
user_ctx.get_accessible_platform_ids.return_value = None
|
||||
|
||||
store = store_team_service.validate_admin_store_access(
|
||||
db, user_ctx, team_store.id
|
||||
)
|
||||
assert store.id == team_store.id
|
||||
|
||||
def test_platform_admin_can_access_store_in_their_platform(self, db, team_store):
|
||||
"""Platform admin can access stores in their assigned platform."""
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
# Create a platform and link the store
|
||||
platform = Platform(
|
||||
code=f"test_plat_{uuid.uuid4().hex[:6]}",
|
||||
name="Test Platform",
|
||||
is_active=True,
|
||||
)
|
||||
db.add(platform)
|
||||
db.flush()
|
||||
|
||||
sp = StorePlatform(
|
||||
store_id=team_store.id,
|
||||
platform_id=platform.id,
|
||||
is_active=True,
|
||||
)
|
||||
db.add(sp)
|
||||
db.flush()
|
||||
|
||||
user_ctx = MagicMock()
|
||||
user_ctx.get_accessible_platform_ids.return_value = [platform.id]
|
||||
|
||||
store = store_team_service.validate_admin_store_access(
|
||||
db, user_ctx, team_store.id
|
||||
)
|
||||
assert store.id == team_store.id
|
||||
|
||||
def test_platform_admin_cannot_access_store_outside_platform(self, db, team_store):
|
||||
"""Platform admin cannot access stores outside their platform."""
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
user_ctx = MagicMock()
|
||||
# Platform ID 99999 does not have the test store
|
||||
user_ctx.get_accessible_platform_ids.return_value = [99999]
|
||||
|
||||
with pytest.raises(InvalidRoleException, match="do not have access"):
|
||||
store_team_service.validate_admin_store_access(
|
||||
db, user_ctx, team_store.id
|
||||
)
|
||||
|
||||
def test_nonexistent_store_raises_error(self, db):
|
||||
"""Accessing a nonexistent store raises InvalidRoleException."""
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
user_ctx = MagicMock()
|
||||
user_ctx.get_accessible_platform_ids.return_value = None
|
||||
|
||||
with pytest.raises(InvalidRoleException, match="not found"):
|
||||
store_team_service.validate_admin_store_access(
|
||||
db, user_ctx, 99999
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user