From e146e6375471b228ae716bb032615af74adac407 Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Oct 07 2019 12:55:40 +0000 Subject: manage repository rights --- diff --git a/action/repo.py b/action/repo.py index 5b8ea4e..5cc8e77 100644 --- a/action/repo.py +++ b/action/repo.py @@ -16,6 +16,10 @@ class RepoBase(UserBase): raise exception.ActionError( request.t('Repository Id incorrect') ) return repository_id + def redirect_to_repo(self, request, repo, path = None): + if path is None: path = list() + return self.redirect_to_user(request, repo.get_user(), ['repo', str(repo.name)] + path) + class RepoCreate(RepoBase): def process(self, request): @@ -25,14 +29,18 @@ class RepoCreate(RepoBase): title = str(request.postvars.get('title', '')) description = str(request.postvars.get('description', '')) + user = request.model.users.get_by_id(user_id) + if not user: + raise exception.ActionError( request.t('User not found') ) + repo = None try: - repo = request.model.repositories.create(user_id, name, repotype, title, description) + repo = request.model.repositories.create(user, name, repotype, title, description) except Exception as e: self.propagate_exception(e) request.connection.commit() - return request.answer.complete_redirect(['user', str(repo.get_user().login), 'repo', str(repo.name)]) + return self.redirect_to_repo(request, repo) class RepoUpdate(RepoBase): @@ -51,7 +59,7 @@ class RepoUpdate(RepoBase): self.propagate_exception(e) request.connection.commit() - return request.answer.complete_redirect(['user', str(repo.get_user().login), 'repo', str(repo.name)]) + return self.redirect_to_repo(request, repo) class RepoDelete(RepoBase): @@ -61,7 +69,7 @@ class RepoDelete(RepoBase): repo = request.model.repositories.get_by_id(repository_id) if not repo: raise exception.ActionError( request.t('Repository not found') ) - login = repo.get_user().login + user = repo.get_user() try: repo.delete() @@ -69,13 +77,55 @@ class RepoDelete(RepoBase): self.propagate_exception(e) request.connection.commit() - return request.answer.complete_redirect(['user', login, 'repos']) + return self.redirect_to_user(request, user, ['repos']) +class RepoSetUserRight(RepoBase): + def process(self, request): + repository_id = self.parse_repository_id(request) + repo = request.model.repositories.get_by_id(repository_id) + if not repo: + raise exception.ActionError( request.t('Repository not found') ) + + allowed = bool(request.postvars.get('allowed', False)) + mode = str(request.postvars.get('mode', '')) + + try: + user_id = int(request.postvars.get('user_id', 0)) + except Exception: + raise exception.ActionError( request.t('User Id incorrect') ) + user_login = str(request.postvars.get('user_login', '')) + all_users = bool(request.postvars.get('all_users', False)) + + if user_id and user_login: + raise exception.ActionError( request.t('Both user id and user login was set') ) + if all_users and (user_id or user_login): + raise exception.ActionError( request.t('All users flag was set with selection of concrete user') ) + + user = None + if user_id: + user = request.model.users.get_by_id(user_id) + elif user_login: + user = request.model.users.get_by_login(user_login) + user_id = user.id + + if not all_users and not user: + raise exception.ActionError( request.t('User not found') ) + + try: + repo.set_user_right(user_id, mode, allowed, all_users = all_users) + except Exception as e: + self.propagate_exception(e) + + request.connection.commit() + return self.redirect_to_repo(request, repo, ['edit']) + + actions = { - 'create' : RepoCreate(), - 'update' : RepoUpdate(), - 'delete' : RepoDelete(), + 'create' : RepoCreate(), + 'update' : RepoUpdate(), + 'delete' : RepoDelete(), + 'setuserright' : RepoSetUserRight(), } diff --git a/action/user.py b/action/user.py index c3520ac..8a1131b 100644 --- a/action/user.py +++ b/action/user.py @@ -17,6 +17,10 @@ class UserBase(Action): raise exception.ActionError( request.t('Used Id incorrect') ) return user_id + def redirect_to_user(self, request, user, path = None): + if path is None: path = list() + return request.answer.complete_redirect(['user', str(user.login)] + path) + class UserLogin(UserBase): def __init__(self): @@ -52,7 +56,7 @@ class UserCreate(UserBase): self.propagate_exception(e) request.connection.commit() - return request.answer.complete_redirect(['user', str(user.login)]) + return self.redirect_to_user(request, user) class UserUpdate(UserBase): @@ -70,7 +74,7 @@ class UserUpdate(UserBase): self.propagate_exception(e) request.connection.commit() - return request.answer.complete_redirect(['user', str(user.login)]) + return self.redirect_to_user(request, user) class UserDelete(UserBase): @@ -114,7 +118,7 @@ class UserSetPassword(UserBase): self.propagate_exception(e) request.connection.commit() - return request.answer.complete_redirect(['user', str(user.login)]) + return self.redirect_to_user(request, user) class UserSetSuperuser(UserBase): @@ -132,7 +136,7 @@ class UserSetSuperuser(UserBase): self.propagate_exception(e) request.connection.commit() - return request.answer.complete_redirect(['user', str(user.login)]) + return self.redirect_to_user(request, user) actions = { diff --git a/data/common.css b/data/common.css index 8b13789..5338f59 100644 --- a/data/common.css +++ b/data/common.css @@ -1 +1,13 @@ +fieldset > div > span { + display: inline-block; + vertical-align: text-top; + text-align: right; + width: 200px; +} + +fieldset > div > div { + display: inline-block; + vertical-align: text-top; + width: 400px; +} diff --git a/db/types.py b/db/types.py index 3120a99..5589c01 100644 --- a/db/types.py +++ b/db/types.py @@ -6,6 +6,9 @@ import datetime dateformat = '%Y-%m-%dT%H:%M:%S' datepattern = '0000-00-00T00:00:00' +def any_to_str(s): + return '' if s is None else str(s) + def date_to_str(date): return date.strftime(dateformat).rjust(len(datepattern), '0') @@ -40,7 +43,7 @@ class Int(Type): class String(Type): def from_raw(self, value): - return '' if value is None else str(value) + return any_to_str(value) def to_db(self, connection, value): return "'" + connection.escape_string(self.from_raw(value)) + "'" @@ -52,14 +55,14 @@ class Float(Type): class Date(Type): def from_raw(self, value): - return str_to_date(date_to_str(value) if type(value) is datetime.datetime else str(value)) + return str_to_date(date_to_str(value) if type(value) is datetime.datetime else any_to_str(value)) def from_db(self, connection, value): return set_timezone(value) class Field(Type): def from_raw(self, value): - result = str(value) + result = any_to_str(value) assert(result.isidentifier()) return result def to_db(self, connection, value): @@ -68,17 +71,27 @@ class Field(Type): class Table(Type): def from_raw(self, value): - result = str(value) + result = any_to_str(value) assert(result.isidentifier()) return result def from_db(self, connection, value): - value = str(value) + value = any_to_str(value) prefix = connection.pool.server.config['db']['prefix'] assert value.startswith(prefix) return self.from_raw(value[len(prefix):]) def to_db(self, connection, value): return '`' + connection.escape_string( connection.pool.server.config['db']['prefix'] + self.from_raw(value)) + '`' +class Query(Type): + def from_raw(self, value): + assert type(value) is str + return value + def from_db(self, connection, value): + assert type(value) is str + return value + def to_db(self, connection, value): + return self.from_raw(value) + tint = Int() tstring = String() @@ -86,6 +99,7 @@ tfloat = Float() tdate = Date() tfield = Field() ttable = Table() +tquery = Query() bytype = { @@ -102,4 +116,5 @@ bychar = { 'D': tdate, 'F': tfield, 'T': ttable, + 'Q': tquery, } diff --git a/doc/plan.ods b/doc/plan.ods index e682e2f..aab4a63 100644 Binary files a/doc/plan.ods and b/doc/plan.ods differ diff --git a/model/base.py b/model/base.py index deeb988..596d6e5 100644 --- a/model/base.py +++ b/model/base.py @@ -1,4 +1,5 @@ + class ModelBase: def __init__(self, model): self.model = model @@ -11,3 +12,36 @@ class ModelBase: return self.translator.translate(text) def t(self, text): return self.translate(text) + + +class ModelItemBase(ModelBase): + def __init__(self, manager, row): + self.manager = manager + super().__init__(self.manager.model) + assert(self.manager.itemtype() == type(self)) + + self.id = int(row['id']) + assert(self.id) + + def reset_cache(self): + self.manager.cache.reset_row(self.table(), self.id) + + def table(self): + return self.manager.table() + + +class ModelManagerBase(ModelBase): + def __init__(self, model): + super().__init__(model) + + def table(self): + raise Exception() + + def itemtype(self): + raise Exception() + + def item(self, *args, **kvargs): + raise self.itemtype()(self, *args, **kvargs) + + def reset_cache(self, id): + self.connection.cache.reset_row(self.table(), id) diff --git a/model/model.py b/model/model.py index e1d6a70..dd7876a 100644 --- a/model/model.py +++ b/model/model.py @@ -10,7 +10,7 @@ class Model: self.connection = connection self.server = self.connection.server self.internal_rights = InternalRights(self.connection, user_id, superuser) - self.myrights = MyRights(self.internal_rights) + self.myrights = MyRights(self.internal_rights, self) self.translator = translator self.users = Users(self) diff --git a/model/repositories.py b/model/repositories.py index 41774ea..ceef0cc 100644 --- a/model/repositories.py +++ b/model/repositories.py @@ -1,13 +1,22 @@ import exception -from model.base import ModelBase +from model.base import ModelItemBase, ModelManagerBase +from model.users import User -class Repository(ModelBase): +class RepositoryRight: + def __init__(self, user, mode): + assert(not user or type(user) is User) + assert(type(mode) is str) + self.all_users = not user + self.user = user + self.mode = mode + + +class Repository(ModelItemBase): def __init__(self, repositories, row, user = None): - self.repositories = repositories - super().__init__(self.repositories.model) + super().__init__(repositories, row) self.id = int(row['id']) self.user_id = int(row['user_id']) @@ -16,9 +25,10 @@ class Repository(ModelBase): self.title = str(row['title']) self.description = str(row['description']) - assert(not user or user.id == self.user_id) + assert(not user or (type(user) is User and user.id == self.user_id)) self.user = user - self.repotype = self.repositories.repotypes[self.type] + self.repotype = self.manager.repotypes[self.type] + self.user_rights = None def get_user(self): if self.user == None: @@ -27,15 +37,31 @@ class Repository(ModelBase): assert(self.user.id == self.user_id) return self.user + def get_user_rights(self): + if self.user_rights is None: + self.user_rights = list() + rights = self.rights.get_list(target_type = self.table(), target_id = self.id) + if self.can_update(): + self.user_rights = rights + else: + for i in rights: + if i.user_id == 0 or i.user_id == self.rights.user_id: + self.user_rights.append(i) + assert(not self.user_rights is None) + return self.user_rights + def reset_cache(self): - self.repositories.reset_cache(self.id, self.user_id, self.name) + self.manager.reset_cache(self.id, self.user_id, self.name) def gen_subpath(self): - return self.repositories.gen_subpath(self.get_user().login, self.name) + return self.manager.gen_subpath(self.get_user().login, self.name) def gen_internalurl(self): return self.repotype.gen_internalurl( self.gen_subpath() ) + def can_write(self): + return self.can_update() or self.rights.isallowed(self.table(), self.id, self.manager.REPOWRITE) + def can_update(self): return self.user_id == self.rights.user_id or self.rights.issuperuser() @@ -43,35 +69,53 @@ class Repository(ModelBase): if self.can_update(): self.connection.execute( 'UPDATE %T SET `title`=%s, `description`=%s WHERE `id`=%d', - self.repositories.TABLE, title, description, self.id ) + self.table(), title, description, self.id ) self.reset_cache() else: raise exception.ModelDeny() def can_delete(self): return self.user_id == self.rights.user_id or self.rights.issuperuser() - - def delete(self, password = None): + + def delete(self): if self.can_delete(): + self.rights.delete_list(target_type = self.table(), target_id = self.id) self.connection.execute( 'DELETE FROM %T WHERE `id`=%d', - self.repositories.TABLE, self.id ) + self.table(), self.id ) self.reset_cache() self.connection.call_on_commit(self.repotype.delete, self.gen_subpath()) else: raise exception.ModelDeny() + + def set_user_right(self, user_id, mode, allowed, all_users = False): + assert(all_users == (user_id == 0)) + assert(type(user_id) is int) + if self.can_update(): + if not mode in (self.manager.READ, self.manager.REPOWRITE): + raise exception.ModelWrongData(self.t('Wrong mode')) + self.rights.set(user_id, self.table(), self.id, mode, allowed) + else: + raise exception.ModelDeny() -class Repositories(ModelBase): - TABLE = 'repositories' +class Repositories(ModelManagerBase): + READ = 'read' + REPOWRITE = 'repowrite' def __init__(self, model): super().__init__(model) self.repotypes = self.server.repotypes + def table(self): + return 'repositories' + + def itemtype(self): + return Repository + def reset_cache(self, id, user_id, name): - self.connection.cache.reset_row(self.TABLE, id) - self.connection.cache.reset(self.TABLE, {'user_id': user_id, 'name': name}) + super().reset_cache(id) + self.connection.cache.reset(self.table(), {'user_id': user_id, 'name': name}) def verify_name(self, name): return self.model.verify_identifier(name) @@ -81,31 +125,32 @@ class Repositories(ModelBase): assert( self.model.verify_path_entry(name) ) return login + '/' + name - def can_create(self, user_id): - assert(type(user_id) is int and user_id) - return user_id == self.rights.user_id or self.rights.issuperuser() + def can_read(self, user, id): + assert(type(user) is User) + assert(type(id) is int) + return user.id == self.rights.user_id \ + or self.rights.issuperuser() \ + or self.rights.isallowed(self.table(), id, self.READ) + + def can_create(self, user): + assert(type(user) is User) + return user.id == self.rights.user_id or self.rights.issuperuser() - def create(self, user_id, name, repotype, title, description, user = None): - assert(not user or user.id == user_id) - if not self.can_create(user_id): + def create(self, user, name, repotype, title, description): + if not self.can_create(user): raise exception.ModelDeny() if not self.verify_name(name): raise exception.ModelWrongData(self.t('Repository name is incorrect')) if not type(repotype) is str or not repotype in self.repotypes: raise exception.ModelWrongData(self.t('Repository type is incorrect')) - if self.get_by_name(user_id, name): + if self.get_by_name(user, name): raise exception.ModelWrongData(self.t('Repository already exists')) - if not user: - user = self.model.users.get_by_id(user_id) - if not user: - raise exception.ModelWrongData(self.t('User not found')) - self.connection.execute( 'INSERT INTO %T SET `user_id`=%d, `name`=%s, `type`=%s, `title`=%s, `description`=%s', - self.TABLE, user_id, name, repotype, title, description ) + self.table(), user.id, name, repotype, title, description ) id = self.connection.insert_id() - self.reset_cache(id, user_id, name) + self.reset_cache(id, user.id, name) subpath = self.gen_subpath(user.login, name) repotype_instance = self.repotypes[repotype] @@ -116,35 +161,35 @@ class Repositories(ModelBase): def get_by_id(self, id, user = None): assert(type(id) is int) - row = self.connection.cache.row(self.TABLE, id) + row = self.connection.cache.row(self.table(), id) if not row: return None if not user: user = self.model.users.get_by_id(row['user_id']) if not user: return None + if not self.can_read(user, row['id']): + return None return Repository(self, row, user) - def get_by_name(self, user_id, name, user = None): - assert(not user or user.id == user_id) - assert(type(user_id) is int) + def get_by_name(self, user, name): + assert(type(user) is User) assert(type(name) is str) - rows = self.connection.cache.select(self.TABLE, {'user_id': user_id, 'name': name}) + rows = self.connection.cache.select(self.table(), {'user_id': user.id, 'name': name}) if not rows or len(rows) > 1: return None row = rows[0] - if not user: - user = self.model.users.get_by_id(row['user_id']) - if not user: - return None + if not self.can_read(user, row['id']): + return None return Repository(self, row, user) def get_list(self, user): - assert(user) + assert(type(user) is User) result = list() - rows = self.connection.query_dict('SELECT * FROM %T WHERE `user_id`=%d ORDER BY `name`', self.TABLE, user.id) + rows = self.connection.query_dict('SELECT * FROM %T WHERE `user_id`=%d ORDER BY `name`', self.table(), user.id) for row in rows: - result.append(Repository(self, row, user)) + if self.can_read(user, row['id']): + result.append(Repository(self, row, user)) return result diff --git a/model/rights.py b/model/rights.py index 478028b..57d46f0 100644 --- a/model/rights.py +++ b/model/rights.py @@ -9,9 +9,20 @@ class Right: class MyRights: - def __init__(self, internal): + def __init__(self, internal, model): self.internal = internal + self.model = model self.user_id = self.internal.user_id + self.user = None + + def get_user(): + if self.user_id: + assert self.user + return None + if not self.user: + self.model.users.get_by_id(self.user_id) + assert self.user + return self.user def issuperuser(self): return self.internal.issuperuser() @@ -45,24 +56,26 @@ class InternalRights: return True if self.user_id and self.get(self.user_id, target_type, target_id, mode): return True + if self.get(0, target_type, target_id, mode): + return True return False def build_where(self, user_id = None, target_type = None, target_id = None, mode = None): where = list() args = list() - if user_id: + if not user_id is None: assert(type(user_id) is int) where.append("`user_id`=%d") args.append(user_id) - if target_type: + if not target_type is None: assert(type(target_type) is str) where.append("`target_type`=%s") args.append(target_type) - if target_id: + if not target_id is None: assert(type(target_id) is int) where.append("`target_id`=%d") args.append(target_id) - if mode: + if not mode is None: assert(type(mode) is str) where.append("`mode`=%s") args.append(mode) @@ -72,7 +85,7 @@ class InternalRights: def get_list(self, user_id = None, target_type = None, target_id = None, mode = None): where, args = self.build_where(user_id, target_type, target_id, mode) - rows = connection.query_dict('SELECT * FROM %T' + where, self.TABLE, *args) + rows = self.connection.query_dict('SELECT * FROM %T' + where, self.TABLE, *args) rights = list() for row in rows: rights.append( Right(row) ) diff --git a/model/users.py b/model/users.py index 4b98f83..f17c86a 100644 --- a/model/users.py +++ b/model/users.py @@ -4,37 +4,43 @@ import hashlib import exception -from model.base import ModelBase +from model.base import ModelItemBase, ModelManagerBase -class User(ModelBase): +class User(ModelItemBase): def __init__(self, users, row): - self.users = users - super().__init__(self.users.model) + super().__init__(users, row) self.id = int(row['id']) self.login = str(row['login']) self.name = str(row['name']) + self.superuser_ready = False self.superuser = None if self.id == self.rights.user_id: self._password = str(row['password']) - if self.id == self.rights.user_id or self.rights.issuperuser(): - self.superuser = self.rights.get_superuser(self.id) + + def get_superuser(self): + if not self.superuser_ready: + self.superuser = None + if self.id == self.rights.user_id or self.rights.issuperuser(): + self.superuser = self.rights.get_superuser(self.id) + self.superuser_ready = True + return self.superuser def reset_cache(self): - self.users.reset_cache(self.id, self.login) + self.manager.reset_cache(self.id, self.login) def change_password(self, newpassword, oldpassword = None): if self.id == self.rights.user_id: if oldpassword is None: raise exception.ModelDeny() - oldhash = self.users.gen_password_hash(self.id, oldpassword) + oldhash = self.manager.gen_password_hash(self.id, oldpassword) if oldhash != self._password: raise exception.ModelWrongData(self.t('Password incorrect')) if self.id != self.rights.user_id and not self.rights.issuperuser(): raise exception.ModelDeny() - hash = self.users.gen_password_hash(self.id, newpassword) - self.connection.execute('UPDATE %T SET `password`=%s WHERE `id`=%d', self.users.TABLE, hash, self.id) + hash = self.manager.gen_password_hash(self.id, newpassword) + self.connection.execute('UPDATE %T SET `password`=%s WHERE `id`=%d', self.table(), hash, self.id) self.reset_cache() self.server.sessions.delete_by_user_id(self.id) @@ -43,7 +49,7 @@ class User(ModelBase): def update(self, name): if self.can_update(): - self.connection.execute('UPDATE %T SET `name`=%s WHERE `id`=%d', self.users.TABLE, name, self.id) + self.connection.execute('UPDATE %T SET `name`=%s WHERE `id`=%d', self.table(), name, self.id) self.reset_cache() else: raise exception.ModelDeny() @@ -56,11 +62,17 @@ class User(ModelBase): if self.id == self.rights.user_id: if password is None: raise exception.ModelDeny() - hash = self.users.gen_password_hash(self.id, str(password)) + hash = self.manager.gen_password_hash(self.id, str(password)) if hash != self._password: raise exception.ModelWrongData(self.t('Password incorrect')) + + repositories = self.model.repositories.get_list(self) + for repo in repositories: + repo.delete() + self.rights.delete_list(user_id = self.id) - self.connection.execute('DELETE FROM %T WHERE `id`=%d', self.users.TABLE, self.id) + self.rights.delete_list(target_type = self.table(), target_id = self.id) + self.connection.execute('DELETE FROM %T WHERE `id`=%d', self.table(), self.id) self.reset_cache() self.server.sessions.delete_by_user_id(self.id) else: @@ -73,15 +85,19 @@ class User(ModelBase): raise exception.ModelDeny() -class Users(ModelBase): - TABLE = 'users' - +class Users(ModelManagerBase): def __init__(self, model): super().__init__(model) + + def table(self): + return 'users' + + def itemtype(self): + return User def reset_cache(self, id, login): - self.connection.cache.reset_row(self.TABLE, id) - self.connection.cache.reset(self.TABLE, {'login': login}) + super().reset_cache(id) + self.connection.cache.reset(self.table(), {'login': login}) def gen_password_hash(self, id, password): salt = self.server.config['users']['salt'] @@ -100,17 +116,17 @@ class Users(ModelBase): raise exception.ModelWrongData(self.t('Login incorrect')) if self.get_by_login(login): raise exception.ModelWrongData(self.t('Login already exists')) - self.connection.execute("INSERT INTO %T SET `login`=%s, `password`='', `name`=%s", self.TABLE, login, name) + self.connection.execute("INSERT INTO %T SET `login`=%s, `password`='', `name`=%s", self.table(), login, name) id = self.connection.insert_id() hash = self.gen_password_hash(int(id), password) - self.connection.execute('UPDATE %T SET `password`=%s WHERE `id`=%d', self.TABLE, hash, id) + self.connection.execute('UPDATE %T SET `password`=%s WHERE `id`=%d', self.table(), hash, id) self.reset_cache(id, login) return self.get_by_id(id) def check_password(self, login, password): assert(type(login) is str) assert(type(password) is str) - rows = self.connection.cache.select(self.TABLE, {'login': login}) + rows = self.connection.cache.select(self.table(), {'login': login}) if not rows or len(rows) > 1: return False row = rows[0] @@ -123,14 +139,14 @@ class Users(ModelBase): assert(type(id) is int) row = None if id == self.rights.user_id or self.rights.issuperuser() or self.server.config['users']['showprofile']: - row = self.connection.cache.row(self.TABLE, id) + row = self.connection.cache.row(self.table(), id) if not row: return None - return User(self, row) + return self.itemtype()(self, row) def get_by_login(self, login): assert(type(login) is str) - rows = self.connection.cache.select(self.TABLE, {'login': login}) + rows = self.connection.cache.select(self.table(), {'login': login}) if not rows or len(rows) > 1: return None row = rows[0] @@ -144,7 +160,7 @@ class Users(ModelBase): def get_list(self): result = list() if self.can_list(): - rows = self.connection.query_dict('SELECT * FROM %T ORDER BY `login`', self.TABLE) + rows = self.connection.query_dict('SELECT * FROM %T ORDER BY `login`', self.table()) for row in rows: result.append(User(self, row)) elif self.rights.user_id: diff --git a/page/repo.py b/page/repo.py index 54c8ecb..d9cbbb0 100644 --- a/page/repo.py +++ b/page/repo.py @@ -10,7 +10,7 @@ class RepoCreatePage(Page): user = request.answer.objects['user'] if path: raise exception.HttpNotFound() - if not request.model.repositories.can_create(user.id): + if not request.model.repositories.can_create(user): raise exception.HttpNotFound() answer = request.answer answer.add_uipath_entry( answer.t('Create repository'), prevpath ) @@ -41,7 +41,7 @@ class RepoPage(Page): answer = request.answer user = request.answer.objects['user'] - repo = request.model.repositories.get_by_name(user.id, str(path[0]), user) + repo = request.model.repositories.get_by_name(user, str(path[0])) if not repo: raise exception.HttpNotFound() @@ -105,7 +105,39 @@ class RepoUpdatePage(Page): form.add_submit() form.end() answer.content += form.content - + + user_rights = repo.get_user_rights() + for i in user_rights: + form = Form(request) + form.begin('Rights', 'repo.setuserright') + form.add_hidden('repository_id', repo.id) + form.add_hidden('allowed', '') + form.add_hidden('all_users', '' if i.user_id else '1') + form.add_hidden('user_id', i.user_id) + form.add_hidden('mode', i.mode) + if i.user_id == 0: + form.add_field_raw('all users', '') + else: + user = request.model.users.get_by_id(i.user_id) + login = user.login if user else '' + form.add_field_raw('login:', answer.e(login)) + form.add_field_raw('mode:', answer.te(i.mode)) + form.add_submit('Delete') + form.end() + answer.content += form.content + + form = Form(request) + form.begin('Add rights', 'repo.setuserright') + form.add_hidden('repository_id', repo.id) + form.add_hidden('allowed', 1) + form.add_checkbox('for all users:', 'all_users') + form.add_input('login:', 'user_login', 'text') + form.add_select('mode:', 'mode', { + request.model.repositories.READ : request.model.repositories.READ, + request.model.repositories.REPOWRITE : request.model.repositories.REPOWRITE }) + form.add_submit() + form.end() + answer.content += form.content if repo.can_delete() and prevpath: url = request.get_urlpath_escaped(prevpath[:-1] + ['delete']) @@ -167,7 +199,7 @@ class RepoListPage(Page): + answer.e(repo.name) + ' ' \ + answer.e(repo.title) + '

\n' - if request.model.repositories.can_create(user.id): + if request.model.repositories.can_create(user): answer.content += '

' + self.make_link(answer, prevpath[:-1] + ['repo_create'], 'Create repository') + '

\n' return answer.complete_content() diff --git a/page/user.py b/page/user.py index d6621e7..7f319a0 100644 --- a/page/user.py +++ b/page/user.py @@ -78,7 +78,7 @@ class UserProfilePage(Page): answer.content += '

' + answer.e(user.login) + '

\n' answer.content += '

' + answer.e(user.name) + '

\n' - if user.superuser: + if user.get_superuser(): answer.content += '

' + answer.te('Site admin') + '

\n' if user.can_update(): answer.content += '

' + self.make_link(answer, prevpath + ['edit'], 'Edit user') + '

\n' @@ -119,11 +119,11 @@ class UserUpdatePage(Page): form.end() answer.content += form.content - if user.id != request.model.myrights.user_id and not user.superuser is None: + if user.id != request.model.myrights.user_id and not user.get_superuser() is None: form = Form(request) form.begin('Global rights', 'user.setsuperuser') form.add_hidden('user_id', user.id) - form.add_checkbox('site admin:', 'superuser', user.superuser) + form.add_checkbox('site admin:', 'superuser', user.get_superuser()) form.add_submit() form.end() answer.content += form.content diff --git a/repoproxy.py b/repoproxy.py index a59c194..4a127a1 100644 --- a/repoproxy.py +++ b/repoproxy.py @@ -165,9 +165,7 @@ class RepoProxy: writeaccess = repo.repotype.iswriteaccess(request, nextpath) if writeaccess: - if not user: - return self.unauthorized() - if user.id != repo.user_id and not request.model.rights.get_superuser(user.id): + if not repo.can_write(): return self.unauthorized() url = repo.gen_internalurl()