2018-11-08 19:45:21 +00:00
|
|
|
"""
|
2021-10-15 03:25:38 -05:00
|
|
|
View for organization administrative actions (/org endpoint).
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
2021-07-10 10:12:35 -05:00
|
|
|
from django.conf import settings
|
2018-11-08 19:45:21 +00:00
|
|
|
from django.contrib.auth.decorators import login_required
|
2021-11-12 11:16:25 -06:00
|
|
|
from django.db import transaction
|
2018-11-08 19:45:21 +00:00
|
|
|
from django.http import JsonResponse
|
|
|
|
from django.template import loader
|
2023-06-20 03:26:06 +03:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
2021-07-10 10:12:35 -05:00
|
|
|
from django.utils.translation import override
|
|
|
|
from django.views.decorators.csrf import csrf_protect
|
2021-01-13 20:35:07 +00:00
|
|
|
from django_grainy.models import UserPermission
|
|
|
|
from django_handleref.models import HandleRefModel
|
2021-08-18 08:21:22 -05:00
|
|
|
from grainy.const import PERM_READ
|
2021-01-13 20:35:07 +00:00
|
|
|
|
2018-11-08 19:45:21 +00:00
|
|
|
from peeringdb_server.models import (
|
2021-07-10 10:12:35 -05:00
|
|
|
Facility,
|
|
|
|
InternetExchange,
|
2019-12-05 16:57:52 +00:00
|
|
|
Network,
|
2021-07-10 10:12:35 -05:00
|
|
|
Organization,
|
|
|
|
User,
|
2019-12-05 16:57:52 +00:00
|
|
|
UserOrgAffiliationRequest,
|
|
|
|
)
|
2021-07-10 10:12:35 -05:00
|
|
|
from peeringdb_server.util import check_permissions
|
|
|
|
|
2022-09-12 16:29:28 +03:00
|
|
|
from .forms import OrgAdminUserPermissionForm, OrgUserOptions
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
def save_user_permissions(org, user, perms):
|
|
|
|
"""
|
2021-10-15 03:25:38 -05:00
|
|
|
Save user permissions for the specified org and user.
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2021-10-15 03:25:38 -05:00
|
|
|
Perms should be a dict of permissioning ids and permission levels.
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
# wipe all the user's perms for the targeted org
|
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
user.grainy_permissions.filter(namespace__startswith=org.grainy_namespace).delete()
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
# collect permissioning namespaces from the provided permissioning ids
|
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
grainy_perms = {}
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2020-01-08 13:29:58 -06:00
|
|
|
for id, permissions in list(perms.items()):
|
2018-11-08 19:45:21 +00:00
|
|
|
if not permissions & PERM_READ:
|
|
|
|
permissions = permissions | PERM_READ
|
|
|
|
|
|
|
|
if id == "org.%d" % org.id:
|
2021-01-13 20:35:07 +00:00
|
|
|
grainy_perms[org.grainy_namespace] = permissions
|
|
|
|
grainy_perms[
|
|
|
|
f"{org.grainy_namespace}.network.*.poc_set.private"
|
2019-12-05 16:57:52 +00:00
|
|
|
] = permissions
|
2018-11-08 19:45:21 +00:00
|
|
|
elif id == "net":
|
2021-01-13 20:35:07 +00:00
|
|
|
grainy_perms[f"{org.grainy_namespace}.network"] = permissions
|
|
|
|
grainy_perms[
|
|
|
|
f"{org.grainy_namespace}.network.*.poc_set.private"
|
2019-12-05 16:57:52 +00:00
|
|
|
] = permissions
|
2018-11-08 19:45:21 +00:00
|
|
|
elif id == "ix":
|
2021-01-13 20:35:07 +00:00
|
|
|
grainy_perms[f"{org.grainy_namespace}.internetexchange"] = permissions
|
2018-11-08 19:45:21 +00:00
|
|
|
elif id == "fac":
|
2021-01-13 20:35:07 +00:00
|
|
|
grainy_perms[f"{org.grainy_namespace}.facility"] = permissions
|
2023-05-16 21:04:05 +03:00
|
|
|
elif id == "sessions":
|
|
|
|
grainy_perms[f"{org.grainy_namespace}.network.*.sessions"] = permissions
|
2018-11-08 19:45:21 +00:00
|
|
|
elif id.find(".") > -1:
|
|
|
|
id = id.split(".")
|
|
|
|
if id[0] == "net":
|
2021-01-13 20:35:07 +00:00
|
|
|
grainy_perms[f"{org.grainy_namespace}.network.{id[1]}"] = permissions
|
|
|
|
grainy_perms[
|
|
|
|
f"{org.grainy_namespace}.network.{id[1]}.poc_set.private"
|
2019-12-05 16:57:52 +00:00
|
|
|
] = permissions
|
2018-11-08 19:45:21 +00:00
|
|
|
elif id[0] == "ix":
|
2021-01-13 20:35:07 +00:00
|
|
|
grainy_perms[
|
|
|
|
f"{org.grainy_namespace}.internetexchange.{id[1]}"
|
2019-12-05 16:57:52 +00:00
|
|
|
] = permissions
|
2018-11-08 19:45:21 +00:00
|
|
|
elif id[0] == "fac":
|
2021-01-13 20:35:07 +00:00
|
|
|
grainy_perms[f"{org.grainy_namespace}.facility.{id[1]}"] = permissions
|
2023-05-16 21:04:05 +03:00
|
|
|
elif id[0] == "sessions":
|
|
|
|
grainy_perms[
|
|
|
|
f"{org.grainy_namespace}.network.{id[1]}.sessions"
|
|
|
|
] = permissions
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
# save
|
2021-01-13 20:35:07 +00:00
|
|
|
for ns, p in list(grainy_perms.items()):
|
|
|
|
UserPermission.objects.create(namespace=ns, permission=p, user=user)
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
return grainy_perms
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
def load_all_user_permissions(org):
|
|
|
|
"""
|
2021-10-15 03:25:38 -05:00
|
|
|
Return dict of all users with all their permissions for
|
|
|
|
the given org.
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
rv = {}
|
|
|
|
for user in org.usergroup.user_set.all():
|
2021-03-09 13:30:30 -06:00
|
|
|
uperms, perms = load_entity_permissions(org, user)
|
2018-11-08 19:45:21 +00:00
|
|
|
rv[user.id] = {
|
|
|
|
"id": user.id,
|
|
|
|
"perms": perms,
|
2020-07-15 02:07:01 -05:00
|
|
|
"name": f"{user.full_name} <{user.email}> {user.username}",
|
2018-11-08 19:45:21 +00:00
|
|
|
}
|
|
|
|
return rv
|
|
|
|
|
|
|
|
|
|
|
|
def load_user_permissions(org, user):
|
2021-03-09 13:30:30 -06:00
|
|
|
return load_entity_permissions(org, user)
|
|
|
|
|
|
|
|
|
|
|
|
def load_entity_permissions(org, entity):
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
2021-10-15 03:25:38 -05:00
|
|
|
Return entity's permissions for the specified org.
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
|
|
|
|
2021-03-09 13:30:30 -06:00
|
|
|
# load all of the entity's permissions related to this org
|
|
|
|
entity_perms = {
|
2021-01-13 20:35:07 +00:00
|
|
|
p.namespace: p.permission
|
2021-03-09 13:30:30 -06:00
|
|
|
for p in entity.grainy_permissions.filter(
|
2021-01-13 20:35:07 +00:00
|
|
|
namespace__startswith=org.grainy_namespace
|
|
|
|
)
|
2020-07-15 02:07:01 -05:00
|
|
|
}
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
perms = {}
|
|
|
|
|
2021-03-09 13:30:30 -06:00
|
|
|
extract_permission_id(entity_perms, perms, org, org)
|
2023-05-16 21:04:05 +03:00
|
|
|
# extract session for any network
|
|
|
|
extract_permission_id(entity_perms, perms, "sessions", org)
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2021-03-09 13:30:30 -06:00
|
|
|
# extract entity's permissioning ids from grainy_namespaces targeting
|
2018-11-08 19:45:21 +00:00
|
|
|
# organization's entities
|
|
|
|
for model in [Network, InternetExchange, Facility]:
|
2021-03-09 13:30:30 -06:00
|
|
|
extract_permission_id(entity_perms, perms, model, org)
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2021-03-09 13:30:30 -06:00
|
|
|
# extract entity's permissioning ids from grainy_namespaces targeting
|
|
|
|
# organization's entities by their id (eg entity has perms only
|
2018-11-08 19:45:21 +00:00
|
|
|
# to THAT specific network)
|
|
|
|
for net in org.net_set_active:
|
2021-03-09 13:30:30 -06:00
|
|
|
extract_permission_id(entity_perms, perms, net, org)
|
2023-05-16 21:04:05 +03:00
|
|
|
# extract session per network
|
|
|
|
extract_permission_id(entity_perms, perms, net, org, True)
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2023-05-16 21:04:05 +03:00
|
|
|
for ix in org.ix_set_active:
|
|
|
|
extract_permission_id(entity_perms, perms, ix, org)
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2023-05-16 21:04:05 +03:00
|
|
|
for fac in org.fac_set_active:
|
|
|
|
extract_permission_id(entity_perms, perms, fac, org)
|
2021-03-09 13:30:30 -06:00
|
|
|
return entity_perms, perms
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
def permission_ids(org):
|
|
|
|
"""
|
2021-10-15 03:25:38 -05:00
|
|
|
Return a dict of a valid permissioning ids for
|
|
|
|
the specified organization.
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
perms = {
|
|
|
|
"org.%d" % org.id: _("Organization and all Entities it owns"),
|
|
|
|
"net": _("Any Network"),
|
|
|
|
"fac": _("Any Facility"),
|
2019-12-05 16:57:52 +00:00
|
|
|
"ix": _("Any Exchange"),
|
2023-05-16 21:04:05 +03:00
|
|
|
"sessions": _("Manage peering sessions - Any Network"),
|
2018-11-08 19:45:21 +00:00
|
|
|
}
|
|
|
|
|
2023-05-16 21:04:05 +03:00
|
|
|
perms.update(
|
|
|
|
{
|
|
|
|
"sessions.%d"
|
|
|
|
% net.id: _("Manage peering sessions - %(net_name)s")
|
|
|
|
% {"net_name": net.name}
|
|
|
|
for net in org.net_set_active
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2018-11-08 19:45:21 +00:00
|
|
|
perms.update(
|
2020-07-15 02:07:01 -05:00
|
|
|
{
|
2020-07-26 23:36:27 -05:00
|
|
|
"net.%d" % net.id: _("Network - %(net_name)s") % {"net_name": net.name}
|
|
|
|
for net in org.net_set_active
|
2020-07-15 02:07:01 -05:00
|
|
|
}
|
2019-12-05 16:57:52 +00:00
|
|
|
)
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
perms.update(
|
2020-07-15 02:07:01 -05:00
|
|
|
{
|
2020-07-26 23:36:27 -05:00
|
|
|
"ix.%d" % ix.id: _("Exchange - %(ix_name)s") % {"ix_name": ix.name}
|
|
|
|
for ix in org.ix_set_active
|
2020-07-15 02:07:01 -05:00
|
|
|
}
|
2019-12-05 16:57:52 +00:00
|
|
|
)
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
perms.update(
|
2020-07-15 02:07:01 -05:00
|
|
|
{
|
2020-07-26 23:36:27 -05:00
|
|
|
"fac.%d" % fac.id: _("Facility - %(fac_name)s") % {"fac_name": fac.name}
|
|
|
|
for fac in org.fac_set_active
|
2020-07-15 02:07:01 -05:00
|
|
|
}
|
2019-12-05 16:57:52 +00:00
|
|
|
)
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
return perms
|
|
|
|
|
|
|
|
|
2023-05-16 21:04:05 +03:00
|
|
|
def extract_permission_id(source, dest, entity, org, is_session=False):
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
2021-10-15 03:25:38 -05:00
|
|
|
Extract a user's permissioning id for the specified
|
|
|
|
entity from source <dict> and store it in dest <dict>.
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2021-10-15 03:25:38 -05:00
|
|
|
Source should be a dict containing django-namespace-perms
|
|
|
|
(namespace, level) items.
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2021-10-15 03:25:38 -05:00
|
|
|
Dest should be a dict where permission ids are to be
|
|
|
|
exracted to.
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2023-05-16 21:04:05 +03:00
|
|
|
Entity can either be a HandleRef instance or class or str.
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2021-10-15 03:25:38 -05:00
|
|
|
Org must be an Organization instance that owns the
|
|
|
|
entity.
|
2023-05-16 21:04:05 +03:00
|
|
|
|
|
|
|
is_session to handle the peering sessions permission
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
if isinstance(entity, HandleRefModel):
|
2023-05-16 21:04:05 +03:00
|
|
|
if not is_session:
|
|
|
|
# instance
|
|
|
|
k = entity.grainy_namespace
|
|
|
|
j = "%s.%d" % (entity.ref_tag, entity.id)
|
|
|
|
else:
|
|
|
|
j = "sessions.%d" % (entity.id)
|
|
|
|
k = f"{entity.grainy_namespace}.sessions"
|
|
|
|
elif entity == "sessions":
|
|
|
|
j = "sessions"
|
|
|
|
k = f"{org.grainy_namespace}.network.*.sessions"
|
2018-11-08 19:45:21 +00:00
|
|
|
else:
|
|
|
|
# class
|
|
|
|
j = entity.handleref.tag
|
2021-01-13 20:35:07 +00:00
|
|
|
namespace = entity.Grainy.namespace()
|
|
|
|
k = f"{org.grainy_namespace}.{namespace}"
|
|
|
|
|
2018-11-08 19:45:21 +00:00
|
|
|
if k in source:
|
|
|
|
dest[j] = source[k]
|
|
|
|
|
|
|
|
|
|
|
|
def org_admin_required(fnc):
|
|
|
|
"""
|
|
|
|
Decorator function that ensures that the requesting user
|
2021-10-15 03:25:38 -05:00
|
|
|
has administrative rights to the targeted organization.
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2021-10-15 03:25:38 -05:00
|
|
|
Also sets "org" in kwargs.
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
def callback(request, **kwargs):
|
|
|
|
org_id = request.POST.get("org_id", request.GET.get("org_id"))
|
|
|
|
|
|
|
|
if not org_id:
|
|
|
|
return JsonResponse({}, status=400)
|
|
|
|
|
|
|
|
try:
|
|
|
|
org = Organization.objects.get(id=org_id)
|
2021-01-13 20:35:07 +00:00
|
|
|
if not check_permissions(request.user, org.grainy_namespace_manage, "u"):
|
2018-11-08 19:45:21 +00:00
|
|
|
return JsonResponse({}, status=403)
|
|
|
|
kwargs["org"] = org
|
|
|
|
return fnc(request, **kwargs)
|
|
|
|
except Organization.DoesNotExist:
|
2019-12-05 16:57:52 +00:00
|
|
|
return JsonResponse(
|
|
|
|
{"non_field_errors": [_("Invalid organization specified")]}, status=400
|
|
|
|
)
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
return callback
|
|
|
|
|
|
|
|
|
|
|
|
def target_user_validate(fnc):
|
|
|
|
"""
|
|
|
|
Decorator function that ensures that the targeted user
|
2021-10-15 03:25:38 -05:00
|
|
|
is a member of the targeted organization.
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2021-10-15 03:25:38 -05:00
|
|
|
Should be below org_admin_required.
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2021-10-15 03:25:38 -05:00
|
|
|
Also sets "user" in kwargs.
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
def callback(request, **kwargs):
|
|
|
|
user_id = request.POST.get("user_id", request.GET.get("user_id"))
|
|
|
|
org = kwargs.get("org")
|
|
|
|
|
|
|
|
if not user_id:
|
|
|
|
return JsonResponse({}, status=400)
|
|
|
|
|
|
|
|
try:
|
|
|
|
user = User.objects.get(id=user_id)
|
|
|
|
except User.DoesNotExist:
|
|
|
|
return JsonResponse({}, status=400)
|
|
|
|
|
|
|
|
if not user.is_org_member(org) and not user.is_org_admin(org):
|
|
|
|
return JsonResponse({}, status=403)
|
|
|
|
|
|
|
|
kwargs["user"] = user
|
|
|
|
return fnc(request, **kwargs)
|
|
|
|
|
|
|
|
return callback
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@org_admin_required
|
|
|
|
def users(request, **kwargs):
|
|
|
|
"""
|
2021-10-15 03:25:38 -05:00
|
|
|
Returns JsonResponse with a list of all users in the specified org.
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
org = kwargs.get("org")
|
|
|
|
|
|
|
|
rv = {
|
2019-12-05 16:57:52 +00:00
|
|
|
"users": [
|
|
|
|
{
|
|
|
|
"id": user.id,
|
2020-07-15 02:07:01 -05:00
|
|
|
"name": f"{user.full_name} <{user.email}, {user.username}>",
|
2019-12-05 16:57:52 +00:00
|
|
|
}
|
|
|
|
for user in org.usergroup.user_set.all()
|
|
|
|
]
|
2018-11-08 19:45:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rv.update({"status": "ok"})
|
|
|
|
|
|
|
|
return JsonResponse(rv)
|
|
|
|
|
|
|
|
|
2022-09-12 16:29:28 +03:00
|
|
|
@login_required
|
|
|
|
@org_admin_required
|
|
|
|
def update_user_options(request, **kwargs):
|
|
|
|
org = kwargs.get("org")
|
|
|
|
|
|
|
|
form = OrgUserOptions(request.POST, instance=org)
|
|
|
|
|
|
|
|
if not form.is_valid():
|
|
|
|
return JsonResponse(form.errors, status=400)
|
|
|
|
|
|
|
|
form.save()
|
|
|
|
|
|
|
|
return JsonResponse({"status": "ok"})
|
|
|
|
|
|
|
|
|
2018-11-08 19:45:21 +00:00
|
|
|
@login_required
|
2021-11-12 11:16:25 -06:00
|
|
|
@transaction.atomic
|
2018-11-08 19:45:21 +00:00
|
|
|
@org_admin_required
|
|
|
|
@target_user_validate
|
|
|
|
def manage_user_delete(request, **kwargs):
|
|
|
|
"""
|
2021-10-15 03:25:38 -05:00
|
|
|
Remove user from org.
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
org = kwargs.get("org")
|
|
|
|
user = kwargs.get("user")
|
|
|
|
save_user_permissions(org, user, {})
|
|
|
|
org.usergroup.user_set.remove(user)
|
|
|
|
org.admin_usergroup.user_set.remove(user)
|
|
|
|
|
|
|
|
return JsonResponse({"status": "ok"})
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
2021-11-12 11:16:25 -06:00
|
|
|
@transaction.atomic
|
2018-11-08 19:45:21 +00:00
|
|
|
@org_admin_required
|
|
|
|
@target_user_validate
|
|
|
|
def manage_user_update(request, **kwargs):
|
|
|
|
"""
|
2021-10-15 03:25:38 -05:00
|
|
|
Udpate a user in the org.
|
2018-11-08 19:45:21 +00:00
|
|
|
|
2021-10-15 03:25:38 -05:00
|
|
|
Currently, this only allows moving the user to either
|
|
|
|
admin or member group.
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
org = kwargs.get("org")
|
|
|
|
user = kwargs.get("user")
|
|
|
|
group = request.POST.get("group")
|
|
|
|
if group not in ["member", "admin"]:
|
2019-12-05 16:57:52 +00:00
|
|
|
return JsonResponse({"group": _("Needs to be member or admin")}, status=400)
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
if group == "admin":
|
|
|
|
org.usergroup.user_set.remove(user)
|
|
|
|
org.admin_usergroup.user_set.add(user)
|
2022-07-15 21:47:59 +03:00
|
|
|
# remove granular permissions user has to the org
|
|
|
|
# since user is now an organization admin (#1157)
|
|
|
|
user.grainy_permissions.filter(
|
|
|
|
namespace__startswith=f"peeringdb.organization.{org.id}."
|
|
|
|
).delete()
|
2018-11-08 19:45:21 +00:00
|
|
|
elif group == "member":
|
|
|
|
org.usergroup.user_set.add(user)
|
|
|
|
org.admin_usergroup.user_set.remove(user)
|
|
|
|
|
|
|
|
return JsonResponse({"status": "ok"})
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@org_admin_required
|
|
|
|
def user_permissions(request, **kwargs):
|
|
|
|
"""
|
2021-10-15 03:25:38 -05:00
|
|
|
Return JsonRespone with list of user's permissions for the targeted
|
|
|
|
org an entities under it.
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
Permisions are returned as a dict of permissioning ids and permission
|
|
|
|
levels.
|
|
|
|
|
|
|
|
Permissioning ids serve as a wrapper for actual permissioning namespaces
|
2021-10-15 03:25:38 -05:00
|
|
|
so they can be exposed to the organization admins for changes without allowing
|
2018-11-08 19:45:21 +00:00
|
|
|
them to set permissioning namespaces directly.
|
|
|
|
"""
|
|
|
|
|
|
|
|
org = kwargs.get("org")
|
|
|
|
perms_rv = {}
|
|
|
|
for user in org.usergroup.user_set.all():
|
|
|
|
uperms, perms = load_user_permissions(org, user)
|
|
|
|
perms_rv[user.id] = perms
|
|
|
|
|
|
|
|
return JsonResponse({"status": "ok", "user_permissions": perms_rv})
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@csrf_protect
|
2021-11-12 11:16:25 -06:00
|
|
|
@transaction.atomic
|
2018-11-08 19:45:21 +00:00
|
|
|
@org_admin_required
|
|
|
|
@target_user_validate
|
|
|
|
def user_permission_update(request, **kwargs):
|
|
|
|
"""
|
2021-10-15 03:25:38 -05:00
|
|
|
Update/Add a user's permission.
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
perms = permission level
|
|
|
|
entity = permission id
|
|
|
|
"""
|
|
|
|
|
|
|
|
org = kwargs.get("org")
|
|
|
|
user = kwargs.get("user")
|
|
|
|
|
2022-07-15 21:47:59 +03:00
|
|
|
# cannot manage permissions for organization admins (#1157)
|
|
|
|
if user.is_org_admin(org):
|
|
|
|
return JsonResponse(
|
|
|
|
{
|
|
|
|
"non_field_errors": [
|
|
|
|
_("Cannot manage permissions for organization admins")
|
|
|
|
]
|
|
|
|
},
|
|
|
|
status=400,
|
|
|
|
)
|
|
|
|
|
2018-11-08 19:45:21 +00:00
|
|
|
uperms, perms = load_user_permissions(org, user)
|
|
|
|
form = OrgAdminUserPermissionForm(request.POST)
|
|
|
|
if not form.is_valid():
|
|
|
|
return JsonResponse(form.errors, status=400)
|
|
|
|
|
|
|
|
level = form.cleaned_data.get("perms")
|
|
|
|
entity = form.cleaned_data.get("entity")
|
|
|
|
perms[entity] = level
|
|
|
|
save_user_permissions(org, user, perms)
|
|
|
|
|
|
|
|
return JsonResponse({"status": "ok"})
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@csrf_protect
|
2021-11-12 11:16:25 -06:00
|
|
|
@transaction.atomic
|
2018-11-08 19:45:21 +00:00
|
|
|
@org_admin_required
|
|
|
|
@target_user_validate
|
|
|
|
def user_permission_remove(request, **kwargs):
|
|
|
|
"""
|
2021-10-15 03:25:38 -05:00
|
|
|
Remove a user's permission.
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
entity = permission id
|
|
|
|
"""
|
|
|
|
|
|
|
|
org = kwargs.get("org")
|
|
|
|
user = kwargs.get("user")
|
|
|
|
entity = request.POST.get("entity")
|
|
|
|
uperms, perms = load_user_permissions(org, user)
|
|
|
|
if entity in perms:
|
|
|
|
del perms[entity]
|
|
|
|
save_user_permissions(org, user, perms)
|
|
|
|
|
|
|
|
return JsonResponse({"status": "ok"})
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@org_admin_required
|
|
|
|
def permissions(request, **kwargs):
|
|
|
|
"""
|
2021-10-15 03:25:38 -05:00
|
|
|
Return list of permissioning ids with labels that
|
|
|
|
are valid to be permissioned out to regular org users.
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
Permissioning ids serve as a wrapper for actual permissioning namespaces
|
2021-10-15 03:25:38 -05:00
|
|
|
so they can be exposed to the organization admins for changes without allowing
|
2018-11-08 19:45:21 +00:00
|
|
|
them to set permissioning namespaces directly.
|
|
|
|
"""
|
|
|
|
|
|
|
|
org = kwargs.get("org")
|
|
|
|
|
2020-01-08 13:29:58 -06:00
|
|
|
perms = [{"id": id, "name": name} for id, name in list(permission_ids(org).items())]
|
2018-11-08 19:45:21 +00:00
|
|
|
perms = sorted(perms, key=lambda x: x.get("name"))
|
|
|
|
return JsonResponse({"status": "ok", "permissions": perms})
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@csrf_protect
|
2021-11-12 11:16:25 -06:00
|
|
|
@transaction.atomic
|
2018-11-08 19:45:21 +00:00
|
|
|
@org_admin_required
|
|
|
|
def uoar_approve(request, **kwargs):
|
|
|
|
"""
|
2021-10-15 03:25:38 -05:00
|
|
|
Approve a user request to affiliate with the organization.
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
org = kwargs.get("org")
|
|
|
|
|
|
|
|
try:
|
|
|
|
uoar = UserOrgAffiliationRequest.objects.get(id=request.POST.get("id"))
|
|
|
|
if uoar.org != org:
|
|
|
|
return JsonResponse({}, status=403)
|
|
|
|
|
|
|
|
try:
|
|
|
|
user = uoar.user
|
|
|
|
except User.DoesNotExist:
|
|
|
|
uoar.delete()
|
|
|
|
return JsonResponse({"status": "ok"})
|
|
|
|
|
2023-07-11 16:20:46 +03:00
|
|
|
if org.require_2fa:
|
|
|
|
if not uoar.user.has_2fa:
|
|
|
|
message = (
|
|
|
|
f"User {uoar.user.full_name} requests affiliation with Organization {uoar.org.name} "
|
|
|
|
f"but has not enabled 2FA. Org {uoar.org.name} does not allow users to affiliate "
|
|
|
|
f"unless they have enabled 2FA on their account. You will be able to approve an "
|
|
|
|
f"affiliation request from User {uoar.user.full_name}, and assign permissions to "
|
|
|
|
f"them, when they have enabled 2FA."
|
|
|
|
)
|
|
|
|
return JsonResponse({"message": message}, status=403)
|
|
|
|
|
2018-11-08 19:45:21 +00:00
|
|
|
uoar.approve()
|
|
|
|
|
|
|
|
# notify rest of org admins that the affiliation request has been
|
|
|
|
# approved
|
|
|
|
|
|
|
|
for admin_user in org.admin_usergroup.user_set.all():
|
|
|
|
if admin_user != request.user:
|
|
|
|
with override(admin_user.locale):
|
|
|
|
admin_user.email_user(
|
2020-09-29 20:01:47 +00:00
|
|
|
_("%(user_name)s's affiliation request has been approved")
|
2019-12-05 16:57:52 +00:00
|
|
|
% {"user_name": uoar.user.full_name},
|
2018-11-08 19:45:21 +00:00
|
|
|
loader.get_template(
|
2019-12-05 16:57:52 +00:00
|
|
|
"email/notify-org-admin-user-affil-approved.txt"
|
|
|
|
).render(
|
|
|
|
{
|
|
|
|
"user": request.user,
|
|
|
|
"uoar": uoar,
|
|
|
|
"org_management_url": "%s/org/%d#users"
|
|
|
|
% (settings.BASE_URL, org.id),
|
|
|
|
}
|
|
|
|
),
|
|
|
|
)
|
|
|
|
|
|
|
|
return JsonResponse(
|
|
|
|
{
|
|
|
|
"status": "ok",
|
|
|
|
"full_name": user.full_name,
|
|
|
|
"id": user.id,
|
|
|
|
"email": user.email,
|
|
|
|
}
|
|
|
|
)
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
except UserOrgAffiliationRequest.DoesNotExist:
|
|
|
|
return JsonResponse({"status": "ok"})
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@csrf_protect
|
2021-11-12 11:16:25 -06:00
|
|
|
@transaction.atomic
|
2018-11-08 19:45:21 +00:00
|
|
|
@org_admin_required
|
|
|
|
def uoar_deny(request, **kwargs):
|
|
|
|
"""
|
2021-11-12 11:16:25 -06:00
|
|
|
Deny a user request to affiliate with the organization.
|
2018-11-08 19:45:21 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
org = kwargs.get("org")
|
|
|
|
|
|
|
|
try:
|
|
|
|
uoar = UserOrgAffiliationRequest.objects.get(id=request.POST.get("id"))
|
|
|
|
if uoar.org != org:
|
|
|
|
return JsonResponse({}, status=403)
|
|
|
|
try:
|
2021-08-18 08:21:22 -05:00
|
|
|
uoar.user
|
2018-11-08 19:45:21 +00:00
|
|
|
uoar.deny()
|
|
|
|
|
|
|
|
except User.DoesNotExist:
|
|
|
|
uoar.delete()
|
|
|
|
return JsonResponse({"status": "ok"})
|
|
|
|
|
|
|
|
# notify rest of org admins that the affiliation request has been
|
2021-11-12 11:16:25 -06:00
|
|
|
# denied
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
for user in org.admin_usergroup.user_set.all():
|
|
|
|
if user != request.user:
|
|
|
|
with override(user.locale):
|
|
|
|
user.email_user(
|
2020-09-29 20:01:47 +00:00
|
|
|
_("%(user_name)s's affiliation request has been denied")
|
2019-12-05 16:57:52 +00:00
|
|
|
% {"user_name": uoar.user.full_name},
|
2018-11-08 19:45:21 +00:00
|
|
|
loader.get_template(
|
2019-12-05 16:57:52 +00:00
|
|
|
"email/notify-org-admin-user-affil-denied.txt"
|
|
|
|
).render(
|
|
|
|
{
|
|
|
|
"user": request.user,
|
|
|
|
"uoar": uoar,
|
|
|
|
"org_management_url": "%s/org/%d#users"
|
|
|
|
% (settings.BASE_URL, org.id),
|
|
|
|
}
|
|
|
|
),
|
|
|
|
)
|
2018-11-08 19:45:21 +00:00
|
|
|
|
|
|
|
except UserOrgAffiliationRequest.DoesNotExist:
|
|
|
|
return JsonResponse({"status": "ok"})
|
|
|
|
|
|
|
|
return JsonResponse({"status": "ok"})
|