diff --git a/app/models.py b/app/models.py index 68eb8ab0..2eff4b21 100644 --- a/app/models.py +++ b/app/models.py @@ -1,12 +1,12 @@ -from app import db, login, mail, socketio +from app import db, hashids, login, mail, socketio from app.converters.vrt import normalize_vrt_file from app.email import create_message +from authlib.jose import jwt, JoseError from datetime import datetime, timedelta from enum import Enum, IntEnum from flask import current_app, url_for from flask_hashids import HashidMixin from flask_login import UserMixin -from itsdangerous import BadSignature, TimedJSONWebSignatureSerializer from time import sleep from tqdm import tqdm from werkzeug.security import generate_password_hash, check_password_hash @@ -15,6 +15,7 @@ import json import os import requests import shutil +import time import xml.etree.ElementTree as ET import yaml @@ -292,10 +293,14 @@ class User(HashidMixin, UserMixin, db.Model): return self.role.has_permission(permission) def confirm(self, token): - s = TimedJSONWebSignatureSerializer(current_app.config['SECRET_KEY']) + # s = TimedJSONWebSignatureSerializer(current_app.config['SECRET_KEY']) + # try: + # data = s.loads(token.encode('utf-8')) + # except BadSignature: + # return False try: - data = s.loads(token.encode('utf-8')) - except BadSignature: + data = jwt.decode(token, current_app.config['SECRET_KEY']) + except JoseError: return False if data.get('confirm') != self.hashid: return False @@ -308,14 +313,21 @@ class User(HashidMixin, UserMixin, db.Model): db.session.delete(self) def generate_confirmation_token(self, expiration=3600): - s = TimedJSONWebSignatureSerializer( - current_app.config['SECRET_KEY'], expiration) - return s.dumps({'confirm': self.hashid}).decode('utf-8') + # s = TimedJSONWebSignatureSerializer( + # current_app.config['SECRET_KEY'], expiration) + # return s.dumps({'confirm': self.hashid}).decode('utf-8') + header = {'alg': 'HS256', 'exp': int(time.time()) + expiration} + payload = {'confirm': self.hashid} + return jwt.encode(header, payload, current_app.config['SECRET_KEY']) + def generate_reset_token(self, expiration=3600): - s = TimedJSONWebSignatureSerializer( - current_app.config['SECRET_KEY'], expiration) - return s.dumps({'reset': self.hashid}).decode('utf-8') + # s = TimedJSONWebSignatureSerializer( + # current_app.config['SECRET_KEY'], expiration) + # return s.dumps({'reset': self.hashid}).decode('utf-8') + header = {'alg': 'HS256', 'exp': int(time.time()) + expiration} + payload = {'reset': self.hashid} + return jwt.encode(header, payload, current_app.config['SECRET_KEY']) def get_token(self, expires_in=3600): now = datetime.utcnow() @@ -398,12 +410,26 @@ class User(HashidMixin, UserMixin, db.Model): @staticmethod def reset_password(token, new_password): - s = TimedJSONWebSignatureSerializer(current_app.config['SECRET_KEY']) + # s = TimedJSONWebSignatureSerializer(current_app.config['SECRET_KEY']) + # try: + # data = s.loads(token.encode('utf-8')) + # except BadSignature: + # return False + # user = User.query.get(data.get('reset')) + # if user is None: + # return False + # user.password = new_password + # db.session.add(user) + # return True try: - data = s.loads(token.encode('utf-8')) - except BadSignature: + data = jwt.decode(token, current_app.config['SECRET_KEY']) + except JoseError: return False - user = User.query.get(data.get('reset')) + user_hashid = data.get('reset') + if user_hashid is None: + return False + user_id = hashids.decode(user_hashid) + user = User.query.get(user_id) if user is None: return False user.password = new_password diff --git a/requirements.txt b/requirements.txt index e9905fae..9a4bc2c2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,8 @@ +Authlib cqi docker eventlet -Flask==1.1.4 +Flask Flask-APScheduler Flask-Assets Flask-Hashids @@ -15,7 +16,6 @@ Flask-SocketIO Flask-SQLAlchemy Flask-WTF hiredis -jsonschema MarkupSafe==2.0.1 psycopg2 pyScss @@ -24,73 +24,3 @@ pyyaml redis tqdm wtforms[email] - - -# Safe to use from 05.05.2022 -# alembic==1.7.7 -# aniso8601==9.0.1 -# APScheduler==3.9.1 -# async-timeout==4.0.2 -# attrs==21.4.0 -# backports.zoneinfo==0.2.1 -# bidict==0.22.0 -# blinker==1.4 -# certifi==2021.10.8 -# charset-normalizer==2.0.12 -# click==7.1.2 -# cqi==0.1.0 -# Deprecated==1.2.13 -# dnspython==2.2.1 -# docker==5.0.3 -# email-validator==1.2.1 -# eventlet==0.33.0 -# Flask==1.1.4 -# Flask-APScheduler==1.12.3 -# Flask-Assets==2.0 -# Flask-Hashids==0.2.0 -# Flask-HTTPAuth==4.6.0 -# Flask-Login==0.6.1 -# Flask-Mail==0.9.1 -# Flask-Migrate==3.1.0 -# Flask-Paranoid==0.3.0 -# flask-restx==0.5.1 -# Flask-SocketIO==5.1.2 -# Flask-SQLAlchemy==2.5.1 -# Flask-WTF==1.0.1 -# greenlet==1.1.2 -# hashids==1.3.1 -# hiredis==2.0.0 -# idna==3.3 -# importlib-metadata==4.11.3 -# importlib-resources==5.7.1 -# itsdangerous==1.1.0 -# Jinja2==2.11.3 -# jsonschema==4.4.0 -# Mako==1.2.0 -# MarkupSafe==2.0.1 -# packaging==21.3 -# psycopg2==2.9.3 -# pyparsing==3.0.8 -# pyrsistent==0.18.1 -# pyScss==1.4.0 -# python-dateutil==2.8.2 -# python-dotenv==0.20.0 -# python-engineio==4.3.2 -# python-socketio==5.6.0 -# pytz==2022.1 -# pytz-deprecation-shim==0.1.0.post0 -# PyYAML==6.0 -# redis==4.2.2 -# requests==2.27.1 -# six==1.16.0 -# SQLAlchemy==1.4.36 -# tqdm==4.64.0 -# tzdata==2022.1 -# tzlocal==4.2 -# urllib3==1.26.9 -# webassets==2.0 -# websocket-client==1.3.2 -# Werkzeug==1.0.1 -# wrapt==1.14.1 -# WTForms==3.0.1 -# zipp==3.8.0