Software repository API
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

100 lines
3.6 KiB

  1. import cherrypy
  2. import logging
  3. from repobot.repos import RepoDb
  4. class AppWeb(object):
  5. def __init__(self, db):
  6. self.db = db
  7. @cherrypy.expose
  8. def addpkg(self, provider, reponame, name, version, f, **params):
  9. self.db.add_package(provider, reponame, name, version, f.filename, f.file, params)
  10. @cherrypy.expose
  11. def repo(self, provider, repo, *args):
  12. return self.db.browse_repo(provider, repo, args)
  13. class FlatDispatch(cherrypy.dispatch.Dispatcher):
  14. def __init__(self, method):
  15. """
  16. Route all sub urls of this one to the single passed method
  17. """
  18. super().__init__(self)
  19. self.method = method
  20. def find_handler(self, path):
  21. # Hack, it does not respect settings of parent nodes
  22. cherrypy.serving.request.config = cherrypy.config
  23. return self.method, [i for i in filter(lambda o: len(o) > 0, path.split("/")[2:])]
  24. def main():
  25. import argparse
  26. import signal
  27. parser = argparse.ArgumentParser(description="Repobot daemon")
  28. parser.add_argument('-p', '--port', default=8080, type=int, help="tcp port to listen on")
  29. parser.add_argument('-s', '--database', default="./repos.db", help="path to persistent database")
  30. parser.add_argument('-d', '--data-root', default="./data/", help="data storage dir")
  31. parser.add_argument('--debug', action="store_true", help="enable development options")
  32. args = parser.parse_args()
  33. logging.basicConfig(level=logging.INFO if args.debug else logging.WARNING,
  34. format="%(asctime)-15s %(levelname)-8s %(filename)s:%(lineno)d %(message)s")
  35. db = RepoDb(args.database, args.data_root)
  36. web = AppWeb(db)
  37. def validate_password(realm, username, password):
  38. s = library.session()
  39. if s.query(User).filter(User.name == username, User.password == pwhash(password)).first():
  40. return True
  41. return False
  42. cherrypy.tree.mount(web, '/', {'/': {'tools.trailing_slash.on': False,
  43. # 'error_page.403': web.error,
  44. # 'error_page.404': web.error
  45. },
  46. '/repo': {'request.dispatch': FlatDispatch(web.repo)},
  47. #'/static': {"tools.staticdir.on": True,
  48. # "tools.staticdir.dir": os.path.join(APPROOT, "styles/dist")
  49. # if not args.debug else os.path.abspath("styles/dist")},
  50. '/login': {'tools.auth_basic.on': True,
  51. 'tools.auth_basic.realm': 'webapp',
  52. 'tools.auth_basic.checkpassword': validate_password}})
  53. cherrypy.config.update({
  54. 'tools.sessions.on': True,
  55. 'tools.sessions.locking': 'explicit',
  56. 'tools.sessions.timeout': 525600,
  57. 'request.show_tracebacks': True,
  58. 'server.socket_port': args.port,
  59. 'server.thread_pool': 25,
  60. 'server.socket_host': '0.0.0.0',
  61. 'server.show_tracebacks': True,
  62. 'log.screen': False,
  63. 'engine.autoreload.on': args.debug
  64. })
  65. def signal_handler(signum, stack):
  66. logging.critical('Got sig {}, exiting...'.format(signum))
  67. cherrypy.engine.exit()
  68. signal.signal(signal.SIGINT, signal_handler)
  69. signal.signal(signal.SIGTERM, signal_handler)
  70. try:
  71. cherrypy.engine.start()
  72. cherrypy.engine.block()
  73. finally:
  74. logging.info("API has shut down")
  75. cherrypy.engine.exit()
  76. if __name__ == '__main__':
  77. main()