diff --git a/bemani/api/app.py b/bemani/api/app.py index fd073bd..4d48d75 100644 --- a/bemani/api/app.py +++ b/bemani/api/app.py @@ -2,11 +2,12 @@ import copy import json import traceback from typing import Any, Callable, Dict -from flask import Flask, abort, request, Response, g # type: ignore +from flask import Flask, abort, request, Response # type: ignore from functools import wraps from bemani.api.exceptions import APIException from bemani.api.objects import RecordsObject, ProfileObject, StatisticsObject, CatalogObject +from bemani.api.types import g from bemani.common import GameConstants, APIConstants, VersionConstants from bemani.data import Data diff --git a/bemani/api/types.py b/bemani/api/types.py new file mode 100644 index 0000000..93ff281 --- /dev/null +++ b/bemani/api/types.py @@ -0,0 +1,19 @@ +from typing import Any, Dict, TYPE_CHECKING + + +if TYPE_CHECKING: + from flask.ctx import _AppCtxGlobals + + from bemani.data import Data + + class RequestGlobals(_AppCtxGlobals): + config: Dict[str, Any] + data: Data + authorized: bool + + g = RequestGlobals() +else: + from flask import g + + +__all__ = ["g"] diff --git a/bemani/data/mysql/machine.py b/bemani/data/mysql/machine.py index 85803de..d9e6fef 100644 --- a/bemani/data/mysql/machine.py +++ b/bemani/data/mysql/machine.py @@ -288,7 +288,7 @@ class MachineData(BaseData): sql = "DELETE FROM `machine` WHERE pcbid = :pcbid LIMIT 1" self.execute(sql, {'pcbid': pcbid}) - def create_arcade(self, name: str, description: str, data: Dict[str, Any], owners: List[int]) -> Arcade: + def create_arcade(self, name: str, description: str, data: Dict[str, Any], owners: List[UserID]) -> Arcade: """ Given a set of values, create a new arcade and return the ID of that arcade. diff --git a/bemani/frontend/account/account.py b/bemani/frontend/account/account.py index 9ecea40..a4d1b48 100644 --- a/bemani/frontend/account/account.py +++ b/bemani/frontend/account/account.py @@ -1,10 +1,12 @@ from typing import Dict, Any -from flask import Blueprint, request, redirect, Response, url_for, make_response, render_template, g # type: ignore +from flask import Blueprint, request, redirect, Response, url_for, make_response, render_template from bemani.common import CardCipher, CardCipherException, AESCipher, Time from bemani.frontend.app import loginrequired, loginprohibited, success, error, jsonify, valid_email, valid_username, valid_pin, render_react from bemani.frontend.templates import templates_location from bemani.frontend.static import static_location +from bemani.frontend.types import g + account_pages = Blueprint( 'account_pages', diff --git a/bemani/frontend/admin/admin.py b/bemani/frontend/admin/admin.py index c4af266..ef5b208 100644 --- a/bemani/frontend/admin/admin.py +++ b/bemani/frontend/admin/admin.py @@ -1,10 +1,10 @@ import random from typing import Dict, Tuple, Any, Optional -from flask import Blueprint, request, Response, render_template, url_for, g # type: ignore +from flask import Blueprint, request, Response, render_template, url_for from bemani.backend.base import Base from bemani.common import CardCipher, CardCipherException, GameConstants -from bemani.data import Arcade, Machine, User, News, Event, Server, Client +from bemani.data import Arcade, Machine, User, UserID, News, Event, Server, Client from bemani.data.api.client import APIClient, NotAuthorizedAPIException, APIException from bemani.frontend.app import adminrequired, jsonify, valid_email, valid_username, valid_pin, render_react from bemani.frontend.iidx.iidx import IIDXFrontend @@ -12,6 +12,7 @@ from bemani.frontend.jubeat.jubeat import JubeatFrontend from bemani.frontend.popn.popn import PopnMusicFrontend from bemani.frontend.templates import templates_location from bemani.frontend.static import static_location +from bemani.frontend.types import g admin_pages = Blueprint( 'admin_pages', @@ -52,7 +53,7 @@ def format_machine(machine: Machine) -> Dict[str, Any]: } -def format_card(card: Tuple[str, Optional[int]]) -> Dict[str, Any]: +def format_card(card: Tuple[str, Optional[UserID]]) -> Dict[str, Any]: owner = None if card[1] is not None: user = g.data.local.user.get_user(card[1]) @@ -316,6 +317,8 @@ def viewnews() -> Response: @admin_pages.route('/users/') @adminrequired def viewuser(userid: int) -> Response: + # Cast the userID. + userid = UserID(userid) user = g.data.local.user.get_user(userid) def __format_card(card: str) -> str: @@ -356,6 +359,8 @@ def viewuser(userid: int) -> Response: @jsonify @adminrequired def listuser(userid: int) -> Dict[str, Any]: + # Cast the userID. + userid = UserID(userid) def __format_card(card: str) -> str: try: @@ -788,9 +793,9 @@ def searchusers() -> Dict[str, Any]: actual_userid = g.data.local.user.from_cardid(cardid) if actual_userid is None: # Force a non-match below - actual_userid = -1 + actual_userid = UserID(-1) except CardCipherException: - actual_userid = -1 + actual_userid = UserID(-1) else: actual_userid = None @@ -809,6 +814,9 @@ def searchusers() -> Dict[str, Any]: @jsonify @adminrequired def updatebalance(userid: int) -> Dict[str, Any]: + # Cast the userID. + userid = UserID(userid) + credits = request.get_json()['credits'] user = g.data.local.user.get_user(userid) arcades = g.data.local.machine.get_all_arcades() @@ -843,6 +851,9 @@ def updatebalance(userid: int) -> Dict[str, Any]: @jsonify @adminrequired def updateusername(userid: int) -> Dict[str, Any]: + # Cast the userID. + userid = UserID(userid) + username = request.get_json()['username'] user = g.data.local.user.get_user(userid) # Make sure the user ID is valid @@ -870,6 +881,9 @@ def updateusername(userid: int) -> Dict[str, Any]: @jsonify @adminrequired def updateemail(userid: int) -> Dict[str, Any]: + # Cast the userID. + userid = UserID(userid) + email = request.get_json()['email'] user = g.data.local.user.get_user(userid) # Make sure the user ID is valid @@ -892,6 +906,9 @@ def updateemail(userid: int) -> Dict[str, Any]: @jsonify @adminrequired def updatepin(userid: int) -> Dict[str, Any]: + # Cast the userID. + userid = UserID(userid) + pin = request.get_json()['pin'] user = g.data.local.user.get_user(userid) # Make sure the user ID is valid @@ -911,6 +928,9 @@ def updatepin(userid: int) -> Dict[str, Any]: @jsonify @adminrequired def updatepassword(userid: int) -> Dict[str, Any]: + # Cast the userID. + userid = UserID(userid) + new1 = request.get_json()['new1'] new2 = request.get_json()['new2'] user = g.data.local.user.get_user(userid) @@ -936,6 +956,9 @@ def updatepassword(userid: int) -> Dict[str, Any]: @jsonify @adminrequired def removeusercard(userid: int) -> Dict[str, Any]: + # Cast the userID. + userid = UserID(userid) + # Grab card, convert it card = request.get_json()['card'] try: @@ -960,6 +983,9 @@ def removeusercard(userid: int) -> Dict[str, Any]: @jsonify @adminrequired def addusercard(userid: int) -> Dict[str, Any]: + # Cast the userID. + userid = UserID(userid) + # Grab card, convert it card = request.get_json()['card'] try: diff --git a/bemani/frontend/app.py b/bemani/frontend/app.py index f7d8a42..0cccdb4 100644 --- a/bemani/frontend/app.py +++ b/bemani/frontend/app.py @@ -3,12 +3,13 @@ import re import traceback from typing import Callable, Dict, Any, Optional, List from react.jsx import JSXTransformer # type: ignore -from flask import Flask, flash, request, redirect, Response, url_for, render_template, got_request_exception, jsonify as flask_jsonify, g +from flask import Flask, flash, request, redirect, Response, url_for, render_template, got_request_exception, jsonify as flask_jsonify from flask_caching import Cache # type: ignore from functools import wraps from bemani.common import AESCipher, GameConstants from bemani.data import Data +from bemani.frontend.types import g from bemani.frontend.templates import templates_location from bemani.frontend.static import static_location diff --git a/bemani/frontend/arcade/arcade.py b/bemani/frontend/arcade/arcade.py index 5f22907..afb19b6 100644 --- a/bemani/frontend/arcade/arcade.py +++ b/bemani/frontend/arcade/arcade.py @@ -1,12 +1,14 @@ from typing import Any, Dict, List -from flask import Blueprint, request, Response, abort, url_for, g # type: ignore +from flask import Blueprint, request, Response, abort, url_for from bemani.backend.base import Base from bemani.common import CardCipher, CardCipherException, ValidatedDict, GameConstants -from bemani.data import Arcade, Event, Machine +from bemani.data import Arcade, ArcadeID, Event, Machine from bemani.frontend.app import loginrequired, jsonify, render_react, valid_pin from bemani.frontend.templates import templates_location from bemani.frontend.static import static_location +from bemani.frontend.types import g + arcade_pages = Blueprint( 'arcade_pages', @@ -132,6 +134,9 @@ def get_game_settings(arcade: Arcade) -> List[Dict[str, Any]]: @arcade_pages.route('/') @loginrequired def viewarcade(arcadeid: int) -> Response: + # Cast the ID for type safety. + arcadeid = ArcadeID(arcadeid) + arcade = g.data.local.machine.get_arcade(arcadeid) if g.userID not in arcade.owners: abort(403) @@ -168,6 +173,9 @@ def viewarcade(arcadeid: int) -> Response: @jsonify @loginrequired def listarcade(arcadeid: int) -> Dict[str, Any]: + # Cast the ID for type safety. + arcadeid = ArcadeID(arcadeid) + # Make sure the arcade is valid arcade = g.data.local.machine.get_arcade(arcadeid) if arcade is None: @@ -190,6 +198,8 @@ def listarcade(arcadeid: int) -> Dict[str, Any]: @jsonify @loginrequired def addbalance(arcadeid: int) -> Dict[str, Any]: + # Cast the ID for type safety. + arcadeid = ArcadeID(arcadeid) credits = request.get_json()['credits'] card = request.get_json()['card'] @@ -234,6 +244,8 @@ def addbalance(arcadeid: int) -> Dict[str, Any]: @jsonify @loginrequired def updatebalance(arcadeid: int) -> Dict[str, Any]: + # Cast the ID for type safety. + arcadeid = ArcadeID(arcadeid) credits = request.get_json()['credits'] # Make sure the arcade is valid @@ -269,6 +281,9 @@ def updatebalance(arcadeid: int) -> Dict[str, Any]: @jsonify @loginrequired def updatepin(arcadeid: int) -> Dict[str, Any]: + # Cast the ID for type safety. + arcadeid = ArcadeID(arcadeid) + pin = request.get_json()['pin'] # Make sure the arcade is valid @@ -293,6 +308,9 @@ def updatepin(arcadeid: int) -> Dict[str, Any]: @jsonify @loginrequired def updatearcade(arcadeid: int, attribute: str) -> Dict[str, Any]: + # Cast the ID for type safety. + arcadeid = ArcadeID(arcadeid) + # Attempt to look this arcade up new_value = request.get_json()['value'] arcade = g.data.local.machine.get_arcade(arcadeid) @@ -322,6 +340,9 @@ def updatearcade(arcadeid: int, attribute: str) -> Dict[str, Any]: @jsonify @loginrequired def updatesettings(arcadeid: int) -> Dict[str, Any]: + # Cast the ID for type safety. + arcadeid = ArcadeID(arcadeid) + # Attempt to look this arcade up arcade = g.data.local.machine.get_arcade(arcadeid) diff --git a/bemani/frontend/bishi/endpoints.py b/bemani/frontend/bishi/endpoints.py index afaaaf1..1c4c75b 100644 --- a/bemani/frontend/bishi/endpoints.py +++ b/bemani/frontend/bishi/endpoints.py @@ -1,7 +1,7 @@ # vim: set fileencoding=utf-8 import re from typing import Any, Dict -from flask import Blueprint, request, Response, url_for, abort, g # type: ignore +from flask import Blueprint, request, Response, url_for, abort from bemani.common import GameConstants from bemani.data import UserID @@ -9,6 +9,7 @@ from bemani.frontend.app import loginrequired, jsonify, render_react from bemani.frontend.bishi.bishi import BishiBashiFrontend from bemani.frontend.templates import templates_location from bemani.frontend.static import static_location +from bemani.frontend.types import g bishi_pages = Blueprint( diff --git a/bemani/frontend/ddr/endpoints.py b/bemani/frontend/ddr/endpoints.py index 3c1675e..d7a0ba6 100644 --- a/bemani/frontend/ddr/endpoints.py +++ b/bemani/frontend/ddr/endpoints.py @@ -1,7 +1,7 @@ # vim: set fileencoding=utf-8 import re from typing import Any, Dict, List, Optional -from flask import Blueprint, request, Response, url_for, abort, g # type: ignore +from flask import Blueprint, request, Response, url_for, abort from bemani.common import ID, GameConstants from bemani.data import Link, UserID @@ -9,6 +9,8 @@ from bemani.frontend.app import loginrequired, jsonify, render_react from bemani.frontend.ddr.ddr import DDRFrontend from bemani.frontend.templates import templates_location from bemani.frontend.static import static_location +from bemani.frontend.types import g + ddr_pages = Blueprint( 'ddr_pages', diff --git a/bemani/frontend/home/home.py b/bemani/frontend/home/home.py index 020180a..72574ea 100644 --- a/bemani/frontend/home/home.py +++ b/bemani/frontend/home/home.py @@ -1,10 +1,12 @@ -from flask import Blueprint, Response, g # type: ignore +from flask import Blueprint, Response from typing import Dict, Any from bemani.data import News from bemani.frontend.app import loginrequired, render_react from bemani.frontend.templates import templates_location from bemani.frontend.static import static_location +from bemani.frontend.types import g + home_pages = Blueprint( 'home_pages', diff --git a/bemani/frontend/iidx/endpoints.py b/bemani/frontend/iidx/endpoints.py index 223cddf..a20a4bd 100644 --- a/bemani/frontend/iidx/endpoints.py +++ b/bemani/frontend/iidx/endpoints.py @@ -1,7 +1,7 @@ # vim: set fileencoding=utf-8 import re from typing import Any, Dict -from flask import Blueprint, request, Response, url_for, abort, g # type: ignore +from flask import Blueprint, request, Response, url_for, abort from bemani.common import ID, GameConstants from bemani.data import UserID @@ -9,6 +9,7 @@ from bemani.frontend.app import loginrequired, jsonify, render_react from bemani.frontend.iidx.iidx import IIDXFrontend from bemani.frontend.templates import templates_location from bemani.frontend.static import static_location +from bemani.frontend.types import g iidx_pages = Blueprint( 'iidx_pages', diff --git a/bemani/frontend/jubeat/endpoints.py b/bemani/frontend/jubeat/endpoints.py index 1e52e14..d7567f1 100644 --- a/bemani/frontend/jubeat/endpoints.py +++ b/bemani/frontend/jubeat/endpoints.py @@ -1,7 +1,7 @@ # vim: set fileencoding=utf-8 import re from typing import Any, Dict -from flask import Blueprint, request, Response, url_for, abort, g # type: ignore +from flask import Blueprint, request, Response, url_for, abort from bemani.common import ID, GameConstants from bemani.data import UserID @@ -9,6 +9,7 @@ from bemani.frontend.app import loginrequired, jsonify, render_react from bemani.frontend.jubeat.jubeat import JubeatFrontend from bemani.frontend.templates import templates_location from bemani.frontend.static import static_location +from bemani.frontend.types import g jubeat_pages = Blueprint( 'jubeat_pages', diff --git a/bemani/frontend/museca/endpoints.py b/bemani/frontend/museca/endpoints.py index 49d6cef..67fb39d 100644 --- a/bemani/frontend/museca/endpoints.py +++ b/bemani/frontend/museca/endpoints.py @@ -1,7 +1,7 @@ # vim: set fileencoding=utf-8 import re from typing import Any, Dict -from flask import Blueprint, request, Response, url_for, abort, g # type: ignore +from flask import Blueprint, request, Response, url_for, abort from bemani.common import GameConstants from bemani.data import UserID @@ -9,6 +9,8 @@ from bemani.frontend.app import loginrequired, jsonify, render_react from bemani.frontend.museca.museca import MusecaFrontend from bemani.frontend.templates import templates_location from bemani.frontend.static import static_location +from bemani.frontend.types import g + museca_pages = Blueprint( 'museca_pages', diff --git a/bemani/frontend/popn/endpoints.py b/bemani/frontend/popn/endpoints.py index 03ab383..9d4e704 100644 --- a/bemani/frontend/popn/endpoints.py +++ b/bemani/frontend/popn/endpoints.py @@ -1,7 +1,7 @@ # vim: set fileencoding=utf-8 import re from typing import Any, Dict -from flask import Blueprint, request, Response, url_for, abort, g # type: ignore +from flask import Blueprint, request, Response, url_for, abort from bemani.common import ID, GameConstants, VersionConstants from bemani.data import UserID @@ -9,6 +9,8 @@ from bemani.frontend.app import loginrequired, jsonify, render_react from bemani.frontend.popn.popn import PopnMusicFrontend from bemani.frontend.templates import templates_location from bemani.frontend.static import static_location +from bemani.frontend.types import g + popn_pages = Blueprint( 'popn_pages', diff --git a/bemani/frontend/reflec/endpoints.py b/bemani/frontend/reflec/endpoints.py index 32d72d4..30d282c 100644 --- a/bemani/frontend/reflec/endpoints.py +++ b/bemani/frontend/reflec/endpoints.py @@ -1,7 +1,7 @@ # vim: set fileencoding=utf-8 import re from typing import Any, Dict -from flask import Blueprint, request, Response, url_for, abort, g # type: ignore +from flask import Blueprint, request, Response, url_for, abort from bemani.common import ID, GameConstants from bemani.data import UserID @@ -9,6 +9,8 @@ from bemani.frontend.app import loginrequired, jsonify, render_react from bemani.frontend.reflec.reflec import ReflecBeatFrontend from bemani.frontend.templates import templates_location from bemani.frontend.static import static_location +from bemani.frontend.types import g + reflec_pages = Blueprint( 'reflec_pages', diff --git a/bemani/frontend/sdvx/endpoints.py b/bemani/frontend/sdvx/endpoints.py index 35c7fe5..e576ba4 100644 --- a/bemani/frontend/sdvx/endpoints.py +++ b/bemani/frontend/sdvx/endpoints.py @@ -1,7 +1,7 @@ # vim: set fileencoding=utf-8 import re from typing import Any, Dict -from flask import Blueprint, request, Response, url_for, abort, g # type: ignore +from flask import Blueprint, request, Response, url_for, abort from bemani.common import ID, GameConstants, VersionConstants from bemani.data import UserID @@ -9,6 +9,8 @@ from bemani.frontend.app import loginrequired, jsonify, render_react from bemani.frontend.sdvx.sdvx import SoundVoltexFrontend from bemani.frontend.templates import templates_location from bemani.frontend.static import static_location +from bemani.frontend.types import g + sdvx_pages = Blueprint( 'sdvx_pages', diff --git a/bemani/frontend/types.py b/bemani/frontend/types.py new file mode 100644 index 0000000..379a3e3 --- /dev/null +++ b/bemani/frontend/types.py @@ -0,0 +1,22 @@ +from typing import Any, Dict, Optional, TYPE_CHECKING + + +if TYPE_CHECKING: + from flask.ctx import _AppCtxGlobals + from flask_caching import Cache # type: ignore + + from bemani.data import Data, UserID + + class RequestGlobals(_AppCtxGlobals): + config: Dict[str, Any] + cache: Cache + data: Data + sessionID: Optional[str] + userID: Optional[UserID] + + g = RequestGlobals() +else: + from flask import g + + +__all__ = ["g"]