|
|
|
@ -50,24 +50,24 @@ def delete_password(name, length=10):
@@ -50,24 +50,24 @@ def delete_password(name, length=10):
|
|
|
|
|
# so redirect this to /dev/null |
|
|
|
|
with open(os.devnull, 'wb') as devnull: |
|
|
|
|
subprocess.check_call(["htpasswd", "-D", HTPWD_PATH, name], stderr=devnull) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# class definitions |
|
|
|
|
class User(object): |
|
|
|
|
""" Collect the username, group and access control lists """ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, name, group): |
|
|
|
|
""" initialization of the class """ |
|
|
|
|
self.name = name |
|
|
|
|
self.group = group |
|
|
|
|
self.write_acl = [] |
|
|
|
|
self.read_acl = [] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __str__(self): |
|
|
|
|
""" return a string representation """ |
|
|
|
|
return self.name |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
|
""" return a string representation of the object """ |
|
|
|
|
return "<User '%s@%s'>" % (self.name, self.group) |
|
|
|
@ -79,12 +79,17 @@ class AuthzConfigParser(ConfigParser.ConfigParser, object):
@@ -79,12 +79,17 @@ class AuthzConfigParser(ConfigParser.ConfigParser, object):
|
|
|
|
|
def __init__(self): |
|
|
|
|
""" initialization of the class """ |
|
|
|
|
self.users = None |
|
|
|
|
self._acl_defaults = { WRITE_ACL: [], READ_ACL: [] } |
|
|
|
|
super(AuthzConfigParser, self).__init__() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def optionxform(self, value): |
|
|
|
|
""" reset the method to use cases ensitive names """ |
|
|
|
|
return str(value) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def read(self, path): |
|
|
|
|
super(AuthzConfigParser, self).read(path) |
|
|
|
|
self._acl_defaults = self.get_folder_info("") |
|
|
|
|
|
|
|
|
|
def extract_users(self): |
|
|
|
|
""" extract user information from config """ |
|
|
|
|
users = dict() |
|
|
|
@ -96,7 +101,7 @@ class AuthzConfigParser(ConfigParser.ConfigParser, object):
@@ -96,7 +101,7 @@ class AuthzConfigParser(ConfigParser.ConfigParser, object):
|
|
|
|
|
raise Exception("Found duplicate entry for user " + username) |
|
|
|
|
user = User(username, group) |
|
|
|
|
users[username] = user |
|
|
|
|
# second we scan each section that is related to an svn folder (it |
|
|
|
|
# second we scan each section that is related to an svn folder (it |
|
|
|
|
# starts with the svn base) for read and write access user entries |
|
|
|
|
for section in self.sections(): |
|
|
|
|
if section.startswith(SVN_BASE): |
|
|
|
@ -116,12 +121,16 @@ class AuthzConfigParser(ConfigParser.ConfigParser, object):
@@ -116,12 +121,16 @@ class AuthzConfigParser(ConfigParser.ConfigParser, object):
|
|
|
|
|
name = SVN_BASE + name |
|
|
|
|
if not self.has_section(name): |
|
|
|
|
return None |
|
|
|
|
info = { WRITE_ACL: [], READ_ACL: [] } |
|
|
|
|
info = self._acl_defaults.copy() |
|
|
|
|
for (option, value) in self.items(name): |
|
|
|
|
if value in (WRITE_ACL, READ_ACL): |
|
|
|
|
info[value].append(option) |
|
|
|
|
if not value: |
|
|
|
|
for acltype in (WRITE_ACL, READ_ACL): |
|
|
|
|
if option in info[acltype]: |
|
|
|
|
info[acltype].remove(option) |
|
|
|
|
return info |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def move_user_to_alumni(self, user): |
|
|
|
|
""" moves a user to the alumni group and removes every access rights """ |
|
|
|
|
for access_to in user.write_acl: |
|
|
|
@ -134,7 +143,7 @@ class AuthzConfigParser(ConfigParser.ConfigParser, object):
@@ -134,7 +143,7 @@ class AuthzConfigParser(ConfigParser.ConfigParser, object):
|
|
|
|
|
user.read_acl = [] |
|
|
|
|
user.group = ALUMNI |
|
|
|
|
delete_password(user.name) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_user_groups(self, users): |
|
|
|
|
""" updates the config settings of the groups section """ |
|
|
|
|
groups = group_users(users) |
|
|
|
@ -147,7 +156,7 @@ class AuthzConfigParser(ConfigParser.ConfigParser, object):
@@ -147,7 +156,7 @@ class AuthzConfigParser(ConfigParser.ConfigParser, object):
|
|
|
|
|
|
|
|
|
|
def write(self, fp): |
|
|
|
|
"""Write an .ini-format representation of the configuration state. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this is adapted from the original library file. changes: |
|
|
|
|
- no default section |
|
|
|
|
- group-section at top |
|
|
|
@ -165,7 +174,7 @@ class AuthzConfigParser(ConfigParser.ConfigParser, object):
@@ -165,7 +174,7 @@ class AuthzConfigParser(ConfigParser.ConfigParser, object):
|
|
|
|
|
key = " = ".join((key, str(value).replace('\n', '\n\t'))) |
|
|
|
|
fp.write("%s\n" % (key)) |
|
|
|
|
fp.write("\n") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
# create configparser instance |
|
|
|
@ -175,30 +184,30 @@ if __name__ == "__main__":
@@ -175,30 +184,30 @@ if __name__ == "__main__":
|
|
|
|
|
# read config file |
|
|
|
|
config.read(AUTHZ_PATH) |
|
|
|
|
users = config.extract_users() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# command line interface: |
|
|
|
|
# no option: display info |
|
|
|
|
# -g display users in a group |
|
|
|
|
# -a add regular user |
|
|
|
|
# -r add restricted user |
|
|
|
|
# -m move to alumni |
|
|
|
|
# -p reset user password |
|
|
|
|
# -p reset user password |
|
|
|
|
parser = optparse.OptionParser( |
|
|
|
|
usage="usage: %prog [option] name", |
|
|
|
|
description="shows and manipulates svn access rights", |
|
|
|
|
epilog="to grant a restricted user access to another folder, you have to carefully edit the authz file") |
|
|
|
|
parser.add_option("-g", "--groupinfo", action="store_const", dest="what", |
|
|
|
|
parser.add_option("-g", "--groupinfo", action="store_const", dest="what", |
|
|
|
|
const="g", help="display users in a group") |
|
|
|
|
parser.add_option("-a", "--add", action="store_const", dest="what", |
|
|
|
|
parser.add_option("-a", "--add", action="store_const", dest="what", |
|
|
|
|
const="a", help="add a regular user") |
|
|
|
|
parser.add_option("-r", "--restricted", action="store_const", dest="what", |
|
|
|
|
parser.add_option("-r", "--restricted", action="store_const", dest="what", |
|
|
|
|
const="r", help="add a restricted user") |
|
|
|
|
parser.add_option("-m", "--move", action="store_const", dest="what", |
|
|
|
|
parser.add_option("-m", "--move", action="store_const", dest="what", |
|
|
|
|
const="m", help="move a user to alumni") |
|
|
|
|
parser.add_option("-p", "--password", action="store_const", dest="what", |
|
|
|
|
parser.add_option("-p", "--password", action="store_const", dest="what", |
|
|
|
|
const="p", help="reset a user password") |
|
|
|
|
options, args = parser.parse_args() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(args)==0: |
|
|
|
|
# no arguments? then display all the users! |
|
|
|
|
groups = group_users(users) |
|
|
|
@ -207,12 +216,12 @@ if __name__ == "__main__":
@@ -207,12 +216,12 @@ if __name__ == "__main__":
|
|
|
|
|
for name in sorted(usernames): |
|
|
|
|
print " " + name |
|
|
|
|
sys.exit() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(args)>1: |
|
|
|
|
# more than one usename? not here, john boy |
|
|
|
|
sys.exit("please provide only one name") |
|
|
|
|
name = args[0] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if options.what == "g": |
|
|
|
|
# show group information |
|
|
|
|
groups = group_users(users) |
|
|
|
@ -222,7 +231,7 @@ if __name__ == "__main__":
@@ -222,7 +231,7 @@ if __name__ == "__main__":
|
|
|
|
|
for usernamename in sorted(groups[name]): |
|
|
|
|
print " " + usernamename |
|
|
|
|
sys.exit() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if options.what in ("a", "r"): |
|
|
|
|
# add a user, restricted or regular |
|
|
|
|
if name in users: |
|
|
|
@ -244,7 +253,7 @@ if __name__ == "__main__":
@@ -244,7 +253,7 @@ if __name__ == "__main__":
|
|
|
|
|
if name not in users: |
|
|
|
|
sys.exit("User '%s' not found, use this without a name to get a list of users." % name) |
|
|
|
|
user = users[name] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if options.what == "m": |
|
|
|
|
# move user to alumni |
|
|
|
|
groups = group_users(users) |
|
|
|
@ -262,7 +271,7 @@ if __name__ == "__main__":
@@ -262,7 +271,7 @@ if __name__ == "__main__":
|
|
|
|
|
password = set_new_password(name) |
|
|
|
|
print "New password for user '%s': '%s'" % (name, password) |
|
|
|
|
sys.exit() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# no option, just a name: |
|
|
|
|
# print all the infos connected to a name |
|
|
|
|
print "User %s is in group '%s':" % (name, user.group) |
|
|
|
@ -282,7 +291,13 @@ if __name__ == "__main__":
@@ -282,7 +291,13 @@ if __name__ == "__main__":
|
|
|
|
|
print " Read access is NOT granted to any folder" |
|
|
|
|
info = config.get_folder_info(name) |
|
|
|
|
print "Labjornal %s%s:" % (SVN_BASE, name) |
|
|
|
|
write_acl = [ "@" + ADMINS ] + info[WRITE_ACL] |
|
|
|
|
print " Write access granted to " + ", ".join(write_acl) |
|
|
|
|
read_acl = [ "@" + ADMINS, "@" + REGULAR ] + info[READ_ACL] |
|
|
|
|
print " Read access granted to: " + ", ".join(read_acl) |
|
|
|
|
if info[WRITE_ACL]: |
|
|
|
|
print " Write and read access granted to: " + ", ".join(info[WRITE_ACL]) |
|
|
|
|
else: |
|
|
|
|
print " No write access granted to anybody" |
|
|
|
|
if info[READ_ACL]: |
|
|
|
|
print " Read access granted to: " + ", ".join(info[READ_ACL]) |
|
|
|
|
else: |
|
|
|
|
print " No read access granted to anybody" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|