def __init__(self, hgwebdirconfig=None, cyd=None): if cyd is None: cyd = cydra.Cydra() self.cydra = self.compmgr = cyd self.authenticator = HTTPBasicAuthenticator(self.compmgr) self.config = config = cyd.config.get_component_config( 'cydra.repository.hg.HgRepositories', {}) if 'base' not in config: raise Exception("hg base path not configured") baseui = None if hgwebdirconfig is None: hgwebdirconfig = {'/': os.path.join(config['base'], '**')} baseui = ui.ui() # provide sensible defaults baseui.setconfig( "web", "allow_archive", "gz, zip, bz2" ) #read access -> downloading archive should be fine baseui.setconfig("web", "allow_push", "*") # we are doing access checks, not hg baseui.setconfig( "web", "push_ssl", "false") # enforcing SSL is left to the user / apache baseui.setconfig("web", "encoding", "utf-8") self.hgwebdir = hgwebdir(hgwebdirconfig, baseui)
def __init__(self, environ_to_perm, cyd=None): """Initialize Authnz helper :param environ_to_perm: Callable that returns the project or project name and the object an environment corresponds to as a tuple(project, object)""" if cyd is None: cyd = cydra.Cydra() self.cydra = self.compmgr = cyd self.environ_to_perm = environ_to_perm
def post_receive_hook(): """Hook for git""" import sys import logging from optparse import OptionParser parser = OptionParser() parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False) (options, args) = parser.parse_args() if options.verbose: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.ERROR) if len(args) != 2: print "Usage: %s <projectname> <reponame>" % sys.argv[0] sys.exit(2) cyd = cydra.Cydra() gitconf = cyd.config.get_component_config( 'cydra.repository.git.GitRepositories', {}) gitcommand = gitconf.get('gitcommand', 'git') project = cyd.get_project(args[0]) if not project: sys.exit("Unknown project") repository = project.get_repository('git', args[1]) if not repository: sys.exit("Unknown repository") for line in sys.stdin.readlines(): old, new, ref = line.split() args = [new] if old == '0' * 40 else [new, '^' + old] commits = subprocess.Popen( [gitcommand, '--git-dir', repository.path, 'rev-list'] + args, stdout=subprocess.PIPE).communicate()[0] repository.notify_post_commit(commits.splitlines()[::-1]) sys.exit(0)
def sync(args): cyd = cydra.Cydra() projects = cyd.get_project_names() for projectname in projects: project = cyd.get_project(projectname) if not project: print "Unknown Project:", projectname else: if project.sync(): print "Synced Project:", projectname else: print "Synced FAILED:", projectname
def __init__(self, cyd=None): if cyd is None: cyd = cydra.Cydra() self.cydra = self.compmgr = cyd self.authenticator = HTTPBasicAuthenticator(self.compmgr) self.config = config = cyd.config.get_component_config( 'cydraplugins.trac.TracEnvironments', {}) if 'base' not in config: raise Exception("trac environments base path not configured") os.environ['TRAC_ENV_PARENT_DIR'] = config['base'] import trac.web.main self.trac = trac.web.main.dispatch_request
def cmd_project(args): if len(args) < 2: print "Syntax: project <projectname> <command>" else: cyd = cydra.Cydra() project = cyd.get_project(args[0]) if project is None: print "Unknown Project" else: cmds = ProjectCmds(cyd, project) if not hasattr(cmds, args[1]): cmds.help([]) else: getattr(cmds, args[1])(args[2:])
def commit_hook(): """Hook for hg""" import sys import logging from optparse import OptionParser parser = OptionParser() parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False) (options, args) = parser.parse_args() if options.verbose: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.ERROR) if len(args) != 3: print "Usage: %s <projectname> <reponame> <node>" % sys.argv[0] sys.exit(2) cyd = cydra.Cydra() hgconf = cyd.config.get_component_config( 'cydra.repository.hg.HgRepositories', {}) hgcommand = hgconf.get('hgcommand', 'hg') project = cyd.get_project(args[0]) if not project: sys.exit("Unknown project") repository = project.get_repository('hg', args[1]) if not repository: sys.exit("Unknown repository") commits = subprocess.Popen([ hgcommand, '--repository', repository.path, 'log', '--template', '{node}\\n', '--rev', args[2] + ':tip' ], stdout=subprocess.PIPE).communicate()[0] repository.notify_post_commit(commits.splitlines())
def commit_hook(): """Hook for svn""" import sys if len(sys.argv) != 4: print "Usage: %s <projectname> <reponame> <revision>" % sys.argv[0] sys.exit(2) cyd = cydra.Cydra() project = cyd.get_project(sys.argv[1]) if not project: sys.exit("Unknown project") repository = project.get_repository('svn', sys.argv[2]) if not repository: sys.exit("Unknown repository") repository.notify_post_commit(sys.argv[3])
def __init__(self, cyd=None, gitviewer=None): if cyd is None: cyd = cydra.Cydra() self.cydra = self.compmgr = cyd self.authenticator = HTTPBasicAuthenticator(self.compmgr) self.gitviewer = gitviewer self.config = config = cyd.config.get_component_config( 'cydra.repository.git.GitRepositories', {}) if 'base' not in config: raise Exception("git base path not configured") self.git_inforefs_handler = GitHTTPBackendInfoRefs( content_path=config['base'], uri_marker='') self.git_rpc_handler = GitHTTPBackendSmartHTTP( content_path=config['base'], uri_marker='') self.static_handler = StaticWSGIServer(content_path=config['base'], uri_marker='') self.git_inforefs_handler.repo_auto_create = False self.git_rpc_handler.repo_auto_create = False self.static_handler.repo_auto_create = False
def __init__(self, cyd=None): if cyd is None: cyd = cydra.Cydra() self.cydra = self.compmgr = cyd self.cache = SimpleCache()
def run_server(): import logging import logging.handlers from optparse import OptionParser parser = OptionParser() parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False) parser.add_option('-p', '--proxy', action='store_true', dest='proxy', default=False) parser.add_option('-s', '--script-name', action='store', dest='script_name', default=None) parser.add_option('-f', '--force-https', action='store_true', dest='force_https', default=False) parser.add_option('-d', '--daemonize', action='store_true', dest='daemonize', default=False) parser.add_option('-i', '--pidfile', action='store', dest='pidfile', default=None) parser.add_option('-l', '--logfile', action='store', dest='logfile', default=None) parser.add_option('-u', '--user', action='store', dest='user', default=None) parser.add_option('-g', '--group', action='store', dest='group', default=None) (options, args) = parser.parse_args() # configure logging formatter = logging.Formatter( '[%(asctime)s] %(levelname)s: <%(name)s@%(filename)s:%(lineno)d> %(message)s' ) if options.verbose: loglevel = logging.DEBUG else: loglevel = logging.ERROR if options.logfile: handler = logging.handlers.TimedRotatingFileHandler(options.logfile, when='midnight', backupCount=7, encoding='utf-8') else: handler = logging.StreamHandler() handler.setFormatter(formatter) logger = logging.getLogger() logger.addHandler(handler) logger.setLevel(loglevel) port = 8080 if len(args) > 0: port = int(args[0]) cyd = cydra.Cydra() helper = CydraHelper(cyd) wsgiapp = cydraplugins.githttp.create_application(cyd=cyd) if options.proxy: wsgiapp = ProxyHelper(wsgiapp) if options.script_name: wsgiapp.script_name = options.script_name if options.force_https: wsgiapp.force_https = True fallbackapp = tornado.wsgi.WSGIContainer(wsgiapp) app = tornado.web.Application([ ('/.*/.*/git-.*', RPCHandler, helper.config_dict), ('/.*/.*/info/refs', InfoRefsHandler, helper.config_dict), ('/.*/.*/HEAD', FileHandler, helper.config_dict), ('/.*/.*/objects/.*', FileHandler, helper.config_dict), ('.*', tornado.web.FallbackHandler, { 'fallback': fallbackapp }) ]) sockets = tornado.netutil.bind_sockets(port) # daemonize if requested if options.daemonize: if not options.logfile: print "Error: Cannot log to stderr, please specify a log file" return import daemon, grp, pwd, lockfile files = sockets + [handler.stream] if options.pidfile: pidf = open(options.pidfile, 'w') files.append(pidf) args = dict(files_preserve=files) #if options.pidfile: # args['pidfile'] = PidFile(pidf) if options.group: if options.group.isdigit(): args['gid'] = int(options.group) else: args['gid'] = grp.getgrnam(options.group).gr_gid elif os.getgid() == 0: args['gid'] = grp.getgrnam('www-data').gr_gid if options.user: if options.user.isdigit(): args['uid'] = int(options.user) else: args['uid'] = pwd.getpwnam(options.user).pw_uid elif os.getuid() == 0: args['uid'] = pwd.getpwnam('www-data').pw_uid context = daemon.DaemonContext(**args) context.open() # save pid to file if options.pidfile: pidf.write(str(os.getpid())) pidf.close() #tornado.process.fork_processes(0) import traceback, signal def dump_stack(sig, frame): logger.debug("Dumping Stack: \n" + ''.join(traceback.format_stack(frame))) signal.signal(signal.SIGUSR1, dump_stack) server = tornado.httpserver.HTTPServer(app) server.add_sockets(sockets) tornado.ioloop.IOLoop.instance().start()
def create_app(cyd=None): """Create the web interface WSGI application""" if cyd is None: cyd = cydra.Cydra() from flask import Flask from flaskext.csrf import csrf from cydra.web.themes import IThemeProvider, ThemedTemplateLoader, patch_static app = Flask(__name__) # register themes theme_providers = ExtensionPoint(IThemeProvider, component_manager=cyd) app.config['cydra_themes'] = dict([(theme.name, theme) for theme in theme_providers.get_themes()]) default_theme = cyd.config.get('web').get('default_theme') if default_theme is not None and default_theme in app.config['cydra_themes']: default_theme = app.config['cydra_themes'][default_theme] logger.debug("Default theme: %s", default_theme.name) else: default_theme = None theme_detector = ThemeDetector(default_theme) app.before_request(theme_detector) # replace default loader app.jinja_options = Flask.jinja_options.copy() app.jinja_options['loader'] = ThemedTemplateLoader(app) # patch static file resolver patch_static(app) # secret key for cookies app.secret_key = os.urandom(24) # consider the cydra instance to be a form of configuration # and therefore store it in the config dict. app.config['cydra'] = cyd # common views app.add_url_rule('/login', 'login', login) # Add shorthands to context app.context_processor(add_shorthands_to_context) # load frontend and backend from cydra.web.frontend import blueprint as frontend_blueprint patch_static(frontend_blueprint, 'frontend') #from cydra.web.admin import blueprint as admin_blueprint #patch_static(admin_blueprint, 'admin') app.register_blueprint(frontend_blueprint) #app.register_blueprint(admin_blueprint) # load additional blueprints pages = ExtensionPoint(IBlueprintProvider, component_manager=cyd) for bpprovider in pages: bp = bpprovider.get_blueprint() patch_static(bp, bp.name) app.register_blueprint(bp) # some utility template filters from cydra.web.filters import filters #map(app.template_filter(), filters) _ = [app.template_filter()(f) for f in filters] # prevent flask from handling exceptions app.debug = True # add CSRF protection csrf(app) # wrap in authentication middleware from cydra.web.wsgihelper import AuthenticationMiddleware app = AuthenticationMiddleware(cyd, app) # enable debugging for certain users debugusers = cyd.config.get('web').get('debug_users', []) if debugusers: from cydra.web.debugging import DebuggingMiddleware app = DebuggingMiddleware(app, debugusers) return app
def __init__(self): self.log.debug('CydraPolicy initializing') self.cydra = cydra.Cydra() # DO NOT set compmgr to cydra as this is a Trac component!
def run_server(): import logging import logging.handlers from optparse import OptionParser parser = OptionParser() parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False) parser.add_option('-d', '--daemonize', action='store_true', dest='daemonize', default=False) parser.add_option('-i', '--pidfile', action='store', dest='pidfile', default=None) parser.add_option('-l', '--logfile', action='store', dest='logfile', default=None) parser.add_option('-u', '--user', action='store', dest='user', default=None) parser.add_option('-g', '--group', action='store', dest='group', default=None) (options, args) = parser.parse_args() # configure logging formatter = logging.Formatter( '[%(asctime)s] %(levelname)s: <%(name)s@%(filename)s:%(lineno)d> %(message)s' ) if options.verbose: loglevel = logging.DEBUG else: loglevel = logging.ERROR if options.logfile: handler = logging.handlers.TimedRotatingFileHandler(options.logfile, when='midnight', backupCount=7, encoding='utf-8') else: handler = logging.StreamHandler() handler.setFormatter(formatter) logger = logging.getLogger() logger.addHandler(handler) logger.setLevel(loglevel) observer = log.PythonLoggingObserver() observer.start() port = 2222 if len(args) > 0: port = int(args[0]) cyd = cydra.Cydra() helper = CydraHelper(cyd) config = cyd.config.get_component_config( 'cydraplugins.twistedgit.TwistedGit', {}) keyfilename = config.get('server_key') if keyfilename is None: # try to find one anyways for location in ['cydra', '/etc/cydra']: if os.path.exists(location + '.key') and os.path.exists(location + '.pub'): keyfilename = location break if keyfilename is None: raise Exception("Failed to find SSH keypair") ssh_factory = ssh.create_factory( public_keys={'ssh-rsa': keys.Key.fromFile(keyfilename + '.pub')}, private_keys={'ssh-rsa': keys.Key.fromFile(keyfilename + '.key')}, authnz=helper, git_configuration=helper) # daemonize if requested if options.daemonize: if not options.logfile: print "Error: Cannot log to stderr, please specify a log file" return import daemon, grp, pwd files = [handler.stream] if options.pidfile: pidf = open(options.pidfile, 'w') files.append(pidf) args = dict(files_preserve=files) if options.group: if options.group.isdigit(): args['gid'] = int(options.group) else: args['gid'] = grp.getgrnam(options.group).gr_gid elif os.getgid() == 0: args['gid'] = grp.getgrnam('www-data').gr_gid if options.user: if options.user.isdigit(): args['uid'] = int(options.user) else: args['uid'] = pwd.getpwnam(options.user).pw_uid elif os.getuid() == 0: args['uid'] = pwd.getpwnam('www-data').pw_uid context = daemon.DaemonContext(**args) context.open() # save pid to file if options.pidfile: pidf.write(str(os.getpid())) pidf.close() import traceback, signal def dump_stack(sig, frame): logger.debug("Dumping Stack: \n" + ''.join(traceback.format_stack(frame))) signal.signal(signal.SIGUSR1, dump_stack) reactor.listenTCP(port, ssh_factory()) reactor.run()
def run_server(): import logging.handlers from optparse import OptionParser parser = OptionParser() parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False) parser.add_option('-i', '--pidfile', action='store', dest='pidfile', default=None) parser.add_option('-l', '--logfile', action='store', dest='logfile', default=None) parser.add_option('-u', '--user', action='store', dest='user', default=None) parser.add_option('-g', '--group', action='store', dest='group', default=None) parser.add_option('-s', '--sshport', action='store', type='int', dest='sshport', default=2222) parser.add_option('-w', '--httpport', action='store', type='int', dest='httpport', default=8080) (options, args) = parser.parse_args() if (options.user is None) ^ (options.group is None): raise Exception("Both user and group have to be specified") # configure logging formatter = logging.Formatter( '[%(asctime)s] %(levelname)s: <%(name)s@%(filename)s:%(lineno)d> %(message)s' ) if options.verbose: loglevel = logging.DEBUG else: loglevel = logging.ERROR if options.logfile: handler = logging.handlers.TimedRotatingFileHandler(options.logfile, when='midnight', backupCount=7, encoding='utf-8') else: handler = logging.StreamHandler() handler.setFormatter(formatter) logger = logging.getLogger() logger.addHandler(handler) logger.setLevel(loglevel) observer = log.PythonLoggingObserver() observer.start() cyd = cydra.Cydra() helper = CydraHelper(cyd) config = cyd.config.get_component_config( 'cydraplugins.gitserverglue.GitServerGlue', {}) keyfilename = config.get('server_key') if keyfilename is None: # try to find one anyways for location in ['cydra', '/etc/cydra']: if os.path.exists(location + '.key') and os.path.exists(location + '.pub'): keyfilename = location break if keyfilename is None: raise Exception("Failed to find SSH keypair") ssh_factory = ssh.create_factory( public_keys={'ssh-rsa': keys.Key.fromFile(keyfilename + '.pub')}, private_keys={'ssh-rsa': keys.Key.fromFile(keyfilename + '.key')}, authnz=helper, git_configuration=helper) http_factory = http.create_factory(authnz=helper, git_configuration=helper, git_viewer=find_git_viewer()) # save pid to file if requested if options.pidfile: with open(options.pidfile) as pidf: pidf.write(str(os.getpid())) try: def dump_stack(sig, frame): logger.debug("Dumping Stack: \n" + ''.join(traceback.format_stack(frame))) signal.signal(signal.SIGUSR1, dump_stack) reactor.listenTCP(options.sshport, ssh_factory) reactor.listenTCP(options.httpport, http_factory) # drop privileges if requested if os.getuid() == 0 and options.user: uid = int( options.user) if options.user.isdigit() else pwd.getpwnam( options.user).pw_uid gid = int( options.group) if options.group.isdigit() else grp.getgrnam( options.group).gr_gid os.setgroups([]) os.setgid(gid) os.setuid(uid) reactor.run() except Exception: logger.exception("Caught exception during run")