def user_index(request): is_w_access = _check_users_file(request) users_file_hash = md5_for_file(settings.AUTH_FILE) form = AddUser(users_file_hash) delete_user_form = FileHashForm(users_file_hash) hgweb = HGWeb(settings.HGWEB_CONFIG) tree = prepare_tree( modhg.repository.get_tree(hgweb.get_paths(), hgweb.get_collections())) model = {"tree": tree} if request.method == "POST": if "delete_user" in request.POST: delete_user_form = FileHashForm(users_file_hash, request.POST) if delete_user_form.is_valid() and is_w_access: login = request.POST.get("login") users.remove(settings.AUTH_FILE, login) messages.success(request, _("User '%s' was deleted.") % login) return HttpResponseRedirect(reverse('users_index')) elif "add_user" in request.POST: form = AddUser(users_file_hash, request.POST) if form.is_valid() and is_w_access: login = form.cleaned_data['login'] password = form.cleaned_data['password2'] users.add(settings.AUTH_FILE, login, password) messages.success(request, _("User '%s' was added.") % login) return HttpResponseRedirect(reverse('users_index')) user_list = users.login_list(settings.AUTH_FILE) model["delete_user_form"] = delete_user_form model["form"] = form model["users"] = user_list return model
def user(request, action, login): users_file_hash = md5_for_file(settings.AUTH_FILE) hgweb = HGWeb(settings.HGWEB_CONFIG) tree = prepare_tree( modhg.repository.get_tree(hgweb.get_paths(), hgweb.get_collections())) model = {"tree": tree} is_write_access = _check_users_file(request) if action == "edit": # todo: check if login exists if request.method == "POST": form = EditUser(users_file_hash, request.POST) if form.is_valid() and is_write_access: password = form.cleaned_data['password2'] users.update(settings.AUTH_FILE, login, password) messages.success(request, _("Password changed successfully.")) return HttpResponseRedirect( reverse("users", args=[action, login])) else: form = EditUser(users_file_hash) model["form"] = form model["login"] = login # sorting permissions dict by key permissions = users.permissions(login) permissions = sorted(permissions.items(), key=lambda elem: elem[0]) model["permissions"] = SortedDict(permissions) return model
def get_group(key): hgweb = HGWeb(settings.HGWEB_CONFIG) path = hgweb.get_path(key) if path: return "-" paths = hgweb.get_paths_and_collections() values = [path_item\ for path_item, val in paths\ if key == path_item or key.startswith(path_item)] if not len(values): raise RepositoryException(_("Invalid repository name.")) return values[0]
def _remove_from_hgrc(login): _remove_hgrc_single(login, settings.HGWEB_CONFIG) hgweb = HGWeb(settings.HGWEB_CONFIG) paths = hgweb.get_paths() collections = hgweb.get_collections() for (name, path) in collections: _remove_from_hgrc_int(name, path, True, login) for (name, path) in paths: if path.endswith("*"): _remove_from_hgrc_int(name, path, path.endswith("**"), login) else: _remove_hgrc_single(login, path)
def clean_path(self): _path = self.cleaned_data['path'].strip() if 'old_group_path' in self.data and _path == self.data['old_group_path']: return _path is_collection = self.cleaned_data.get('is_collection') if not is_collection == 'True' and not re.search(r"([/]\*{1,2})$", _path): raise forms.ValidationError(_("Path should be ended with /* or /**")) hgweb = HGWeb(settings.HGWEB_CONFIG) groups = hgweb.get_paths_and_collections() for name, path_item in groups: if path_item.rstrip('*/') == _path.rstrip('*/'): raise forms.ValidationError(_("The path is already defined by group: %s") % name) return _path
def _extract_permission(login, path, global_web): hgrc_path = os.path.join(path, ".hg", "hgrc") if not os.path.exists(hgrc_path): return False hgrc = HGWeb(hgrc_path) web = hgrc.get_web() allow_read = not _is_in_list(web, global_web, "deny_read", login) and \ _is_in_list(web, global_web, "allow_read", login) allow_push = not _is_in_list(web, global_web, "deny_push", login) and \ _is_in_list(web, global_web, "allow_push", login) if allow_read or allow_push: return {"read": allow_read, "push": allow_push} return False
def get_absolute_repository_path(key): """ Resolves absolute path to repository. Waits 'key' or 'group_name/key'. """ hgweb = HGWeb(settings.HGWEB_CONFIG) path = hgweb.get_path(key) if path: return path paths = hgweb.get_paths_and_collections() values = [key.replace(path_item, val.strip("*").rstrip("/"), 1)\ for path_item, val in paths\ if key == path_item or key.startswith(path_item)] if not len(values): raise RepositoryException(_("Invalid repository name.")) return values[0]
def delete(path, item_name=""): """ Deletes single repository with it directory tree. """ if not is_repository(path): raise RepositoryException( _("There is no repository by path: [%s]") % path) try: shutil.rmtree( path ) #, ignore_errors=True - to ignore any problem like "Permission denied" except (shutil.Error, OSError) as e: #probably more specific exception is needed raise RepositoryException( _("Failed to delete [%(path)s], because of error: %(cause)s") % { "path": path, "cause": str(e) }) if item_name != "": # no group hgweb = HGWeb(settings.HGWEB_CONFIG) hgweb.del_paths(item_name)
def rename(old_path, new_path, old_item_name="", new_item_name=""): if not is_repository(old_path): raise RepositoryException( _("There is no repository by path: [%s]") % old_path) if os.path.exists(new_path) and not os.path.isdir(new_path): raise RepositoryException(_("There is file by path: [%s]") % new_path) elif os.path.exists(new_path) and not os.access(new_path, os.R_OK or os.W_OK): raise RepositoryException( _("There is no access rights by path: [%s]") % new_path) try: shutil.move(old_path, new_path) except (shutil.Error, OSError) as e: raise RepositoryException( _("Repository [%(old_path)s] is not moved to [%(new_path)s], because of error: %(cause)s" ) % { "old_path": old_path, "new_path": new_path, "cause": str(e) }) if old_item_name != "": # no group hgweb = HGWeb(settings.HGWEB_CONFIG) hgweb.del_paths(old_item_name) hgweb.add_paths(new_item_name, new_path)
def permissions(login, path_as_key=False): #check is login exists permission_list = {} hgweb = HGWeb(settings.HGWEB_CONFIG) global_web = hgweb.get_web() paths = hgweb.get_paths() collections = hgweb.get_collections() for (name, path) in collections: permission_list.update( _scan(name, path, True, login, path_as_key, global_web)) for (name, path) in paths: if path.endswith("*"): permission_list.update( _scan(name, path, path.endswith("**"), login, path_as_key, global_web)) else: if repository.is_repository(path): perm = _extract_permission(login, path, global_web) if perm: key = path if path_as_key else name.strip(os.sep) permission_list[key] = perm return permission_list
def create(path, name, has_no_group=False): """ http://mercurial.selenic.com/wiki/MercurialApi#Repositories """ if is_repository(path): raise RepositoryException( _("There is already such a repository." )) #make here something more informative or exception uio = ui.ui() try: hg.repository(uio, path, create=True) except Exception as e: #probably more specific exception is needed raise RepositoryException( _("Repository [%(path)s] is not created, because of error: %(cause)s" ) % { "path": path, "cause": str(e) }) if has_no_group: #another one try-except block for this hgweb = HGWeb(settings.HGWEB_CONFIG) hgweb.add_paths(name, path)
def create_group(path, name, is_collection=False): hgweb = HGWeb(settings.HGWEB_CONFIG) groups = hgweb.get_groups() if not groups or not ( name in zip(*groups)[0] ): # zip(*groups)[0] - groups is a list of tuples, so unzip it and take list of keys try: if not is_collection: _path = path.rstrip('*') if not os.path.exists(_path): os.makedirs(_path) #may be OSError hgweb.add_paths(name, path) #may be IOError else: if not os.path.exists(path): os.makedirs(path) #may be OSError hgweb.add_collections(name, path) #may be IOError except (OSError, IOError) as e: raise RepositoryException("Error: %s" % str(e)) else: raise RepositoryException( _("There is already a group with such a name."))
def _remove_hgrc_single(login, path): if os.path.isfile(path): hgrc = HGWeb(path) else: if not repository.is_repository(path): return hgrc_path = os.path.join(path, ".hg", "hgrc") if not os.path.exists(hgrc_path): return hgrc = HGWeb(hgrc_path) required_keys = ["allow_read", "allow_push", "deny_read", "deny_push"] for key in required_keys: val = hgrc.get_web_key(key) if not val is None: raw_login_list = val.split(",") login_list = [item.strip() for item in raw_login_list] try: login_list.remove(login) logins = ",".join(login_list) hgrc.set_web_key(key, logins) except ValueError: continue
def delete_group(path, name, is_collection=False, delete_content=True): """ Deletes group: deletes name from [paths] section of it is collection or from [collections] section; Also deletes directory tree py path. """ hgweb = HGWeb(settings.HGWEB_CONFIG) try: if not is_collection: hgweb.del_paths(name) # may throw IOError path = path.rstrip('*') else: hgweb.del_collections(name) # may throw IOError if delete_content: shutil.rmtree( path ) #, ignore_errors=True - to ignore any problem like "Permission denied". os.makedirs(path) # def onerror function to hahdle errors or handle exception shutil.Error except (IOError, shutil.Error) as e: raise RepositoryException( _("There is a problem while deleting group: %s") % str(e))
def index(request): hgweb = HGWeb(settings.HGWEB_CONFIG) collections = hgweb.get_collections() _tree = modhg.repository.get_tree(hgweb.get_paths(), collections) tree = prepare_tree(_tree) groups = hgweb.get_groups() # unzipping collections unzipped_collections = zip(*hgweb.get_collections()) if unzipped_collections: collection_names = unzipped_collections[0] else: collection_names = [] hgweb_cfg_hash = md5_for_file(settings.HGWEB_CONFIG) create_repo_form = CreateRepoForm(groups, hgweb_cfg_hash) groups_form = ManageGroupsForm(hgweb_cfg_hash) delete_group_form = DeleteGroupForm(hgweb_cfg_hash) EDIT_GROUP_FORM_PREFIX = "edit_group" edit_group_form = ManageGroupsForm(hgweb_cfg_hash, prefix=EDIT_GROUP_FORM_PREFIX) model = { "tree": tree, "groups": _ext_groups_with_amount_of_repos_and_collection_flag( groups, collection_names, _tree), "default_path": settings.REPOSITORIES_ROOT } if request.method == 'POST': if "create_group" in request.POST: groups_form = ManageGroupsForm(hgweb_cfg_hash, request.POST) if groups_form.is_valid(): return groups_form.create_group(request) elif "create_repo" in request.POST: create_repo_form = CreateRepoForm(groups, hgweb_cfg_hash, request.POST) if create_repo_form.is_valid(): return create_repo_form.create_repository(request, groups) elif "delete_group" in request.POST: delete_group_form = DeleteGroupForm(hgweb_cfg_hash, request.POST) if delete_group_form.is_valid(): return delete_group_form.delete_group(request, groups) elif "old_group_name" in request.POST: # edit group request edit_group_form = ManageGroupsForm(hgweb_cfg_hash, request.POST, prefix=EDIT_GROUP_FORM_PREFIX) if edit_group_form.is_valid(): return edit_group_form.edit_group(request, groups, hgweb) else: old_name = request.POST.get("old_group_name") old_path = request.POST.get("old_group_path") model["old_group_name"] = old_name model["old_group_path"] = old_path model["groups_form"] = groups_form model["edit_group_form"] = edit_group_form model["repo_form"] = create_repo_form model["delete_group_form"] = delete_group_form return model
def repo(request, repo_path): hgweb = HGWeb(settings.HGWEB_CONFIG) tree = prepare_tree( modhg.repository.get_tree(hgweb.get_paths(), hgweb.get_collections())) is_raw_mode = False full_repository_path = repository.get_absolute_repository_path(repo_path) hgrc_path = os.path.join(full_repository_path, ".hg", "hgrc") _check_access_local_hgrc(request, hgrc_path) groups = hgweb.get_groups() hgweb_cfg_hash = md5_for_file(settings.HGWEB_CONFIG) edit_repo_form = CreateRepoForm(default_groups=groups, file_hash=hgweb_cfg_hash, initial={ "name": os.path.split(full_repository_path)[1], "group": repository.get_group(repo_path), "file_hash": hgweb_cfg_hash }) hgrc = HGWeb(hgrc_path, True) def _hgweb_or_hgrc_list(hgweb, hgrc, param_name): """ checks if user list is not specified in the hgrc, tries to read it from hgweb """ _list = _split_users(hgrc.get_web_key(param_name)) if not _list: _list = _split_users(hgweb.get_web_key(param_name)) return _list allow_read_list = _hgweb_or_hgrc_list(hgweb, hgrc, 'allow_read') allow_push_list = _hgweb_or_hgrc_list(hgweb, hgrc, 'allow_push') deny_read_list = _hgweb_or_hgrc_list(hgweb, hgrc, 'deny_read') deny_push_list = _hgweb_or_hgrc_list(hgweb, hgrc, 'deny_push') user_list = users.login_list(settings.AUTH_FILE) add_to_allow_read_list = [ val for val in user_list if val.strip() not in allow_read_list ] add_to_allow_push_list = [ val for val in user_list if val.strip() not in allow_push_list ] add_to_deny_read_list = [ val for val in user_list if val.strip() not in deny_read_list ] add_to_deny_push_list = [ val for val in user_list if val.strip() not in deny_push_list ] model = { "tree": tree, "global": False, "repo_path": repo_path, "add_to_allow_read_list": add_to_allow_read_list, "add_to_allow_push_list": add_to_allow_push_list, "add_to_deny_read_list": add_to_deny_read_list, "add_to_deny_push_list": add_to_deny_push_list, "allow_read_list": allow_read_list, "allow_push_list": allow_push_list, "deny_read_list": deny_read_list, "deny_push_list": deny_push_list } local_hgrc_hash = md5_for_file(hgrc_path) delete_repo_form = FileHashForm(local_hgrc_hash) repo_field_delete_form = FileHashForm(local_hgrc_hash) form = RepositoryForm(local_hgrc_hash) with open(hgrc_path, 'r') as f: hgrc_content = f.read() raw_mode_form = RawModeForm(local_hgrc_hash, initial={ "hgrc": hgrc_content, "file_hash": local_hgrc_hash }) if request.method == 'POST' and hgrc is not None: if 'save' in request.POST: form = RepositoryForm(local_hgrc_hash, request.POST) if form.is_valid(): form.export_values(hgrc, request.POST) messages.success(request, _("Repository settings saved successfully.")) return HttpResponseRedirect( reverse("repository", args=[repo_path])) elif 'delete_field' in request.POST: repo_field_delete_form = FileHashForm(local_hgrc_hash, request.POST) if repo_field_delete_form.is_valid(): parameter = request.POST.get('parameter') hgrc.del_web_key(parameter) return HttpResponseRedirect( reverse("repository", args=[repo_path])) elif 'sure_delete' in request.POST: delete_repo_form = FileHashForm(local_hgrc_hash, request.POST) if delete_repo_form.is_valid(): try: repository.delete(full_repository_path, repo_path) messages.success( request, _("Repository '%s' deleted successfully.") % repo_path) except RepositoryException as e: messages.warning( request, _("Repository '%(repo)s' was not deleted, cause: %(cause)." ) % { "repo": repo_path, "cause": unicode(e) }) return HttpResponseRedirect(reverse("index")) elif 'save_repo' in request.POST: edit_repo_form = CreateRepoForm(groups, hgweb_cfg_hash, request.POST) if edit_repo_form.is_valid(): return edit_repo_form.rename(request, repo_path, groups, full_repository_path) elif 'raw_save' in request.POST: is_raw_mode = True raw_mode_form = RawModeForm(local_hgrc_hash, request.POST) if raw_mode_form.is_valid(): with open(hgrc_path, 'w') as f: f.write(raw_mode_form.cleaned_data['hgrc']) messages.success(request, _("Repository settings saved successfully.")) return HttpResponseRedirect( reverse("repository", args=[repo_path])) # finally # local hgrc might be changed, recreate dependence forms local_hgrc_hash = md5_for_file(hgrc_path) repo_field_delete_form = FileHashForm(local_hgrc_hash) delete_repo_form = FileHashForm(local_hgrc_hash) # raw_mode form may have _errors set, so just update data in it with open(hgrc_path, 'r') as f: hgrc_content = f.read() raw_mode_form.data['hgrc'] = hgrc_content raw_mode_form.data['file_hash'] = local_hgrc_hash # re-set errors if any occurs in the is_valid method. errors = form._errors form = RepositoryForm(local_hgrc_hash) form._errors = errors form.set_default(hgweb, hgrc) model["form"] = form model["repo_field_delete_form"] = repo_field_delete_form model["delete_repo_form"] = delete_repo_form model["repo_form"] = edit_repo_form model["raw_mode_form"] = raw_mode_form model["is_raw_mode"] = is_raw_mode model["hgweb_repo_url"] = _hgweb_repo_url( full_repository_path) if _is_collection( repo_path, hgweb) else _hgweb_repo_url(repo_path) return model
def hgweb(request): hgweb = HGWeb(settings.HGWEB_CONFIG) tree = prepare_tree( modhg.repository.get_tree(hgweb.get_paths(), hgweb.get_collections())) is_raw_mode = False allow_read_list = _split_users(hgweb.get_web_key('allow_read')) allow_push_list = _split_users(hgweb.get_web_key('allow_push')) deny_read_list = _split_users(hgweb.get_web_key('deny_read')) deny_push_list = _split_users(hgweb.get_web_key('deny_push')) user_list = users.login_list(settings.AUTH_FILE) add_to_allow_read_list = [ val for val in user_list if val.strip() not in allow_read_list ] add_to_allow_push_list = [ val for val in user_list if val.strip() not in allow_push_list ] add_to_deny_read_list = [ val for val in user_list if val.strip() not in deny_read_list ] add_to_deny_push_list = [ val for val in user_list if val.strip() not in deny_push_list ] model = { "tree": tree, "global": True, "add_to_allow_read_list": add_to_allow_read_list, "add_to_allow_push_list": add_to_allow_push_list, "add_to_deny_read_list": add_to_deny_read_list, "add_to_deny_push_list": add_to_deny_push_list, "allow_read_list": allow_read_list, "allow_push_list": allow_push_list, "deny_read_list": deny_read_list, "deny_push_list": deny_push_list } file_hash = md5_for_file(settings.HGWEB_CONFIG) form = RepositoryForm(file_hash) repo_field_delete_form = FileHashForm(file_hash) with open(settings.HGWEB_CONFIG, 'r') as f: hgrc_content = f.read() raw_mode_form = RawModeForm(file_hash, initial={"hgrc": hgrc_content}) if request.method == 'POST': if 'save' in request.POST: form = RepositoryForm(file_hash, request.POST) if form.is_valid(): form.export_values(hgweb, request.POST) messages.success(request, _("Global settings saved successfully.")) return HttpResponseRedirect(reverse("hgweb")) elif 'raw_save' in request.POST: is_raw_mode = True raw_mode_form = RawModeForm(file_hash, request.POST) if raw_mode_form.is_valid(): with open(settings.HGWEB_CONFIG, 'w') as f: f.write(raw_mode_form.cleaned_data['hgrc']) messages.success(request, _("Global settings saved successfully.")) return HttpResponseRedirect(reverse("hgweb")) # re-set errors if any occurs in the is_valid method. file_hash = md5_for_file(settings.HGWEB_CONFIG) repo_field_delete_form = FileHashForm(file_hash) # raw_mode form may have _errors set, so just update data in it with open(settings.HGWEB_CONFIG, 'r') as f: hgrc_content = f.read() raw_mode_form.data['hgrc'] = hgrc_content raw_mode_form.data['file_hash'] = file_hash # re-set errors if any occurs in the is_valid method. errors = form._errors form = RepositoryForm(file_hash) form._errors = errors form.set_default(hgweb, None) model["form"] = form model["repo_field_delete_form"] = repo_field_delete_form model["raw_mode_form"] = raw_mode_form model["is_raw_mode"] = is_raw_mode return model