Compare commits

2 Commits

Author SHA1 Message Date
55a60dbb1d Merge branch 'auth' into 'main'
Auth

added login and signup + json web token authorization

See merge request daniel/rona-backend!1
2020-07-30 17:23:01 +02:00
7d6f98ffda added authorization, signup, login with jwt 2020-07-30 17:23:01 +02:00
9 changed files with 74 additions and 125 deletions

2
.gitignore vendored
View File

@@ -214,3 +214,5 @@ dmypy.json
.pytype/
# End of https://www.toptal.com/developers/gitignore/api/python,intellij
*.sqlite

43
auth/auth.py Normal file
View File

@@ -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

View File

@@ -1,35 +0,0 @@
from typing import Dict
import re
import numpy as np
from dice.dice import Dice
commands: Dict = {}
def command(*commandlist):
def add_command(function):
for command in commandlist:
commands[command] = function
return function
return add_command
def handle_command(kwargs):
c = kwargs['message'].split()[0]
params = kwargs['message'].replace(c, '')
if c in commands:
commands[c](kwargs, params)
else:
error_response(kwargs, params)
@command('/roll')
def custom_roll(kwargs, params):
print(f'Kwargs: {kwargs}. Params: {params}')
dice = Dice()
print(dice.roll(params))
def error_response(kwargs, params):
print(f'Error, received unknown command: {kwargs}')

3
database/__init__.py Normal file
View File

@@ -0,0 +1,3 @@
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()

8
database/user.py Normal file
View File

@@ -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)

View File

@@ -1,75 +0,0 @@
import pyparsing
import math
import operator
import numpy as np
from pyparsing import (
Literal,
CaselessLiteral,
Word,
Optional,
Group,
Forward,
nums,
ParseException,
)
class Dice:
exprStack = []
def __init__(self):
pass
def roll(self, roll_params):
self.exprStack[:] = [] # Reset the stack
try:
results = self.BNF().parseString(roll_params, parseAll=True)
except ParseException as pe:
print("Parse exception ", str(pe))
return
except Exception as e:
print("Exception ", str(e), self.exprStack)
return results
def push_first(self, tokens):
self.exprStack.append(tokens[0])
def BNF(self):
integer = Word(nums)
plus, minus = map(Literal, "+-")
addop = plus | minus
rollop = CaselessLiteral('d')
# lowop = CaselessLiteral('l')
# highop = CaselessLiteral('h')
# Define roll as a group
roll = Group(Optional(integer, default=1) + rollop + integer)
expression = Forward()
operand = (
addop[...]
+ (
# Numbers as a fallback, add everything else as (roll | exception | ...)
(roll).setParseAction(self.push_first)
| integer
)
)
term = operand + (rollop + operand).setParseAction(self.push_first)[...]
expression <<= term + (addop + term).setParseAction(self.push_first)[...]
bnf = expression
return bnf

23
main.py
View File

@@ -1,20 +1,19 @@
import random
import time
import chatCommands
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'}
@@ -38,13 +37,17 @@ def test(user):
@sio.on('public message')
def public_message(kwargs):
kwargs['message'].strip()
if 'message' in kwargs:
if kwargs['message'][0] == '/':
chatCommands.handle_command(kwargs)
else:
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)

View File

@@ -1,7 +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
numpy==1.19.1
pyparsing==2.4.7
flask-sqlalchemy==2.4.4
Werkzeug~=1.0.1