Skip to content

Commit 6c69ce3

Browse files
committed
return empty org at the time of authentication
1 parent c5cf62d commit 6c69ce3

File tree

2 files changed

+43
-64
lines changed

2 files changed

+43
-64
lines changed

api/utils/keycloak_utils.py

Lines changed: 34 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ def validate_token(self, token: str) -> Dict[str, Any]:
7979
from authorization.models import User
8080

8181
user = User.objects.get(id=user_id)
82+
user.save()
83+
84+
# NOTE: Organizations are managed in DataSpace database, not Keycloak
85+
# Organization memberships should be created/managed through DataSpace's
86+
# organization management interface, not during Keycloak sync
87+
88+
# Log for debugging Keycloak validation")
8289
# Return user info in Keycloak format
8390
return {
8491
"sub": (
@@ -167,31 +174,18 @@ def get_user_organizations_from_token_info(self, token_info: dict) -> List[Dict[
167174
"""
168175
Get organizations from token introspection data.
169176
177+
NOTE: In DataSpace, organizations are ALWAYS managed in the database.
178+
This method always returns an empty list.
179+
170180
Args:
171-
token_info: Token introspection response
181+
token_info: Token introspection response (not used)
172182
173183
Returns:
174-
List of organization information
184+
Empty list - organizations are managed in DataSpace database
175185
"""
176-
try:
177-
# Get organization info from resource_access or attributes
178-
resource_access = token_info.get("resource_access", {})
179-
client_roles = resource_access.get(self.client_id, {}).get("roles", [])
180-
181-
# Extract organization info from roles
182-
organizations = []
183-
for role in client_roles:
184-
if role.startswith("org_"):
185-
parts = role.split("_")
186-
if len(parts) >= 3:
187-
org_id = parts[1]
188-
role_name = parts[2]
189-
organizations.append({"organization_id": org_id, "role": role_name})
190-
191-
return organizations
192-
except Exception as e:
193-
logger.error(f"Error getting user organizations: {e}")
194-
return []
186+
# Organizations are managed in DataSpace database, not Keycloak
187+
logger.debug("Organizations are managed in DataSpace DB, returning empty list")
188+
return []
195189

196190
def get_user_roles(self, token: str) -> list[str]:
197191
"""
@@ -229,40 +223,24 @@ def get_user_roles(self, token: str) -> list[str]:
229223
def get_user_organizations(self, token: str) -> List[Dict[str, Any]]:
230224
"""
231225
Get the organizations a user belongs to from their token.
232-
This assumes that organization information is stored in the token
233-
as client roles or in user attributes.
226+
227+
NOTE: In DataSpace, organizations and memberships are ALWAYS managed
228+
in the database, NOT in Keycloak. This method always returns an empty list.
229+
230+
Organizations should be retrieved using AuthorizationService.get_user_organizations()
231+
which queries the OrganizationMembership table.
234232
235233
Args:
236-
token: The user's token
234+
token: The user's token (not used)
237235
238236
Returns:
239-
List of organization information
237+
Empty list - organizations are managed in DataSpace database
240238
"""
241-
try:
242-
# Decode the token to get user info
243-
token_info = self.keycloak_openid.decode_token(token)
244-
245-
# Get organization info from resource_access or attributes
246-
# This implementation depends on how organizations are represented in Keycloak
247-
# This is a simplified example - adjust based on your Keycloak configuration
248-
resource_access = token_info.get("resource_access", {})
249-
client_roles = resource_access.get(self.client_id, {}).get("roles", [])
250-
251-
# Extract organization info from roles
252-
# Format could be 'org_<org_id>_<role>' or similar
253-
organizations = []
254-
for role in client_roles:
255-
if role.startswith("org_"):
256-
parts = role.split("_")
257-
if len(parts) >= 3:
258-
org_id = parts[1]
259-
role_name = parts[2]
260-
organizations.append({"organization_id": org_id, "role": role_name})
261-
262-
return organizations
263-
except KeycloakError as e:
264-
logger.error(f"Error getting user organizations: {e}")
265-
return []
239+
# Organizations are managed in DataSpace database, not Keycloak
240+
# Always return empty list - the actual organizations will be fetched
241+
# from the database via AuthorizationService.get_user_organizations()
242+
logger.debug("Organizations are managed in DataSpace DB, returning empty list")
243+
return []
266244

267245
def update_user_in_keycloak(self, user: User) -> bool:
268246
"""Update user details in Keycloak using admin credentials."""
@@ -367,10 +345,14 @@ def sync_user_from_keycloak(
367345
Synchronize user information from Keycloak to Django.
368346
Creates or updates the User record.
369347
348+
NOTE: Organizations are ALWAYS managed in DataSpace database, not Keycloak.
349+
Organization memberships should be created/managed through DataSpace's
350+
organization management interface. This method does NOT sync organizations.
351+
370352
Args:
371353
user_info: User information from Keycloak
372-
roles: User roles from Keycloak
373-
organizations: Deprecated - organizations are managed in DataSpace
354+
roles: User roles from Keycloak (for is_staff/is_superuser only)
355+
organizations: Ignored - organizations are managed in DataSpace database
374356
375357
Returns:
376358
The synchronized User object or None if failed

authorization/services.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,14 @@ def get_user_organizations(user_id: int) -> List[Dict[str, Any]]:
2727
List of dictionaries containing organization info and user's role
2828
"""
2929
# Use explicit type annotation for the queryset result
30-
memberships = OrganizationMembership.objects.filter(
31-
user_id=user_id
32-
).select_related(
30+
memberships = OrganizationMembership.objects.filter(user_id=user_id).select_related(
3331
"organization", "role"
3432
) # type: ignore[attr-defined]
33+
34+
logger.info(
35+
f"Getting organizations for user_id={user_id}, found {memberships.count()} memberships"
36+
)
37+
3538
return [
3639
{
3740
"id": membership.organization.id, # type: ignore[attr-defined]
@@ -59,9 +62,7 @@ def get_user_datasets(user_id: int) -> List[Dict[str, Any]]:
5962
List of dictionaries containing dataset info and user's role
6063
"""
6164
# Use explicit type annotation for the queryset result
62-
dataset_permissions = DatasetPermission.objects.filter(
63-
user_id=user_id
64-
).select_related(
65+
dataset_permissions = DatasetPermission.objects.filter(user_id=user_id).select_related(
6566
"dataset", "role"
6667
) # type: ignore[attr-defined]
6768
return [
@@ -80,9 +81,7 @@ def get_user_datasets(user_id: int) -> List[Dict[str, Any]]:
8081
]
8182

8283
@staticmethod
83-
def check_organization_permission(
84-
user_id: int, organization_id: int, operation: str
85-
) -> bool:
84+
def check_organization_permission(user_id: int, organization_id: int, operation: str) -> bool:
8685
"""
8786
Check if a user has permission to perform an operation on an organization.
8887
@@ -120,9 +119,7 @@ def check_organization_permission(
120119
return False
121120

122121
@staticmethod
123-
def check_dataset_permission(
124-
user_id: int, dataset_id: Union[int, str], operation: str
125-
) -> bool:
122+
def check_dataset_permission(user_id: int, dataset_id: Union[int, str], operation: str) -> bool:
126123
"""
127124
Check if a user has permission to perform an operation on a dataset.
128125
Checks both organization-level and dataset-specific permissions.

0 commit comments

Comments
 (0)