class Pagination_handler(Handler): __arguments_schema__ = good.Schema({ 'per_page': good.Any( good.All( [good.All(good.Coerce(int), good.Range(min=1))], good.Length(max=1), ), good.Default([constants.PER_PAGE]) ), 'page': good.Any( good.All( [good.All(good.Coerce(int), good.Range(min=1))], good.Length(max=1), ), good.Default([1]) ), }, default_keys=good.Required, extra_keys=good.Allow,) def get(self, *args, **kwargs): args = self.validate_arguments(Pagination_handler.__arguments_schema__) self.per_page = args.pop('per_page', [0])[0] self.page = args.pop('page', [0])[0] self.request.arguments.pop('per_page', None) self.request.arguments.pop('page', None)
class Handler(base.Handler): __schema__ = good.Schema( { 'subtitle_lang': good.Maybe(good.All(good.Lower(), good.Length(min=1, max=20))), 'audio_lang': good.Maybe(good.All(good.Lower(), good.Length(min=1, max=20))) }, default_keys=good.Optional) @authenticated(constants.LEVEL_USER) def get(self, show_id): data = models.User_show_subtitle_lang.get( user_id=self.current_user.id, show_id=show_id, ) if data: self.write_object(data) else: self.set_status(204) @authenticated(constants.LEVEL_USER) async def put(self, show_id): await self._put(show_id) self.set_status(204) @run_on_executor def _put(self, show_id): data = self.validate() with new_session() as session: d = models.User_show_subtitle_lang( user_id=self.current_user.id, show_id=show_id, subtitle_lang=data.get('subtitle_lang', None), audio_lang=data.get('audio_lang', None), ) session.merge(d) session.commit() @authenticated(constants.LEVEL_USER) async def patch(self, show_id): await self._patch(show_id) self.set_status(204) @run_on_executor def _patch(self, show_id): data = self.validate() with new_session() as session: d = models.User_show_subtitle_lang( user_id=self.current_user.id, show_id=show_id, ) if 'subtitle_lang' in data: d.subtitle_lang = data['subtitle_lang'] if 'audio_lang' in data: d.audio_lang = data['audio_lang'] session.merge(d) session.commit()
class Collection_handler(base.Handler): __schema__ = good.Schema({ 'name': good.All( str, good.Length(min=1, max=45), good.Match(re.compile(r'^[a-z0-9-_]+$', re.I), message='must only contain a-z, 0-9, _ and -')), 'email': good.All(str, good.Length(min=1, max=100), schemas.validate_email), 'password': good.All(str, good.Length(min=6)), }) async def get(self): users = await self.get_users() self.write_object(users) async def post(self, user_id=None): if user_id: raise exceptions.Parameter_restricted('user_id must not be set.') user = await self.create() self.set_status(201) self.write_object(user) @run_on_executor def get_users(self): username = self.get_argument('username') with new_session() as session: user = session.query(models.User).filter( models.User.name == username, ).first() if user: return [self.user_wrapper(user.serialize())] return [] @run_on_executor def create(self): user = self.validate() with new_session() as session: u = session.query(models.User.id).filter( models.User.email == user['email']).first() if u: raise exceptions.User_email_duplicate() u = session.query(models.User.id).filter( models.User.name == user['name']).first() if u: raise exceptions.User_username_duplicate() user = models.User( name=user['name'], email=user['email'], password=pbkdf2_sha256.encrypt(user['password']), ) session.add(user) session.commit() return user.serialize()
class Handler(Api_handler): __schema__ = good.Schema({ 'message': good.All(str, good.Length(min=1, max=500)), 'webhook_url': good.Any(good.Url('https'), good.All(str, good.Length(max=0))), }) @Level(3) async def get(self, channel_id): r = await self.db.fetchone( 'SELECT webhook_url, message FROM twitch_discord_live_notification WHERE channel_id=%s', (channel_id, )) if not r: self.set_status(204) else: self.write_object({ 'webhook_url': r['webhook_url'], 'message': r['message'], }) @Level(3) async def put(self, channel_id): data = self.validate() r = await self.db.fetchone( 'SELECT webhook_url, message FROM twitch_discord_live_notification WHERE channel_id=%s', (channel_id, )) if not r: await self.db.execute( ''' INSERT INTO twitch_discord_live_notification (channel_id, webhook_url, message) VALUES (%s, %s, %s); ''', ( channel_id, data['webhook_url'], data['message'], )) else: await self.db.execute( ''' UPDATE twitch_discord_live_notification SET webhook_url=%s, message=%s WHERE channel_id=%s ''', ( data['webhook_url'], data['message'], channel_id, ))
class Handler(Api_handler): __schema__ = good.Schema({ str: [{ 'message': good.All(str, good.Length(min=0, max=200)), good.Optional('min_amount'): good.All(good.Coerce(int), good.Range(min=0, max=1000)), }], }, default_keys=good.Optional) @Level(1) async def get(self, channel_id): alerts = await self.db.fetchall( 'SELECT type, message, min_amount FROM twitch_chat_alerts WHERE channel_id=%s', (channel_id,) ) grouped_alerts = {} for a in alerts: l = grouped_alerts.setdefault(a['type'], []) l.append({ 'message': a['message'], 'min_amount': a['min_amount'] or 0, }) self.write_object(grouped_alerts) @Level(1) async def put(self, channel_id): data = self.validate() for key in data: ins = [] for d in data[key]: if d['message']: ins.append(( channel_id, key, d['message'], d.get('min_amount', 0), )) await self.db.execute( 'DELETE FROM twitch_chat_alerts WHERE channel_id=%s AND type=%s;', (channel_id, key,) ) if ins: await self.db.executemany(''' INSERT INTO twitch_chat_alerts (channel_id, type, message, min_amount) VALUES (%s, %s, %s, %s) ''', ins ) await self.get(channel_id)
class Slots_handler(Api_handler): __schema__ = good.Schema({ 'emote_pool_size': good.All(good.Coerce(int), good.Range(min=2)), 'payout_percent': good.All(good.Coerce(int), good.Range(min=1)), 'min_bet': good.All(good.Coerce(int), good.Range(min=1)), 'max_bet': good.All(good.Coerce(int), good.Range(min=0)), 'emotes': [str], 'win_message': good.All(good.Coerce(str), good.Length(min=1, max=250)), 'allin_win_message': good.All(good.Coerce(str), good.Length(min=1, max=250)), 'lose_message': good.All(good.Coerce(str), good.Length(min=1, max=250)), 'allin_lose_message': good.All(good.Coerce(str), good.Length(min=1, max=250)), }) async def get(self, channel_id): settings = await self.db.fetchone( 'select * from twitch_gambling_slots_settings where channel_id=%s', (channel_id), ) if not settings: self.set_status(204) else: settings.pop('channel_id') settings['emotes'] = json.loads(settings['emotes']) self.write_object(settings) @Level(3) async def put(self, channel_id): data = self.validate() if 'emotes' in data: data['emotes'] = json.dumps(data['emotes']) fields = ','.join([f for f in data]) values = ','.join(['%s' for f in data]) dup = ','.join([f'{f}=VALUES({f})' for f in data]) await self.db.execute( f''' INSERT INTO twitch_gambling_slots_settings (channel_id, {fields}) VALUES (%s, {values}) ON DUPLICATE KEY UPDATE {dup} ''', ( channel_id, *data.values(), )) self.set_status(204)
class Handler(base.Handler): __schema__ = good.Schema({ 'rating': good.All(int, good.Range(min=1, max=10)), }) @authenticated(0) async def put(self, show_id): await self.save(show_id) self.set_status(204) @authenticated(0) async def get(self, show_id): r = await self.get_rating(show_id) self.write_object(r) @authenticated(0) async def delete(self, show_id): await self.delete_rating(show_id) self.set_status(204) @run_on_executor def save(self, show_id): d = self.validate() with new_session() as session: r = models.User_show_rating( show_id=show_id, user_id=self.current_user.id, rating=d['rating'], updated_at=datetime.utcnow(), ) session.merge(r) session.commit() @run_on_executor def get_rating(self, show_id): with new_session() as session: r = session.query(models.User_show_rating.rating).filter( models.User_show_rating.user_id == self.current_user.id, models.User_show_rating.show_id == show_id, ).first() return { 'rating': r.rating if r else None, } @run_on_executor def delete_rating(self, show_id): with new_session() as session: session.query(models.User_show_rating).filter( models.User_show_rating.user_id == self.current_user.id, models.User_show_rating.show_id == show_id, ).delete() session.commit()
class Banned_words_handler(Api_handler): __schema__ = good.Schema({ 'banned_words': good.All(str, good.Length(min=1, max=1000)), }) @Level(1) async def post(self, channel_id, filter_id): d = self.validate() c = await self.db.execute(''' INSERT INTO twitch_filter_banned_words (channel_id, filter_id, banned_words) VALUES (%s, %s, %s) ''', (channel_id, filter_id, d['banned_words'])) r = await self.redis.publish_json( 'tbot:server:commands', ['reload_filter_banned_words', channel_id, filter_id] ) self.set_status(201) self.write_object({ 'id': c.lastrowid, 'banned_words': d['banned_words'], }) @Level(1) async def put(self, channel_id, filter_id, id_): d = self.validate() await self.db.execute(''' UPDATE twitch_filter_banned_words SET banned_words=%s WHERE id=%s and channel_id=%s and filter_id=%s ''', (d['banned_words'], id_, channel_id, filter_id,)) r = await self.redis.publish_json( 'tbot:server:commands', ['reload_filter_banned_words', channel_id, filter_id] ) self.set_status(204) @Level(1) async def delete(self, channel_id, filter_id, id_): await self.db.execute(''' DELETE FROM twitch_filter_banned_words WHERE id=%s and channel_id=%s and filter_id=%s ''', (id_, channel_id, filter_id,)) r = await self.redis.publish_json( 'tbot:server:commands', ['reload_filter_banned_words', channel_id, filter_id] ) self.set_status(204)
class Change_password_handler(base.Handler): __schema__ = good.Schema({ 'password': str, 'new_password': good.All(str, good.Length(min=6)), }) @authenticated(constants.LEVEL_USER) async def post(self, user_id=None): user_id = user_id if user_id else self.current_user.id self.check_user_edit(user_id) await self.change_password(user_id) self.set_status(204) @run_on_executor def change_password(self, user_id): data = self.validate() if not models.User.login(int(user_id), data['password']): raise exceptions.Wrong_email_or_password_exception() with new_session() as session: models.User.change_password( user_id=user_id, new_password=data['new_password'], session=session, ) tokens = session.query(models.Token).filter( models.Token.user_id == user_id, or_( models.Token.expires >= datetime.utcnow(), models.Token.expires == None, )).all() for token in tokens: if token.token == self.access_token: continue session.delete(token) session.commit()
import good import sqlalchemy as sa from seplis.api.handlers import base from seplis.api.decorators import authenticated, new_session, run_on_executor from seplis.api import exceptions, constants, models from seplis import schemas _schema = { 'name': good.All(str, good.Length(min=1, max=45)), 'url': good.All(str, good.Length(min=1, max=200)), 'secret': good.All(str, good.Length(min=1, max=200)), } class Handler(base.Handler): '''Edit a play server. The user must be the owner.''' __schema__ = good.Schema(_schema, default_keys=good.Optional) @authenticated(0) async def get(self, id_): server = await self._get(id_) self.write_object(server) @authenticated(0) async def put(self, id_): ps = await self._put(id_) self.write_object(ps) @authenticated(0) async def delete(self, id_):
import logging, good, asyncio from ..base import Api_handler, Level, Api_exception from tbot import config, utils from datetime import datetime, timedelta __schema__ = { 'name': good.All(str, good.Length(min=1, max=100)), 'messages': good.All([good.All(str, good.Length(min=1, max=500))], good.Length(min=1, max=100)), good.Optional('enabled'): good.All(good.Coerce(int), good.Range(min=0, max=1)), good.Optional('enabled_status'): good.All(good.Coerce(int), good.Range(min=0, max=2)), good.Optional('interval'): good.All(good.Coerce(int), good.Range(min=1, max=10080)), good.Optional('send_message_order'): good.All(good.Coerce(int), good.Range(min=1, max=2)), } class Handler(Api_handler): __schema__ = good.Schema(__schema__, default_keys=good.Optional) @Level(1) async def put(self, channel_id, id_): data = self.validate() data['updated_at'] = datetime.utcnow() if 'interval' in data: data['next_run'] = datetime.utcnow()+timedelta(minutes=data['interval']) if 'messages' in data: data['messages'] = utils.json_dumps(data['messages']) fields = ', '.join(['`{}`=%s'.format(k) for k in data]) values = list(data.values()) values.append(channel_id) values.append(id_) await self.db.execute(
class Handler(base.Handler): __schema__ = good.Schema( { 'times': good.All(int, good.Range(min=-20, max=20)), }, default_keys=good.Optional) @authenticated(constants.LEVEL_PROGRESS) async def get(self, show_id, episode_number): w = await self._get( show_id=show_id, episode_number=episode_number, ) if w: self.write_object(w) else: self.set_status(204) @authenticated(constants.LEVEL_PROGRESS) async def put(self, show_id, episode_number): w = await self._put(show_id, episode_number) if w: self.write_object(w) else: self.set_status(204) @authenticated(0) async def delete(self, show_id, episode_number): await self._delete(show_id, episode_number) self.set_status(204) @run_on_executor def _get(self, show_id, episode_number): with new_session() as session: ew = session.query(models.Episode_watched).filter( models.Episode_watched.show_id == show_id, models.Episode_watched.episode_number == episode_number, models.Episode_watched.user_id == self.current_user.id, ).first() if ew: return ew.serialize() @run_on_executor def _put(self, show_id, episode_number): data = self.validate() with new_session() as session: ew = set_watched( session=session, user_id=self.current_user.id, show_id=show_id, episode_number=episode_number, times=data.get('times', 1), ) session.commit() if ew: return ew.serialize() @run_on_executor def _delete(self, show_id, episode_number): with new_session() as session: ew = session.query(models.Episode_watched).filter( models.Episode_watched.show_id == show_id, models.Episode_watched.episode_number == episode_number, models.Episode_watched.user_id == self.current_user.id, ).first() if ew: ew.set_prev_as_watching() session.delete(ew) session.commit()
def SHOW_EPISODE_TYPE(msg=None): def f(v): if v not in constants.SHOW_EPISODE_TYPE: raise good.Invalid('invalid episodes type: {}'.format(v)) return v return f Description_schema = good.Schema({ 'text': good.Maybe(str), 'title': good.Maybe(str), 'url': good.Maybe(str), }, default_keys=good.Optional) _Episode_schema = { 'title': good.Maybe(str), good.Required('number'): good.All(good.Coerce(int), good.Range(min=1)), good.Optional('season'): good.Maybe(good.All(good.Coerce(int), good.Range(min=1))), good.Optional('episode'): good.Maybe(good.All(good.Coerce(int), good.Range(min=1))), 'air_date': good.Maybe(date_()), 'air_time': good.Maybe(time_()), 'air_datetime': good.Maybe(iso8601_to_utc()), 'description': good.Any(None, Description_schema), 'runtime': good.Maybe(good.Coerce(int)), } Episode_schema = good.Schema(_Episode_schema, default_keys=good.Optional) External_schema = good.Schema({ good.All(good.Length(min=1, max=45)):good.Any(None, good.All(good.Coerce(str), good.Length(min=1, max=45))) }, default_keys=good.Optional) Importer_schema = good.Schema( {key: good.Maybe(good.All(str, good.Length(min=1, max=45))) \ for key in constants.IMPORTER_TYPE_NAMES},
class Points_settings_handler(Api_handler): __schema__ = good.Schema({ 'enabled': good.Boolean(), 'points_name': good.All(str, good.Length(min=1, max=45)), 'points_per_min': good.All(good.Coerce(int), good.Range(min=0)), 'points_per_min_sub_multiplier': good.All(good.Coerce(int), good.Range(min=0)), 'points_per_sub': good.All(good.Coerce(int), good.Range(min=0)), 'points_per_cheer': good.All(good.Coerce(int), good.Range(min=0)), 'ignore_users': [str], }) async def get(self, channel_id): settings = await self.db.fetchone( 'select * from twitch_channel_point_settings where channel_id=%s', (channel_id), ) if not settings: self.set_status(204) else: self.write_object({ 'enabled': True if settings['enabled'] == 1 else False, 'points_name': settings['points_name'], 'points_per_min': settings['points_per_min'], 'points_per_min_sub_multiplier': settings['points_per_min_sub_multiplier'], 'points_per_sub': settings['points_per_sub'], 'points_per_cheer': settings['points_per_cheer'], 'ignore_users': json.loads(settings['ignore_users']), }) @Level(3) async def put(self, channel_id): data = self.validate() if 'ignore_users' in data: data['ignore_users'] = json.dumps(data['ignore_users']) fields = ','.join([f for f in data]) values = ','.join(['%s' for f in data]) dup = ','.join([f'{f}=VALUES({f})' for f in data]) await self.db.execute( f''' INSERT INTO twitch_channel_point_settings (channel_id, {fields}) VALUES (%s, {values}) ON DUPLICATE KEY UPDATE {dup} ''', ( channel_id, *data.values(), )) self.set_status(204)
def All(*validators, **kwargs): msg = kwargs.pop('msg', None) assert not kwargs, 'Sorry, All() does not support Schema keyword arguments anymore' return _wrapMsg(good.All(*validators), msg)
class Handler(base.Handler): __arguments_schema__ = good.Schema( { 'days_back': good.Any( good.All(good.Coerce(int), good.Range(min=0, max=7)), good.Default(2), ), 'days_ahead': good.Any(good.All(good.Coerce(int), good.Range(min=0, max=14)), good.Default(7)), }, default_keys=good.Required) async def get(self, user_id): user_id = self.user_id_or_current(user_id) shows_episodes = await self.get_shows_episodes(user_id) if not shows_episodes: self.write_object([]) return ids = [] shows = {se[0]['id']: se[0] for se in shows_episodes} airdates = OrderedDict() airdate_shows = OrderedDict() prev = None for se in shows_episodes: if prev == None: prev = se[1]['air_datetime'].date() if prev != se[1]['air_datetime'].date(): airdates[prev] = list(airdate_shows.values()) prev = se[1]['air_datetime'].date() airdate_shows = {} if se[1]['show_id'] not in airdate_shows: airdate_shows[se[1]['show_id']] = copy.copy( shows[se[1]['show_id']]) show = airdate_shows[se[1]['show_id']] show.setdefault('episodes', []) show['episodes'].append(self.episode_wrapper(se[1])) if shows_episodes: airdates[prev] = list(airdate_shows.values()) self.write_object([{'air_date': ad, 'shows': airdates[ad]}\ for ad in airdates]) @run_on_executor def get_shows_episodes(self, user_id): args = self.validate_arguments() now = datetime.utcnow() from_ = (now - timedelta(days=args['days_back'])).date() to_ = (now + timedelta(days=args['days_ahead'])).date() with new_session() as session: rows = session.query(models.Episode, models.Show).filter( models.Show_fan.user_id == user_id, models.Show_fan.show_id == models.Show.id, models.Episode.show_id == models.Show.id, sa.func.date(models.Episode.air_datetime) >= from_, sa.func.date(models.Episode.air_datetime) <= to_, ).order_by( models.Episode.air_datetime, models.Show.id, ).all() return [(r.Show.serialize(), r.Episode.serialize()) for r in rows]
def validate_response(): def f(v): try: utils.validate_cmd_response(v) return v except Exception as e: raise good.Invalid(str(e)) return f _schema = { 'cmd': good.All(str, validate_cmd()), 'response': good.All(str, validate_response()), good.Optional('user_level'): good.All(good.Coerce(int), good.Range(min=0, max=9)), good.Optional('enabled_status'): good.All(good.Coerce(int), good.Range(min=0, max=2)), good.Optional('global_cooldown'): good.All(good.Coerce(int), good.Range(min=0, max=86400)), good.Optional('user_cooldown'): good.All(good.Coerce(int), good.Range(min=0, max=86400)), good.Optional('mod_cooldown'): good.All(good.Coerce(int), good.Range(min=0, max=86400)), good.Optional('enabled'): good.All(good.Coerce(int), good.Range(min=0, max=1)), good.Optional('public'):
class Handler(base.Handler): __schema__ = good.Schema({ 'position': good.All(int, good.Range(min=0, max=86400)), }) @authenticated(constants.LEVEL_PROGRESS) async def get(self, show_id, episode_number): w = await self._get(show_id, episode_number) if not w: self.set_status(204) else: self.write_object(w) @run_on_executor def _get(self, show_id, episode_number): with new_session() as session: r = session.query(models.Episode_watched).filter( models.Episode_watched.show_id == show_id, models.Episode_watched.episode_number == episode_number, ).first() if r: return r.serialize() @authenticated(constants.LEVEL_PROGRESS) async def put(self, show_id, episode_number): await self._put(show_id, episode_number) self.set_status(204) @authenticated(constants.LEVEL_PROGRESS) async def delete(self, show_id, episode_number): self.request.body = {'position': 0} await self.reset_position(show_id, episode_number) self.set_status(204) @run_on_executor def _put(self, show_id, episode_number): data = self.validate(self.__schema__) with new_session() as session: episode = session.query(models.Episode).filter( models.Episode.show_id == show_id, models.Episode.number == episode_number, ).first() if not episode: raise exceptions.Episode_unknown() ew = session.query(models.Episode_watched).filter( models.Episode_watched.show_id == show_id, models.Episode_watched.episode_number == episode_number, models.Episode_watched.user_id == self.current_user.id, ).first() if not ew: ew = models.Episode_watched( show_id=show_id, episode_number=episode_number, user_id=self.current_user.id, ) session.add(ew) ew.position = data['position'] if ew.position > 0: ew.watched_at = datetime.utcnow() ew.set_as_watching() else: ew.set_prev_as_watching() if ew.times == 0 and ew.position == 0: session.delete(ew) session.commit() @run_on_executor def reset_position(self, show_id, episode_number): with new_session() as session: ew = session.query(models.Episode_watched).filter( models.Episode_watched.show_id == show_id, models.Episode_watched.episode_number == episode_number, models.Episode_watched.user_id == self.current_user.id, ).first() if ew: ew.position = 0 if ew.times == 0: ew.set_prev_as_watching() session.delete(ew) session.commit()
class Channel_admins(Api_handler): __schema__ = good.Schema({ 'user': good.All(str, good.Length(min=4, max=25)), 'level': good.All(good.Coerce(int), good.Range(min=1, max=3)), }) __update_schema__ = good.Schema({ 'level': good.All(good.Coerce(int), good.Range(min=1, max=3)), }) @Level(3) async def get(self, channel_id): admins = await self.db.fetchall( ''' SELECT user_id as id, user as name, level FROM twitch_channel_admins WHERE channel_id=%s ORDER BY level DESC ''', (channel_id, )) self.write_object(admins) @Level(3) async def post(self, channel_id): data = self.validate() url = 'https://api.twitch.tv/helix/users' users = await twitch_request(self.ahttp, url, { 'login': data['user'], }) if not users['data']: raise Api_exception(400, 'User does not exist on Twitch') user = users['data'][0] await self.db.execute( ''' INSERT INTO twitch_channel_admins (channel_id, user_id, user, level, created_at, updated_at) VALUES (%s, %s, %s, %s, now(), now()) ON DUPLICATE KEY UPDATE user=VALUES(user), level=VALUES(level), updated_at=VALUES(updated_at) ''', (channel_id, user['id'], user['display_name'], data['level'])) self.set_status(204) @Level(3) async def put(self, channel_id, user_id): data = self.validate(self.__update_schema__) await self.db.execute( 'UPDATE twitch_channel_admins SET level=%s WHERE channel_id=%s AND user_id=%s', (data['level'], channel_id, user_id)) @Level(3) async def delete(self, channel_id, user_id): await self.db.execute( 'DELETE FROM twitch_channel_admins WHERE channel_id=%s AND user_id=%s', (channel_id, user_id)) self.set_status(204)
class Handler(base.Handler): __schema__ = good.Schema({ 'key': str, 'new_password': good.All(str, good.Length(min=6)), }) __arguments_schema__ = good.Schema({ 'email': [str], }) async def get(self): args = self.validate_arguments() user_id = await self.get_user_id(args['email'][0]) if not user_id: self.set_status(204) return smtp = aiosmtplib.SMTP( hostname=config['smtp']['server'], port=int(config['smtp']['port']), use_tls=config['smtp']['use_tls'], loop=self.application.ioloop, ) await smtp.connect() if config['smtp']['user']: await smtp.login(config['smtp']['user'], config['smtp']['password']) url = await self.create_reset_url(user_id) message = MIMEText(''' <html> <body> Reset your SEPLIS password here: <a href="{0}">{0}</a> </body> </html> '''.format(url), 'html') message["From"] = config['smtp']['from'] message["To"] = args['email'][0] message["Subject"] = "Reset password" await smtp.send_message(message) self.set_status(204) async def post(self): await self.reset() self.set_status(204) @run_on_executor def get_user_id(self, email): with new_session() as session: u = session.query(models.User.id).filter( models.User.email == email, ).first() if u: return u.id @run_on_executor def create_reset_url(self, user_id): with new_session() as session: r = models.Reset_password( user_id=user_id, ) session.add(r) session.commit() return config['web']['url'] + '/reset-password/{}'.format(r.key) @run_on_executor def reset(self): data = self.validate() with new_session() as session: r = session.query(models.Reset_password.user_id).filter( models.Reset_password.key == data['key'], models.Reset_password.expires >= datetime.utcnow(), ).first() if not r: raise exceptions.Forbidden('Invalid reset key') session.query(models.Reset_password).filter( models.Reset_password.user_id == r.user_id, ).delete() user_id = r.user_id models.User.change_password( user_id=user_id, new_password=data['new_password'], session=session, ) tokens = session.query(models.Token).filter( models.Token.user_id == user_id, sa.or_( models.Token.expires >= datetime.utcnow(), models.Token.expires == None, ) ).all() for token in tokens: if token.token == self.access_token: continue session.delete(token) session.commit()