diff --git a/.gitignore b/.gitignore index 614107f..9219425 100644 --- a/.gitignore +++ b/.gitignore @@ -214,3 +214,5 @@ dmypy.json .pytype/ # End of https://www.toptal.com/developers/gitignore/api/python,intellij + +*.sqlite \ No newline at end of file diff --git a/auth/__init__.py b/auth/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/auth/auth.py b/auth/auth.py new file mode 100644 index 0000000..29d0f3a --- /dev/null +++ b/auth/auth.py @@ -0,0 +1,43 @@ +from flask import Blueprint, request +from flask_jwt_extended import create_access_token +from http import HTTPStatus +from werkzeug.security import check_password_hash, generate_password_hash + +from database import db +from database.user import User + +auth = Blueprint('auth', __name__) + + +@auth.route('/login', methods=['POST']) +def login(): + username = request.form.get('username') + password = request.form.get('password') + + user = User.query.filter_by(username=username).first() + if user and check_password_hash(user.password, password): + return {'id': user.id, + 'username': user.username, + 'email': user.email, + 'token': create_access_token(identity=user.username)} + return {'description': 'Username or password is invalid'}, HTTPStatus.UNAUTHORIZED + + +@auth.route('/signup', methods=['POST']) +def signup(): + username = request.form.get('username') + email = request.form.get('email') + password = request.form.get('password') + + user = User.query.filter_by(username=username).first() + if user: + return {'description': f'A user called {username} exists already.'}, HTTPStatus.CONFLICT + + # TODO sanity check for password length etc + user = User(username=username, + email=email, + password=generate_password_hash(password)) + db.session.add(user) + db.session.commit() + + return '', HTTPStatus.NO_CONTENT diff --git a/database/__init__.py b/database/__init__.py new file mode 100644 index 0000000..f0b13d6 --- /dev/null +++ b/database/__init__.py @@ -0,0 +1,3 @@ +from flask_sqlalchemy import SQLAlchemy + +db = SQLAlchemy() diff --git a/database/user.py b/database/user.py new file mode 100644 index 0000000..1e9ba4a --- /dev/null +++ b/database/user.py @@ -0,0 +1,8 @@ +from . import db + + +class User(db.Model): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String, unique=True) + email = db.Column(db.String, unique=True) + password = db.Column(db.String) diff --git a/main.py b/main.py index 564b91f..604cb05 100644 --- a/main.py +++ b/main.py @@ -1,18 +1,19 @@ import random -import time from flask import Flask, request from flask_cors import CORS -# from flask_restful import Api +from flask_jwt_extended import JWTManager, jwt_required from flask_socketio import SocketIO +from database import db + app = Flask(__name__) cors = CORS(app) -# api = Api(app) sio = SocketIO(app, cors_allowed_origins='*') @app.route('/') +@jwt_required def home(): return {'url': '/', 'body': 'test body'} @@ -39,5 +40,14 @@ def public_message(kwargs): print(kwargs) sio.emit('public message', kwargs) + if __name__ == '__main__': + from auth.auth import auth as auth_blueprint + app.config['JWT_SECRET_KEY'] = 'super-secret-key' # TODO FIX THIS + app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite' + db.init_app(app) + JWTManager(app) + app.register_blueprint(auth_blueprint) + with app.app_context(): + db.create_all() sio.run(app, port=5005) diff --git a/requirements.txt b/requirements.txt index 9cff871..8d68396 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,7 @@ eventlet==0.25.2 flask==1.1.2 flask-cors==3.0.8 -flask-restful==0.3.8 +flask-jwt-extended==3.24.1 flask-socketio==4.3.1 +flask-sqlalchemy==2.4.4 +Werkzeug~=1.0.1 \ No newline at end of file