Skip to content

Commit

Permalink
update remote sync (#1367)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie committed Jul 15, 2024
1 parent af47a25 commit b6c938b
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 15 deletions.
40 changes: 31 additions & 9 deletions projectroles/remote_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
REMOTE_LEVEL_VIEW_AVAIL = SODAR_CONSTANTS['REMOTE_LEVEL_VIEW_AVAIL']
REMOTE_LEVEL_READ_INFO = SODAR_CONSTANTS['REMOTE_LEVEL_READ_INFO']
REMOTE_LEVEL_READ_ROLES = SODAR_CONSTANTS['REMOTE_LEVEL_READ_ROLES']
SYSTEM_USER_GROUP = SODAR_CONSTANTS['SYSTEM_USER_GROUP']

# Local constants
APP_NAME = 'projectroles'
Expand Down Expand Up @@ -80,6 +81,9 @@ def __init__(self):
#: Updated parent projects in current sync operation
self.updated_parents = []

#: User name/UUID lookup
self.user_lookup = {}

# Internal Source Site Functions -------------------------------------------

@classmethod
Expand Down Expand Up @@ -370,6 +374,18 @@ def get_remote_data(self, site):

# Internal Target Site Functions -------------------------------------------

@staticmethod
def _is_local_user(user_data):
"""
Return True if user data denotes a local user.
:param user_data: Dict
:return: Boolean
"""
return (
SYSTEM_USER_GROUP in user_data['groups'] or not user_data['groups']
)

@staticmethod
def _update_obj(obj, obj_data, fields):
"""
Expand Down Expand Up @@ -422,7 +438,7 @@ def _sync_user(self, uuid, user_data):
"""
# Don't sync local users if disallowed
allow_local = getattr(settings, 'PROJECTROLES_ALLOW_LOCAL_USERS', False)
if '@' not in user_data['username'] and not allow_local:
if self._is_local_user(user_data) and not allow_local:
logger.info(NO_LOCAL_USERS_MSG)
return
# Add UUID to user_data to ensure it gets synced
Expand Down Expand Up @@ -477,7 +493,7 @@ def _sync_user(self, uuid, user_data):

# Create new user
except User.DoesNotExist:
if '@' not in user_data['username']:
if self._is_local_user(user_data):
logger.warning(
'Local user "{}" not found: local users must '
'be manually created before they can be synced'.format(
Expand Down Expand Up @@ -724,8 +740,11 @@ def _update_roles(self, project, project_data):
continue

# Ensure the user is valid
local_user = self._is_local_user(
self.remote_data['users'][self.user_lookup[r['user']]]
)
if (
'@' not in r['user']
local_user
and not allow_local
and r['role'] != PROJECT_ROLE_OWNER
):
Expand All @@ -735,10 +754,9 @@ def _update_roles(self, project, project_data):
)
self._handle_user_error(error_msg, project, r_uuid)
continue

# If local user, ensure they exist
elif (
'@' not in r['user']
local_user
and allow_local
and r['role'] != PROJECT_ROLE_OWNER
and not User.objects.filter(username=r['user']).first()
Expand All @@ -749,16 +767,15 @@ def _update_roles(self, project, project_data):
)
self._handle_user_error(error_msg, project, r_uuid)
continue

# Use the default owner, if owner role is for local user and local
# users are not allowed
if (
r['role'] == PROJECT_ROLE_OWNER
local_user
and r['role'] == PROJECT_ROLE_OWNER
and (
not allow_local
or not User.objects.filter(username=r['user']).first()
)
and '@' not in r['user']
):
role_user = self.default_owner
# Notify of assigning role to default owner
Expand Down Expand Up @@ -1118,10 +1135,13 @@ def _sync_app_setting(self, uuid, set_data):
)
return
if user_name:
local_user = self._is_local_user(
self.remote_data['users'][user_uuid]
)
allow_local = getattr(
settings, 'PROJECTROLES_ALLOW_LOCAL_USERS', False
)
if '@' not in user_name and not allow_local:
if local_user and not allow_local:
logger.info(skip_msg + NO_LOCAL_USERS_MSG)
return
user = User.objects.filter(sodar_uuid=user_uuid).first()
Expand Down Expand Up @@ -1270,6 +1290,8 @@ def sync_remote_data(self, site, remote_data, request=None):
# NOTE: Add all users here, only update local users within _sync_user()
for u_uuid, u_data in self.remote_data['users'].items():
self._sync_user(u_uuid, u_data)
# HACK: Populate user lookup
self.user_lookup[u_data['username']] = u_uuid
logger.info('User sync OK')

# Categories and Projects
Expand Down
14 changes: 8 additions & 6 deletions projectroles/tests/test_remote_project_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
REMOTE_LEVEL_READ_INFO = SODAR_CONSTANTS['REMOTE_LEVEL_READ_INFO']
REMOTE_LEVEL_READ_ROLES = SODAR_CONSTANTS['REMOTE_LEVEL_READ_ROLES']
REMOTE_LEVEL_REVOKED = SODAR_CONSTANTS['REMOTE_LEVEL_REVOKED']
SYSTEM_USER_GROUP = SODAR_CONSTANTS['SYSTEM_USER_GROUP']

# Local constants
SOURCE_SITE_NAME = 'Test source site'
Expand Down Expand Up @@ -1240,6 +1241,7 @@ def test_create_local_owner(self):

remote_data = self.default_data
remote_data['users'][SOURCE_USER_UUID]['username'] = 'source_admin'
remote_data['users'][SOURCE_USER_UUID]['groups'] = [SYSTEM_USER_GROUP]
remote_data['projects'][SOURCE_CATEGORY_UUID]['roles'][
SOURCE_CATEGORY_ROLE_UUID
]['user'] = 'source_admin'
Expand Down Expand Up @@ -1345,7 +1347,7 @@ def test_create_local_user(self):
'last_name': SOURCE_USER_LAST_NAME,
'email': SOURCE_USER_EMAIL,
'additional_emails': [],
'groups': ['system'],
'groups': [SYSTEM_USER_GROUP],
}
remote_data['projects'][SOURCE_PROJECT_UUID]['roles'][role_uuid] = {
'user': local_user_username,
Expand Down Expand Up @@ -1377,7 +1379,7 @@ def test_create_local_user_allow(self):
'last_name': SOURCE_USER_LAST_NAME,
'email': SOURCE_USER_EMAIL,
'additional_emails': [],
'groups': ['system'],
'groups': [SYSTEM_USER_GROUP],
}
remote_data['projects'][SOURCE_PROJECT_UUID]['roles'][role_uuid] = {
'user': local_user_username,
Expand Down Expand Up @@ -1407,7 +1409,7 @@ def test_create_local_user_allow_unavailable(self):
'last_name': SOURCE_USER_LAST_NAME,
'email': SOURCE_USER_EMAIL,
'additional_emails': [],
'groups': ['system'],
'groups': [SYSTEM_USER_GROUP],
}
remote_data['projects'][SOURCE_PROJECT_UUID]['roles'][role_uuid] = {
'user': local_user_username,
Expand Down Expand Up @@ -1438,7 +1440,7 @@ def test_create_local_owner_allow(self):
'last_name': SOURCE_USER_LAST_NAME,
'email': SOURCE_USER_EMAIL,
'additional_emails': [],
'groups': ['system'],
'groups': [SYSTEM_USER_GROUP],
}
remote_data['projects'][SOURCE_PROJECT_UUID]['roles'] = {
role_uuid: {
Expand Down Expand Up @@ -1473,7 +1475,7 @@ def test_create_local_owner_allow_unavailable(self):
'last_name': SOURCE_USER_LAST_NAME,
'email': SOURCE_USER_EMAIL,
'additional_emails': [],
'groups': ['system'],
'groups': [SYSTEM_USER_GROUP],
}
remote_data['projects'][SOURCE_PROJECT_UUID]['roles'] = {
role_uuid: {
Expand Down Expand Up @@ -1982,7 +1984,7 @@ def test_update_user_uuid_local_disallow(self):
'last_name': local_name.split(' ')[1],
'email': '[email protected]',
'additional_emails': [],
'groups': [SOURCE_USER_GROUP],
'groups': [SYSTEM_USER_GROUP],
}
self.assertEqual(User.objects.all().count(), 3)
self.remote_api.sync_remote_data(self.source_site, remote_data)
Expand Down

0 comments on commit b6c938b

Please sign in to comment.