mirror of
				https://github.com/peeringdb/peeringdb.git
				synced 2024-05-11 05:55:09 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			517 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			517 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""
 | 
						|
Views for organization administrative actions
 | 
						|
"""
 | 
						|
from django.contrib.auth.decorators import login_required
 | 
						|
from django.views.decorators.csrf import csrf_protect
 | 
						|
from django.http import JsonResponse
 | 
						|
from django.template import loader
 | 
						|
from django.conf import settings
 | 
						|
from forms import OrgAdminUserPermissionForm
 | 
						|
 | 
						|
from peeringdb_server.models import (
 | 
						|
    User, Organization, Network, NetworkContact, InternetExchange, Facility,
 | 
						|
    UserOrgAffiliationRequest)
 | 
						|
 | 
						|
import django_namespace_perms.util as nsp
 | 
						|
from django_namespace_perms.constants import *
 | 
						|
from django_namespace_perms.models import UserPermission
 | 
						|
 | 
						|
from django_handleref.models import HandleRefModel
 | 
						|
 | 
						|
from django.utils.translation import ugettext_lazy as _
 | 
						|
from django.utils.translation import override
 | 
						|
 | 
						|
 | 
						|
def save_user_permissions(org, user, perms):
 | 
						|
    """
 | 
						|
    Save user permissions for the specified org and user
 | 
						|
 | 
						|
    perms should be a dict of permissioning ids and permission levels
 | 
						|
    """
 | 
						|
 | 
						|
    # wipe all the user's perms for the targeted org
 | 
						|
 | 
						|
    user.userpermission_set.filter(
 | 
						|
        namespace__startswith=org.nsp_namespace).delete()
 | 
						|
 | 
						|
    # collect permissioning namespaces from the provided permissioning ids
 | 
						|
 | 
						|
    nsp_perms = {}
 | 
						|
 | 
						|
    for id, permissions in perms.items():
 | 
						|
 | 
						|
        if not permissions & PERM_READ:
 | 
						|
            permissions = permissions | PERM_READ
 | 
						|
 | 
						|
        if id == "org.%d" % org.id:
 | 
						|
            nsp_perms[org.nsp_namespace] = permissions
 | 
						|
            nsp_perms[NetworkContact.nsp_namespace_from_id(
 | 
						|
                org.id, "*", "private")] = permissions
 | 
						|
        elif id == "net":
 | 
						|
            nsp_perms[Network.nsp_namespace_from_id(
 | 
						|
                org.id, "*").strip(".*")] = permissions
 | 
						|
            nsp_perms[NetworkContact.nsp_namespace_from_id(
 | 
						|
                org.id, "*", "private")] = permissions
 | 
						|
        elif id == "ix":
 | 
						|
            nsp_perms[InternetExchange.nsp_namespace_from_id(
 | 
						|
                org.id, "*").strip(".*")] = permissions
 | 
						|
        elif id == "fac":
 | 
						|
            nsp_perms[Facility.nsp_namespace_from_id(
 | 
						|
                org.id, "*").strip(".*")] = permissions
 | 
						|
        elif id.find(".") > -1:
 | 
						|
            id = id.split(".")
 | 
						|
            if id[0] == "net":
 | 
						|
                nsp_perms[Network.nsp_namespace_from_id(org.id,
 | 
						|
                                                        id[1])] = permissions
 | 
						|
                nsp_perms[NetworkContact.nsp_namespace_from_id(
 | 
						|
                    org.id, id[1], "private")] = permissions
 | 
						|
            elif id[0] == "ix":
 | 
						|
                nsp_perms[InternetExchange.nsp_namespace_from_id(
 | 
						|
                    org.id, id[1])] = permissions
 | 
						|
            elif id[0] == "fac":
 | 
						|
                nsp_perms[Facility.nsp_namespace_from_id(org.id,
 | 
						|
                                                         id[1])] = permissions
 | 
						|
 | 
						|
    # save
 | 
						|
    for ns, p in nsp_perms.items():
 | 
						|
        UserPermission.objects.create(namespace=ns, permissions=p, user=user)
 | 
						|
 | 
						|
    return nsp_perms
 | 
						|
 | 
						|
 | 
						|
def load_all_user_permissions(org):
 | 
						|
    """
 | 
						|
    Returns dict of all users with all their permissions for
 | 
						|
    the given org
 | 
						|
    """
 | 
						|
 | 
						|
    rv = {}
 | 
						|
    for user in org.usergroup.user_set.all():
 | 
						|
        uperms, perms = load_user_permissions(org, user)
 | 
						|
        rv[user.id] = {
 | 
						|
            "id": user.id,
 | 
						|
            "perms": perms,
 | 
						|
            "name": "%s <%s> %s" % (user.full_name, user.email, user.username)
 | 
						|
        }
 | 
						|
    return rv
 | 
						|
 | 
						|
 | 
						|
def load_user_permissions(org, user):
 | 
						|
    """
 | 
						|
    Returns user's permissions for the specified org
 | 
						|
    """
 | 
						|
 | 
						|
    # load all of the user's permissions related to this org
 | 
						|
    uperms = dict([(p.namespace, p.permissions)
 | 
						|
                   for p in user.userpermission_set.filter(
 | 
						|
                       namespace__startswith=org.nsp_namespace)])
 | 
						|
 | 
						|
    perms = {}
 | 
						|
 | 
						|
    extract_permission_id(uperms, perms, org, org)
 | 
						|
 | 
						|
    # extract user's permissioning ids from nsp_namespaces targeting
 | 
						|
    # organization's entities
 | 
						|
    for model in [Network, InternetExchange, Facility]:
 | 
						|
        extract_permission_id(uperms, perms, model, org)
 | 
						|
 | 
						|
    # extract user's permissioning ids from nsp_namespaces targeting
 | 
						|
    # organization's entities by their id (eg user has perms only
 | 
						|
    # to THAT specific network)
 | 
						|
    for net in org.net_set_active:
 | 
						|
        extract_permission_id(uperms, perms, net, org)
 | 
						|
 | 
						|
    for net in org.ix_set_active:
 | 
						|
        extract_permission_id(uperms, perms, net, org)
 | 
						|
 | 
						|
    for net in org.fac_set_active:
 | 
						|
        extract_permission_id(uperms, perms, net, org)
 | 
						|
 | 
						|
    return uperms, perms
 | 
						|
 | 
						|
 | 
						|
def permission_ids(org):
 | 
						|
    """
 | 
						|
    returns a dict of a valid permissioning ids for
 | 
						|
    the specified organization
 | 
						|
    """
 | 
						|
 | 
						|
    perms = {
 | 
						|
        "org.%d" % org.id: _("Organization and all Entities it owns"),
 | 
						|
        "net": _("Any Network"),
 | 
						|
        "fac": _("Any Facility"),
 | 
						|
        "ix": _("Any Exchange")
 | 
						|
    }
 | 
						|
 | 
						|
    perms.update(
 | 
						|
        dict([("net.%d" % net.id, _("Network - %(net_name)s") % {
 | 
						|
            'net_name': net.name
 | 
						|
        }) for net in org.net_set_active]))
 | 
						|
 | 
						|
    perms.update(
 | 
						|
        dict([("ix.%d" % ix.id, _("Exchange - %(ix_name)s") % {
 | 
						|
            'ix_name': ix.name
 | 
						|
        }) for ix in org.ix_set_active]))
 | 
						|
 | 
						|
    perms.update(
 | 
						|
        dict([("fac.%d" % fac.id, _("Facility - %(fac_name)s") % {
 | 
						|
            'fac_name': fac.name
 | 
						|
        }) for fac in org.fac_set_active]))
 | 
						|
 | 
						|
    return perms
 | 
						|
 | 
						|
 | 
						|
def extract_permission_id(source, dest, entity, org):
 | 
						|
    """
 | 
						|
    extract a user's permissioning id for the specified
 | 
						|
    entity from source <dict> and store it in dest <dict>
 | 
						|
 | 
						|
    source should be a dict containing django-namespace-perms
 | 
						|
    (namespace, level) items
 | 
						|
 | 
						|
    dest should be a dict where permission ids are to be
 | 
						|
    exracted to
 | 
						|
 | 
						|
    entity can either be a HandleRef instance or clas
 | 
						|
 | 
						|
    org needs to be an Organization instance that owns the
 | 
						|
    entity
 | 
						|
    """
 | 
						|
 | 
						|
    if isinstance(entity, HandleRefModel):
 | 
						|
        # instance
 | 
						|
        k = entity.nsp_namespace
 | 
						|
        j = "%s.%d" % (entity.ref_tag, entity.id)
 | 
						|
    else:
 | 
						|
        # class
 | 
						|
        k = entity.nsp_namespace_from_id(org.id, "*").strip(".*")
 | 
						|
        j = entity.handleref.tag
 | 
						|
    if k in source:
 | 
						|
        dest[j] = source[k]
 | 
						|
 | 
						|
 | 
						|
def org_admin_required(fnc):
 | 
						|
    """
 | 
						|
    Decorator function that ensures that the requesting user
 | 
						|
    has administrative rights to the targeted organization
 | 
						|
 | 
						|
    Also sets "org" in kwargs
 | 
						|
    """
 | 
						|
 | 
						|
    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)
 | 
						|
            if not nsp.has_perms(request.user, org.nsp_namespace_manage,
 | 
						|
                                 "update"):
 | 
						|
                return JsonResponse({}, status=403)
 | 
						|
            kwargs["org"] = org
 | 
						|
            return fnc(request, **kwargs)
 | 
						|
        except Organization.DoesNotExist:
 | 
						|
            return JsonResponse({
 | 
						|
                "non_field_errors": [_("Invalid organization specified")]
 | 
						|
            }, status=400)
 | 
						|
 | 
						|
    return callback
 | 
						|
 | 
						|
 | 
						|
def target_user_validate(fnc):
 | 
						|
    """
 | 
						|
    Decorator function that ensures that the targeted user
 | 
						|
    is a member of the targeted organization
 | 
						|
 | 
						|
    Should be below org_admin_required
 | 
						|
 | 
						|
    Also sets "user" in kwargs
 | 
						|
    """
 | 
						|
 | 
						|
    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):
 | 
						|
    """
 | 
						|
    Returns JsonResponse with a list of all users in the specified org
 | 
						|
    """
 | 
						|
 | 
						|
    org = kwargs.get("org")
 | 
						|
 | 
						|
    rv = {
 | 
						|
        "users": [{
 | 
						|
            "id": user.id,
 | 
						|
            "name": "%s <%s, %s>" % (user.full_name, user.email, user.username)
 | 
						|
        } for user in org.usergroup.user_set.all()]
 | 
						|
    }
 | 
						|
 | 
						|
    rv.update({"status": "ok"})
 | 
						|
 | 
						|
    return JsonResponse(rv)
 | 
						|
 | 
						|
 | 
						|
@login_required
 | 
						|
@org_admin_required
 | 
						|
@target_user_validate
 | 
						|
def manage_user_delete(request, **kwargs):
 | 
						|
    """
 | 
						|
    remove user from org
 | 
						|
    """
 | 
						|
 | 
						|
    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
 | 
						|
@org_admin_required
 | 
						|
@target_user_validate
 | 
						|
def manage_user_update(request, **kwargs):
 | 
						|
    """
 | 
						|
    udpate a user in the org
 | 
						|
 | 
						|
    right now this only allows for moving the user either
 | 
						|
    to admin or member group
 | 
						|
    """
 | 
						|
 | 
						|
    org = kwargs.get("org")
 | 
						|
    user = kwargs.get("user")
 | 
						|
    group = request.POST.get("group")
 | 
						|
    if group not in ["member", "admin"]:
 | 
						|
        return JsonResponse({
 | 
						|
            "group": _("Needs to be member or admin")
 | 
						|
        }, status=400)
 | 
						|
 | 
						|
    if group == "admin":
 | 
						|
        org.usergroup.user_set.remove(user)
 | 
						|
        org.admin_usergroup.user_set.add(user)
 | 
						|
    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):
 | 
						|
    """
 | 
						|
    Returns JsonRespone with list of user's permissions for the targeted
 | 
						|
    org an entities under it
 | 
						|
 | 
						|
    Permisions are returned as a dict of permissioning ids and permission
 | 
						|
    levels.
 | 
						|
 | 
						|
    Permissioning ids serve as a wrapper for actual permissioning namespaces
 | 
						|
    so we can expose them to the organization admins for changes without allowing
 | 
						|
    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
 | 
						|
@org_admin_required
 | 
						|
@target_user_validate
 | 
						|
def user_permission_update(request, **kwargs):
 | 
						|
    """
 | 
						|
    Update/Add a user's permission
 | 
						|
 | 
						|
    perms = permission level
 | 
						|
    entity = permission id
 | 
						|
    """
 | 
						|
 | 
						|
    org = kwargs.get("org")
 | 
						|
    user = kwargs.get("user")
 | 
						|
 | 
						|
    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
 | 
						|
@org_admin_required
 | 
						|
@target_user_validate
 | 
						|
def user_permission_remove(request, **kwargs):
 | 
						|
    """
 | 
						|
    Remove a user's permission
 | 
						|
 | 
						|
    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):
 | 
						|
    """
 | 
						|
    Returns list of permissioning ids with labels that
 | 
						|
    are valid to be permissioned out to regular org users
 | 
						|
 | 
						|
    Permissioning ids serve as a wrapper for actual permissioning namespaces
 | 
						|
    so we can expose them to the organization admins for changes without allowing
 | 
						|
    them to set permissioning namespaces directly.
 | 
						|
    """
 | 
						|
 | 
						|
    org = kwargs.get("org")
 | 
						|
 | 
						|
    perms = [{
 | 
						|
        "id": id,
 | 
						|
        "name": name
 | 
						|
    } for id, name in permission_ids(org).items()]
 | 
						|
    perms = sorted(perms, key=lambda x: x.get("name"))
 | 
						|
    return JsonResponse({"status": "ok", "permissions": perms})
 | 
						|
 | 
						|
 | 
						|
@login_required
 | 
						|
@csrf_protect
 | 
						|
@org_admin_required
 | 
						|
def uoar_approve(request, **kwargs):
 | 
						|
    """
 | 
						|
    Approve a user request to affiliate with the organization
 | 
						|
    """
 | 
						|
 | 
						|
    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"})
 | 
						|
 | 
						|
        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(
 | 
						|
                        _("%(user_name)s's afilliation request has been approved"
 | 
						|
                          ) % {'user_name': uoar.user.full_name},
 | 
						|
                        loader.get_template(
 | 
						|
                            '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
 | 
						|
        })
 | 
						|
 | 
						|
    except UserOrgAffiliationRequest.DoesNotExist:
 | 
						|
        return JsonResponse({"status": "ok"})
 | 
						|
 | 
						|
    return JsonResponse({"status": "ok"})
 | 
						|
 | 
						|
 | 
						|
@login_required
 | 
						|
@csrf_protect
 | 
						|
@org_admin_required
 | 
						|
def uoar_deny(request, **kwargs):
 | 
						|
    """
 | 
						|
    Approve a user request to affiliate with the organization
 | 
						|
    """
 | 
						|
 | 
						|
    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
 | 
						|
            uoar.deny()
 | 
						|
 | 
						|
        except User.DoesNotExist:
 | 
						|
            uoar.delete()
 | 
						|
            return JsonResponse({"status": "ok"})
 | 
						|
 | 
						|
        # notify rest of org admins that the affiliation request has been
 | 
						|
        # approved
 | 
						|
 | 
						|
        for user in org.admin_usergroup.user_set.all():
 | 
						|
            if user != request.user:
 | 
						|
                with override(user.locale):
 | 
						|
                    user.email_user(
 | 
						|
                        _("%(user_name)s's afilliation request has been denied"
 | 
						|
                          ) % {'user_name': uoar.user.full_name},
 | 
						|
                        loader.get_template(
 | 
						|
                            '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)
 | 
						|
                        }))
 | 
						|
 | 
						|
    except UserOrgAffiliationRequest.DoesNotExist:
 | 
						|
        return JsonResponse({"status": "ok"})
 | 
						|
 | 
						|
    return JsonResponse({"status": "ok"})
 |