def git_dir_wrong_perms(): submin_env = options.env_path() git_dir = options.env_path("git_dir") try: git_user = pwd.getpwnam(options.value("git_user")) except UnknownKeyError: return [] apache = www_user() wrong_permissions = [] checkdir = git_dir while checkdir != "/" and checkdir != submin_env: try: st = os.stat(checkdir) except OSError as e: if e.errno == errno.EACCES: wrong_permissions.append({"dir": checkdir, "reason": "unknown"}) else: if (st.st_uid != git_user.pw_uid or st.st_gid != apache.pw_gid or st.st_mode & 0o750 != 0o750) and ( st.st_mode & 0o005 != 0o005 ): wrong_permissions.append({"dir": checkdir, "reason": "incorrect"}) checkdir = os.path.dirname(checkdir) return wrong_permissions
def trigger_user_hook(event, **args): user_hooks_path = options.env_path() + "hooks" + event if not user_hooks_path.exists(): return user_hooks = sorted(glob.glob(str(user_hooks_path + "*"))) cwd = os.getcwd() os.chdir(str(options.env_path())) env = dict([(key.upper(), value) for key, value in args.iteritems() if value]) for hook in user_hooks: try: # XXX What to do with system hooks which are not executable? # (since they are located in the site-packages directory) p = Popen([hook], env=env) p.wait() # wait for the hook to terminate except OSError as e: # XXX: log the error # log("An OS error occured while processing hook " # "%s. The error was: %s" % (hook, e)) pass os.chdir(cwd)
def git_dir_wrong_perms(): submin_env = options.env_path() git_dir = options.env_path("git_dir") try: git_user = pwd.getpwnam(options.value("git_user")) except UnknownKeyError: return [] apache = www_user() wrong_permissions = [] checkdir = git_dir while checkdir != '/' and checkdir != submin_env: try: st = os.stat(checkdir) except OSError as e: if e.errno == errno.EACCES: wrong_permissions.append({ 'dir': checkdir, 'reason': 'unknown' }) else: if (st.st_uid != git_user.pw_uid or st.st_gid != apache.pw_gid or st.st_mode & 0o750 != 0o750) and (st.st_mode & 0o005 != 0o005): wrong_permissions.append({ 'dir': checkdir, 'reason': 'incorrect' }) checkdir = os.path.dirname(checkdir) return wrong_permissions
def setUp(self): self.submin_env = tempfile.mkdtemp(prefix='submin-unittest') self.conf_dir = os.path.join(self.submin_env, 'conf') os.mkdir(self.conf_dir) self.authz_file = os.path.join(self.submin_env, 'conf', 'authz') mock_settings.base_dir = self.submin_env storage.open(mock_settings) storage.database_evolve() options.set_value('vcs_plugins', 'svn') options.set_value('svn_dir', 'svn') options.set_value('trac_dir', 'trac') options.set_value('svn_authz_file', 'conf/authz') options.set_value('enabled_trac', 'no') options.set_value('http_vhost', 'localhost') options.set_value('base_url_submin', '/submin') self.svn_dir = str(options.env_path('svn_dir')) self.trac_dir = str(options.env_path('trac_dir')) os.mkdir(self.svn_dir) os.mkdir(self.trac_dir) # now make some repositories self.repositories = [ {'name': 'foo', 'status': 'ok', 'vcs': 'svn'}, {'name': 'invalidperm', 'status': 'permission denied', 'vcs': 'svn'}, {'name': 'invalidperm2', 'status': 'permission denied', 'vcs': 'svn'}, {'name': 'example', 'status': 'ok', 'vcs': 'svn'}, {'name': 'subdirs', 'status': 'ok', 'vcs': 'svn'}, ] self.has_invalidperm = False self.has_invalidperm2 = False
def export_notifications(**kwargs): """Export a mailer.py config file For each user/repository pair, a config group is created. Only if a user has read or read/write permission to one or multiple paths in that repository, _and_ if the user has notifications enabled for that repository, _and_ if the user has a non-empty email-address. Multiple paths are grouped together by a regexp group (multiple|paths)""" bindir = options.static_path("hooks") + 'svn' # get a list of all users from submin.models import user users = [user.User(name) for name in user.list(user.FakeAdminUser())] groups = [] for u in users: if not u.email: continue u_notif = u.notifications() for repos in u_notif: repos_path = str(options.env_path("svn_dir") + repos) if not u_notif[repos]["enabled"]: continue # strip leading / paths = [ x[1:] for x in permissions.list_readable_user_paths(repos, "svn", u) ] if len(paths) == 0: continue elif len(paths) == 1: for_paths = paths[0] elif len(paths) > 0: for_paths = "(" + "|".join(paths) + ")" # Only match complete path, not partial paths (ticket #257) repos_path_re = '^' + repos_path + '$' g = { "repos_name": repos, "for_repos": repos_path_re, "email": u.email, "for_paths": for_paths, "username": u.name } groups.append(g) email = options.value( 'commit_email_from', 'Please configure commit_email_from <*****@*****.**>') templatevariables = {"groups": groups, 'from_addr': email} from submin.template.shortcuts import evaluate content = evaluate("plugins/vcs/svn/mailer.conf", templatevariables) filename = str((options.env_path() + 'conf') + 'mailer.py.conf') file(filename, 'w').writelines(content.encode('utf-8'))
def create(vcs_type, reposname, adminUser): from submin.models.repository import directory as repodir basedir = options.env_path('trac_dir') mkdirs(str(basedir)) tracenv = basedir + reposname projectname = reposname vcsdir = repodir(vcs_type, reposname) admin_command( tracenv, ['initenv', projectname, 'sqlite:db/trac.db', vcs_type, vcsdir]) admin_command(tracenv, ['permission', 'add', adminUser.name, "TRAC_ADMIN"]) components = [ 'tracopt.ticket.commit_updater.*', 'tracopt.versioncontrol.%s.*' % vcs_type ] for component in components: admin_command(tracenv, ['config', 'set', 'components', component, 'enabled']) admin_command(tracenv, ['config', 'set', 'header_logo', 'alt', 'Trac']) admin_command(tracenv, ['config', 'set', 'header_logo', 'height', '61']) admin_command(tracenv, [ 'config', 'set', 'header_logo', 'link', "%s/%s" % (options.value('base_url_trac'), reposname) ]) admin_command(tracenv, ['config', 'set', 'header_logo', 'src', 'trac_banner.png']) admin_command(tracenv, ['config', 'set', 'header_logo', 'width', '214']) admin_command( tracenv, ['config', 'set', 'project', 'descr', 'Repository %s' % reposname]) admin_command(tracenv, [ 'config', 'set', 'svn', 'authz_file', options.env_path('svn_authz_file') ]) admin_command(tracenv, ['config', 'set', 'svn', 'authz_module_name', reposname]) admin_command(tracenv, [ 'config', 'set', 'trac', 'authz_file', options.env_path('svn_authz_file') ]) permission_policies = admin_command( tracenv, ['config', 'get', 'trac', 'permission_policies']) admin_command(tracenv, [ 'config', 'set', 'trac', 'permission_policies', 'AuthzSourcePolicy,' + permission_policies ]) admin_command(tracenv, ['config', 'set', 'trac', 'repository_dir', vcsdir])
def setUp(self): self.submin_env = tempfile.mkdtemp(prefix='submin-unittest') self.conf_dir = os.path.join(self.submin_env, 'conf') os.mkdir(self.conf_dir) self.authz_file = os.path.join(self.submin_env, 'conf', 'authz') mock_settings.base_dir = self.submin_env storage.open(mock_settings) storage.database_evolve() options.set_value('vcs_plugins', 'svn') options.set_value('svn_dir', 'svn') options.set_value('trac_dir', 'trac') options.set_value('svn_authz_file', 'conf/authz') options.set_value('enabled_trac', 'no') options.set_value('http_vhost', 'localhost') options.set_value('base_url_submin', '/submin') self.svn_dir = str(options.env_path('svn_dir')) self.trac_dir = str(options.env_path('trac_dir')) os.mkdir(self.svn_dir) os.mkdir(self.trac_dir) # now make some repositories self.repositories = [ { 'name': 'foo', 'status': 'ok', 'vcs': 'svn' }, { 'name': 'invalidperm', 'status': 'permission denied', 'vcs': 'svn' }, { 'name': 'invalidperm2', 'status': 'permission denied', 'vcs': 'svn' }, { 'name': 'example', 'status': 'ok', 'vcs': 'svn' }, { 'name': 'subdirs', 'status': 'ok', 'vcs': 'svn' }, ] self.has_invalidperm = False self.has_invalidperm2 = False
def run(self): os.environ['SUBMIN_ENV'] = self.sa.env from submin.models import options if len(self.argv) < 1: self.sa.execute(['help', 'apacheconf']) return self.defaults = { 'type': 'all', } cgi_bin_dir = os.path.join(self.sa.env, 'cgi-bin') self.init_vars = { 'submin_env': self.canonicalize(self.sa.env), 'www_dir': self.canonicalize(str(self.sa.basedir_www)), 'cgi_bin_dir': self.canonicalize(str(cgi_bin_dir)), # Don't use options.url_path here, we need the url without # trailing slash. 'submin_base_url': self.urlpath(options.value('base_url_submin')), 'svn_base_url': self.urlpath(options.value('base_url_svn')), 'trac_base_url': self.urlpath(options.value('base_url_trac')), 'svn_dir': options.env_path('svn_dir'), 'trac_dir': options.env_path('trac_dir'), 'authz_file': options.env_path('svn_authz_file'), 'enabled_external': options.value('enabled_external', 'no') != 'no', 'external_server': options.value('external_server'), 'external_base_dn': options.value('external_base_dn'), 'external_group_dn': options.value('external_group_dn'), 'external_user': options.value('external_user'), 'external_passwd': options.value('external_passwd'), 'external_upn_suffix': options.value('external_upn_suffix'), } self.auth_type = options.value('auth_type') # variables depending on auth type if self.auth_type == "sql": pass elif options.value('auth_type') == "htaccess": self.init_vars.update({ 'access file': options.value('auth_access_file'), }) try: subcmd = getattr(self, 'subcmd_%s' % self.argv[0]) except AttributeError: self.sa.execute(['help', 'apacheconf']) return subcmd(self.argv[1:])
def export_notifications(**kwargs): """Export a mailer.py config file For each user/repository pair, a config group is created. Only if a user has read or read/write permission to one or multiple paths in that repository, _and_ if the user has notifications enabled for that repository, _and_ if the user has a non-empty email-address. Multiple paths are grouped together by a regexp group (multiple|paths)""" bindir = options.static_path("hooks") + 'svn' # get a list of all users from submin.models import user users = [user.User(name) for name in user.list(user.FakeAdminUser())] groups = [] for u in users: if not u.email: continue u_notif = u.notifications() for repos in u_notif: repos_path = str(options.env_path("svn_dir") + repos) if not u_notif[repos]["enabled"]: continue # strip leading / paths = [x[1:] for x in permissions.list_readable_user_paths(repos, "svn", u)] if len(paths) == 0: continue elif len(paths) == 1: for_paths = paths[0] elif len(paths) > 0: for_paths = "(" + "|".join(paths) + ")" # Only match complete path, not partial paths (ticket #257) repos_path_re = '^' + repos_path + '$' g = {"repos_name": repos, "for_repos": repos_path_re, "email": u.email, "for_paths": for_paths, "username": u.name} groups.append(g) email = options.value('commit_email_from', 'Please configure commit_email_from <*****@*****.**>') templatevariables = {"groups": groups, 'from_addr': email} from submin.template.shortcuts import evaluate content = evaluate("plugins/vcs/svn/mailer.conf", templatevariables) filename = str((options.env_path() + 'conf') + 'mailer.py.conf') file(filename, 'w').writelines(content.encode('utf-8'))
def diagnostics(): results = {} results['enabled_svn'] = 'svn' in options.value('vcs_plugins', '') if not results['enabled_svn']: results['enabled_svn_label'] = 'disabled' results['svn_all_label'] = 'disabled' return results try: svn_dir = options.env_path('svn_dir') except UnknownKeyError: results['svn_dir_set'] = False else: results['svn_dir_set'] = True found_mods = {} amods = [] required_mods = ['dav', 'dav_svn', 'authz_svn', 'authn_dbd', 'dbd'] try: amods = apache_modules() except ApacheCtlError as e: results['svn_apache_modules_ok'] = False results['svn_apache_modules_exec_ok'] = False results['svn_apache_modules_errmsg'] = str(e) else: results['svn_apache_modules_exec_ok'] = True for mod in required_mods: found_mods.update({mod: mod in amods}) results['svn_apache_modules'] = found_mods results['svn_apache_modules_ok'] = False not in found_mods.values() return add_labels(results, 'svn_all', warnings, fails)
def subcmd_fix(self, argv): from submin.models import options if os.getuid() != 0: print(''' To set permissions and ownerships properly, execute: sudo submin2-admin %s unixperms fix This should also remove possible following warnings. ''' % self.sa.env) self.root = False vcs_plugins = options.value("vcs_plugins") # git should be owned by the git user, let 'git fix_perms' handle it if 'git' in vcs_plugins.split(','): git_dir = options.env_path('git_dir') self.ignore_dirs.append(git_dir) if len(argv) > 0: self._fix(argv[0]) else: self._fix('') if 'git' in vcs_plugins.split(','): self.sa.execute(['git', 'fix_perms'])
def run(self): os.environ['SUBMIN_ENV'] = self.sa.env from submin.models import options if len(self.argv) < 1: self.sa.execute(['help', 'nginxconf']) return self.defaults = { 'output': options.env_path() + 'conf' + 'nginx.conf' } user = www_user() self.init_vars = { 'submin_env': self.canonicalize(str(self.sa.env)), 'www_dir': self.canonicalize(str(self.sa.basedir_www)), # Don't use options.url_path here, we need the url without # trailing slash. 'submin_base_url': self.urlpath(options.value('base_url_submin')), 'www_uid': user.pw_uid, 'www_gid': user.pw_gid, } self.init_vars['real_wsgi'] = os.path.realpath( os.path.join(self.init_vars['www_dir'], 'submin.wsgi')) try: subcmd = getattr(self, 'subcmd_%s' % self.argv[0]) except AttributeError: self.sa.execute(['help', 'nginxconf']) return subcmd(self.argv[1:])
def run(self): os.environ['SUBMIN_ENV'] = self.sa.env from submin.models import options if len(self.argv) < 1: self.sa.execute(['help', 'nginxconf']) return self.defaults = {'output': options.env_path() + 'conf' + 'nginx.conf'} user = www_user() self.init_vars = { 'submin_env': self.canonicalize(str(self.sa.env)), 'www_dir': self.canonicalize(str(self.sa.basedir_www)), # Don't use options.url_path here, we need the url without # trailing slash. 'submin_base_url': self.urlpath(options.value('base_url_submin')), 'www_uid': user.pw_uid, 'www_gid': user.pw_gid, } self.init_vars['real_wsgi'] = os.path.realpath( os.path.join(self.init_vars['www_dir'], 'submin.wsgi')) try: subcmd = getattr(self, 'subcmd_%s' % self.argv[0]) except AttributeError: self.sa.execute(['help', 'nginxconf']) return subcmd(self.argv[1:])
def setTracSyncHook(reponame, enable): prepare(reponame) hook_dir = repository.directory('git', reponame) + 'hooks' hook = hook_dir + 'post-receive.d' + '002-trac-sync.hook' try: os.unlink(hook) except OSError as e: if e.errno != errno.ENOENT: raise repository.PermissionError( "Removing trac-sync hook failed: %s" % (str(e), )) if not enable: return variables = { 'submin_env': str(options.env_path()), 'repository': reponame, 'hook_version': HOOK_VERSIONS['trac-sync'], } contents = evaluate('plugins/vcs/git/trac-sync', variables) with file(hook, 'w') as f: f.writelines(contents) os.chmod(hook, 0o755)
def export_authz(**kwargs): """Export authorization/authentication info""" # XXX the import here is to prevent a circular import :( design problem! from .repository import list as list_repos authz_filename = options.env_path("svn_authz_file") authz = codecs.open(str(authz_filename), "w+", "utf-8") # Write all groups authz.write("[groups]\n") for groupname in group.list(FakeAdminUser()): g = group.Group(groupname) authz.write("%s = %s\n" % (groupname, ', '.join(g.members()))) authz.write("\n") # Write all repositories and their permissions for repository in list_repos(): if repository["status"] != "ok": continue for path in permissions.list_paths(repository["name"], "svn"): authz.write("[%s:%s]\n" % (repository["name"], path)) for perm in permissions.list_by_path(repository["name"], "svn", path): if perm["type"] == "group": authz.write("@") authz.write("%s = %s\n" % (perm["name"], perm["permission"])) authz.write("\n") authz.close()
def setTracSyncHook(reponame, enable): prepare(reponame) hook_dir = repository.directory('git', reponame) + 'hooks' hook = hook_dir + 'post-receive.d' + '002-trac-sync.hook' try: os.unlink(hook) except OSError as e: if e.errno != errno.ENOENT: raise repository.PermissionError( "Removing trac-sync hook failed: %s" % (str(e),)) if not enable: return variables = { 'submin_env': str(options.env_path()), 'repository': reponame, 'hook_version': HOOK_VERSIONS['trac-sync'], } contents = evaluate('plugins/vcs/git/trac-sync', variables) with file(hook, 'w') as f: f.writelines(contents) os.chmod(hook, 0o755)
def run(self): from submin.models import options from submin.template.shortcuts import evaluate from submin.diagnostics import trac, git, svn, email localvars = {} diagnostics = {} if len(self.argv) > 0: which = self.argv[0] else: which = 'all' if which in ('all', 'email'): diagnostics.update(email.diagnostics()) if which in ('all', 'git'): diagnostics.update(git.diagnostics()) if which in ('all', 'svn'): diagnostics.update(svn.diagnostics()) if which in ('all', 'trac'): diagnostics.update(trac.diagnostics()) localvars['diag'] = diagnostics localvars['subminenv'] = options.env_path() formatted = evaluate('diagnostics.%s.print' % (which, ), localvars) print(formatted)
def subcmd_fix(self, argv): from submin.models import options if os.getuid() != 0: print ''' To set permissions and ownerships properly, execute: sudo submin2-admin %s unixperms fix This should also remove possible following warnings. ''' % self.sa.env self.root = False vcs_plugins = options.value("vcs_plugins") # git should be owned by the git user, let 'git fix_perms' handle it if 'git' in vcs_plugins.split(','): git_dir = options.env_path('git_dir') self.ignore_dirs.append(git_dir) if len(argv) > 0: self._fix(argv[0]) else: self._fix('') if 'git' in vcs_plugins.split(','): self.sa.execute(['git', 'fix_perms'])
def run(self): from submin.models import options from submin.template.shortcuts import evaluate from submin.diagnostics import trac, git, svn, email localvars = {} diagnostics = {} if len(self.argv) > 0: which = self.argv[0] else: which = 'all' if which in ('all', 'email'): diagnostics.update(email.diagnostics()) if which in ('all', 'git'): diagnostics.update(git.diagnostics()) if which in ('all', 'svn'): diagnostics.update(svn.diagnostics()) if which in ('all', 'trac'): diagnostics.update(trac.diagnostics()) localvars['diag'] = diagnostics localvars['subminenv'] = options.env_path() formatted = evaluate('diagnostics.%s.print' % (which,), localvars) print(formatted)
def dispatcher(request): # Add session information to request request.session = Session(request) # session expiry time is for cleanup purposes, not for security purposes future_expiry = int(time.time()) + 60 * 60 * 24 * 7 future_refresh = request.session.expires - 60 * 60 * 24 if time.time() >= future_refresh: request.session.expires = future_expiry path = request.path_info.strip('/').split('/') handlerName = 'handler' if path[0].lower() in classes: tupl = classes[path[0].lower()] cls = tupl[0](request, tupl[1]) if not hasattr(cls, handlerName): raise Exception("No handler %r found for view %r" % (handlerName, path[0].lower())) del path[0] handler = getattr(cls, handlerName) try: response = handler(request, path) if not issubclass(response.__class__, Response): raise Exception("Handler %r should return a Response instance" % handler) except UnknownKeyError as e: env = options.env_path() # this should never trigger another UnknownKeyError summary = "It seems your installation is missing a configuration option (%s)" % str(e) details = """ You can add the missing config option by executing the following commandline: submin2-admin %s config set %s <value> Unfortunately, this error handling does not know the value you should set, but the name of the missing option should give you a hint to its value :)""" % \ (env, str(e)) if not request.is_ajax(): response = ErrorResponse(summary, request=request, details=details) else: details = summary + '\n\n' + details response = XMLStatusResponse('', False, details) except Exception as e: import traceback details = traceback.format_exc() if not request.is_ajax(): response = ErrorResponse(str(e), request=request, details=details) else: response = XMLStatusResponse('', False, str(e), details=details) else: response = HTTP404('/'.join(path)) response.setCookieHeaders(request.cookieHeaders()) return response
def subcmd_init(self, argv): from submin.models import options from submin.subminadmin import trac """Initialize trac Why not just distribute them with submin? Two reasons: one is because they might change with each version of trac, two is because those scripts have a different license and IANAL so this is easier (reason one should be enough anyway). """ tmp_trac_dir = options.env_path() + 'tmp-trac' tmp_deploy_dir = tmp_trac_dir + 'deploy' if not trac.exists(): print( "Could not find 'trac-admin' command. If you want to use Trac, please" ), print("install trac and run: `submin2-admin %s trac init`" % options.env_path()) return print( 'Initializing trac files. This might take a while, please wait ...' ) # first, create a temp trac env, because 'deploy' needs a working trac # env (sigh) trac.initenv(str(tmp_trac_dir), 'dummy', 'svn', '/tmp/non-existing') # then generate the scripts trac.deploy(str(tmp_trac_dir), str(tmp_deploy_dir)) # copy them to our cgi-bin cgi_bin_dir = options.env_path() + 'cgi-bin' for root, dirs, files in os.walk(str(tmp_deploy_dir + 'cgi-bin')): for filename in files: src = os.path.join(root, filename) dst = os.path.join(str(cgi_bin_dir), filename) self.generate_Xgi_script(src, dst) # ... and remove the temporary trac env shutil.rmtree(str(tmp_trac_dir)) # finally, set all permissions and ownerships self.sa.execute(['unixperms', 'fix']) print('Done.') return
def rewritePostCommitHook(self, signature, new_hook, enable): reposdir = options.env_path('svn_dir') hook = reposdir + self.name + 'hooks' + 'post-commit' shellscript.rewriteWithSignature(hook, signature, new_hook, enable, mode=0o755)
def setUp(self): self.submin_env = tempfile.mkdtemp(prefix='submin-unittest') self.conf_dir = os.path.join(self.submin_env, 'conf') os.mkdir(self.conf_dir) mock_settings.base_dir = self.submin_env storage.open(mock_settings) storage.database_evolve() options.set_value('vcs_plugins', 'svn') options.set_value('svn_dir', 'svn') options.set_value('trac_dir', 'trac') options.set_value('svn_authz_file', 'conf/authz') options.set_value('enabled_trac', 'yes') self.svn_dir = str(options.env_path('svn_dir')) self.trac_dir = str(options.env_path('trac_dir')) os.mkdir(self.svn_dir) os.mkdir(self.trac_dir)
def directory(reposname): # FIXME: encoding? base_dir = options.env_path('svn_dir') reposdir = base_dir + reposname # We could use realpath to check, but we don't want to prevent usage of # symlinks in their svn directory if not os.path.normpath(reposdir).startswith(os.path.normpath(base_dir)): raise Exception('Subversion directory outside base path'); return reposdir
def _repositoriesOnDisk(): reposdir = options.env_path('mock_dir', default="mock") reps = glob.glob(str(reposdir + '*.mock')) repositories = [] for rep in reps: if os.path.isdir(rep): name = rep[rep.rfind('/') + 1:] repositories.append(unicode(name, 'utf-8')) return repositories
def add(name): """Create a new repository with name *name*""" if not name.endswith(".mock"): name += ".mock" reposdir = options.env_path('mock_dir', default='mock') + name if os.path.exists(str(reposdir)): raise PermissionError("Could not create %s, already exists." % name) mkdirs(reposdir)
def add(name): reposdir = options.env_path('svn_dir') newrepos = reposdir + name path = options.value('env_path', "/bin:/usr/bin:/usr/local/bin:/opt/local/bin") cmd = "PATH='%s' svnadmin create '%s'" % (path, str(newrepos)) (exitstatus, outtext) = subprocess.getstatusoutput(cmd) if exitstatus != 0: raise PermissionError("External command 'svnadmin' failed: %s" % outtext) repos = Repository(name)
def remove(self): reposdir = options.env_path('svn_dir') newrepos = reposdir + self.name if not newrepos.absolute: raise Exception("Error, repository path is relative, this should be fixed") cmd = 'rm -rf "%s"' % newrepos (exitstatus, outtext) = subprocess.getstatusoutput(cmd) if exitstatus != 0: raise Exception("could not remove repository %s" % self.name)
def add(name): reposdir = options.env_path('svn_dir') newrepos = reposdir + name path = options.value('env_path', "/bin:/usr/bin:/usr/local/bin:/opt/local/bin") cmd = "PATH='%s' svnadmin create '%s'" % (path, str(newrepos)) (exitstatus, outtext) = commands.getstatusoutput(cmd) if exitstatus != 0: raise PermissionError("External command 'svnadmin' failed: %s" % outtext) repos = Repository(name)
def remove_system_hooks(self): from submin.models import options env_event_dir = options.env_path() + "hooks" for script in glob.glob(str(env_event_dir + "*/[3-6]*")): try: os.unlink(script) except OSError as e: print "updating hook %s failed, do you have permissions?" % script raise e
def remove(self): reposdir = options.env_path('svn_dir') newrepos = reposdir + self.name if not newrepos.absolute: raise Exception("Error, repository path is relative, this should be fixed") cmd = 'rm -rf "%s"' % newrepos (exitstatus, outtext) = commands.getstatusoutput(cmd) if exitstatus != 0: raise Exception("could not remove repository %s" % self.name)
def copy_system_hooks(self, event_dir): from submin.models import options sys_event_dir = options.static_path("hooks") + "submin" + event_dir env_event_dir = options.env_path() + "hooks" + event_dir for script in glob.glob(str(sys_event_dir + "[3-6]*")): try: shutil.copy(script, str(env_event_dir)) except IOError as e: print "updating hook %s failed, do you have permissions?" % script
def run(self): os.environ['SUBMIN_ENV'] = self.sa.env from submin.models import options if len(self.argv) < 1: self.sa.execute(['help', 'apacheconf']) return self.defaults = { 'type': 'all', } cgi_bin_dir = os.path.join(self.sa.env, 'cgi-bin') self.init_vars = { 'submin_env': self.canonicalize(self.sa.env), 'www_dir': self.canonicalize(str(self.sa.basedir_www)), 'cgi_bin_dir': self.canonicalize(str(cgi_bin_dir)), # Don't use options.url_path here, we need the url without # trailing slash. 'submin_base_url': self.urlpath(options.value('base_url_submin')), 'svn_base_url': self.urlpath(options.value('base_url_svn')), 'trac_base_url': self.urlpath(options.value('base_url_trac')), 'svn_dir': options.env_path('svn_dir'), 'trac_dir': options.env_path('trac_dir'), 'authz_file': options.env_path('svn_authz_file'), } self.auth_type = options.value('auth_type') # variables depending on auth type if self.auth_type == "sql": pass elif options.value('auth_type') == "htaccess": self.init_vars.update({ 'access file': options.value('auth_access_file'), }) try: subcmd = getattr(self, 'subcmd_%s' % self.argv[0]) except AttributeError: self.sa.execute(['help', 'apacheconf']) return subcmd(self.argv[1:])
def _repositoriesOnDisk(): """Returns all repositories that are found on disk""" import glob, os.path reposdir = options.env_path('svn_dir') reps = glob.glob(str(reposdir + '*')) repositories = [] for rep in reps: if os.path.isdir(rep): repositories.append(rep[rep.rfind('/') + 1:]) return repositories
def _repositoriesOnDisk(): reposdir = options.env_path('git_dir') reps = glob.glob(str(reposdir + '*.git')) repositories = [] for rep in reps: if os.path.isdir(rep): name = rep[rep.rfind('/') + 1:] name = name[:-4] # chop off '.git' repositories.append(unicode(name, 'utf-8')) return repositories
def remove_system_hooks(self): from submin.models import options env_event_dir = options.env_path() + "hooks" for script in glob.glob(str(env_event_dir + "*/[3-6]*")): try: os.unlink(script) except OSError as e: print 'updating hook %s failed, do you have permissions?' % \ script raise e
def copy_system_hooks(self, event_dir): from submin.models import options sys_event_dir = options.static_path("hooks") + "submin" + event_dir env_event_dir = options.env_path() + "hooks" + event_dir for script in glob.glob(str(sys_event_dir + "[3-6]*")): try: shutil.copy(script, str(env_event_dir)) except IOError as e: print 'updating hook %s failed, do you have permissions?' % \ script
def enableTracCommitHook(self, enable): """Add or remove trac commit script to/from the post-commit hook""" import os bindir = options.static_path('hooks') + 'svn' fullpath = str(bindir + 'trac-post-commit-hook') trac_env = str(options.env_path('trac_dir') + self.name) new_hook = '/usr/bin/python %s -p %s -r "$2"\n' % \ (fullpath, trac_env) self.rewritePostCommitHook(self.trac_signature, new_hook, enable)
def _repositoriesOnDisk(): """Returns all repositories that are found on disk""" import glob, os.path reposdir = options.env_path('svn_dir') repositories = [] if not os.path.lexists(reposdir): return [] for rep in os.listdir(reposdir): if os.path.isdir((reposdir + rep).encode('utf-8')): repositories.append(rep) return repositories
def subcmd_init(self, argv): from submin.models import options from submin.subminadmin import trac """Initialize trac Why not just distribute them with submin? Two reasons: one is because they might change with each version of trac, two is because those scripts have a different license and IANAL so this is easier (reason one should be enough anyway). """ tmp_trac_dir = options.env_path() + 'tmp-trac' tmp_deploy_dir = tmp_trac_dir + 'deploy' if not trac.exists(): print "Could not find 'trac-admin' command. If you want to use Trac, please", print "install trac and run: `submin2-admin %s trac init`" % options.env_path() return print 'Initializing trac files. This might take a while, please wait ...' # first, create a temp trac env, because 'deploy' needs a working trac # env (sigh) trac.initenv(str(tmp_trac_dir), 'dummy', 'svn', '/tmp/non-existing') # then generate the scripts trac.deploy(str(tmp_trac_dir), str(tmp_deploy_dir)) # copy them to our cgi-bin cgi_bin_dir = options.env_path() + 'cgi-bin' for root, dirs, files in os.walk(str(tmp_deploy_dir + 'cgi-bin')): for filename in files: src = os.path.join(root, filename) dst = os.path.join(str(cgi_bin_dir), filename) self.generate_Xgi_script(src, dst) # ... and remove the temporary trac env shutil.rmtree(str(tmp_trac_dir)) # finally, set all permissions and ownerships self.sa.execute(['unixperms', 'fix']) print 'Done.' return
def diagnostics(): results = {} results['enabled_git'] = 'git' in options.value('vcs_plugins', '') if not results['enabled_git']: results['enabled_git_label'] = 'disabled' results['git_all_label'] = 'disabled' return results try: git_dir = options.env_path('git_dir') except UnknownKeyError: results['git_dir_set'] = False results['git_hooks_all_new'] = True # because no repositories results['git_old_hook_repos'] = [] else: results['git_dir_set'] = True old_repos = list(old_hook_repos(git_dir)) results['git_hooks_all_new'] = len(old_repos) == 0 results['git_old_hook_repos'] = old_repos # check dirs for correct permissions bad_dirs = git_repos_wrong_perms(git_dir) results['git_repos_correct_perms'] = len(bad_dirs) == 0 results['git_repos_bad_dirs'] = bad_dirs try: git_ssh_host = options.value('git_ssh_host') except UnknownKeyError: results['git_hostname_ok'] = False else: results['git_hostname_ok'] = True if git_ssh_host in ('localhost', '127.0.0.1', '::1'): results['git_hostname_ok'] = False try: remote.execute("update-auth") except (remote.NonZeroExitStatus, UnknownKeyError) as e: results['git_admin_test'] = False results['git_admin_test_errmsg'] = str(e) results['git_ssh_host_internal'] = options.value( 'git_ssh_host_internal', 'git_ssh_host_internal') results['git_user'] = options.value('git_user', 'git_user') results['git_ssh_port'] = options.value('git_ssh_port', 'git_ssh_port') else: results['git_admin_test'] = True wrong_perms = git_dir_wrong_perms() results['git_dir_perms_wrong'] = wrong_perms results['git_dir_perms'] = len(wrong_perms) == 0 return add_labels(results, 'git_all', warnings, fails)
def handler(self, req, path): localvars = {} diagnostics = {} diagnostics.update(trac.diagnostics()) diagnostics.update(svn.diagnostics()) diagnostics.update(git.diagnostics()) diagnostics.update(email.diagnostics()) localvars['diag'] = diagnostics localvars['subminenv'] = options.env_path() formatted = evaluate_main('diagnostics.html', localvars, request=req) return Response(formatted)
def diagnostics(): results = {} results["enabled_git"] = "git" in options.value("vcs_plugins", "") if not results["enabled_git"]: results["enabled_git_label"] = "disabled" results["git_all_label"] = "disabled" return results try: git_dir = options.env_path("git_dir") except UnknownKeyError: results["git_dir_set"] = False results["git_hooks_all_new"] = True # because no repositories results["git_old_hook_repos"] = [] else: results["git_dir_set"] = True old_repos = list(old_hook_repos(git_dir)) results["git_hooks_all_new"] = len(old_repos) == 0 results["git_old_hook_repos"] = old_repos # check dirs for correct permissions bad_dirs = git_repos_wrong_perms(git_dir) results["git_repos_correct_perms"] = len(bad_dirs) == 0 results["git_repos_bad_dirs"] = bad_dirs try: git_ssh_host = options.value("git_ssh_host") except UnknownKeyError: results["git_hostname_ok"] = False else: results["git_hostname_ok"] = True if git_ssh_host in ("localhost", "127.0.0.1", "::1"): results["git_hostname_ok"] = False try: remote.execute("update-auth") except (remote.NonZeroExitStatus, UnknownKeyError) as e: results["git_admin_test"] = False results["git_admin_test_errmsg"] = str(e) results["git_ssh_host_internal"] = options.value("git_ssh_host_internal", "git_ssh_host_internal") results["git_user"] = options.value("git_user", "git_user") results["git_ssh_port"] = options.value("git_ssh_port", "git_ssh_port") else: results["git_admin_test"] = True wrong_perms = git_dir_wrong_perms() results["git_dir_perms_wrong"] = wrong_perms results["git_dir_perms"] = len(wrong_perms) == 0 return add_labels(results, "git_all", warnings, fails)
def execute(remote_command): ssh_key_path = options.env_path() + 'conf' + 'id_dsa' # The options provided with the -o flags are to prevent ssh trying to # create a '.ssh' directory in the homedir of the www user. cmd = 'ssh -i "%s" %s@%s -p %s -o "StrictHostKeyChecking=no"' cmd += ' -o "PreferredAuthentications=publickey"' cmd += ' -o "UserKnownHostsFile=/dev/null" %s' (exitstatus, outtext) = commands.getstatusoutput(cmd % (ssh_key_path, options.value("git_user"), options.value("git_ssh_host_internal"), options.value("git_ssh_port"), remote_command)) if exitstatus != 0: raise NonZeroExitStatus(outtext)
def export_htpasswd(*args, **kwargs): try: htpasswd_file = options.env_path("htpasswd_file") except UnknownKeyError: return if not os.path.exists(htpasswd_file.dirname()): return with open(htpasswd_file, "w+") as htpasswd: for username in user.list(FakeAdminUser()): u = user.User(username) htpasswd.write("%s:%s\n" % (username, u.get_password_hash())) os.chmod(htpasswd_file, 0o600)
def __init__(self, name): self.name = name if not self.name.endswith(".mock"): self.name += ".mock" reposdir = options.env_path('mock_dir', default='mock') self.dir = reposdir + self.name self.url = str(reposdir + self.name) if not os.path.exists(str(self.dir)): raise DoesNotExistError(str(self.dir)) self.initialized = False self.dirs = self.branches() self.initialized = True
def enableCommitEmails(self, enable): """Add or remove our script to/from the post-commit hook""" import os bindir = options.static_path('hooks') + 'svn' fullpath = str(bindir + 'mailer.py') base_env = options.env_path() mailer_conf = str((base_env + 'conf') + 'mailer.py.conf') if not os.path.exists(mailer_conf): export_notifications() # create mailer_conf new_hook = '/usr/bin/python %s commit "$1" "$2" "%s"\n' % \ (fullpath, mailer_conf) self.rewritePostCommitHook(self.svn_signature, new_hook, enable)