yunohost/src/tests/test_permission.py

1151 lines
38 KiB
Python

import socket
import requests
import pytest
import string
import os
import json
import shutil
from .conftest import message, raiseYunohostError, get_test_apps_dir
from yunohost.app import (
app_install,
app_upgrade,
app_remove,
app_change_url,
app_map,
_installed_apps,
APPS_SETTING_PATH,
_set_app_settings,
_get_app_settings,
)
from yunohost.user import (
user_list,
user_create,
user_delete,
user_group_list,
user_group_delete,
)
from yunohost.permission import (
user_permission_update,
user_permission_list,
user_permission_reset,
permission_create,
permission_delete,
permission_url,
)
from yunohost.domain import _get_maindomain, domain_add, domain_remove, domain_list
# Get main domain
maindomain = ""
other_domains = []
dummy_password = "test123Ynh"
# Dirty patch of DNS resolution. Force the DNS to 127.0.0.1 address even if dnsmasq have the public address.
# Mainly used for 'can_access_webpage' function
prv_getaddrinfo = socket.getaddrinfo
def _permission_create_with_dummy_app(
permission,
allowed=None,
url=None,
additional_urls=None,
auth_header=True,
label=None,
show_tile=False,
protected=True,
sync_perm=True,
domain=None,
path=None,
):
app = permission.split(".")[0]
if app not in _installed_apps():
app_setting_path = os.path.join(APPS_SETTING_PATH, app)
if not os.path.exists(app_setting_path):
os.makedirs(app_setting_path)
settings = {"id": app, "dummy_permission_app": True}
if domain:
settings["domain"] = domain
if path:
settings["path"] = path
_set_app_settings(app, settings)
with open(os.path.join(APPS_SETTING_PATH, app, "manifest.json"), "w") as f:
json.dump(
{
"name": app,
"id": app,
"description": {"en": "Dummy app to test permissions"},
"arguments": {"install": []},
},
f,
)
permission_create(
permission=permission,
allowed=allowed,
url=url,
additional_urls=additional_urls,
auth_header=auth_header,
label=label,
show_tile=show_tile,
protected=protected,
sync_perm=sync_perm,
)
def _clear_dummy_app_settings():
# Clean dummy app settings
for app in _installed_apps():
if _get_app_settings(app).get("dummy_permission_app", False):
app_setting_path = os.path.join(APPS_SETTING_PATH, app)
if os.path.exists(app_setting_path):
shutil.rmtree(app_setting_path)
def clean_user_groups_permission():
for u in user_list()["users"]:
user_delete(u)
for g in user_group_list()["groups"]:
if g not in ["all_users", "visitors", "admins"]:
user_group_delete(g)
for p in user_permission_list()["permissions"]:
if any(
p.startswith(name)
for name in ["wiki", "blog", "site", "web", "permissions_app"]
):
permission_delete(p, force=True, sync_perm=False)
socket.getaddrinfo = prv_getaddrinfo
def setup_function(function):
clean_user_groups_permission()
global maindomain
global other_domains
maindomain = _get_maindomain()
markers = {
m.name: {"args": m.args, "kwargs": m.kwargs}
for m in function.__dict__.get("pytestmark", [])
}
if "other_domains" in markers:
other_domains = [
"domain_%s.dev" % string.ascii_lowercase[number]
for number in range(markers["other_domains"]["kwargs"]["number"])
]
for domain in other_domains:
if domain not in domain_list()["domains"]:
domain_add(domain)
# Dirty patch of DNS resolution. Force the DNS to 127.0.0.1 address even if dnsmasq have the public address.
# Mainly used for 'can_access_webpage' function
dns_cache = {(maindomain, 443, 0, 1): [(2, 1, 6, "", ("127.0.0.1", 443))]}
for domain in other_domains:
dns_cache[(domain, 443, 0, 1)] = [(2, 1, 6, "", ("127.0.0.1", 443))]
def new_getaddrinfo(*args):
try:
return dns_cache[args]
except KeyError:
res = prv_getaddrinfo(*args)
dns_cache[args] = res
return res
socket.getaddrinfo = new_getaddrinfo
user_create("alice", maindomain, dummy_password, fullname="Alice White", admin=True)
user_create("bob", maindomain, dummy_password, fullname="Bob Snow")
_permission_create_with_dummy_app(
permission="wiki.main",
url="/",
additional_urls=["/whatever", "/idontnow"],
auth_header=False,
label="Wiki",
show_tile=True,
allowed=["all_users"],
protected=False,
sync_perm=False,
domain=maindomain,
path="/wiki",
)
_permission_create_with_dummy_app(
permission="blog.main",
url="/",
auth_header=True,
show_tile=False,
protected=False,
sync_perm=False,
allowed=["alice"],
domain=maindomain,
path="/blog",
)
_permission_create_with_dummy_app(
permission="blog.api", allowed=["visitors"], protected=True, sync_perm=True
)
def teardown_function(function):
clean_user_groups_permission()
global other_domains
for domain in other_domains:
domain_remove(domain)
other_domains = []
_clear_dummy_app_settings()
try:
app_remove("permissions_app")
except Exception:
pass
try:
app_remove("legacy_app")
except Exception:
pass
def teardown_module(module):
global other_domains
for domain in other_domains:
domain_remove(domain)
@pytest.fixture(autouse=True)
def check_LDAP_db_integrity_call():
check_LDAP_db_integrity()
yield
check_LDAP_db_integrity()
def check_LDAP_db_integrity():
# Here we check that all attributes in all object are sychronized.
# Here is the list of attributes per object:
# user : memberOf, permission
# group : member, permission
# permission : groupPermission, inheritPermission
#
# The idea is to check that all attributes on all sides of object are sychronized.
# One part should be done automatically by the "memberOf" overlay of LDAP.
# The other part is done by the the "permission_sync_to_user" function of the permission module
from yunohost.utils.ldap import _get_ldap_interface, _ldap_path_extract
ldap = _get_ldap_interface()
user_search = ldap.search(
"ou=users",
"(&(objectclass=person)(!(uid=root))(!(uid=nobody)))",
["uid", "memberOf", "permission"],
)
group_search = ldap.search(
"ou=groups",
"(objectclass=groupOfNamesYnh)",
["cn", "member", "memberUid", "permission"],
)
permission_search = ldap.search(
"ou=permission",
"(objectclass=permissionYnh)",
["cn", "groupPermission", "inheritPermission", "memberUid"],
)
user_map = {u["uid"][0]: u for u in user_search}
group_map = {g["cn"][0]: g for g in group_search}
permission_map = {p["cn"][0]: p for p in permission_search}
for user in user_search:
user_dn = "uid=" + user["uid"][0] + ",ou=users,dc=yunohost,dc=org"
group_list = [_ldap_path_extract(m, "cn") for m in user.get("memberOf", [])]
permission_list = [
_ldap_path_extract(m, "cn") for m in user.get("permission", [])
]
# This user's DN sould be found in all groups it is a member of
for group in group_list:
assert user_dn in group_map[group]["member"]
# This user's DN should be found in all perms it has access to
for permission in permission_list:
assert user_dn in permission_map[permission]["inheritPermission"]
for permission in permission_search:
permission_dn = (
"cn=" + permission["cn"][0] + ",ou=permission,dc=yunohost,dc=org"
)
# inheritPermission uid's should match memberUids
user_list = [
_ldap_path_extract(m, "uid")
for m in permission.get("inheritPermission", [])
]
assert set(user_list) == set(permission.get("memberUid", []))
# This perm's DN should be found on all related users it is related to
for user in user_list:
assert permission_dn in user_map[user]["permission"]
# Same for groups : we should find the permission's DN for all related groups
group_list = [
_ldap_path_extract(m, "cn") for m in permission.get("groupPermission", [])
]
for group in group_list:
assert permission_dn in group_map[group]["permission"]
# The list of user in the group should be a subset of all users related to the current permission
users_in_group = [
_ldap_path_extract(m, "uid") for m in group_map[group].get("member", [])
]
assert set(users_in_group) <= set(user_list)
for group in group_search:
group_dn = "cn=" + group["cn"][0] + ",ou=groups,dc=yunohost,dc=org"
user_list = [_ldap_path_extract(m, "uid") for m in group.get("member", [])]
# For primary groups, we should find that :
# - len(user_list) is 1 (a primary group has only 1 member)
# - the group name should be an existing yunohost user
# - memberUid is empty (meaning no other member than the corresponding user)
if group["cn"][0] in user_list:
assert len(user_list) == 1
assert group["cn"][0] in user_map
assert group.get("memberUid", []) == []
# Otherwise, user_list and memberUid should have the same content
else:
assert set(user_list) == set(group.get("memberUid", []))
# For all users members, this group should be in the "memberOf" on the other side
for user in user_list:
assert group_dn in user_map[user]["memberOf"]
# For all the permissions of this group, the group should be among the "groupPermission" on the other side
permission_list = [
_ldap_path_extract(m, "cn") for m in group.get("permission", [])
]
for permission in permission_list:
assert group_dn in permission_map[permission]["groupPermission"]
# And the list of user of this group (user_list) should be a subset of all allowed users for this perm...
allowed_user_list = [
_ldap_path_extract(m, "uid")
for m in permission_map[permission].get("inheritPermission", [])
]
assert set(user_list) <= set(allowed_user_list)
def check_permission_for_apps():
# We check that the for each installed apps we have at last the "main" permission
# and we don't have any permission linked to no apps. The only exception who is not liked to an app
# is mail, xmpp, and sftp
app_perms = user_permission_list(ignore_system_perms=True)["permissions"].keys()
# Keep only the prefix so that
# ["foo.main", "foo.pwet", "bar.main"]
# becomes
# {"bar", "foo"}
# and compare this to the list of installed apps ...
app_perms_prefix = {p.split(".")[0] for p in app_perms}
assert set(_installed_apps()) == app_perms_prefix
def can_access_webpage(webpath, logged_as=None):
webpath = webpath.rstrip("/")
sso_url = "https://" + maindomain + "/yunohost/portalapi/login"
# Anonymous access
if not logged_as:
r = requests.get(webpath, verify=False)
# Login as a user using dummy password
else:
with requests.Session() as session:
session.post(
sso_url,
data={"credentials": f"{logged_as}:{dummy_password}"},
headers={
"Referer": sso_url,
"Content-Type": "application/x-www-form-urlencoded",
},
verify=False,
)
# We should have some cookies related to authentication now
assert session.cookies
r = session.get(webpath, verify=False)
# If we can't access it, we got redirected to the SSO
return not r.url.startswith(sso_url)
#
# List functions
#
def test_permission_list():
res = user_permission_list(full=True)["permissions"]
assert "mail.main" in res
assert "xmpp.main" in res
assert "wiki.main" in res
assert "blog.main" in res
assert "blog.api" in res
assert res["wiki.main"]["allowed"] == ["all_users"]
assert res["blog.main"]["allowed"] == ["alice"]
assert res["blog.api"]["allowed"] == ["visitors"]
assert set(res["wiki.main"]["corresponding_users"]) == {"alice", "bob"}
assert res["blog.main"]["corresponding_users"] == ["alice"]
assert res["blog.api"]["corresponding_users"] == []
assert res["wiki.main"]["url"] == "/"
assert res["blog.main"]["url"] == "/"
assert res["blog.api"]["url"] is None
assert set(res["wiki.main"]["additional_urls"]) == {"/whatever", "/idontnow"}
assert res["wiki.main"]["protected"] is False
assert res["blog.main"]["protected"] is False
assert res["blog.api"]["protected"] is True
assert res["wiki.main"]["label"] == "Wiki"
assert res["blog.main"]["label"] == "Blog"
assert res["blog.api"]["label"] == "Blog (api)"
assert res["wiki.main"]["show_tile"] is True
assert res["blog.main"]["show_tile"] is False
assert res["blog.api"]["show_tile"] is False
assert res["wiki.main"]["auth_header"] is False
assert res["blog.main"]["auth_header"] is True
assert res["blog.api"]["auth_header"] is True
res = user_permission_list(full=True, absolute_urls=True)["permissions"]
assert res["wiki.main"]["url"] == maindomain + "/wiki"
assert res["blog.main"]["url"] == maindomain + "/blog"
assert res["blog.api"]["url"] is None
assert set(res["wiki.main"]["additional_urls"]) == {
maindomain + "/wiki/whatever",
maindomain + "/wiki/idontnow",
}
assert res["blog.main"]["additional_urls"] == []
assert res["blog.api"]["additional_urls"] == []
#
# Create - Remove functions
#
def test_permission_create_main():
with message("permission_created", permission="site.main"):
permission_create("site.main", allowed=["all_users"], protected=False)
res = user_permission_list(full=True)["permissions"]
assert "site.main" in res
assert res["site.main"]["allowed"] == ["all_users"]
assert set(res["site.main"]["corresponding_users"]) == {"alice", "bob"}
assert res["site.main"]["protected"] is False
def test_permission_create_extra():
with message("permission_created", permission="site.test"):
permission_create("site.test")
res = user_permission_list(full=True)["permissions"]
assert "site.test" in res
# all_users is only enabled by default on .main perms
assert "all_users" not in res["site.test"]["allowed"]
assert res["site.test"]["corresponding_users"] == []
assert res["site.test"]["protected"] is False
def test_permission_create_with_specific_user():
permission_create("site.test", allowed=["alice"])
res = user_permission_list(full=True)["permissions"]
assert "site.test" in res
assert res["site.test"]["allowed"] == ["alice"]
def test_permission_create_with_tile_management():
with message("permission_created", permission="site.main"):
_permission_create_with_dummy_app(
"site.main",
allowed=["all_users"],
label="The Site",
show_tile=False,
domain=maindomain,
path="/site",
)
res = user_permission_list(full=True)["permissions"]
assert "site.main" in res
assert res["site.main"]["label"] == "The Site"
assert res["site.main"]["show_tile"] is False
def test_permission_create_with_tile_management_with_main_default_value():
with message("permission_created", permission="site.main"):
_permission_create_with_dummy_app(
"site.main",
allowed=["all_users"],
show_tile=True,
url="/",
domain=maindomain,
path="/site",
)
res = user_permission_list(full=True)["permissions"]
assert "site.main" in res
assert res["site.main"]["label"] == "Site"
assert res["site.main"]["show_tile"] is True
def test_permission_create_with_tile_management_with_not_main_default_value():
with message("permission_created", permission="wiki.api"):
_permission_create_with_dummy_app(
"wiki.api",
allowed=["all_users"],
show_tile=True,
url="/",
domain=maindomain,
path="/site",
)
res = user_permission_list(full=True)["permissions"]
assert "wiki.api" in res
assert res["wiki.api"]["label"] == "Wiki (api)"
assert res["wiki.api"]["show_tile"] is True
def test_permission_create_with_urls_management_without_url():
with message("permission_created", permission="wiki.api"):
_permission_create_with_dummy_app(
"wiki.api", allowed=["all_users"], domain=maindomain, path="/site"
)
res = user_permission_list(full=True)["permissions"]
assert "wiki.api" in res
assert res["wiki.api"]["url"] is None
assert res["wiki.api"]["additional_urls"] == []
assert res["wiki.api"]["auth_header"] is True
def test_permission_create_with_urls_management_simple_domain():
with message("permission_created", permission="site.main"):
_permission_create_with_dummy_app(
"site.main",
allowed=["all_users"],
url="/",
additional_urls=["/whatever", "/idontnow"],
auth_header=False,
domain=maindomain,
path="/site",
)
res = user_permission_list(full=True, absolute_urls=True)["permissions"]
assert "site.main" in res
assert res["site.main"]["url"] == maindomain + "/site"
assert set(res["site.main"]["additional_urls"]) == {
maindomain + "/site/whatever",
maindomain + "/site/idontnow",
}
assert res["site.main"]["auth_header"] is False
@pytest.mark.other_domains(number=2)
def test_permission_create_with_urls_management_multiple_domain():
with message("permission_created", permission="site.main"):
_permission_create_with_dummy_app(
"site.main",
allowed=["all_users"],
url=maindomain + "/site/something",
additional_urls=[other_domains[0] + "/blabla", other_domains[1] + "/ahh"],
auth_header=True,
domain=maindomain,
path="/site",
)
res = user_permission_list(full=True, absolute_urls=True)["permissions"]
assert "site.main" in res
assert res["site.main"]["url"] == maindomain + "/site/something"
assert set(res["site.main"]["additional_urls"]) == {
other_domains[0] + "/blabla",
other_domains[1] + "/ahh",
}
assert res["site.main"]["auth_header"] is True
def test_permission_delete():
with message("permission_deleted", permission="wiki.main"):
permission_delete("wiki.main", force=True)
res = user_permission_list()["permissions"]
assert "wiki.main" not in res
with message("permission_deleted", permission="blog.api"):
permission_delete("blog.api", force=False)
res = user_permission_list()["permissions"]
assert "blog.api" not in res
#
# Error on create - remove function
#
def test_permission_create_already_existing(mocker):
with raiseYunohostError(mocker, "permission_already_exist"):
permission_create("wiki.main")
def test_permission_delete_doesnt_existing(mocker):
with raiseYunohostError(mocker, "permission_not_found"):
permission_delete("doesnt.exist", force=True)
res = user_permission_list()["permissions"]
assert "wiki.main" in res
assert "blog.main" in res
assert "mail.main" in res
assert "xmpp.main" in res
def test_permission_delete_main_without_force(mocker):
with raiseYunohostError(mocker, "permission_cannot_remove_main"):
permission_delete("blog.main")
res = user_permission_list()["permissions"]
assert "blog.main" in res
#
# Update functions
#
# user side functions
def test_permission_add_group():
with message("permission_updated", permission="wiki.main"):
user_permission_update("wiki.main", add="alice")
res = user_permission_list(full=True)["permissions"]
assert set(res["wiki.main"]["allowed"]) == {"all_users", "alice"}
assert set(res["wiki.main"]["corresponding_users"]) == {"alice", "bob"}
def test_permission_remove_group():
with message("permission_updated", permission="blog.main"):
user_permission_update("blog.main", remove="alice")
res = user_permission_list(full=True)["permissions"]
assert res["blog.main"]["allowed"] == []
assert res["blog.main"]["corresponding_users"] == []
def test_permission_add_and_remove_group():
with message("permission_updated", permission="wiki.main"):
user_permission_update("wiki.main", add="alice", remove="all_users")
res = user_permission_list(full=True)["permissions"]
assert res["wiki.main"]["allowed"] == ["alice"]
assert res["wiki.main"]["corresponding_users"] == ["alice"]
def test_permission_add_group_already_allowed():
with message(
"permission_already_allowed", permission="blog.main", group="alice"
):
user_permission_update("blog.main", add="alice")
res = user_permission_list(full=True)["permissions"]
assert res["blog.main"]["allowed"] == ["alice"]
assert res["blog.main"]["corresponding_users"] == ["alice"]
def test_permission_remove_group_already_not_allowed():
with message(
"permission_already_disallowed", permission="blog.main", group="bob"
):
user_permission_update("blog.main", remove="bob")
res = user_permission_list(full=True)["permissions"]
assert res["blog.main"]["allowed"] == ["alice"]
assert res["blog.main"]["corresponding_users"] == ["alice"]
def test_permission_reset():
with message("permission_updated", permission="blog.main"):
user_permission_reset("blog.main")
res = user_permission_list(full=True)["permissions"]
assert res["blog.main"]["allowed"] == ["all_users"]
assert set(res["blog.main"]["corresponding_users"]) == {"alice", "bob"}
def test_permission_reset_idempotency():
# Reset permission
user_permission_reset("blog.main")
user_permission_reset("blog.main")
res = user_permission_list(full=True)["permissions"]
assert res["blog.main"]["allowed"] == ["all_users"]
assert set(res["blog.main"]["corresponding_users"]) == {"alice", "bob"}
def test_permission_change_label():
with message("permission_updated", permission="wiki.main"):
user_permission_update("wiki.main", label="New Wiki")
res = user_permission_list(full=True)["permissions"]
assert res["wiki.main"]["label"] == "New Wiki"
def test_permission_change_label_with_same_value():
with message("permission_updated", permission="wiki.main"):
user_permission_update("wiki.main", label="Wiki")
res = user_permission_list(full=True)["permissions"]
assert res["wiki.main"]["label"] == "Wiki"
def test_permission_switch_show_tile():
# Note that from the actionmap the value is passed as string, not as bool
# Try with lowercase
with message("permission_updated", permission="wiki.main"):
user_permission_update("wiki.main", show_tile="false")
res = user_permission_list(full=True)["permissions"]
assert res["wiki.main"]["show_tile"] is False
# Try with uppercase
with message("permission_updated", permission="wiki.main"):
user_permission_update("wiki.main", show_tile="TRUE")
res = user_permission_list(full=True)["permissions"]
assert res["wiki.main"]["show_tile"] is True
def test_permission_switch_show_tile_with_same_value():
# Note that from the actionmap the value is passed as string, not as bool
with message("permission_updated", permission="wiki.main"):
user_permission_update("wiki.main", show_tile="True")
res = user_permission_list(full=True)["permissions"]
assert res["wiki.main"]["show_tile"] is True
#
# Error on update function
#
def test_permission_add_group_that_doesnt_exist(mocker):
with raiseYunohostError(mocker, "group_unknown"):
user_permission_update("blog.main", add="doesnt_exist")
res = user_permission_list(full=True)["permissions"]
assert res["blog.main"]["allowed"] == ["alice"]
assert res["blog.main"]["corresponding_users"] == ["alice"]
def test_permission_update_permission_that_doesnt_exist(mocker):
with raiseYunohostError(mocker, "permission_not_found"):
user_permission_update("doesnt.exist", add="alice")
def test_permission_protected_update(mocker):
res = user_permission_list(full=True)["permissions"]
assert res["blog.api"]["allowed"] == ["visitors"]
with raiseYunohostError(mocker, "permission_protected"):
user_permission_update("blog.api", remove="visitors")
res = user_permission_list(full=True)["permissions"]
assert res["blog.api"]["allowed"] == ["visitors"]
user_permission_update("blog.api", remove="visitors", force=True)
res = user_permission_list(full=True)["permissions"]
assert res["blog.api"]["allowed"] == []
with raiseYunohostError(mocker, "permission_protected"):
user_permission_update("blog.api", add="visitors")
res = user_permission_list(full=True)["permissions"]
assert res["blog.api"]["allowed"] == []
# Permission url management
def test_permission_redefine_url():
permission_url("blog.main", url="/pwet")
res = user_permission_list(full=True)["permissions"]
assert res["blog.main"]["url"] == "/pwet"
def test_permission_remove_url():
permission_url("blog.main", clear_urls=True)
res = user_permission_list(full=True)["permissions"]
assert res["blog.main"]["url"] is None
def test_permission_main_url_regex():
permission_url("blog.main", url="re:/[a-z]+reboy/.*")
res = user_permission_list(full=True)["permissions"]
assert res["blog.main"]["url"] == "re:/[a-z]+reboy/.*"
res = user_permission_list(full=True, absolute_urls=True)["permissions"]
assert res["blog.main"]["url"] == "re:%s/blog/[a-z]+reboy/.*" % maindomain.replace(
".", r"\."
)
def test_permission_main_url_bad_regex(mocker):
with raiseYunohostError(mocker, "invalid_regex"):
permission_url("blog.main", url="re:/[a-z]+++reboy/.*")
@pytest.mark.other_domains(number=1)
def test_permission_add_additional_url():
permission_url("wiki.main", add_url=[other_domains[0] + "/heyby", "/myhouse"])
res = user_permission_list(full=True, absolute_urls=True)["permissions"]
assert res["wiki.main"]["url"] == maindomain + "/wiki"
assert set(res["wiki.main"]["additional_urls"]) == {
maindomain + "/wiki/whatever",
maindomain + "/wiki/idontnow",
other_domains[0] + "/heyby",
maindomain + "/wiki/myhouse",
}
def test_permission_add_additional_regex():
permission_url("blog.main", add_url=["re:/[a-z]+reboy/.*"])
res = user_permission_list(full=True)["permissions"]
assert res["blog.main"]["additional_urls"] == ["re:/[a-z]+reboy/.*"]
res = user_permission_list(full=True, absolute_urls=True)["permissions"]
assert res["blog.main"]["additional_urls"] == [
"re:%s/blog/[a-z]+reboy/.*" % maindomain.replace(".", r"\.")
]
def test_permission_add_additional_bad_regex(mocker):
with raiseYunohostError(mocker, "invalid_regex"):
permission_url("blog.main", add_url=["re:/[a-z]+++reboy/.*"])
def test_permission_remove_additional_url():
permission_url("wiki.main", remove_url=["/whatever"])
res = user_permission_list(full=True, absolute_urls=True)["permissions"]
assert res["wiki.main"]["url"] == maindomain + "/wiki"
assert res["wiki.main"]["additional_urls"] == [maindomain + "/wiki/idontnow"]
def test_permssion_add_additional_url_already_exist():
permission_url("wiki.main", add_url=["/whatever", "/myhouse"])
permission_url("wiki.main", add_url=["/whatever"])
res = user_permission_list(full=True, absolute_urls=True)["permissions"]
assert res["wiki.main"]["url"] == maindomain + "/wiki"
assert set(res["wiki.main"]["additional_urls"]) == {
maindomain + "/wiki/whatever",
maindomain + "/wiki/idontnow",
maindomain + "/wiki/myhouse",
}
def test_permission_remove_additional_url_dont_exist():
permission_url("wiki.main", remove_url=["/shouldntexist", "/whatever"])
permission_url("wiki.main", remove_url=["/shouldntexist"])
res = user_permission_list(full=True, absolute_urls=True)["permissions"]
assert res["wiki.main"]["url"] == maindomain + "/wiki"
assert res["wiki.main"]["additional_urls"] == [maindomain + "/wiki/idontnow"]
def test_permission_clear_additional_url():
permission_url("wiki.main", clear_urls=True)
res = user_permission_list(full=True)["permissions"]
assert res["wiki.main"]["url"] is None
assert res["wiki.main"]["additional_urls"] == []
def test_permission_switch_auth_header():
permission_url("wiki.main", auth_header=True)
res = user_permission_list(full=True)["permissions"]
assert res["wiki.main"]["auth_header"] is True
permission_url("wiki.main", auth_header=False)
res = user_permission_list(full=True)["permissions"]
assert res["wiki.main"]["auth_header"] is False
def test_permission_switch_auth_header_with_same_value():
permission_url("wiki.main", auth_header=False)
res = user_permission_list(full=True)["permissions"]
assert res["wiki.main"]["auth_header"] is False
# Permission protected
def test_permission_switch_protected():
user_permission_update("wiki.main", protected=True)
res = user_permission_list(full=True)["permissions"]
assert res["wiki.main"]["protected"] is True
user_permission_update("wiki.main", protected=False)
res = user_permission_list(full=True)["permissions"]
assert res["wiki.main"]["protected"] is False
def test_permission_switch_protected_with_same_value():
user_permission_update("wiki.main", protected=False)
res = user_permission_list(full=True)["permissions"]
assert res["wiki.main"]["protected"] is False
# Test SSOWAT conf generation
def test_ssowat_conf():
with open("/etc/ssowat/conf.json") as f:
res = json.load(f)
permissions = res["permissions"]
assert "wiki.main" in permissions
assert "blog.main" in permissions
assert (
"blog.api" not in permissions
) # blog.api has no url/additional url defined and therefore is not added to ssowat conf
assert set(permissions["wiki.main"]["users"]) == {"alice", "bob"}
assert permissions["blog.main"]["users"] == ["alice"]
assert permissions["wiki.main"]["uris"][0] == maindomain + "/wiki"
assert set(permissions["wiki.main"]["uris"]) == {
maindomain + "/wiki",
maindomain + "/wiki/whatever",
maindomain + "/wiki/idontnow",
}
assert permissions["blog.main"]["uris"] == [maindomain + "/blog"]
assert permissions["wiki.main"]["public"] is False
assert permissions["blog.main"]["public"] is False
assert permissions["wiki.main"]["auth_header"] is False
assert permissions["blog.main"]["auth_header"] is True
def test_show_tile_cant_be_enabled():
_permission_create_with_dummy_app(
permission="site.main",
auth_header=False,
label="Site",
show_tile=True,
allowed=["all_users"],
protected=False,
sync_perm=False,
domain=maindomain,
path="/site",
)
_permission_create_with_dummy_app(
permission="web.main",
url="re:/[a-z]{3}/bla",
auth_header=False,
label="Web",
show_tile=True,
allowed=["all_users"],
protected=False,
sync_perm=True,
domain=maindomain,
path="/web",
)
permissions = user_permission_list(full=True)["permissions"]
assert permissions["site.main"]["show_tile"] is False
assert permissions["web.main"]["show_tile"] is False
#
# Application interaction
#
@pytest.mark.other_domains(number=1)
def test_permission_app_install():
app_install(
os.path.join(get_test_apps_dir(), "permissions_app_ynh"),
args="domain=%s&domain_2=%s&path=%s&is_public=0&admin=%s"
% (maindomain, other_domains[0], "/urlpermissionapp", "alice"),
force=True,
)
res = user_permission_list(full=True)["permissions"]
assert "permissions_app.main" in res
assert "permissions_app.admin" in res
assert "permissions_app.dev" in res
assert res["permissions_app.main"]["url"] == "/"
assert res["permissions_app.admin"]["url"] == "/admin"
assert res["permissions_app.dev"]["url"] == "/dev"
assert res["permissions_app.main"]["allowed"] == ["all_users"]
assert set(res["permissions_app.main"]["corresponding_users"]) == {"alice", "bob"}
assert res["permissions_app.admin"]["allowed"] == ["alice"]
assert res["permissions_app.admin"]["corresponding_users"] == ["alice"]
assert res["permissions_app.dev"]["allowed"] == []
assert set(res["permissions_app.dev"]["corresponding_users"]) == set()
# Check that we get the right stuff in app_map, which is used to generate the ssowatconf
assert maindomain + "/urlpermissionapp" in app_map(user="alice").keys()
user_permission_update("permissions_app.main", remove="all_users", add="bob")
assert maindomain + "/urlpermissionapp" not in app_map(user="alice").keys()
assert maindomain + "/urlpermissionapp" in app_map(user="bob").keys()
@pytest.mark.other_domains(number=1)
def test_permission_app_remove():
app_install(
os.path.join(get_test_apps_dir(), "permissions_app_ynh"),
args="domain=%s&domain_2=%s&path=%s&is_public=0&admin=%s"
% (maindomain, other_domains[0], "/urlpermissionapp", "alice"),
force=True,
)
app_remove("permissions_app")
# Check all permissions for this app got deleted
res = user_permission_list(full=True)["permissions"]
assert not any(p.startswith("permissions_app.") for p in res.keys())
@pytest.mark.other_domains(number=1)
def test_permission_app_change_url():
app_install(
os.path.join(get_test_apps_dir(), "permissions_app_ynh"),
args="domain=%s&domain_2=%s&path=%s&is_public=1&admin=%s"
% (maindomain, other_domains[0], "/urlpermissionapp", "alice"),
force=True,
)
# FIXME : should rework this test to look for differences in the generated app map / app tiles ...
res = user_permission_list(full=True)["permissions"]
assert res["permissions_app.main"]["url"] == "/"
assert res["permissions_app.admin"]["url"] == "/admin"
assert res["permissions_app.dev"]["url"] == "/dev"
app_change_url("permissions_app", maindomain, "/newchangeurl")
res = user_permission_list(full=True)["permissions"]
assert res["permissions_app.main"]["url"] == "/"
assert res["permissions_app.admin"]["url"] == "/admin"
assert res["permissions_app.dev"]["url"] == "/dev"
@pytest.mark.other_domains(number=1)
def test_permission_protection_management_by_helper():
app_install(
os.path.join(get_test_apps_dir(), "permissions_app_ynh"),
args="domain=%s&domain_2=%s&path=%s&is_public=1&admin=%s"
% (maindomain, other_domains[0], "/urlpermissionapp", "alice"),
force=True,
)
res = user_permission_list(full=True)["permissions"]
assert res["permissions_app.main"]["protected"] is False
assert res["permissions_app.admin"]["protected"] is True
assert res["permissions_app.dev"]["protected"] is False
app_upgrade(
["permissions_app"],
file=os.path.join(get_test_apps_dir(), "permissions_app_ynh"),
)
res = user_permission_list(full=True)["permissions"]
assert res["permissions_app.main"]["protected"] is False
assert res["permissions_app.admin"]["protected"] is False
assert res["permissions_app.dev"]["protected"] is True
@pytest.mark.other_domains(number=1)
def test_permission_app_propagation_on_ssowat():
app_install(
os.path.join(get_test_apps_dir(), "permissions_app_ynh"),
args="domain=%s&domain_2=%s&path=%s&is_public=1&admin=%s"
% (maindomain, other_domains[0], "/urlpermissionapp", "alice"),
force=True,
)
res = user_permission_list(full=True)["permissions"]
assert "visitors" in res["permissions_app.main"]["allowed"]
assert "all_users" in res["permissions_app.main"]["allowed"]
app_webroot = "https://%s/urlpermissionapp" % maindomain
assert can_access_webpage(app_webroot, logged_as=None)
assert can_access_webpage(app_webroot, logged_as="alice")
user_permission_update(
"permissions_app.main", remove=["visitors", "all_users"], add="bob"
)
res = user_permission_list(full=True)["permissions"]
assert not can_access_webpage(app_webroot, logged_as=None)
assert not can_access_webpage(app_webroot, logged_as="alice")
assert can_access_webpage(app_webroot, logged_as="bob")
# Test admin access, as configured during install, only alice should be able to access it
# alice gotta be allowed on the main permission to access the admin tho
user_permission_update("permissions_app.main", remove="bob", add="all_users")
assert not can_access_webpage(app_webroot + "/admin", logged_as=None)
assert can_access_webpage(app_webroot + "/admin", logged_as="alice")
assert not can_access_webpage(app_webroot + "/admin", logged_as="bob")
@pytest.mark.other_domains(number=1)
def test_permission_legacy_app_propagation_on_ssowat():
app_install(
os.path.join(get_test_apps_dir(), "legacy_app_ynh"),
args="domain=%s&domain_2=%s&path=%s&is_public=0"
% (maindomain, other_domains[0], "/legacy"),
force=True,
)
# App is configured as public by default using the legacy unprotected_uri mechanics
# It should automatically be migrated during the install
res = user_permission_list(full=True)["permissions"]
assert "visitors" not in res["legacy_app.main"]["allowed"]
assert "all_users" in res["legacy_app.main"]["allowed"]
app_webroot = "https://%s/legacy" % maindomain
assert not can_access_webpage(app_webroot, logged_as=None)
assert can_access_webpage(app_webroot, logged_as="alice")
# Try to update the permission and check that permissions are still consistent
user_permission_update(
"legacy_app.main", remove=["visitors", "all_users"], add="bob"
)
assert not can_access_webpage(app_webroot, logged_as=None)
assert not can_access_webpage(app_webroot, logged_as="alice")
assert can_access_webpage(app_webroot, logged_as="bob")