import os import random import string import tempfile import subprocess # noqa: S404 from typing import Set from pathlib import Path from datetime import datetime from dataclasses import field, dataclass @dataclass class ElabUser: name: str group: str write_acl: Set = field(default_factory=set) read_acl: Set = field(default_factory=set) def __str__(self): """return a string representation""" return self.name def set_new_password(self, htpasswd_path, length=10, handler=subprocess): """sets a new random password for a user""" characters = string.ascii_letters + string.digits password = "".join( random.choice(characters) for i in range(length) # noqa: S311 ) handler.check_call( ["htpasswd", "-b", htpasswd_path, self.name, password] ) return password def delete_password(self, htpasswd_path, handler=subprocess): """deletes a password for a user""" # if the user was not added to the password db, the removal will show # an error message that is confusing to the user - at least it # confused me - so redirect this to /dev/null with open(os.devnull, "wb") as devnull: handler.check_call( ["htpasswd", "-D", htpasswd_path, self.name], stderr=devnull ) def create_new_repository(self, data_dir, handler=subprocess): """creates a repository for a user and checks in some stuff""" # create the new repository data_dir = Path(data_dir) new_repo = data_dir / self.name handler.check_call( ["svnadmin", "create", str(new_repo)], stderr=handler.STDOUT ) with tempfile.TemporaryDirectory() as tmpdir: tmpdir = Path(tmpdir) # check out a temporary working copy handler.check_call( ["svn", "checkout", f"file://{new_repo}", str(tmpdir)] ) # create subfolders today = datetime.now() year_path = tmpdir / f"{today.year:0>4}" year_path.mkdir() for month in range(today.month, 13): month_path = year_path / f"{month:0>2}" month_path.mkdir() handler.check_call(["touch", str(month_path / ".empty")]) # copy some examples for temp in ("experiment", "synthesis", "toc"): filename = f"template-{temp}.doc" in_file = data_dir / filename out_file = tmpdir / filename handler.check_call(["cp", str(in_file), str(out_file)]) # add and commit the changes handler.check_call( ["svn", "add", "--force", str(tmpdir) + "/"] # noqa: S604 ) handler.check_call( ["svn", "commit", "-m", f"New User: {self.name}", str(tmpdir)] )