Skip to content

Commit

Permalink
🚜 🐎 Simplify setting schedules (#614)
Browse files Browse the repository at this point in the history
  • Loading branch information
shnizzedy committed Jan 17, 2020
2 parents 6461f27 + 231526c commit 66c752c
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 7 deletions.
43 changes: 40 additions & 3 deletions girderformindlogger/api/v1/applet.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def __init__(self):
self.route('PUT', (':id', 'informant'), self.updateInformant)
self.route('PUT', (':id', 'assign'), self.assignGroup)
self.route('PUT', (':id', 'constraints'), self.setConstraints)
self.route('PUT', (':id', 'schedule'), self.setSchedule)
self.route('POST', (':id', 'invite'), self.invite)
self.route('GET', (':id', 'roles'), self.getAppletRoles)
self.route('GET', (':id', 'users'), self.getAppletUsers)
Expand Down Expand Up @@ -444,22 +445,23 @@ def invite(self, applet, role="user", idCode=None, profile=None):

@access.user(scope=TokenScope.DATA_WRITE)
@autoDescribeRoute(
Description('Set or update schedule information for an activity.')
Description('Deprecated. Do not use')
.modelParam('id', model=AppletModel, level=AccessType.READ)
.param(
'activity',
'Girder ID (or Array thereof) of the activity/activities to '
'Deprecated. Do not use.'
'schedule.',
required=False
)
.jsonParam(
'schedule',
'A JSON object containing schedule information for an activity',
'Deprecated. Do not use.',
paramType='form',
required=False
)
.errorResponse('Invalid applet ID.')
.errorResponse('Read access was denied for this applet.', 403)
.deprecated()
)
def setConstraints(self, folder, activity, schedule, **kwargs):
thisUser = self.getCurrentUser()
Expand All @@ -476,6 +478,41 @@ def setConstraints(self, folder, activity, schedule, **kwargs):
thread.start()
return(applet)

@access.user(scope=TokenScope.DATA_WRITE)
@autoDescribeRoute(
Description('Set or update schedule information for an applet.')
.modelParam(
'id',
model=AppletModel,
level=AccessType.READ,
destName='applet'
)
.jsonParam(
'schedule',
'A JSON object containing schedule information for an applet',
paramType='form',
required=False
)
.errorResponse('Invalid applet ID.')
.errorResponse('Read access was denied for this applet.', 403)
)
def setSchedule(self, applet, schedule, **kwargs):
thisUser = self.getCurrentUser()
if not AppletModel().isCoordinator(applet['_id'], thisUser):
raise AccessException(
"Only coordinators and managers can update applet schedules."
)
appletMeta = applet['meta'] if 'meta' in applet else {'applet': {}}
if 'applet' not in appletMeta:
appletMeta['applet'] = {}
appletMeta['applet']['schedule'] = schedule
AppletModel().setMetadata(applet, appletMeta)
thread = threading.Thread(
target=AppletModel().updateUserCacheAllUsersAllRoles,
args=(applet, thisUser)
)
thread.start()
return(appletMeta)


def authorizeReviewer(applet, reviewer, user):
Expand Down
107 changes: 107 additions & 0 deletions girderformindlogger/api/v1/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ def __init__(self):
self.route('GET', (), self.find)
self.route('GET', ('me',), self.getMe)
self.route('GET', ('authentication',), self.login)
self.route('PUT', ('applet', ':id', 'schedule'), self.setSchedule)
self.route(
'PUT',
(':uid', 'applet', ':aid', 'schedule'),
self.setOtherSchedule
)
self.route('GET', (':id',), self.getUserByID)
self.route('GET', (':id', 'access'), self.getUserAccess)
self.route('PUT', (':id', 'access'), self.updateUserAccess)
Expand Down Expand Up @@ -163,6 +169,107 @@ def getUserByID(self, id):
user = self.getCurrentUser()
return(ProfileModel().getProfile(id, user))

@access.user(scope=TokenScope.DATA_WRITE)
@autoDescribeRoute(
Description('Set or update your own custom schedule information for an applet.')
.modelParam(
'id',
model=AppletModel,
level=AccessType.READ,
destName='applet'
)
.jsonParam(
'schedule',
'A JSON object containing schedule information for an activity',
paramType='form',
required=False
)
.errorResponse('Invalid applet ID.')
.errorResponse('Read access was denied for this applet.', 403)
)
def setSchedule(self, applet, schedule, **kwargs):
import threading

thisUser = self.getCurrentUser()
if not AppletModel()._hasRole(applet['_id'], thisUser, 'user'):
raise AccessException(
"You aren't a user of this applet."
)
profile = ProfileModel().findOne(
{
'appletId': applet['_id'],
'userId': thisUser['_id'],
'profile': True
}
)
if not profile:
raise AccessException(
"You aren't a user of this applet."
)
ud = profile["userDefined"] if "userDefined" in profile else {}
ud["schedule"] = schedule
profile["userDefined"] = ud
ProfileModel().save(profile, validate=False)

thread = threading.Thread(
target=AppletModel().updateUserCacheAllUsersAllRoles,
args=(applet, thisUser)
)
thread.start()
return(profile["userDefined"])

@access.user(scope=TokenScope.DATA_WRITE)
@autoDescribeRoute(
Description('Set or update custom schedule information for a user of an applet you manage or coordinate.')
.modelParam(
'uid',
model=ProfileModel,
force=True,
destName='profile',
description='The ID of the user\'s profile for this applet.'
)
.modelParam(
'aid',
model=AppletModel,
level=AccessType.READ,
destName='applet',
description="The ID of the applet."
)
.jsonParam(
'schedule',
'A JSON object containing schedule information for an activity',
paramType='form',
required=False
)
.errorResponse('Invalid ID.')
.errorResponse('Read access was denied.', 403)
)
def setOtherSchedule(self, profile, applet, schedule, **kwargs):
import threading

thisUser = self.getCurrentUser()
if not AppletModel().isCoordinator(applet['_id'], thisUser):
raise AccessException(
"You aren't a coordinator or manager of this applet."
)
if profile["appletId"] not in [applet['_id'], str(applet['_id'])]:
raise AccessException(
"That profile is not a user of this applet."
)
ud = profile[
"coordinatorDefined"
] if "coordinatorDefined" in profile else {}
ud["schedule"] = schedule
profile["coordinatorDefined"] = ud
ProfileModel().save(profile, validate=False)

thread = threading.Thread(
target=AppletModel().updateUserCacheAllUsersAllRoles,
args=(applet, thisUser)
)
thread.start()
return(profile["coordinatorDefined"])

@access.public(scope=TokenScope.USER_INFO_READ)
@autoDescribeRoute(
Description('Add a relationship between users.')
Expand Down
25 changes: 22 additions & 3 deletions girderformindlogger/models/applet.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,10 +374,20 @@ def getAppletsForGroup(self, role, groupId, active=True):
return(applets if isinstance(applets, list) else [applets])

def updateUserCacheAllUsersAllRoles(self, applet, coordinator):
[self.updateUserCacheAllRoles(user) for user in self.getAppletUsers(
from .profile import Profile as ProfileModel

[self.updateUserCacheAllRoles(
UserModel().load(
id=ProfileModel().load(
user['_id'],
force=True
).get('userId'),
force=True
)
) for user in self.getAppletUsers(
applet,
coordinator
)]
).get('active', [])]

def updateUserCacheAllRoles(self, user):
[self.updateUserCache(role, user) for role in list(USER_ROLES.keys())]
Expand Down Expand Up @@ -510,7 +520,16 @@ def getAppletsForUser(self, role, user, active=True):
'roles.' + role + '.groups.id': {'$in': user.get('groups', [])}
}
))
return(applets if isinstance(applets, list) else [applets])

# filter out duplicates for coordinators
temp = set()
applets = [
k for k in applets if '_id' in k and k[
'_id'
] not in temp and not temp.add(k['_id'])
] if isinstance(applets, list) else [applets]

return(applets)

def listUsers(self, applet, role, user=None, force=False):
from .profile import Profile
Expand Down
8 changes: 7 additions & 1 deletion girderformindlogger/models/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,13 @@ def profileAsUser(self, profile, requester):
])
))

def displayProfileFields(self, profile, user=None, forceManager=False, forceReviewer=False):
def displayProfileFields(
self,
profile,
user=None,
forceManager=False,
forceReviewer=False
):
"""
:param profile: Profile or Invitation
:type profile: dict
Expand Down

0 comments on commit 66c752c

Please sign in to comment.