diff --git a/db.py b/db.py index 5b34a15c..f16d5964 100644 --- a/db.py +++ b/db.py @@ -1,7 +1,7 @@ import datetime from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker, relationship -from sqlalchemy import Column, BigInteger, Integer, String, DateTime, ForeignKey, Float, Enum, create_engine, UniqueConstraint, PrimaryKeyConstraint, Boolean, or_ +from sqlalchemy import Column, BigInteger, Integer, String, DateTime, ForeignKey, Float, Enum, create_engine, UniqueConstraint, PrimaryKeyConstraint, Boolean, or_, LargeBinary import requests from errors import RequestError, NotFoundError, AlreadyExistingError import re @@ -25,6 +25,8 @@ class Royal(Base): id = Column(Integer, primary_key=True) username = Column(String, unique=True, nullable=False) + password = Column(LargeBinary) + fiorygi = Column(Integer, default=0) @staticmethod def create(session: Session, username: str): diff --git a/requirements.txt b/requirements.txt index 4643bba1..637c8e29 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,5 @@ requests psycopg2 PyNaCl async_timeout -raven \ No newline at end of file +raven +bcrypt \ No newline at end of file diff --git a/static/nryg.css b/static/nryg.css new file mode 100644 index 00000000..d367808b --- /dev/null +++ b/static/nryg.css @@ -0,0 +1,9 @@ +body { + font-family: sans-serif; + color: #a0ccff; + background-color: #0d193b; +} + +h1, h2, h3, h4, h5, h6 { + color: #fff; +} diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 00000000..35d2dbe7 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,13 @@ + + + + + {% block pagetitle %}{% endblock %} - Royal Games + {% block prehead %}{% endblock %} + + {% block posthead %}{% endblock %} + + + {% block body %}{% endblock %} + + \ No newline at end of file diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 00000000..125e3a50 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,22 @@ +{% extends 'base.html' %} + +{% block pagetitle %} + Royal Games +{% endblock %} + +{% block body %} +

+ Login +

+
+ + + +
+{% endblock %} \ No newline at end of file diff --git a/templates/password.html b/templates/password.html new file mode 100644 index 00000000..1bcbc806 --- /dev/null +++ b/templates/password.html @@ -0,0 +1,20 @@ + + + + + Login + + +
+ + + +
+ + \ No newline at end of file diff --git a/webserver.py b/webserver.py index a4923569..a72c6c67 100644 --- a/webserver.py +++ b/webserver.py @@ -1,12 +1,20 @@ -from flask import Flask, render_template -from db import Session, Royal, Steam, RocketLeague, Dota, Osu, Overwatch, LeagueOfLegends, Diario, Telegram, PlayedMusic, Discord -from sqlalchemy import func +from flask import Flask, render_template, request, abort, redirect, url_for +from flask import session as fl_session +import db +from sqlalchemy import func, alias +import bcrypt +import configparser app = Flask(__name__) app.jinja_env.trim_blocks = True app.jinja_env.lstrip_blocks = True +config = configparser.ConfigParser() +config.read("config.ini") + +app.secret_key = config["Flask"]["secret_key"] + @app.route("/") def page_index(): @@ -15,33 +23,82 @@ def page_index(): @app.route("/diario") def page_diario(): - session = Session() - diario_data = session.query(Diario).outerjoin((Telegram, Diario.author), aliased=True).outerjoin(Royal, aliased=True).outerjoin((Telegram, Diario.saver), aliased=True).outerjoin(Royal, aliased=True).all() - session.close() + db_session = db.Session() + diario_data = db_session.query(db.Diario).outerjoin((db.Telegram, db.Diario.author), aliased=True).outerjoin(db.Royal, aliased=True).outerjoin((db.Telegram, db.Diario.saver), aliased=True).outerjoin(db.Royal, aliased=True).all() + db_session.close() return render_template("diario.html", diario_data=diario_data) @app.route("/leaderboards") def page_leaderboards(): - session = Session() - dota_data = session.query(Dota).join(Steam).join(Royal).order_by(Dota.rank_tier).all() - rl_data = session.query(RocketLeague).join(Steam).join(Royal).order_by(RocketLeague.doubles_mmr).all() - ow_data = session.query(Overwatch).join(Royal).order_by(Overwatch.rank).all() - osu_data = session.query(Osu).join(Royal).order_by(Osu.std_pp).all() - lol_data = session.query(LeagueOfLegends).join(Royal).order_by(LeagueOfLegends.summoner_name).all() - session.close() + db_session = db.Session() + dota_data = db_session.query(db.Dota).join(db.Steam).join(db.Royal).order_by(db.Dota.rank_tier).all() + rl_data = db_session.query(db.RocketLeague).join(db.Steam).join(db.Royal).order_by(db.RocketLeague.doubles_mmr).all() + ow_data = db_session.query(db.Overwatch).join(db.Royal).order_by(db.Overwatch.rank).all() + osu_data = db_session.query(db.Osu).join(db.Royal).order_by(db.Osu.std_pp).all() + lol_data = db_session.query(db.LeagueOfLegends).join(db.Royal).order_by(db.LeagueOfLegends.summoner_name).all() + db_session.close() return render_template("leaderboards.html", dota_data=dota_data, rl_data=rl_data, ow_data=ow_data, osu_data=osu_data, lol_data=lol_data) @app.route("/music") def page_music(): - session = Session() - music_counts = session.query(PlayedMusic.filename, func.count(PlayedMusic.filename)).group_by(PlayedMusic.filename).all() - music_last = session.query(PlayedMusic).join(Discord).join(Royal).order_by(PlayedMusic.id.desc()).limit(50).all() - session.close() + db_session = db.Session() + music_counts = db_session.query(db.PlayedMusic.filename, alias(func.count(db.PlayedMusic.filename), "count")).order_by("count").group_by(db.PlayedMusic.filename).all() + music_last = db_session.query(db.PlayedMusic).join(db.Discord).join(db.Royal).order_by(db.PlayedMusic.id.desc()).limit(50).all() + db_session.close() return render_template("music.html", music_counts=music_counts, music_last=music_last) +@app.route("/login") +def page_login(): + return render_template("login.html") + + +@app.route("/loggedin", methods=["GET", "POST"]) +def page_loggedin(): + if request.method == "GET": + username = fl_session.get("username") + if username is None: + return "Not logged in" + else: + return username + elif request.method == "POST": + username = request.form["username"] + password = request.form["password"] + db_session = db.Session() + user = db_session.query(db.Royal).filter_by(username=username).one_or_none() + db_session.close() + if bcrypt.checkpw(bytes(password, encoding="utf8"), user.password): + fl_session["username"] = username + return username + else: + abort(403) + return + + +@app.route("/password", methods=["GET", "POST"]) +def page_password(): + username = fl_session.get("username") + if request.method == "GET": + if username is None: + abort(403) + return + return render_template("password.html") + elif request.method == "POST": + old_password = request.form["old"] + new_password = request.form["new"] + db_session = db.Session() + user = db_session.query(db.Royal).filter_by(username=username).one_or_none() + if bcrypt.checkpw(bytes(old_password, encoding="utf8"), user.password): + user.password = bcrypt.hashpw(bytes(new_password, encoding="utf8"), bcrypt.gensalt()) + db_session.commit() + db_session.close() + return "Password changed" + else: + db_session.close() + abort(403) + if __name__ == "__main__": try: app.run(host="0.0.0.0", port=1234)