from json import load, loads from subprocess import run, PIPE, CalledProcessError from argparse import ArgumentParser from pathlib import Path # From nextcloud/lib/public/Constants.php # Based on nextcloud/custom_apps/groupfolders/lib/Command/Group.php permission_matrix = { 1: "read", 2 | 4: "write", 16: "share", 8: "delete", # 31: "all" } def convert_permission_to_text(permission_number) -> [str] : """Converts a permission number to text format.""" permissions = [] for permission_bit, permission_string in permission_matrix.items(): if permission_number & permission_bit == permission_bit: permissions.append(permission_string) return permissions def main(path : str, php :str, groups_file : str, group_folders_file : str): groups_file = Path(groups_file) if group_folders_file: group_folders_file = Path(group_folders_file) with groups_file.open("r", encoding="UTF-8") as file: groups = load(file) for gid, display_name in groups.items(): if gid == 'admin': continue try: run([php, "occ", "group:add", "--no-interaction", "--display-name", display_name, gid], cwd=path, check=True, stdout=PIPE, stderr=PIPE) print(f"Group {gid} created") except CalledProcessError as exception: if exception.returncode == 1: print(f"Group {gid} already already exist") if group_folders_file: with group_folders_file.open("r", encoding="UTF-8") as file: group_folders = load(file) out = run([php, "occ", "groupfolders:list", "--output", "json"], cwd=path, check=True, stdout=PIPE, stderr=PIPE) existing_gf = list(map(lambda gf: gf["mount_point"] , loads(out.stdout.decode().strip()))) for gf in group_folders: if gf["mount_point"] in existing_gf: print(f"Group folder {gf['mount_point']} already exist") continue out = run([php, "occ", "groupfolders:create", "--no-interaction", "--output", "json", gf["mount_point"]], cwd=path, check=True, stdout=PIPE, stderr=PIPE) new_gf = loads(out.stdout.decode().strip()) print(f"Group folder {gf['mount_point']} created") if gf["quota"] > 0: run([php, "occ", "groupfolders:quota", "--no-interaction", "--output", "json", str(new_gf), str(gf["quota"])], cwd=path, check=True, stdout=PIPE, stderr=PIPE) print(f"Group folder {gf['mount_point']} quota set to {gf['quota']}") else: print(f"Group folder {gf['mount_point']} quota set to unlimited") if gf["groups"]: for g_name, g_perms in gf["groups"].items(): perms = convert_permission_to_text(g_perms) run([php, "occ", "groupfolders:group", "--no-interaction", "--output", "json", str(new_gf), g_name, *perms], cwd=path, check=True, stdout=PIPE, stderr=PIPE) print(f"Group folder {gf['mount_point']} add group {g_name} with permissions "\ f"{' '.join(perms)}") # if gf["acl"]: # run([php, "occ", "groupfolders:permissions", "--no-interaction", "--output", "json", "-e", str(new_gf)], cwd=path, check=True, stdout=PIPE, stderr=PIPE) # print(f"Group folder {gf['mount_point']} now use ACL") # for manager in gf["manage"]: # try: # run([php, "occ", "groupfolders:permissions", "--no-interaction", "--output", "json", "-m", str(new_gf), manager], cwd=path, check=True, stdout=PIPE, stderr=PIPE) # print(f"Group folder {gid} manager {manager} added") # except CalledProcessError as e: # if e.returncode == 1: # print(f"Group folder {gid} manager {manager} can't be added") if __name__ == '__main__': parser = ArgumentParser(prog="groups_import") parser.add_argument("--path", "-p", default="/var/www/nextcloud") parser.add_argument("--php", "-P", default="php7.4") parser.add_argument("--groups", "-g", default="groups.json") parser.add_argument("--group-folders", "-f", default=None) args = parser.parse_args() main(args.path, args.php, args.groups, args.group_folders)