def extract_email(self, id=None, doc=None): doc = doc or self.collection.read(id) email = doc.data.get(self.email_field, 'null') if re.match(EMAIL_RE, email) is None: raise exceptions.BadRequest( detail='"{}" at "{}" is not a valid email'.format( email, self.email_field)) return email
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 post(self): try: data = self.json['data'] except (TypeError, ValueError, KeyError): raise exceptions.MalformedData() if data.get('type') != 'users': raise exceptions.IncorrectParameter('data.type', 'users', data.get('type', 'null')) if not isinstance(data.get('attributes'), dict): raise exceptions.InvalidType('data.attributes', 'dict', type(data.get('type'))) try: provider = driver.DriverManager( namespace='jam.auth.providers', name=data['attributes'].pop('provider'), invoke_on_load=True, ).driver except (KeyError, driver.NoMatches): raise exceptions.BadRequest(detail='Unknown provider') user = await provider.authenticate(self.current_user, data['attributes']) self.write({ 'data': { 'id': user.uid, 'type': 'users', 'attributes': { 'id': user.id, 'type': user.type, 'provider': user.provider, 'token': user.token.decode(), # 'refreshable': provider.refreshable, #TODO Implement refreshing } } })
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()
def post(self, handler): if not self.template: raise exceptions.BadRequest( detail= 'template must be provided via collection.plugins.template') if not self.from_email: raise exceptions.BadRequest( detail= 'fromEmail must be provided via collection.plugins.fromEmail') if not handler.payload: raise exceptions.BadRequest() if not handler.payload.attributes.get('id'): raise exceptions.BadRequest(detail='Id must be provided') try: doc = self.collection.read(handler.payload.attributes['id']) except exceptions.NotFound: return handler.write({ 'data': { 'id': handler.payload.attributes.get('id'), 'type': 'reset', 'attributes': { 'status': 'success' } } }) email = doc.data.get(self.email_field, 'null') if re.match(EMAIL_RE, email) is None: raise exceptions.BadRequest( detail='"{}" at "{}" is not a valid email'.format( email, self.email_field)) namespace = handler._view._namespace # A little hack never hurt anyone from jam.auth.providers.self import SelfAuthProvider user = User.create(SelfAuthProvider.type, '{}:{}'.format(namespace.ref, self.collection.ref), doc.ref, exp=8) try: sg = sendgrid.SendGridClient(self.sendgrid_key, raise_errors=True) mail = sendgrid.Mail(to=email) mail.set_from(self.from_email) mail.add_substitution(':token', user.token.decode()) mail.add_substitution(':user', user.id) mail.add_filter('templates', 'enable', 1) mail.add_filter('templates', 'template_id', self.template) # Sendgrid requires subject text and html to be set to a non falsey value # It is highly recommended that you overwrite these in your own templates mail.set_subject('JamDB password reset') mail.set_text('Your temporary token is :token') mail.set_html('Your temporary token is :token') logger.info(sg.send(mail)) except sendgrid.SendGridError: logger.exception('Sendgrid Error:') raise exceptions.ServiceUnavailable( detail='Unable to submit request to sendgrid') return handler.write({ 'data': { 'id': handler.payload.attributes.get('id'), 'type': 'reset', 'attributes': { 'status': 'success' } } })
def prerequisite_check(self): super().prerequisite_check() if not isinstance(self.collection._state._backend.raw_backend(), get_backend('elasticsearch')): raise exceptions.BadRequest( detail='This collection does not support searching')