def joinGroup(self, group, user): """ This method either accepts an invitation to join a group, or if the given user has not been invited to the group, this will create an invitation request that moderators and admins may grant or deny later. """ from girderformindlogger.models.user import User if 'groupInvites' not in user: user['groupInvites'] = [] if group.get('openRegistration', False): self.addUser(group, user, level=AccessType.READ) User().save(user, validate=False) else: for invite in user['groupInvites']: if invite['groupId'] == group['_id']: self.addUser(group, user, level=invite['level']) user['groupInvites'].remove(invite) User().save(user, validate=False) break else: if 'requests' not in group: group['requests'] = [] if not user['_id'] in group['requests']: group['requests'].append(user['_id']) group = self.save(group, validate=False) return (group)
def setUp(self): base.TestCase.setUp(self) admin = { 'email': '*****@*****.**', 'login': '******', 'firstName': 'Admin', 'lastName': 'Last', 'password': '******', 'admin': True } self.admin = User().createUser(**admin) user = { 'email': '*****@*****.**', 'login': '******', 'firstName': 'First', 'lastName': 'Last', 'password': '******', 'admin': False } self.user = User().createUser(**user) coll = { 'name': 'Test Collection', 'description': 'The description', 'public': True, 'creator': self.admin } self.collection = Collection().createCollection(**coll) Folder().createFolder(parent=self.collection, parentType='collection', name='Public', public=True, creator=self.admin)
def setUp(self): base.TestCase.setUp(self) self.admin = User().createUser(email='*****@*****.**', login='******', lastName='admin', firstName='admin', password='******', admin=True) self.user = User().createUser(email='*****@*****.**', login='******', lastName='u', firstName='u', password='******') self.f1 = Folder().createFolder(self.admin, 'f1', creator=self.admin, parentType='user') self.f2 = Folder().createFolder(self.admin, 'f2', creator=self.admin, parentType='user') self.virtual = Folder().createFolder(self.user, 'v', creator=self.user, parentType='user') self.virtual['isVirtual'] = True
def load(self, info): User().ensureIndex(( (('oauth.provider', SortDir.ASCENDING), ('oauth.id', SortDir.ASCENDING)), {})) User().reconnect() events.bind('no_password_login_attempt', 'oauth', checkOauthUser) info['apiRoot'].oauth = rest.OAuth()
def fastCrypt(): """ Use faster password hashing to avoid unnecessary testing bottlenecks. """ from girderformindlogger.models.user import User # CryptContext.update could be used to mutate the existing instance, but if this fixture's scope # is ever made more limited (so that the teardown matters), this approach is more maintainable originalCryptContext = User()._cryptContext User()._cryptContext = originalCryptContext.copy(schemes=['plaintext']) yield User()._cryptContext = originalCryptContext
def _getLdapUser(attrs, server): emails = attrs.get('mail') if not emails: raise Exception('No email record present for the given LDAP user.') if not isinstance(emails, (list, tuple)): emails = (emails, ) emails = [e.decode('utf8').lower() for e in emails] existing = User().find({'email': {'$in': emails}}, limit=1) if existing.count(): return next(existing) return _registerLdapUser(attrs, emails[0], server)
def _testLogin(cls, login): """ When attempting to generate a username, use this to test if the given name is valid. """ try: User()._validateLogin(login) except ValidationException: # Still doesn't match regex, we're hosed return False # See if this is already taken. user = User().findOne({'login': login}) return not user
def inviteUser(self, group, user, level=AccessType.READ): """ Invite a user to join the group. Inviting them automatically grants the user read access to the group so that they can see it. Once they accept the invitation, they will be given the specified level of access. If the user has requested an invitation to this group, calling this will accept their request and add them to the group at the access level specified. """ from girderformindlogger.models.user import User if group['_id'] in user.get('groups', []): raise ValidationException('User is already in this group.') # If there is an outstanding request to join from this user, we # just add them to the group instead of invite them. if user['_id'] in group.get('requests', []): return self.addUser(group, user, level) if 'groupInvites' not in user: user['groupInvites'] = [] for invite in user['groupInvites']: if invite['groupId'] == group['_id']: invite['level'] = level break else: user['groupInvites'].append({ 'groupId': group['_id'], 'level': level }) return User().save(user, validate=False)
def validate(self, doc): from girderformindlogger.models.token import Token from girderformindlogger.models.user import User if doc['tokenDuration']: doc['tokenDuration'] = float(doc['tokenDuration']) else: doc['tokenDuration'] = None doc['name'] = doc['name'].strip() doc['active'] = bool(doc.get('active', True)) if doc['scope'] is not None: if not isinstance(doc['scope'], (list, tuple)): raise ValidationException('Scope must be a list, or None.') if not doc['scope']: raise ValidationException('Custom scope list must not be empty.') # Ensure only registered scopes are being set admin = User().load(doc['userId'], force=True)['admin'] scopes = TokenScope.scopeIds(admin) unknownScopes = set(doc['scope']) - scopes if unknownScopes: raise ValidationException('Invalid scopes: %s.' % ','.join(unknownScopes)) # Deactivating an already existing token if '_id' in doc and not doc['active']: Token().clearForApiKey(doc) return doc
def createToken(self, key, days=None): """ Create a token using an API key. :param key: The API key (the key itself, not the full document). :type key: str :param days: You may request a token duration up to the token duration of the API key itself, or pass None to use the API key duration. :type days: float or None """ from girderformindlogger.models.setting import Setting from girderformindlogger.models.token import Token from girderformindlogger.models.user import User apiKey = self.findOne({ 'key': key }) if apiKey is None or not apiKey['active']: raise ValidationException('Invalid API key.') cap = apiKey['tokenDuration'] or Setting().get(SettingKey.COOKIE_LIFETIME) days = min(float(days or cap), cap) user = User().load(apiKey['userId'], force=True) # Mark last used stamp apiKey['lastUse'] = datetime.datetime.utcnow() apiKey = self.save(apiKey) token = Token().createToken(user=user, days=days, scope=apiKey['scope'], apiKey=apiKey) return (user, token)
def __init__(self): super(User, self).__init__() self.resourceName = 'user' self._model = UserModel() self.route('DELETE', ('authentication', ), self.logout) self.route('DELETE', (':id', ), self.deleteUser) self.route('GET', (), self.find) self.route('GET', ('me', ), self.getMe) self.route('GET', ('authentication', ), self.login) self.route('GET', (':id', ), self.getUserByID) self.route('GET', (':id', 'access'), self.getUserAccess) self.route('PUT', (':id', 'access'), self.updateUserAccess) self.route('PUT', (':id', 'code'), self.updateIDCode) self.route('DELETE', (':id', 'code'), self.removeIDCode) self.route('GET', ('applets', ), self.getOwnApplets) self.route('GET', (':id', 'details'), self.getUserDetails) self.route('GET', ('invites', ), self.getGroupInvites) self.route('PUT', (':id', 'knows'), self.setUserRelationship) self.route('GET', ('details', ), self.getUsersDetails) self.route('POST', (), self.createUser) self.route('PUT', (':id', ), self.updateUser) self.route('PUT', ('password', ), self.changePassword) self.route('PUT', (':id', 'password'), self.changeUserPassword) self.route('GET', ('password', 'temporary', ':id'), self.checkTemporaryPassword) self.route('PUT', ('password', 'temporary'), self.generateTemporaryPassword) self.route('POST', (':id', 'otp'), self.initializeOtp) self.route('PUT', (':id', 'otp'), self.finalizeOtp) self.route('DELETE', (':id', 'otp'), self.removeOtp) self.route('PUT', ('profile', ), self.updateProfile) self.route('PUT', (':id', 'verification'), self.verifyEmail) self.route('POST', ('verification', ), self.sendVerificationEmail)
def _uploadComplete(event): """ Called after an upload finishes. We check if our current token is a special authorized upload token, and if so, delete it. TODO we could alternatively keep a reference count inside each token that authorized more than a single upload at a time, and just decrement it here. """ token = getCurrentToken() if token and 'authorizedUploadId' in token: user = User().load(token['userId'], force=True) item = Item().load(event.info['file']['itemId'], force=True) # Save the metadata on the item item['description'] = token['authorizedUploadDescription'] item['authorizedUploadEmail'] = token['authorizedUploadEmail'] Item().save(item) text = mail_utils.renderTemplate('authorized_upload.uploadFinished.mako', { 'itemId': item['_id'], 'itemName': item['name'], 'itemDescription': item.get('description', '') }) mail_utils.sendMail('Authorized upload complete', text, [user['email']]) Token().remove(token)
def setUp(self): base.TestCase.setUp(self) self.users = [ User().createUser('usr%s' % num, 'passwd', 'tst', 'usr', '*****@*****.**' % num) for num in [0, 1] ]
def testLdapStatusCheck(self): admin = User().createUser(login='******', email='*****@*****.**', firstName='admin', lastName='admin', password='******', admin=True) params = { 'bindName': 'cn=foo,cn=Users,dc=foo,dc=bar,dc=org', 'password': '******', 'uri': 'ldap://foo.bar.org:389' } with mock.patch('ldap.initialize', return_value=MockLdap(bindFail=True)): resp = self.request('/system/ldap_server/status', user=admin, params=params) self.assertStatusOk(resp) self.assertFalse(resp.json['connected']) self.assertEqual(resp.json['error'], 'LDAP connection error: failed to connect') with mock.patch('ldap.initialize', return_value=MockLdap(bindFail=False)): resp = self.request('/system/ldap_server/status', user=admin, params=params) self.assertStatusOk(resp) self.assertTrue(resp.json['connected']) self.assertNotIn('error', resp.json)
def getCollectionCreationPolicyAccess(self): cpp = Setting().get(SettingKey.COLLECTION_CREATE_POLICY) acList = { 'users': [{ 'id': x } for x in cpp.get('users', [])], 'groups': [{ 'id': x } for x in cpp.get('groups', [])] } for user in acList['users'][:]: userDoc = User().load(user['id'], force=True, fields=['firstName', 'login', 'email']) if userDoc is None: acList['users'].remove(user) else: user['login'] = userDoc['login'] user['name'] = userDoc['firstName'] user['email'] = userDoc['email'] for grp in acList['groups'][:]: grpDoc = Group().load(grp['id'], force=True, fields=['name', 'description']) if grpDoc is None: acList['groups'].remove(grp) else: grp['name'] = grpDoc['name'] grp['description'] = grpDoc['description'] return acList
def setUp(self): base.TestCase.setUp(self) self.siteAdminUser = User().createUser(email='*****@*****.**', login='******', firstName='Robert', lastName='Balboa', password='******') self.creatorUser = User().createUser(email='*****@*****.**', login='******', firstName='Apollo', lastName='Creed', password='******') creationSetting = Setting().getDefault( SettingKey.COLLECTION_CREATE_POLICY) creationSetting['open'] = True Setting().set(SettingKey.COLLECTION_CREATE_POLICY, creationSetting)
def setUp(self): base.TestCase.setUp(self) self.dataDir = os.path.join( os.environ['GIRDER_TEST_DATA_PREFIX'], 'plugins', 'dicom_viewer') self.users = [User().createUser( 'usr%s' % num, 'passwd', 'tst', 'usr', '*****@*****.**' % num) for num in [0, 1]]
def _canonicalUser(self, appletId, user): from girderformindlogger.models.user import User if isinstance(user, dict): userId = str(user['_id']) user = User().load(userId, force=True) profile = self.load(userId, force=True) return (user if user is not None else ( User().load(str(profile['userId']), force=True) if (isinstance(profile, dict) and 'userId' in profile) else {})) if isinstance(user, str): try: return (self._canonicalUser(appletId, User().load(user, force=True))) except: return (self._canonicalUser(appletId, self.load(user, force=True)))
def listMembers(self, group, offset=0, limit=0, sort=None): """ List members of the group. """ from girderformindlogger.models.user import User return User().find({'groups': group['_id']}, limit=limit, offset=offset, sort=sort)
def check_auth_password(self, username, password): if username.lower() == 'anonymous': return paramiko.AUTH_SUCCESSFUL try: self.girderUser = User().authenticate(username, password, otpToken=True) return paramiko.AUTH_SUCCESSFUL except AccessException: return paramiko.AUTH_FAILED
def setUp(self): # Since our plugin updates the model singleton, don't drop models base.TestCase.setUp(self, dropModels=False) self.admin = User().createUser(email='*****@*****.**', login='******', firstName='first', lastName='last', password='******', admin=True)
def getFullRequestList(self, group): """ Return the set of all outstanding requests, filled in with the login and full names of the corresponding users. :param group: The group to get requests for. :type group: dict """ from girderformindlogger.models.user import User userModel = User() for userId in group.get('requests', []): user = userModel.load(userId, force=True, fields=['firstName', 'login']) yield { 'id': userId, 'login': user['login'], 'name': user['firstName'] }
def _registerLdapUser(attrs, email, server): first, last = None, None if attrs.get('givenName'): first = attrs['givenName'][0].decode('utf8') elif attrs.get('cn'): first = attrs['cn'][0].decode('utf8').split()[0] if attrs.get('sn'): last = attrs['sn'][0].decode('utf8') elif attrs.get('cn'): last = attrs['cn'][0].decode('utf8').split()[-1] if not first or not last: raise Exception('No LDAP name entry found for %s.' % email) # Try using the search field value as the login. If it's an email address, # use the part before the @. try: login = attrs[server['searchField']][0].decode('utf8').split('@')[0] return User().createUser(login, password=None, firstName=first, lastName=last, email=email) except ValidationException as e: if e.field != 'login': raise # Fall back to deriving login from user's name for i in six.moves.range(_MAX_NAME_ATTEMPTS): login = ''.join((first, last, str(i) if i else '')) try: return User().createUser(login, password=None, firstName=first, lastName=last, email=email) except ValidationException as e: if e.field != 'login': raise raise Exception('Failed to generate login name for LDAP user %s.' % email)
def _recalculateSizes(self, progress): fixes = 0 models = [Collection(), User()] steps = sum(model.find().count() for model in models) progress.update(total=steps, current=0) for model in models: for doc in model.find(): progress.update(increment=1) _, f = model.updateSize(doc) fixes += f return fixes
def listKeys(self, userId, limit, offset, sort): user = self.getCurrentUser() if userId not in {None, str(user['_id'])}: self.requireAdmin(user) user = User().load(userId, force=True, exc=True) return list(ApiKeyModel().list(user, offset=offset, limit=limit, sort=sort))
def load(self, info): getPlugin('jobs').load(info) name = 'thumbnails' info['apiRoot'].thumbnail = rest.Thumbnail() for model in (Item(), Collection(), Folder(), User()): model.exposeFields(level=AccessType.READ, fields='_thumbnails') events.bind('model.%s.remove' % model.name, name, removeThumbnails) events.bind('model.file.remove', name, removeThumbnailLink) events.bind('data.process', name, _onUpload)
def _grantCreatorAccess(self, event): """ This callback makes the group creator an administrator member of the group. This generally should not be called or overridden directly, but it may be unregistered from the `model.group.save.created` event. """ from girderformindlogger.models.user import User group = event.info creator = User().load(group['creatorId'], force=True, exc=True) self.addUser(group, creator, level=AccessType.ADMIN)
def lookUpPath(path, user=None, filter=True, force=False): """ Look up a resource in the data hierarchy by path. :param path: path of the resource :param user: user with correct privileges to access path :param filter: Whether the returned model should be filtered. :type filter: bool :param force: if True, don't validate the access. :type force: bool """ path = path.lstrip('/') pathArray = split(path) model = pathArray[0] if model == 'user': username = pathArray[1] parent = User().findOne({'login': username}) if parent is None: raise ResourcePathNotFound('User not found: %s' % username) elif model == 'collection': collectionName = pathArray[1] parent = Collection().findOne({'name': collectionName}) if parent is None: raise ResourcePathNotFound('Collection not found: %s' % collectionName) else: raise ValidationException('Invalid path format') try: document = parent if not force: ModelImporter.model(model).requireAccess(document, user) for token in pathArray[2:]: document, model = lookUpToken(token, model, document) if not force: ModelImporter.model(model).requireAccess(document, user) except (ValidationException, AccessException): # We should not distinguish the response between access and validation errors so that # adversarial users cannot discover the existence of data they don't have access to by # looking up a path. raise ResourcePathNotFound('Path not found: %s' % path) if filter: document = ModelImporter.model(model).filter(document, user) return {'model': model, 'document': document}
def admin(db): """ Require an admin user. Provides a user with the admin flag set to True. """ from girderformindlogger.models.user import User u = User().createUser(email='*****@*****.**', login='******', firstName='Admin', password='******', admin=True) yield u
def listChildJobs(self, job): """ Lists the child jobs for a given job :param job: Job document :type job: Job """ query = {'parentId': job['_id']} cursor = self.find(query) user = User().load(job['userId'], force=True) for r in self.filterResultsByPermission(cursor=cursor, user=user, level=AccessType.READ): yield r