new kw for it services & sectors alignment & viewer access partial fixed
This commit is contained in:
@@ -171,6 +171,7 @@ class TeamManagementViewSet(viewsets.ViewSet):
|
||||
'email': user.email,
|
||||
'first_name': user.first_name,
|
||||
'last_name': user.last_name,
|
||||
'role': user.role,
|
||||
'is_active': user.is_active,
|
||||
'is_staff': user.is_staff,
|
||||
'date_joined': user.date_joined.isoformat(),
|
||||
@@ -182,9 +183,11 @@ class TeamManagementViewSet(viewsets.ViewSet):
|
||||
})
|
||||
|
||||
def create(self, request):
|
||||
"""Invite new team member"""
|
||||
"""Invite new team member with role and optional site access."""
|
||||
account = request.user.account
|
||||
email = request.data.get('email')
|
||||
role = request.data.get('role', 'viewer')
|
||||
site_ids = request.data.get('site_ids', []) # For viewer role: which sites to grant access
|
||||
|
||||
if not email:
|
||||
return Response(
|
||||
@@ -192,6 +195,13 @@ class TeamManagementViewSet(viewsets.ViewSet):
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
# Validate role - only admin and viewer allowed for invites
|
||||
if role not in ['admin', 'viewer']:
|
||||
return Response(
|
||||
{'error': 'Role must be either "admin" or "viewer"'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
# Check if user already exists
|
||||
if User.objects.filter(email=email).exists():
|
||||
return Response(
|
||||
@@ -217,15 +227,39 @@ class TeamManagementViewSet(viewsets.ViewSet):
|
||||
username = f"{base_username}{counter}"
|
||||
counter += 1
|
||||
|
||||
# Create user and send invitation email
|
||||
# Create user with assigned role
|
||||
user = User.objects.create_user(
|
||||
username=username,
|
||||
email=email,
|
||||
first_name=request.data.get('first_name', ''),
|
||||
last_name=request.data.get('last_name', ''),
|
||||
account=account
|
||||
account=account,
|
||||
role=role,
|
||||
)
|
||||
|
||||
# Grant site access based on role
|
||||
from igny8_core.auth.models import SiteUserAccess, Site
|
||||
if role == 'viewer' and site_ids:
|
||||
# Viewer: grant access only to specified sites
|
||||
sites = Site.objects.filter(id__in=site_ids, account=account)
|
||||
for site in sites:
|
||||
SiteUserAccess.objects.get_or_create(
|
||||
user=user,
|
||||
site=site,
|
||||
defaults={'granted_by': request.user}
|
||||
)
|
||||
elif role == 'admin':
|
||||
# Admin: automatically grant access to ALL current sites
|
||||
# (admin also sees all sites via get_accessible_sites, but
|
||||
# creating records ensures consistency)
|
||||
sites = Site.objects.filter(account=account)
|
||||
for site in sites:
|
||||
SiteUserAccess.objects.get_or_create(
|
||||
user=user,
|
||||
site=site,
|
||||
defaults={'granted_by': request.user}
|
||||
)
|
||||
|
||||
# Create password reset token for invite
|
||||
token = secrets.token_urlsafe(32)
|
||||
expires_at = timezone.now() + timedelta(hours=24)
|
||||
@@ -248,6 +282,7 @@ class TeamManagementViewSet(viewsets.ViewSet):
|
||||
'email': user.email,
|
||||
'first_name': user.first_name,
|
||||
'last_name': user.last_name,
|
||||
'role': user.role,
|
||||
}
|
||||
}, status=status.HTTP_201_CREATED)
|
||||
|
||||
|
||||
@@ -89,8 +89,8 @@ class IsViewerOrAbove(permissions.BasePermission):
|
||||
# Check user role
|
||||
if hasattr(request.user, 'role'):
|
||||
role = request.user.role
|
||||
# viewer, editor, admin, owner all have access
|
||||
allowed = role in ['viewer', 'editor', 'admin', 'owner']
|
||||
# viewer, editor, admin, owner, developer, system_bot all have access
|
||||
allowed = role in ['viewer', 'editor', 'admin', 'owner', 'developer', 'system_bot']
|
||||
if allowed:
|
||||
logger.info(f"[IsViewerOrAbove] ALLOWED: User {request.user.email} has role {role}")
|
||||
else:
|
||||
@@ -114,8 +114,8 @@ class IsEditorOrAbove(permissions.BasePermission):
|
||||
# Check user role
|
||||
if hasattr(request.user, 'role'):
|
||||
role = request.user.role
|
||||
# editor, admin, owner have access
|
||||
return role in ['editor', 'admin', 'owner']
|
||||
# editor, admin, owner, developer have access
|
||||
return role in ['editor', 'admin', 'owner', 'developer']
|
||||
|
||||
# If no role system, allow authenticated users
|
||||
return True
|
||||
|
||||
@@ -13,7 +13,7 @@ from rest_framework.views import APIView
|
||||
from django.shortcuts import get_object_or_404
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiParameter
|
||||
|
||||
from igny8_core.api.permissions import IsAuthenticatedAndActive, IsEditorOrAbove
|
||||
from igny8_core.api.permissions import IsAuthenticatedAndActive, IsEditorOrAbove, IsViewerOrAbove
|
||||
from igny8_core.api.response import success_response, error_response
|
||||
from igny8_core.api.throttles import DebugScopedRateThrottle
|
||||
from igny8_core.auth.models import Site
|
||||
@@ -74,7 +74,13 @@ class UnifiedSiteSettingsViewSet(viewsets.ViewSet):
|
||||
permission_classes = [IsAuthenticatedAndActive, IsEditorOrAbove]
|
||||
throttle_scope = 'settings'
|
||||
throttle_classes = [DebugScopedRateThrottle]
|
||||
|
||||
|
||||
def get_permissions(self):
|
||||
"""Viewers can read settings; writes require editor+."""
|
||||
if self.action == 'retrieve':
|
||||
return [IsAuthenticatedAndActive(), IsViewerOrAbove()]
|
||||
return [IsAuthenticatedAndActive(), IsEditorOrAbove()]
|
||||
|
||||
def retrieve(self, request, site_id=None):
|
||||
"""Get all settings for a site in one response"""
|
||||
site = get_object_or_404(Site, id=site_id, account=request.user.account)
|
||||
|
||||
Reference in New Issue
Block a user