Holger Frey
3 years ago
7 changed files with 459 additions and 850 deletions
@ -1,6 +1,2 @@ |
|||||||
foo:$apr1$SzJRyvJU$U3luHwCA6xHfKowizE.Gl. |
AlexanderDietz:$apr1$n0Oaok6e$wyHcUg6Upm9sE2AoYlVMO/ |
||||||
FOO:$apr1$LSPDdLqg$tiGbDGgNEXcRA/oyadYSw1 |
|
||||||
AndreasEvers:$apr1$n0Oaok6e$wyHcUg6Upm9sE2AoYlVMO/ |
|
||||||
FOOBar:$apr1$pZCbClF5$smEDwhMJIVmPsNmMEkRPd1 |
|
||||||
FooBar:$apr1$24r9zF2e$9q30fNOqSlvn6itdhZMpc1 |
|
||||||
UrmilShh:$apr1$WxMGE8Wb$H0xWao6KZGqBJoXj7fJ420 |
UrmilShh:$apr1$WxMGE8Wb$H0xWao6KZGqBJoXj7fJ420 |
||||||
|
@ -0,0 +1,66 @@ |
|||||||
|
import shutil |
||||||
|
import tempfile |
||||||
|
from typing import Dict, List |
||||||
|
from pathlib import Path |
||||||
|
from dataclasses import dataclass |
||||||
|
|
||||||
|
import pytest |
||||||
|
|
||||||
|
|
||||||
|
@dataclass |
||||||
|
class StubCall: |
||||||
|
func: str |
||||||
|
args: List |
||||||
|
kargs: Dict |
||||||
|
|
||||||
|
|
||||||
|
class StubShell: |
||||||
|
|
||||||
|
STDOUT = "STDOUT" |
||||||
|
|
||||||
|
def __init__(self): |
||||||
|
self.stack = [] |
||||||
|
|
||||||
|
def _add(self, func, args, kargs): |
||||||
|
sc = StubCall(func, args, kargs) |
||||||
|
self.stack.append(sc) |
||||||
|
|
||||||
|
def check_call(self, args, **kargs): |
||||||
|
self._add("check_call", args, kargs) |
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture |
||||||
|
def stub_handler(): |
||||||
|
return StubShell() |
||||||
|
|
||||||
|
|
||||||
|
def temporary_data_file(src_data_dir, file_name): |
||||||
|
source = src_data_dir / file_name |
||||||
|
with tempfile.TemporaryDirectory() as tmpdirname: |
||||||
|
destination = Path(tmpdirname) / file_name |
||||||
|
shutil.copy(source, destination) |
||||||
|
yield destination |
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture |
||||||
|
def example_data_dir(): |
||||||
|
this_file = Path(__file__).absolute() |
||||||
|
src_dir = this_file.parent.parent |
||||||
|
return src_dir / "test-data" |
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture |
||||||
|
def example_authz(example_data_dir): |
||||||
|
yield from temporary_data_file(example_data_dir, "authz") |
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture |
||||||
|
def example_htpasswd(example_data_dir): |
||||||
|
yield from temporary_data_file(example_data_dir, "htpasswd") |
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture |
||||||
|
def example_empty_file(): |
||||||
|
with tempfile.TemporaryDirectory() as tmpdirname: |
||||||
|
destination = Path(tmpdirname) / "empty" |
||||||
|
yield destination |
@ -0,0 +1,258 @@ |
|||||||
|
import pytest |
||||||
|
|
||||||
|
|
||||||
|
def read_lines(path): |
||||||
|
with path.open("r") as fh: |
||||||
|
content = fh.read().strip() |
||||||
|
lines = content.splitlines() |
||||||
|
return [line.strip() for line in lines] |
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize( |
||||||
|
"value, expected", |
||||||
|
[ |
||||||
|
("no line break", "KEY = no line break"), |
||||||
|
("with\nline\nbreak", "KEY = with\n\tline\n\tbreak"), |
||||||
|
], |
||||||
|
) |
||||||
|
def test_authz_format_ini_option(value, expected): |
||||||
|
from elab_users.authz import format_ini_option |
||||||
|
|
||||||
|
result = format_ini_option("KEY", value) |
||||||
|
|
||||||
|
assert result == expected |
||||||
|
|
||||||
|
|
||||||
|
def test_authz_parser_init(): |
||||||
|
import configparser |
||||||
|
|
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser() |
||||||
|
|
||||||
|
assert isinstance(parser, configparser.ConfigParser) |
||||||
|
assert parser.elab_users == {} |
||||||
|
assert parser.original_path is None |
||||||
|
|
||||||
|
|
||||||
|
def test_authz_parser_optionxfrom(): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser() |
||||||
|
|
||||||
|
assert parser.optionxform(123) == "123" |
||||||
|
|
||||||
|
|
||||||
|
def test_authz_parser_read(example_authz): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser() |
||||||
|
parser.read(example_authz) |
||||||
|
|
||||||
|
assert parser.original_path == example_authz |
||||||
|
assert parser.elab_users != {} |
||||||
|
|
||||||
|
|
||||||
|
def test_authz_parser_from_file(example_authz): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser.from_file(example_authz) |
||||||
|
|
||||||
|
assert isinstance(parser, AuthzConfigParser) |
||||||
|
assert parser.original_path == example_authz |
||||||
|
assert parser.elab_users != {} |
||||||
|
|
||||||
|
|
||||||
|
def test_authz_parser_write_to_file_raises_error(): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser() |
||||||
|
|
||||||
|
with pytest.raises(IOError): |
||||||
|
parser.write_to_file(path=None) |
||||||
|
|
||||||
|
|
||||||
|
def test_authz_parser_write_to_file_uses_original_path( |
||||||
|
example_authz, example_empty_file |
||||||
|
): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser.from_file(example_authz) |
||||||
|
parser.original_path = example_empty_file |
||||||
|
parser.write_to_file(path=None) |
||||||
|
|
||||||
|
assert example_empty_file.is_file() |
||||||
|
|
||||||
|
|
||||||
|
def test_authz_parser_write_to_file_custom_path( |
||||||
|
example_authz, example_empty_file |
||||||
|
): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser.from_file(example_authz) |
||||||
|
parser.write_to_file(path=example_empty_file) |
||||||
|
|
||||||
|
assert example_empty_file.is_file() |
||||||
|
|
||||||
|
|
||||||
|
def test_authz_parser_write(example_authz, example_empty_file): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser.from_file(example_authz) |
||||||
|
with open(example_empty_file, "w") as fh: |
||||||
|
parser.write(fh) |
||||||
|
|
||||||
|
original = read_lines(example_authz) |
||||||
|
created = read_lines(example_empty_file) |
||||||
|
assert original == created |
||||||
|
|
||||||
|
|
||||||
|
def test_authz_parser_extract_user_info_from_config(example_authz): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser() |
||||||
|
|
||||||
|
super(type(parser), parser).read(example_authz) |
||||||
|
assert parser.elab_users == {} |
||||||
|
|
||||||
|
parser._extract_user_info_from_config() |
||||||
|
assert parser.elab_users != {} |
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize( |
||||||
|
"name, group", |
||||||
|
[ |
||||||
|
("OswaldPrucker", "administrators"), |
||||||
|
("AlexanderDietz", "users"), |
||||||
|
("UrmilShah", "restricted"), |
||||||
|
("CamillaOestevold", "alumni"), |
||||||
|
], |
||||||
|
) |
||||||
|
def test_authz_parser_extract_group_definitions(name, group, example_authz): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser() |
||||||
|
|
||||||
|
super(type(parser), parser).read(example_authz) |
||||||
|
parser._extract_group_definitions() |
||||||
|
|
||||||
|
user = parser.elab_users[name] |
||||||
|
assert user.group == group |
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize( |
||||||
|
"name, read, write", |
||||||
|
[ |
||||||
|
("OswaldPrucker", [], []), |
||||||
|
("AlexanderDietz", [], ["AlexanderDietz"]), |
||||||
|
("UrmilShah", ["AndreasEvers"], ["UrmilShah"]), |
||||||
|
], |
||||||
|
) |
||||||
|
def test_authz_parser_extract_individual_acls( |
||||||
|
name, read, write, example_authz |
||||||
|
): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser() |
||||||
|
|
||||||
|
super(type(parser), parser).read(example_authz) |
||||||
|
parser._extract_group_definitions() |
||||||
|
parser._extract_individual_acls() |
||||||
|
|
||||||
|
user = parser.elab_users[name] |
||||||
|
assert user.read_acl == set(read) |
||||||
|
assert user.write_acl == set(write) |
||||||
|
|
||||||
|
|
||||||
|
def test_authz_parser_group_users(example_authz): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser.from_file(example_authz) |
||||||
|
|
||||||
|
groups = parser.group_users() |
||||||
|
|
||||||
|
assert len(groups) == 4 |
||||||
|
assert len(groups["administrators"]) == 2 |
||||||
|
assert len(groups["users"]) == 54 |
||||||
|
assert len(groups["restricted"]) == 5 |
||||||
|
assert len(groups["alumni"]) == 62 |
||||||
|
|
||||||
|
|
||||||
|
def test_authz_parser_add_journal_acl_for(example_authz): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser.from_file(example_authz) |
||||||
|
|
||||||
|
user = parser.add_journal_acl_for("JaneDoe", "users") |
||||||
|
|
||||||
|
assert user.name == "JaneDoe" |
||||||
|
assert user.group == "users" |
||||||
|
assert parser.elab_users["JaneDoe"] == user |
||||||
|
assert "JaneDoe:/" in parser.sections() |
||||||
|
items = parser.items("JaneDoe:/") |
||||||
|
assert sorted(items) == [ |
||||||
|
("@administrators", "rw"), |
||||||
|
("@alumni", ""), |
||||||
|
("@restricted", ""), |
||||||
|
("@users", "r"), |
||||||
|
("JaneDoe", "rw"), |
||||||
|
] |
||||||
|
|
||||||
|
|
||||||
|
def test_authz_parser_move_user_to_alumni(example_authz): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser.from_file(example_authz) |
||||||
|
|
||||||
|
user = parser.move_user_to_alumni("UrmilShah") |
||||||
|
|
||||||
|
assert user.name == "UrmilShah" |
||||||
|
assert user.group == "alumni" |
||||||
|
assert user.write_acl == set() |
||||||
|
assert user.read_acl == set() |
||||||
|
|
||||||
|
for group, userlist in parser.items("groups"): |
||||||
|
if group == "alumni": |
||||||
|
assert "UrmilShah" in userlist |
||||||
|
else: |
||||||
|
assert "UrmilShah" not in userlist |
||||||
|
|
||||||
|
|
||||||
|
def test_authz_parser_update_user_group_config(example_authz): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser.from_file(example_authz) |
||||||
|
parser.elab_users["UrmilShah"].group = "alumni" |
||||||
|
|
||||||
|
parser._update_user_group_config() |
||||||
|
|
||||||
|
for group, userlist in parser.items("groups"): |
||||||
|
if group == "alumni": |
||||||
|
assert "UrmilShah" in userlist |
||||||
|
else: |
||||||
|
assert "UrmilShah" not in userlist |
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize( |
||||||
|
"elab, read, write", |
||||||
|
[ |
||||||
|
("AlexeyKopyshev:/", ["@users"], ["@administrators"]), |
||||||
|
( |
||||||
|
"AndreasEvers:/", |
||||||
|
["@users", "UrmilShah"], |
||||||
|
["@administrators"], |
||||||
|
), |
||||||
|
( |
||||||
|
"UrmilShah:/", |
||||||
|
["@users"], |
||||||
|
["@administrators", "UrmilShah"], |
||||||
|
), |
||||||
|
], |
||||||
|
) |
||||||
|
def test_authz_parser_get_journal_info(elab, read, write, example_authz): |
||||||
|
from elab_users.authz import AuthzConfigParser |
||||||
|
|
||||||
|
parser = AuthzConfigParser.from_file(example_authz) |
||||||
|
|
||||||
|
info = parser.get_journal_info(elab) |
||||||
|
assert info == {"r": read, "rw": write} |
@ -0,0 +1,104 @@ |
|||||||
|
# import pytest |
||||||
|
from datetime import datetime |
||||||
|
|
||||||
|
|
||||||
|
def test_elabuser_string_representation(): |
||||||
|
from elab_users.users import ElabUser |
||||||
|
|
||||||
|
eu = ElabUser("John Doe", "Some Group") |
||||||
|
|
||||||
|
assert str(eu) == "John Doe" |
||||||
|
|
||||||
|
|
||||||
|
def test_elabuser_set_new_password(stub_handler): |
||||||
|
from elab_users.users import ElabUser |
||||||
|
|
||||||
|
eu = ElabUser("John Doe", "Some Group") |
||||||
|
|
||||||
|
password = eu.set_new_password("some path", 12, handler=stub_handler) |
||||||
|
|
||||||
|
assert len(password) == 12 |
||||||
|
assert len(stub_handler.stack) == 1 |
||||||
|
called = stub_handler.stack[0] |
||||||
|
assert called.func == "check_call" |
||||||
|
assert called.args == [ |
||||||
|
"htpasswd", |
||||||
|
"-b", |
||||||
|
"some path", |
||||||
|
"John Doe", |
||||||
|
password, |
||||||
|
] |
||||||
|
assert called.kargs == {} |
||||||
|
|
||||||
|
|
||||||
|
def test_elabuser_delete_password(stub_handler): |
||||||
|
from elab_users.users import ElabUser |
||||||
|
|
||||||
|
eu = ElabUser("John Doe", "Some Group") |
||||||
|
|
||||||
|
eu.delete_password("some path", handler=stub_handler) |
||||||
|
|
||||||
|
assert len(stub_handler.stack) == 1 |
||||||
|
called = stub_handler.stack[0] |
||||||
|
assert called.func == "check_call" |
||||||
|
assert called.args == [ |
||||||
|
"htpasswd", |
||||||
|
"-D", |
||||||
|
"some path", |
||||||
|
"John Doe", |
||||||
|
] |
||||||
|
assert list(called.kargs.keys()) == ["stderr"] |
||||||
|
|
||||||
|
|
||||||
|
def test_elabuser_create_new_repo(stub_handler): |
||||||
|
from elab_users.users import ElabUser |
||||||
|
|
||||||
|
eu = ElabUser("John Doe", "Some Group") |
||||||
|
|
||||||
|
eu.create_new_repository("some path", handler=stub_handler) |
||||||
|
|
||||||
|
today = datetime.now() |
||||||
|
current_month = today.month |
||||||
|
current_year = today.year |
||||||
|
|
||||||
|
assert len(stub_handler.stack) == 8 + (12 - current_month) |
||||||
|
|
||||||
|
called = stub_handler.stack[0] |
||||||
|
assert called.func == "check_call" |
||||||
|
assert called.args == ["svnadmin", "create", "some path/John Doe"] |
||||||
|
assert called.kargs == {"stderr": stub_handler.STDOUT} |
||||||
|
|
||||||
|
called = stub_handler.stack[1] |
||||||
|
assert called.func == "check_call" |
||||||
|
assert called.args[:3] == ["svn", "checkout", "file://some path/John Doe"] |
||||||
|
assert called.args[3].startswith("/tmp/") # noqa: S108 |
||||||
|
assert called.kargs == {} |
||||||
|
|
||||||
|
called = stub_handler.stack[2] |
||||||
|
assert called.func == "check_call" |
||||||
|
assert called.args[0] == "touch" |
||||||
|
assert called.args[1].startswith("/tmp/") # noqa: S108 |
||||||
|
assert called.args[1].endswith( |
||||||
|
f"/{current_year:0>4}/{current_month:0>2}/.empty" |
||||||
|
) |
||||||
|
assert called.kargs == {} |
||||||
|
|
||||||
|
called = stub_handler.stack[-3] |
||||||
|
assert called.func == "check_call" |
||||||
|
assert called.args[0] == "cp" |
||||||
|
assert called.args[1] == "some path/template-toc.doc" |
||||||
|
assert called.args[2].startswith("/tmp/") # noqa: S108 |
||||||
|
assert called.args[2].endswith("/template-toc.doc") |
||||||
|
assert called.kargs == {} |
||||||
|
|
||||||
|
called = stub_handler.stack[-2] |
||||||
|
assert called.func == "check_call" |
||||||
|
assert called.args[:2] == ["svn", "add"] |
||||||
|
assert called.args[2].startswith("/tmp/") # noqa: S108 |
||||||
|
assert called.args[2].endswith("/*") |
||||||
|
assert called.kargs == {"shell": True} |
||||||
|
|
||||||
|
called = stub_handler.stack[-1] |
||||||
|
assert called.func == "check_call" |
||||||
|
assert called.args[:4] == ["svn", "commit", "-m", "New User: John Doe"] |
||||||
|
assert called.args[4].startswith("/tmp/") # noqa: S108 |
Loading…
Reference in new issue