async def search(self, permission, permissions=None, users=None, fields=None, sort=None, page=None, limit=None): query = {} self._filter_re(query, 'id', permission) self._filter_re(query, 'permissions', permissions) self._filter_re(query, 'users', users) self._filter_boolean(query, 'deleting', False) try: cursor = self._coll.find(filter=query, projection=self._projection(fields)) cursor.sort(self._sort(sort)) cursor.skip(self._pagination_skip(page, limit)) cursor.limit(self._pagination_limit(limit)) result = list() for item in await cursor.to_list(self._pagination_limit(limit)): result.append(self._format(item)) return self._format(result, multi=True) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err)
async def search(self, instances=None, dns_indicator=None, fqdn=None, ip_address=None, fields=None, sort=None, page=None, limit=None): query = {} self._filter_re(query, 'id', instances) self._filter_re(query, 'dns_indicator', dns_indicator) self._filter_re(query, 'fqdn', fqdn) self._filter_re(query, 'ip_address', ip_address) try: cursor = self._coll.find(filter=query, projection=self._projection(fields)) cursor.sort(self._sort(sort)) cursor.skip(self._pagination_skip(page, limit)) cursor.limit(self._pagination_limit(limit)) result = list() for item in await cursor.to_list(self._pagination_limit(limit)): result.append(self._format(item)) return self._format(result, multi=True) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err)
async def delete_user_from_all(self, user): try: await self._coll.update_many(filter={"users": user}, update={"$pull": { "users": user }}) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err)
async def delete(self, _id): try: result = await self._coll.delete_one(filter={'id': _id}) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err) if result.deleted_count is 0: raise ResourceNotFound(_id) return
async def delete_mark(self, _id): update = {'$set': {'deleting': True}} try: await self._coll.update_one( filter={'id': _id}, update=update, ) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err)
async def create(self, _id, payload): payload['id'] = _id payload['deleting'] = False try: await self._coll.insert_one(payload) except pymongo.errors.DuplicateKeyError: raise DuplicateResource(_id) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err) return await self.get(_id)
async def get(self, _id, fields=None): try: result = await self._coll.find_one( filter={ 'id': _id, }, projection=self._projection(fields)) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err) if result is None: raise ResourceNotFound(_id) return self._format(result)
async def check_credential(self, credentials): try: result = await self._coll.find_one( filter={'id': self._str_uuid_2_bin(credentials['id'])}, ) if not result: raise CredentialError if not pbkdf2_sha512.verify(credentials['secret'], result['secret']): raise CredentialError return self._format({'user': result['owner']}) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err)
async def check(self, user, fields, permission): query = {'deleting': False, 'users': user} self._filter_list(query, 'permissions', permission) try: result = await self._coll.find_one( filter=query, projection=self._projection(fields)) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err) if result is None: raise PermError( msg="Required Permissions {0} not found for user {1}".format( permission, user)) return result
async def get_all(self, owner): try: cursor = self._coll.find(filter={'owner': owner}, projection=self._projection()) result = list() for item in await cursor.to_list(1000): if 'created' in item: item['created'] = str(item['created']) if 'id' in item: item['id'] = str(item['id']) result.append(self._format(item)) return self._format(result, multi=True) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err)
async def create(self, _id, payload): payload['id'] = _id fqdn = "{0}{1}".format(payload['dns_indicator'], self.domain_suffix) if 'NUM' in payload['dns_indicator']: number = await self._next_num(payload['dns_indicator']) fqdn = fqdn.replace('NUM', number) payload['fqdn'] = fqdn try: await self._coll.insert_one(payload) except pymongo.errors.DuplicateKeyError: raise DuplicateResource(_id) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err) return await self.get(_id)
async def check_credentials(self, credentials): try: password = await self._coll.find_one(filter={ 'id': credentials['user'], 'deleting': False }, projection={'password': 1}) if not password: raise AuthenticationError if not pbkdf2_sha512.verify(credentials['password'], password['password']): raise AuthenticationError return credentials['user'] except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err)
async def update(self, _id, payload): update = {'$set': {}} for k, v in payload.items(): update['$set'][k] = v try: result = await self._coll.find_one_and_update( filter={'id': _id}, update=update, projection=self._projection(), return_document=pymongo.ReturnDocument.AFTER) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err) if result is None: raise ResourceNotFound(_id) return self._format(result)
async def get(self, _id, owner): try: result = await self._coll.find_one(filter={ 'id': self._str_uuid_2_bin(_id), 'owner': owner }, projection=self._projection()) if result is None: raise ResourceNotFound(_id) if 'created' in result: result['created'] = str(result['created']) if 'id' in result: result['id'] = str(result['id']) return self._format(result) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err)
async def error_catcher(request, handler): _request_id = request['X-Request-ID'] try: try: return await handler(request) except (jsonschema.exceptions.ValidationError, json.decoder.JSONDecodeError) as err: log.error('{0} received invalid JSON body {1}'.format(_request_id, err)) raise InvalidBody(err) except pymongo.errors.ConnectionFailure as err: log.error('{0} error communicating with MongoDB: {1}'.format(_request_id, err)) raise MongoConnError(err) except BaseError as err: return json_response( data=err.err_rsp, status=err.status )
async def set_ipa_otp(self, _id, ipa_otp): if not ipa_otp: ipa_otp = "" update = {'$set': {}} update['$set']['ipa_otp'] = ipa_otp try: result = await self._coll.find_one_and_update( filter={'id': _id}, update=update, projection=self._projection(), return_document=pymongo.ReturnDocument.AFTER) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err) if result is None: raise ResourceNotFound(_id) return self._format(result)
async def create(self, owner, payload): _id = uuid.uuid4() secret = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits + '_-.') for _ in range(128)) created = datetime.datetime.utcnow() payload['id'] = Binary(_id.bytes, STANDARD) payload['secret'] = self._create_secret(str(secret)) payload['created'] = created payload['owner'] = owner try: await self._coll.insert_one(payload) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err) result = { 'id': str(_id), 'created': str(created), 'description': payload['description'], 'secret': str(secret) } return self._format(result)
async def delete_all_from_owner(self, owner): try: await self._coll.delete_many(filter={"owner": owner}) except pymongo.errors.ConnectionFailure as err: raise MongoConnError(err)