async def _authenticate(self, data): namespace = manager.get_namespace(data['namespace']) collection = namespace.get_collection(data['collection']) if not GrantPlugin.is_enabled(collection): raise exceptions.PluginNotEnabled(GrantPlugin.NAME) if data.get('document'): if not collection.plugin('grant').document_enabled: raise exceptions.BadRequest( detail= 'document permissions must be provided via collection.plugins.grant.document' ) resource = data['document'] else: if not collection.plugin('grant').collection_enabled: raise exceptions.BadRequest( detail= 'collection permissions must be provided via collection.plugins.grant.collection' ) resource = data['collection'] async with aiohttp.request( 'GET', '{}/oauth2/profile'.format(settings.OSF['ACCOUNTS_URL']), headers={ 'Authorization': 'Bearer {}'.format(data.get('access_token')) }) as resp: if resp.status != 200: raise exceptions.Unauthorized() user_id = (await resp.json())['id'] async with aiohttp.request( 'GET', '{}/v2/nodes/{}/'.format(settings.OSF['API_URL'], resource), headers={ 'Content-Type': 'application/json', 'Authorization': 'Bearer {}'.format(data['access_token']), }) as resp: if resp.status != 200: raise exceptions.Unauthorized() ref = '{namespace}.{collection}'.format(**data) granted = Permissions.from_string( data['permissions']) & functools.reduce( lambda acc, x: acc | PERMISSION_MAP.get( x, Permissions.NONE), (await resp.json())['data']['attributes'] ['current_user_permissions'], Permissions.NONE) if data.get('document'): ref += '.' + data['document'] granted &= collection.plugin('grant').document_permissions else: granted &= collection.plugin('grant').collection_permissions return 'user', 'osf', user_id, .06, False, {ref: granted}
def list(self, filter, sort, page, page_size, user): if not user.permissions & Permissions.READ: if not user.uid: raise exceptions.Unauthorized() if filter: filter &= Q('created_by', 'eq', user.uid) else: filter = Q('created_by', 'eq', user.uid) return super().list(filter, sort, page, page_size, user)
async def _authenticate(self, data): async with aiohttp.request( 'GET', '{}/oauth2/profile'.format(settings.OSF['ACCOUNTS_URL']), headers={ 'Authorization': 'Bearer {}'.format(data.get('access_token')) }) as resp: if resp.status != 200: raise exceptions.Unauthorized() return 'user', 'osf', (await resp.json())['id']
def check_permissions(self): permissions = self._view.get_permissions(self.current_user, self._view.loaded) required_permissions = self._view.get_required_permissions( self.request) # For use later on self.current_user.permissions = permissions # Check permissions if (required_permissions & permissions) != required_permissions: if self.current_user.uid is None: raise exceptions.Unauthorized() raise exceptions.Forbidden(required_permissions)
def prepare(self): super().prepare() if self.request.method == 'OPTIONS': return # Dont do anything for OPTIONS requests loaded = [] try: for view in self._view_class.lineage(): key = view.name + '_id' if self.path_kwargs[key] is None: break loaded.append(view.load(self.path_kwargs[key], *loaded)) except exceptions.NotFound as e: err = e # Load as many resources as are available to do a permissions check # A 404 will be thrown if the user has the required permissions self._view = view(*loaded) else: err = None self._view = self._view_class(*loaded) # If this is a relationship swap out the current view with the relation if 'relationship' in self.path_kwargs: relationship = self._serializer.relations[self.path_kwargs['relationship']] self._view = relationship.view(*loaded) self._serializer = relationship.serializer() permissions = Permissions.get_permissions(self.current_user, *loaded) required_permissions = self._view.get_permissions(self.request) # For use later on self.current_user.permissions = permissions # Check permissions if (required_permissions & permissions) != required_permissions: if self.current_user.uid is None: raise exceptions.Unauthorized() raise exceptions.Forbidden(required_permissions) # Not found is always raised AFTER permissions checks if err: raise err if self.request.method in ('GET', 'DELETE'): return # GET and DELETE bodies are ignored self.payload # Force payload to load and validate
def list(self, filter, sort, page, page_size, user): if not user.permissions & Permissions.ADMIN: if not user.uid: raise exceptions.Unauthorized() query = functools.reduce(operator.or_, [ Q('data.permissions.*', 'and', Permissions.READ), Q('data.permissions.{0.type}-*'.format(user), 'and', Permissions.READ), Q('data.permissions.{0.type}-{0.provider}-*'.format(user), 'and', Permissions.READ), Q('data.permissions.{0.type}-{0.provider}-{0.id}'.format(user), 'and', Permissions.READ), ]) if filter: filter &= query else: filter = query return super().list(filter, sort, page, page_size, user)
async def _authenticate(self, data): namespace = manager.get_namespace(data['namespace']) collection = namespace.get_collection(data['collection']) # TODO handle exceptions if not (collection.schema and 'password' in collection.schema._schema['required'] and collection.schema._schema['properties']['password'] == self.PASSWORD_SCHEMA): raise exceptions.BadRequest() # TODO Better error message # TODO validate retrieved document doc = collection.read(data['username']) password = doc.data['password'].encode() hashed = await asyncio.get_event_loop().run_in_executor( None, lambda: bcrypt.hashpw(data['password'].encode(), password)) if hashed == password: return SelfAuthProvider.type, '{}:{}'.format( namespace.name, data['collection']), data['username'] raise exceptions.Unauthorized()
async def _authenticate(self, data): namespace = manager.get_namespace(data['namespace']) collection = namespace.get_collection(data['collection']) if not UserPlugin.is_enabled(collection): raise exceptions.PluginNotEnabled(UserPlugin.NAME) if not ( collection.schema and 'password' in collection.schema._schema.get('required', []) and collection.schema._schema['properties']['password'] == self.PASSWORD_SCHEMA ): raise exceptions.BadRequest(title='Bad password schema', detail='The schema for password must be {} and must be a required field'.format(self.PASSWORD_SCHEMA)) # TODO validate retrieved document doc = collection.read(data['username']) password = doc.data['password'].encode() hashed = await asyncio.get_event_loop().run_in_executor(None, lambda: bcrypt.hashpw(data['password'].encode(), password)) if hashed == password: return SelfAuthProvider.type, '{}:{}'.format(namespace.ref, collection.ref), data['username'], 8 raise exceptions.Unauthorized()