import cherrypy import logging from repobot.repos import RepoDb class AppWeb(object): def __init__(self, db): self.db = db @cherrypy.expose def addpkg(self, provider, reponame, name, version, f, **params): self.db.add_package(provider, reponame, name, version, f.filename, f.file, params) @cherrypy.expose def repo(self, provider, repo, *args): return self.db.browse_repo(provider, repo, args) class FlatDispatch(cherrypy.dispatch.Dispatcher): def __init__(self, method): """ Route all sub urls of this one to the single passed method """ super().__init__(self) self.method = method def find_handler(self, path): # Hack, it does not respect settings of parent nodes cherrypy.serving.request.config = cherrypy.config return self.method, [i for i in filter(lambda o: len(o) > 0, path.split("/")[2:])] def main(): import argparse import signal parser = argparse.ArgumentParser(description="Repobot daemon") parser.add_argument('-p', '--port', default=8080, type=int, help="tcp port to listen on") parser.add_argument('-s', '--database', default="./repos.db", help="path to persistent database") parser.add_argument('-d', '--data-root', default="./data/", help="data storage dir") parser.add_argument('--debug', action="store_true", help="enable development options") args = parser.parse_args() logging.basicConfig(level=logging.INFO if args.debug else logging.WARNING, format="%(asctime)-15s %(levelname)-8s %(filename)s:%(lineno)d %(message)s") db = RepoDb(args.database, args.data_root) web = AppWeb(db) def validate_password(realm, username, password): s = library.session() if s.query(User).filter(User.name == username, User.password == pwhash(password)).first(): return True return False cherrypy.tree.mount(web, '/', {'/': {'tools.trailing_slash.on': False, # 'error_page.403': web.error, # 'error_page.404': web.error }, '/repo': {'request.dispatch': FlatDispatch(web.repo)}, #'/static': {"tools.staticdir.on": True, # "tools.staticdir.dir": os.path.join(APPROOT, "styles/dist") # if not args.debug else os.path.abspath("styles/dist")}, '/login': {'tools.auth_basic.on': True, 'tools.auth_basic.realm': 'webapp', 'tools.auth_basic.checkpassword': validate_password}}) cherrypy.config.update({ 'tools.sessions.on': True, 'tools.sessions.locking': 'explicit', 'tools.sessions.timeout': 525600, 'request.show_tracebacks': True, 'server.socket_port': args.port, 'server.thread_pool': 25, 'server.socket_host': '0.0.0.0', 'server.show_tracebacks': True, 'log.screen': False, 'engine.autoreload.on': args.debug }) def signal_handler(signum, stack): logging.critical('Got sig {}, exiting...'.format(signum)) cherrypy.engine.exit() signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) try: cherrypy.engine.start() cherrypy.engine.block() finally: logging.info("API has shut down") cherrypy.engine.exit() if __name__ == '__main__': main()