示例#1
0
    def checkTemporaryPassword(self, user, token):
        token = Token().load(
            token, user=user, level=AccessType.ADMIN, objectId=False, exc=True)
        delta = (token['expires'] - datetime.datetime.utcnow()).total_seconds()
        hasScope = Token().hasScope(token, TokenScope.TEMPORARY_USER_AUTH)

        if delta <= 0:
            raise AccessException("The token is expired")

        if token.get('userId') != user['_id'] or not hasScope:
            raise AccessException('The token does not grant temporary access to this user.')

        # Temp auth is verified, send an actual auth token now. We keep the
        # temp token around since it can still be used on a subsequent request
        # to change the password
        authToken = self.sendAuthTokenCookie(user)

        return {
            'user': self._model.filter(user, user),
            'authToken': {
                'token': authToken['_id'],
                'expires': authToken['expires'],
                'temporary': True
            },
            'message': 'Temporary access token is valid.'
        }
示例#2
0
    def updateUser(
        self,
        user,
        displayName="",
        email="",
        admin=False,
        status=None,
        firstName=None,
        lastName=None
    ):  # 🔥 delete firstName and lastName once fully deprecated
        user['firstName'] = displayName if len(
            displayName) else firstName if firstName is not None else ""
        user['email'] = email

        # Only admins can change admin state
        if admin is not None:
            if self.getCurrentUser()['admin']:
                user['admin'] = admin
            elif user['admin'] is not admin:
                raise AccessException('Only admins may change admin status.')

        # Only admins can change status
        if status is not None and status != user.get('status', 'enabled'):
            if not self.getCurrentUser()['admin']:
                raise AccessException('Only admins may change status.')
            if user['status'] == 'pending' and status == 'enabled':
                # Send email on the 'pending' -> 'enabled' transition
                self._model._sendApprovedEmail(user)
            user['status'] = status

        return self._model.save(user)
示例#3
0
    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)

        return(profile["userDefined"])
示例#4
0
    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"])
示例#5
0
    def login(self):
        import threading
        from girderformindlogger.utility.mail_utils import validateEmailAddress

        if not Setting().get(SettingKey.ENABLE_PASSWORD_LOGIN):
            raise RestException('Password login is disabled on this instance.')

        user, token = self.getCurrentUser(returnToken=True)

        # Only create and send new cookie if user isn't already sending a valid
        # one.
        if not user:
            authHeader = cherrypy.request.headers.get('Authorization')

            if not authHeader:
                authHeader = cherrypy.request.headers.get(
                    'Girder-Authorization')

            if not authHeader or not authHeader[0:6] == 'Basic ':
                raise RestException('Use HTTP Basic Authentication', 401)

            try:
                credentials = base64.b64decode(authHeader[6:]).decode('utf8')
                if ':' not in credentials:
                    raise TypeError
            except Exception:
                raise RestException('Invalid HTTP Authorization header', 401)

            login, password = credentials.split(':', 1)
            if validateEmailAddress(login):
                raise AccessException(
                    "Please log in with a username, not an email address.")
            otpToken = cherrypy.request.headers.get('Girder-OTP')
            try:
                user = self._model.authenticate(login, password, otpToken)
            except:
                raise AccessException(
                    "Incorrect password for {} if that user exists".format(
                        login))

            thread = threading.Thread(
                target=AppletModel().updateUserCacheAllRoles, args=(user, ))

            setCurrentUser(user)
            token = self.sendAuthTokenCookie(user)

        return {
            'user': self._model.filter(user, user),
            'authToken': {
                'token': token['_id'],
                'expires': token['expires'],
                'scope': token['scope']
            },
            'message': 'Login succeeded.'
        }
示例#6
0
 def getAppletUsers(self, applet):
     thisUser = self.getCurrentUser()
     if AppletModel().isCoordinator(applet['_id'], thisUser):
         return (AppletModel().getAppletUsers(applet, thisUser, force=True))
     else:
         raise AccessException(
             "Only coordinators and managers can see user lists.")
示例#7
0
def ensureTokenScopes(token, scope):
    """
    Call this to validate a token scope for endpoints that require tokens
    other than a user authentication token. Raises an AccessException if the
    required scopes are not allowed by the given token.

    :param token: The token object used in the request.
    :type token: dict
    :param scope: The required scope or set of scopes.
    :type scope: `str or list of str`
    """
    tokenModel = Token()
    if tokenModel.hasScope(token, TokenScope.USER_AUTH):
        return

    if not tokenModel.hasScope(token, scope):
        setCurrentUser(None)
        if isinstance(scope, six.string_types):
            scope = (scope,)
        raise AccessException(
            'Invalid token scope.\n'
            'Required: %s.\n'
            'Allowed: %s' % (
                ' '.join(scope),
                '' if token is None else ' '.join(tokenModel.getAllowedScopes(token))))
示例#8
0
 def wrapped(*args, **kwargs):
     if not rest.getCurrentToken():
         raise AccessException(
             'You must be logged in or have a valid auth token.')
     if required:
         Token().requireScope(rest.getCurrentToken(), scope)
     return fun(*args, **kwargs)
示例#9
0
    def removeFromGroup(self, group, userToRemove, delete):
        user = self.getCurrentUser()
        if not (bool(
            group.get('_id') in [
                *user.get('groups', []),
                *user.get('formerGroups', []),
                *[
                    g.get('groupId') for g  in [
                        *user.get('groupInvites', []),
                        *user.get('declinedInvites', [])
                    ]
                ]
            ]
        )):
            raise AccessException(message="You haven't been invited to that group.")
        else:
            groupModel = self._model
            if userToRemove is None:
                # Assume user is removing themself from the group
                userToRemove = user

            # # If removing someone else, you must have at least as high an
            # # access level as they do, and you must have at least write access
            # # to remove any user other than yourself.
            # if user['_id'] != userToRemove['_id']:
            #     if groupModel.hasAccess(group, userToRemove, AccessType.ADMIN):
            #         groupModel.requireAccess(group, user, AccessType.ADMIN)
            #     else:
            #         groupModel.requireAccess(group, user, AccessType.WRITE)
            group = groupModel.removeUser(group, userToRemove, delete)
            group['access'] = groupModel.getFullAccessList(group)
            group['requests'] = list(groupModel.getFullRequestList(group))
            return(group)
示例#10
0
    def acceptInvitationByToken(self, invitation, lang, email, token):
        """
        Accept an invitation.
        """
        currentUser = Token().load(
            token,
            force=True,
            objectId=False,
            exc=False
        ).get('userId', None)
        if currentUser is not None:
            currentUser = UserModel().load(currentUser, force=True)
        if currentUser is None:
            raise AccessException(
                "Invalid token."
            )
        if invitation.get('role', 'user') == 'owner':
            AppletModel().receiveOwnerShip(AppletModel().load(invitation['appletId'], force=True), currentUser, email)
        else:
            profile = InvitationModel().acceptInvitation(invitation, currentUser, email)

            # editors should be able to access duplicated applets
            if invitation.get('role','user') == 'editor' or invitation.get('role', 'user') == 'manager':
                InvitationModel().accessToDuplicatedApplets(invitation, currentUser, email)

        InvitationModel().remove(invitation)
        return profile
示例#11
0
    def verifyEmail(self, user, token):
        token = Token().load(token,
                             user=user,
                             level=AccessType.ADMIN,
                             objectId=False,
                             exc=True)
        delta = (token['expires'] - datetime.datetime.utcnow()).total_seconds()
        hasScope = Token().hasScope(token, TokenScope.EMAIL_VERIFICATION)

        if token.get('userId') != user['_id'] or delta <= 0 or not hasScope:
            raise AccessException('The token is invalid or expired.')

        user['emailVerified'] = True
        Token().remove(token)
        user = self._model.save(user)

        if self._model.canLogin(user):
            setCurrentUser(user)
            authToken = self.sendAuthTokenCookie(user)
            return {
                'user': self._model.filter(user, user),
                'authToken': {
                    'token': authToken['_id'],
                    'expires': authToken['expires'],
                    'scope': authToken['scope']
                },
                'message': 'Email verification succeeded.'
            }
        else:
            return {
                'user': self._model.filter(user, user),
                'message': 'Email verification succeeded.'
            }
示例#12
0
    def createCollection(self, name, description, public):
        user = self.getCurrentUser()

        if not self._model.hasCreatePrivilege(user):
            raise AccessException('You are not authorized to create collections.')

        return self._model.createCollection(
            name=name, description=description, public=public, creator=user)
示例#13
0
    def cancelUpload(self, upload):
        user = self.getCurrentUser()

        if upload['userId'] != user['_id'] and not user['admin']:
            raise AccessException('You did not initiate this upload.')

        Upload().cancelUpload(upload)
        return {'message': 'Upload canceled.'}
示例#14
0
 def getUserApplets(self, user, role, ids_only):
     from bson.objectid import ObjectId
     reviewer = self.getCurrentUser()
     if reviewer is None:
         raise AccessException("You must be logged in to get user applets.")
     if user.get('_id') != reviewer.get('_id') and user.get(
             '_id') is not None:
         raise AccessException("You can only get your own applets.")
     role = role.lower()
     if role not in USER_ROLES.keys():
         raise RestException('Invalid user role.', 'role')
     try:
         applets = AppletModel().getAppletsForUser(role, user, active=True)
         if len(applets) == 0:
             return ([])
         if ids_only == True:
             return ([applet.get('_id') for applet in applets])
         return ([{
             **jsonld_expander.formatLdObject(applet,
                                              'applet',
                                              reviewer,
                                              refreshCache=False), "users":
             AppletModel().getAppletUsers(applet, user),
             "groups":
             AppletModel().getAppletGroups(applet, arrayOfObjects=True)
         } if role == "manager" else {
             **jsonld_expander.formatLdObject(applet,
                                              'applet',
                                              reviewer,
                                              dropErrors=True), "groups": [
                 group for group in AppletModel().getAppletGroups(
                     applet).get(role) if ObjectId(group) in [
                         *user.get('groups', []),
                         *user.get('formerGroups', []), *[
                             invite['groupId'] for invite in [
                                 *user.get('groupInvites', []),
                                 *user.get('declinedInvites', [])
                             ]
                         ]
                     ]
             ]
         } for applet in applets if (applet is not None and not applet.get(
             'meta', {}).get('applet', {}).get('deleted'))])
     except Exception as e:
         return (e)
示例#15
0
    def setUserRelationship(self, id, rel, otherId, otherName):
        from girderformindlogger.models.invitation import Invitation
        from girderformindlogger.utility.jsonld_expander import                \
            inferRelationships, oidIffHex

        user = self.getCurrentUser()
        grammaticalSubject = ProfileModel().getProfile(id, user)
        gsp = ProfileModel().load(
            grammaticalSubject['_id'],
            force=True
        )
        grammaticalSubject = Invitation().load(
            grammaticalSubject['_id'],
            force=True
        ) if gsp is None else gsp
        print(grammaticalSubject)
        if grammaticalSubject is None or not AppletModel().isCoordinator(
            grammaticalSubject['appletId'], user
        ):
            raise AccessException(
                'You do not have permission to update this user.'
            )

        appletId = grammaticalSubject['appletId']
        grammaticalObject = ProfileModel().getSubjectProfile(
            otherId,
            otherName,
            user
        )
        if grammaticalObject is None:
            grammaticalObject = ProfileModel().getProfile(
                ProfileModel().createPassiveProfile(
                    appletId,
                    otherId,
                    otherName,
                    user
                )['_id'],
                grammaticalSubject
            )
        if 'schema:knows' in grammaticalSubject:
            if rel in grammaticalSubject['schema:knows'] and grammaticalObject[
                '_id'
            ] not in grammaticalSubject['schema:knows'][rel]:
                grammaticalSubject['schema:knows'][rel].append(
                    grammaticalObject['_id']
                )
            else:
                grammaticalSubject['schema:knows'][rel] = [
                    grammaticalObject['_id']
                ]
        else:
            grammaticalSubject['schema:knows'] = {
                rel: [grammaticalObject['_id']]
            }
        ProfileModel().save(grammaticalSubject, validate=False)
        inferRelationships(grammaticalSubject)
        return(ProfileModel().getProfile(id, user))
示例#16
0
 def acceptInvitation(self, invitation):
     """
     Accept an invitation.
     """
     currentUser = self.getCurrentUser()
     if currentUser is None:
         raise AccessException(
             "You must be logged in to accept an invitation.")
     return (InvitationModel().acceptInvitation(invitation, currentUser))
示例#17
0
 def updateInformant(self, applet, informant):
     user = self.getCurrentUser()
     if not AppletModel().isManager(applet['_id'], user):
         raise AccessException(
             "Only managers can update informant relationship")
     AppletModel().updateRelationship(applet, informant)
     return (jsonld_expander.formatLdObject(applet,
                                            'applet',
                                            user,
                                            refreshCache=False))
示例#18
0
    def updateUser(
        self,
        user,
        displayName="",
        email="",
        admin=False,
        status=None,
        firstName=None,
        lastName=None
    ):
        user['displayName'] = displayName if len(
            displayName
        ) else firstName if firstName is not None else ""
        user['email'] = UserModel().hash(email)
        user['email_encrypted'] = True

        # Only admins can change admin state
        if admin is not None:
            if self.getCurrentUser()['admin']:
                user['admin'] = admin
            elif user['admin'] is not admin:
                raise AccessException('Only admins may change admin status.')

            # Only admins can change status
            if status is not None and status != user.get('status', 'enabled'):
                if not self.getCurrentUser()['admin']:
                    raise AccessException('Only admins may change status.')
                if user['status'] == 'pending' and status == 'enabled':
                    # Send email on the 'pending' -> 'enabled' transition
                    self._model._sendApprovedEmail(user, email)
                user['status'] = status

        try:
            self._model.save(user)
        except:
            raise RestException(
                'Update failed, and `PUT /user/{:id}` is deprecated.'
            )

        return(
            {'message': 'Update saved, but `PUT /user/{:id}` is deprecated.'}
        )
示例#19
0
    def requireScope(self, token, scope):
        """
        Raise an error if given set of scopes are not included.

        :param token: The token object.
        :type token: dict
        :param scope: A scope or set of scopes that will be tested as a subset
            of the given token's allowed scopes.
        :type scope: str or list of str
        """
        if not self.hasScope(token, scope):
            raise AccessException('Invalid token scope, required: %s.' % (scope))
示例#20
0
def requireAdmin(user, message=None):
    """
    Calling this on a user will ensure that they have admin rights.  If not,
    raises an AccessException.

    :param user: The user to check admin flag on.
    :type user: dict.
    :param message: The exception message.
    :type message: str or None
    :raises AccessException: If the user is not an administrator.
    """
    if user is None or not user['admin']:
        raise AccessException(message or 'Administrator access required.')
示例#21
0
 def removeIDCode(self, id, code):
     from bson.objectid import ObjectId
     user = self.getCurrentUser()
     try:
         p = ProfileModel().findOne({'_id': ObjectId(id)})
     except:
         p = None
     if p is None or not AppletModel().isCoordinator(p['appletId'], user):
         raise AccessException(
             'You do not have permission to update this user\'s ID code.')
     else:
         IDCode().removeCode(p['_id'], code)
     return (ProfileModel().profileAsUser(
         ProfileModel().load(p['_id'], force=True), user))
示例#22
0
 def acceptInvitationByToken(self, invitation, email, token):
     """
     Accept an invitation.
     """
     currentUser = Token().load(token,
                                force=True,
                                objectId=False,
                                exc=False).get('userId', None)
     if currentUser is not None:
         currentUser = UserModel().load(currentUser, force=True)
     if currentUser is None:
         raise AccessException("Invalid token.")
     return (InvitationModel().acceptInvitation(invitation, currentUser,
                                                email))
示例#23
0
    def getSchedule(self, applet, getAllEvents=False, refreshCache=False):
        user = self.getCurrentUser()

        if not getAllEvents:
            schedule = EventsModel().getScheduleForUser(
                applet['_id'], user['_id'],
                AppletModel().isCoordinator(applet['_id'], user))
        else:
            if not AppletModel().isCoordinator(applet['_id'], user):
                raise AccessException(
                    "Only coordinators and managers can get all events.")
            schedule = EventsModel().getSchedule(applet['_id'])

        return schedule
示例#24
0
 def acceptInvitationByToken(self, invitation, token):
     """
     Accept an invitation.
     """
     currentUser = Token().load(token,
                                force=True,
                                objectId=False,
                                exc=False).get('userId')
     if currentUser is not None:
         currentUser = UserModel().load(currentUser, force=True)
     if currentUser is None:
         raise AccessException(
             "You must be logged in to accept an invitation.")
     return (InvitationModel().acceptInvitation(invitation, currentUser))
示例#25
0
 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)
示例#26
0
 def __enter__(self):
     try:
         if self.encryption == 'ssl':
             self.connection = smtplib.SMTP_SSL(self.host, self.port)
         else:
             self.connection = smtplib.SMTP(self.host, self.port)
             if self.encryption == 'starttls':
                 self.connection.starttls()
         if self.username and self.password:
             self.connection.login(self.username, self.password)
     except:
         raise AccessException(
             "An error occured when we were sending message. "
             "Please try again later.")
     return self
    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.")
        if 'events' in schedule:
            for event in schedule['events']:
                if 'data' in event and 'useNotifications' in event[
                        'data'] and event['data']['useNotifications']:
                    if event['data']['notifications'][0]['start']:
                        sendTime = event['data']['notifications'][0]['start']
                    else:
                        sendTime = '09:00'

                    # in case of sigle event with exact year, month, day
                    if 'year' in event['schedule'] and 'month' in event[
                            'schedule'] and 'dayOfMonth' in event['schedule']:
                        sendTime = (
                            str(event['schedule']['year'][0]) + '/' +
                            ('0' + str(event['schedule']['month'][0] + 1))[-2:]
                            + '/' +
                            ('0' +
                             str(event['schedule']['dayOfMonth'][0]))[-2:] +
                            ' ' + sendTime)
                        existNotification = PushNotificationModel().findOne(
                            query={
                                'applet': applet['_id'],
                                'creator_id': thisUser['_id'],
                                'sendTime': str(sendTime)
                            })
                        if not existNotification:
                            PushNotificationModel().createNotification(
                                applet['_id'], 1, event['data']['title'],
                                event['data']['description'], str(sendTime),
                                thisUser['_id'])

                    # in case of daily event

        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)
示例#28
0
    def _promote(self, group, user, level):
        """
        Promote a user to moderator or administrator.

        :param group: The group to promote within.
        :param user: The user to promote.
        :param level: Either WRITE or ADMIN, for moderator or administrator.
        :type level: AccessType
        :returns: The updated group document.
        """
        if not group['_id'] in user.get('groups', []):
            raise AccessException('That user is not a group member.')

        group = self._model.setUserAccess(group, user, level=level, save=True)
        group['access'] = self._model.getFullAccessList(group)
        return group
示例#29
0
 def updateProfile(self, profileId, user, profileUpdate):
     from copy import deepcopy
     from girderformindlogger.models.applet import Applet
     profile = self.load(profileId, force=True)
     if str(user["_id"] == profile["userId"]):
         update = deepcopy(profile.get("userDefined", {}))
         update.update(profileUpdate)
         profile["userDefined"] = update
     elif Applet().isCoordinator(profile["appletId"], user):
         update = deepcopy(profile.get("coordinatorDefined", {}))
         update.update(profileUpdate)
         profile["coordinatorDefined"] = update
     else:
         raise AccessException(
             "You do not have adequate permissions to update this profile.")
     return self.save(profile, validate=False)
示例#30
0
    def refresh(self, applet):
        user = self.getCurrentUser()

        if not AppletModel().isCoordinator(applet['_id'], user):
            raise AccessException(
                "Only coordinators and managers can update applet.")

        thread = threading.Thread(target=AppletModel().reloadAndUpdateCache,
                                  args=(applet, user))

        thread.start()

        return ({
            "message":
            "The protocol is being reloaded and cached data is being updated. Please check back "
            "in several mintutes to see it."
        })