from flask import Flask, redirect, flash, render_template, session, g, request, get_flashed_messages from wtforms import Form, BooleanField, StringField, PasswordField, validators, SubmitField, IntegerField, DateTimeField from wtforms.validators import ValidationError from flask_wtf import FlaskForm from flask_bootstrap import Bootstrap import time from datetime import datetime from flask_sqlalchemy import SQLAlchemy from sqlalchemy import exc, update import hashlib import bcrypt import os import werkzeug.exceptions import wtforms from wtforms.fields import EmailField from wtforms.widgets import NumberInput import hra.config as config import hra.web.html as html import hra.db as db import json import logging logging.basicConfig() logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO) static_dir = os.path.abspath('static') app = Flask(__name__, static_folder=static_dir) app.config.from_object(config) Bootstrap(app) db.flask_db = SQLAlchemy(app, metadata=db.metadata) class NeedLoginError(werkzeug.exceptions.Forbidden): description = 'Need to log in' class MenuItem: url: str name: str def __init__(self, url: str, name: str): self.url = url self.name = name def init_request(): path = request.path # XXX: Když celá aplikace běží v adresáři, request.path je relativní ke kořeni aplikace, ne celého webu if path.startswith('/static/') or path.startswith('/assets/'): # Pro statické soubory v development nasazení nepotřebujeme nastavovat # nic dalšího (v ostrém nasazení je servíruje uwsgi) return user = None g.user = None g.org = False if path.startswith('/api/'): token = request.args.get('token') if token is not None: user = db.get_session().query(db.User).filter_by(token=token).first() if user is None: raise werkzeug.exceptions.Forbidden("Wrong token.") else: if 'uid' in session: user = db.get_session().query(db.User).filter_by(id=session['uid']).first() path = request.path if path.startswith('/org/'): if not user or not user.org: raise werkzeug.exceptions.Forbidden() g.user = user g.org = g.user and g.user.org g.menu = [ MenuItem('/', "Domů"), ] if g.org: g.menu += [ MenuItem(app.url_for(pages.web_org_games.__name__), "Hry"), MenuItem(app.url_for(pages.web_org_users.__name__), "Uživatelé"), MenuItem(app.url_for(pages.web_org_logs.__name__), "Logy"), ] else: g.menu += [ ] app.before_request(init_request) @app.errorhandler(werkzeug.exceptions.HTTPException) def handle_exception(e): path = request.path if path.startswith('/api/'): ses = db.get_session() ses.rollback() response = e.get_response() response.data = json.dumps({ "status": "error", "description": e.description, "http-code": e.code, "http-name": e.name, }) response.content_type = "application/json" x = db.Log( source_ip=request.remote_addr, user_id=g.user.id if g.user is not None else None, endpoint=db.Endpoint.error, status="http-error", text=f"{e.code} ({e.name}): {e.description}", url=request.path, get=request.args, time=datetime.now(), ) ses.add(x) ses.commit() return response else: return e import hra.web.pages as pages import hra.web.api