def before_request() -> None: global config g.cache = Cache(app, config={ 'CACHE_TYPE': 'filesystem', 'CACHE_DIR': config['cache_dir'], }) if request.endpoint in ['jsx', 'static']: # This is just serving cached compiled frontends, skip loading from DB return g.config = config g.data = Data(config) g.sessionID = None g.userID = None try: aes = AESCipher(config['secret_key']) sessionID = aes.decrypt(request.cookies.get('SessionID')) except Exception: sessionID = None g.sessionID = sessionID if sessionID is not None: g.userID = g.data.local.user.from_session(sessionID) else: g.userID = None
def main() -> None: parser = argparse.ArgumentParser( description= "A utility for working with databases created with this codebase.") parser.add_argument( "operation", help= "Operation to perform, options include 'create', 'generate', 'upgrade', 'change-password', 'add-admin' and 'remove-admin'.", type=str, ) parser.add_argument( "-u", "--username", help="Username of user to add/remove admin rights for.", type=str, ) parser.add_argument( "-m", "--message", help="Message to use for auto-generated migration scripts.", type=str, ) parser.add_argument( "-e", "--allow-empty", help= "Allow empty migration script to be generated. Useful for data-only migrations.", action='store_true', ) parser.add_argument("-c", "--config", help="Core configuration. Defaults to server.yaml", type=str, default="server.yaml") args = parser.parse_args() config = yaml.safe_load(open(args.config)) config['database']['engine'] = Data.create_engine(config) try: if args.operation == "create": create(config) elif args.operation == "generate": generate(config, args.message, args.allow_empty) elif args.operation == "upgrade": upgrade(config) elif args.operation == "add-admin": add_admin(config, args.username) elif args.operation == "remove-admin": remove_admin(config, args.username) elif args.operation == 'change-password': change_password(config, args.username) else: raise Exception(f"Unknown operation '{args.operation}'") except DBCreateException as e: print(str(e)) sys.exit(1)
def remove_admin(config: Dict[str, Any], username: Optional[str]) -> None: if username is None: raise Exception('Please provide a username!') data = Data(config) userid = data.local.user.from_username(username) if userid is None: raise Exception('User not found!') user = data.local.user.get_user(userid) user.admin = False data.local.user.put_user(user) print(f'User {username} lost admin rights.')
def add_admin(config: Dict[str, Any], username: Optional[str]) -> None: if username is None: raise Exception('Please provide a username!') data = Data(config) userid = data.local.user.from_username(username) if userid is None: raise Exception('User not found!') user = data.local.user.get_user(userid) user.admin = True data.local.user.put_user(user) print('User {} gained admin rights.'.format(username))
def generate(config: Dict[str, Any], message: Optional[str], allow_empty: bool) -> None: if message is None: raise Exception('Please provide a message!') data = Data(config) data.generate(message, allow_empty) data.close()
def change_password(config: Dict[str, Any], username: Optional[str]) -> None: if username is None: raise Exception('Please provide a username!') password1 = getpass.getpass('Password: '******'Re-enter password: '******'Passwords don\'t match!') data = Data(config) userid = data.local.user.from_username(username) if userid is None: raise Exception('User not found!') data.local.user.update_password(userid, password1) print(f'User {username} changed password.')
def before_request() -> None: global config g.config = config g.data = Data(config) g.authorized = False authkey = request.headers.get('Authorization') if authkey is not None: try: authtype, authtoken = authkey.split(' ', 1) except ValueError: authtype = None authtoken = None if authtype.lower() == 'token': g.authorized = g.data.local.api.validate_client(authtoken)
def run_scheduled_work(config: Dict[str, Any]) -> None: data = Data(config) # Only run scheduled work for enabled components enabled_factories: List[Any] = [] enabled_caches: List[Any] = [] if config.get('support', {}).get(GameConstants.IIDX, False): enabled_factories.append(IIDXFactory) enabled_caches.append(IIDXCache) if config.get('support', {}).get(GameConstants.POPN_MUSIC, False): enabled_factories.append(PopnMusicFactory) enabled_caches.append(PopnMusicCache) if config.get('support', {}).get(GameConstants.JUBEAT, False): enabled_factories.append(JubeatFactory) enabled_caches.append(JubeatCache) if config.get('support', {}).get(GameConstants.BISHI_BASHI, False): enabled_factories.append(BishiBashiFactory) enabled_caches.append(BishiBashiCache) if config.get('support', {}).get(GameConstants.DDR, False): enabled_factories.append(DDRFactory) enabled_caches.append(DDRCache) if config.get('support', {}).get(GameConstants.SDVX, False): enabled_factories.append(SoundVoltexFactory) enabled_caches.append(SoundVoltexCache) if config.get('support', {}).get(GameConstants.REFLEC_BEAT, False): enabled_factories.append(ReflecBeatFactory) enabled_caches.append(ReflecBeatCache) if config.get('support', {}).get(GameConstants.MUSECA, False): enabled_factories.append(MusecaFactory) enabled_caches.append(MusecaCache) # First, run any backend scheduled work for factory in enabled_factories: factory.run_scheduled_work(data, config) # type: ignore # Now, warm the caches for the frontend for cache in enabled_caches: cache.preload(data, config) # type: ignore # Now, possibly delete old log entries keep_duration = config.get('event_log_duration', 0) if keep_duration > 0: # Calculate timestamp of events we should delete oldest_event = Time.now() - keep_duration data.local.network.delete_events(oldest_event)
def run_scheduled_work(config: Dict[str, Any]) -> None: data = Data(config) # Only run scheduled work for enabled components enabled_factories: List[Any] = [] enabled_caches: List[Any] = [] if config.get('support', {}).get(GameConstants.IIDX, False): enabled_factories.append(IIDXFactory) enabled_caches.append(IIDXCache) if config.get('support', {}).get(GameConstants.POPN_MUSIC, False): enabled_factories.append(PopnMusicFactory) enabled_caches.append(PopnMusicCache) if config.get('support', {}).get(GameConstants.JUBEAT, False): enabled_factories.append(JubeatFactory) enabled_caches.append(JubeatCache) if config.get('support', {}).get(GameConstants.BISHI_BASHI, False): enabled_factories.append(BishiBashiFactory) enabled_caches.append(BishiBashiCache) if config.get('support', {}).get(GameConstants.DDR, False): enabled_factories.append(DDRFactory) enabled_caches.append(DDRCache) if config.get('support', {}).get(GameConstants.SDVX, False): enabled_factories.append(SoundVoltexFactory) enabled_caches.append(SoundVoltexCache) if config.get('support', {}).get(GameConstants.REFLEC_BEAT, False): enabled_factories.append(ReflecBeatFactory) enabled_caches.append(ReflecBeatCache) if config.get('support', {}).get(GameConstants.MUSECA, False): enabled_factories.append(MusecaFactory) enabled_caches.append(MusecaCache) # First, run any backend scheduled work for factory in enabled_factories: factory.run_scheduled_work(data, config) # type: ignore # Now, warm the caches for the frontend for cache in enabled_caches: cache.preload(data, config) # type: ignore
def create(config: Dict[str, Any]) -> None: data = Data(config) data.create() data.close()
def upgrade(config: Dict[str, Any]) -> None: data = Data(config) data.upgrade() data.close()
def load_config(filename: str) -> None: global config config.update(yaml.safe_load(open(filename))) # type: ignore config['database']['engine'] = Data.create_engine(config) app.secret_key = config['secret_key']
factory.run_scheduled_work(data, config) # type: ignore # Now, warm the caches for the frontend for cache in enabled_caches: cache.preload(data, config) # type: ignore # Now, possibly delete old log entries keep_duration = config.get('event_log_duration', 0) if keep_duration > 0: # Calculate timestamp of events we should delete oldest_event = Time.now() - keep_duration data.local.network.delete_events(oldest_event) if __name__ == '__main__': parser = argparse.ArgumentParser( description="A scheduler for work that needs to be done periodically.") parser.add_argument("-c", "--config", help="Core configuration. Defaults to server.yaml", type=str, default="server.yaml") args = parser.parse_args() # Set up global configuration config = yaml.safe_load(open(args.config)) # type: ignore config['database']['engine'] = Data.create_engine(config) # Run out of band work run_scheduled_work(config)
def receive_request(path: str) -> Response: proto = EAmuseProtocol() remote_address = request.headers.get('x-remote-address', None) compression = request.headers.get('x-compress', None) encryption = request.headers.get('x-eamuse-info', None) req = proto.decode( compression, encryption, request.data, ) if req is None: # Nothing to do here return Response("Unrecognized packet!", 500) if req.name in {'soapenv:Envelope', 'soap:Envelope', 'methodCall'}: # We get lots of spam from random bots trying to SOAP # us up, so ignore this shit. return Response("Unrecognized packet!", 500) # Create and format config global config requestconfig = copy.copy(config) requestconfig['client'] = { 'address': remote_address or request.remote_addr, } dataprovider = Data(requestconfig) try: dispatch = Dispatch(requestconfig, dataprovider, True) resp = dispatch.handle(req) if resp is None: # Nothing to do here dataprovider.local.network.put_event( 'unhandled_packet', { 'request': str(req), }, ) return Response("No response generated", 404) compression = None data = proto.encode( compression, encryption, resp, ) response = make_response(data) # Some old clients are case-sensitive, even though http spec says these # shouldn't matter, so capitalize correctly. if compression: response.headers['X-Compress'] = compression else: response.headers['X-Compress'] = 'none' if encryption: response.headers['X-Eamuse-Info'] = encryption return response except UnrecognizedPCBIDException as e: dataprovider.local.network.put_event( 'unauthorized_pcbid', { 'pcbid': e.pcbid, 'model': e.model, 'ip': e.ip, }, ) return Response("Unauthorized client", 403) except Exception: stack = traceback.format_exc() print(stack) dataprovider.local.network.put_event( 'exception', { 'service': 'xrpc', 'request': str(req), 'traceback': stack, }, ) return Response("Crash when handling packet!", 500) finally: dataprovider.close()
def load_config(filename: str) -> None: global config config.update(yaml.safe_load(open(filename))) config['database']['engine'] = Data.create_engine(config)