def listGroupUsers(self, req, g): members = list(g.members()) asking_user = user.User(req.session['user']['name']) if asking_user.is_admin: nonmembers = [] usernames = user.list(asking_user) for username in usernames: if username not in members: nonmembers.append(username) return XMLTemplateResponse("ajax/groupmembers.xml", { "members": members, "nonmembers": nonmembers, "group": g.name }) if asking_user.name not in g.members(): return XMLStatusResponse( 'listGroupUsers', False, "You do not have permission to view this group.") return XMLTemplateResponse("ajax/groupmembers.xml", { "members": members, "nonmembers": [], "group": g.name })
def testRemoveUser(self): mock_user = Mock() mock_user.is_admin = True user.add("foo", email="[email protected]", password="******") foo = user.User("foo") foo.remove() self.assert_("foo" not in [x for x in user.list(mock_user)])
def testListUsersNonAdmin(self): mock_user = Mock() mock_user.is_admin = False mock_user.name = "foo" user.add("foo", email="[email protected]", password="******") users = sorted([x for x in user.list(mock_user)]) self.assertEquals(users, ["foo"])
def listUsers(self, req): session_user = user.User(req.session['user']['name']) try: usernames = user.list(session_user) return XMLTemplateResponse("ajax/listusers.xml", {'usernames': usernames}) except Exception as e: return XMLStatusResponse('listUsers', False, 'Failed to get a list: %s' % e)
def getpermissions(self, req, repos): session_user = req.session['user'] asking_user = user.User(session_user['name']) path = req.post.get('getPermissions') branch_or_path = Path(path) if not repos.has_path_permissions: branch_or_path = branch_or_path.lstrip('/') perms = permissions.list_by_path(repos.name, repos.vcs_type, path) usernames = [] if 'userlist' in req.post: usernames = user.list(asking_user) groupnames = [] if 'grouplist' in req.post: groupnames = group.list(asking_user) templatevars = { 'perms': perms, 'repository': repos.name, 'path': branch_or_path, 'usernames': usernames, 'groupnames': groupnames } return XMLTemplateResponse('ajax/repositoryperms.xml', templatevars)
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 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 external_sync(): """Synchronizes external users""" from submin.models import user errormsgs = [] if options.value('enabled_external', 'no') == 'no': errormsgs.append('external is not enabled') return {'errormsgs': errormsgs, 'success': False} group = LDAPGroup(options.value('external_passwd'), options.value('external_user')) if not group: errormsgs.append('cannot connect to LDAP server') return {'errormsgs': errormsgs, 'success': False} group_members = group.members if not group_members: errormsgs.append('cannot find LDAP group or its members') return {'errormsgs': errormsgs, 'success': False} user_list = user.list(user.FakeAdminUser()) for username in group_members: email = group_members[username]['email'] fullname = group_members[username]['fullname'] if not validate_username(username): errormsgs.append(InvalidUsername(username)) continue if not validate_email(email): errormsgs.append(InvalidEmail(email)) continue if not validate_fullname(fullname): errormsgs.append(InvalidFullname(fullname)) fullname = username if username not in user_list: # A new user user.add(username=username, email=email, send_mail=False) user.User(username).fullname = fullname else: u = user.User(username) # Update fullname and email if necessary if (u.email, u.fullname) != (email, fullname): u.email = email u.fullname = fullname return {'errormsgs': errormsgs, 'success': True}
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 run(): env_path = options.env_path() filename = os.path.expanduser("~/.ssh/authorized_keys") filename = options.value("git_dev_authorized_keysfile", filename) if not os.path.exists(os.path.dirname(filename)): try: # create dir and file if one of them doesn't exist os.mkdir(os.path.dirname(filename)) open(filename, 'a') except OSError as e: if e.errno != errno.EACCES: raise raise Exception( 'Could not write "%s", please check that git user can write it.' % filename) # Make the authorized_keys file only readable to the git-user gituser = options.value("git_user") owner = getpwnam(gituser) os.chown(os.path.dirname(filename), owner.pw_uid, owner.pw_gid) os.chmod(filename, 0o600) www_key_file = env_path + "conf" + "id_dsa.pub" if not www_key_file.exists(): raise Exception( "Could not find the submin ssh-key. Please run submin2-admin git init" ) key_fp = open(str(www_key_file)) www_key = key_fp.readline().strip() key_fp.close() # instead of writing ascii, write utf-8 encoding fp = codecs.open(str(filename), "a+", 'utf-8') env_vars = "PATH='%s' PYTHONPATH='%s'" % \ (options.value("env_path"), ':'.join(sys.path)) fp.write('command="%s submin2-admin \'%s\' git admin" %s\n' % \ (env_vars, env_path, www_key)) userlist = user.list(user.FakeAdminUser()) for x in userlist: u = user.User(x) ssh_keys = u.ssh_keys() if not ssh_keys: continue for ssh_key in ssh_keys: fp.write('command="%s submin2-admin \'%s\' git user %s" %s\n' % \ (env_vars, env_path, u, ssh_key["key"])) fp.close()
def run(reposname): failed, succeeded = [], [] errors = [] if reposname: repositories = [reposname] else: # even though we might know the username, it we can't filter on # username, as permissions might be revoked from a repository # and it won't show up if we use Repositor.list() (because it is # revoked). So regenerate for all repositories repositories = [ x['name'] for x in repository.Repository.list_all() if x['vcs'] == 'git' ] # get a list of all users + their notifications as tuples: (u, n) # We get the notifications straight away, otherwise we have to # call it user * repositories times, and the u.notifications() # function can be heavy on the database if called that many times # (for a couple of users and 36 repositories, database was hit # almost 3000 times during profiling) user_notifications = [] for name in user.list(user.FakeAdminUser()): u = user.User(name) if not u.email: # user without emails cannot be notified continue n = u.notifications() user_notifications.append((u, n)) for reposname in repositories: try: update_notification(reposname, user_notifications) except SetGitConfigError as e: errors.append(str(e)) failed.append(reposname) else: succeeded.append(reposname) if len(failed) > 0: total = len(failed) + len(succeeded) msg = "Some repositories failed to update: %s. (%s/%s)" % ( ','.join(failed), len(failed), total) raise UpdateFailed(msg)
def run(): env_path = options.env_path() filename = os.path.expanduser("~/.ssh/authorized_keys") filename = options.value("git_dev_authorized_keysfile", filename) if not os.path.exists(os.path.dirname(filename)): try: # create dir and file if one of them doesn't exist os.mkdir(os.path.dirname(filename)) file(filename, 'a') except OSError as e: if e.errno != errno.EACCES: raise raise Exception('Could not write "%s", please check that git user can write it.' % filename) # Make the authorized_keys file only readable to the git-user gituser = options.value("git_user") owner = getpwnam(gituser) os.chown(os.path.dirname(filename), owner.pw_uid, owner.pw_gid) os.chmod(filename, 0o600) www_key_file = env_path + "conf" + "id_dsa.pub" if not www_key_file.exists(): raise Exception("Could not find the submin ssh-key. Please run submin2-admin git init") key_fp = open(str(www_key_file)) www_key = key_fp.readline().strip() key_fp.close() # instead of writing ascii, write utf-8 encoding fp = codecs.open(str(filename), "w+", 'utf-8') env_vars = "PATH='%s' PYTHONPATH='%s'" % \ (options.value("env_path"), ':'.join(sys.path)) fp.write('command="%s submin2-admin \'%s\' git admin" %s\n' % \ (env_vars, env_path, www_key)) userlist = user.list(user.FakeAdminUser()) for x in userlist: u = user.User(x) ssh_keys = u.ssh_keys() if not ssh_keys: continue for ssh_key in ssh_keys: fp.write('command="%s submin2-admin \'%s\' git user %s" %s\n' % \ (env_vars, env_path, u, ssh_key["key"])) fp.close()
def run(reposname): failed, succeeded = [], [] errors = [] if reposname: repositories = [reposname] else: # even though we might know the username, it we can't filter on # username, as permissions might be revoked from a repository # and it won't show up if we use Repositor.list() (because it is # revoked). So regenerate for all repositories repositories = [x['name'] for x in repository.Repository.list_all() if x['vcs'] == 'git'] # get a list of all users + their notifications as tuples: (u, n) # We get the notifications straight away, otherwise we have to # call it user * repositories times, and the u.notifications() # function can be heavy on the database if called that many times # (for a couple of users and 36 repositories, database was hit # almost 3000 times during profiling) user_notifications = [] for name in user.list(user.FakeAdminUser()): u = user.User(name) if not u.email: # user without emails cannot be notified continue n = u.notifications() user_notifications.append((u, n)) for reposname in repositories: try: update_notification(reposname, user_notifications) except SetGitConfigError as e: errors.append(str(e)) failed.append(reposname) else: succeeded.append(reposname) if len(failed) > 0: total = len(failed) + len(succeeded) msg = "Some repositories failed to update: %s. (%s/%s)" % ( ','.join(failed), len(failed), total) raise UpdateFailed(msg)
def listGroupUsers(self, req, g): members = list(g.members()) asking_user = user.User(req.session['user']['name']) if asking_user.is_admin: nonmembers = [] usernames = user.list(asking_user) for username in usernames: if username not in members: nonmembers.append(username) return XMLTemplateResponse("ajax/groupmembers.xml", {"members": members, "nonmembers": nonmembers, "group": g.name}) if asking_user.name not in g.members(): return XMLStatusResponse('listGroupUsers', False, "You do not have permission to view this group.") return XMLTemplateResponse("ajax/groupmembers.xml", {"members": members, "nonmembers": [], "group": g.name})
def main(): from sys import argv, path import os path.append('_SUBMIN_LIB_DIR_') interpreter = "perl" scriptname = 'commit-email.pl' scriptdir = os.path.dirname(argv[0]) env = 'SUBMIN_LIB_DIR' if env in os.environ: path.append(os.environ[env]) if len(argv) < 4: print "Usage: %s <configfile> <repository path> <revision>" % argv[0] return os.environ['SUBMIN_ENV'] = argv[1] repospath = argv[2] rev = argv[3] from submin.models import storage storage.open() from submin.models import options bindir = options.static_path("hooks") + 'svn' from submin.models import user userlist = [user.User(name) for name in user.list(user.FakeAdminUser())] n = buildNotifications(userlist) repos = os.path.basename(repospath) if repos not in n: print "no such repository" return mailer = bindir + scriptname for email in n[repos]: os.system("%s %s '%s' '%s' -s '[%s]' '%s'" % (interpreter, mailer, repospath, rev, repos, email))
def getpermissions(self, req, repos): session_user = req.session['user'] asking_user = user.User(session_user['name']) path = req.post.get('getPermissions') branch_or_path = Path(path) if not repos.has_path_permissions: branch_or_path = branch_or_path.lstrip('/') perms = permissions.list_by_path(repos.name, repos.vcs_type, path) usernames = [] if 'userlist' in req.post: usernames = user.list(asking_user) groupnames = [] if 'grouplist' in req.post: groupnames = group.list(asking_user) templatevars = {'perms': perms, 'repository': repos.name, 'path': branch_or_path, 'usernames': usernames, 'groupnames': groupnames} return XMLTemplateResponse('ajax/repositoryperms.xml', templatevars)
def testListUsersAdmin(self): mock_user = Mock() mock_user.is_admin = True user.add("foo", email="[email protected]", password="******") users = sorted([x for x in user.list(mock_user)]) self.assertEquals(users, ["foo", "test"])