def view_import_net_ixf_preview(request, net_id): # check if request was blocked by rate limiting was_limited = getattr(request, "limited", False) if was_limited: return error_response( _("Please wait a bit before requesting " "another ixf import preview."), status=400, ) try: net = Network.objects.get(id=net_id, status="ok") except Network.DoesNotExist: return error_response(_("Network not found"), status=404) if not has_perms(request.user, net, "update"): return error_response(_("Permission denied"), status=403) total_log = {"data": [], "errors": []} for ixlan in net.ixlan_set_ixf_enabled: importer = ixf.Importer() importer.cache_only = True success, netixlans, deleted, log = importer.update(ixlan, asn=net.asn, save=False) total_log["data"].extend(log["data"]) total_log["errors"].extend([ "{}({}): {}".format(ixlan.ix.name, ixlan.id, err) for err in log["errors"] ]) return pretty_response(total_log)
def destroy(self, request, pk, format=None): """ Delete object """ try: try: obj = self.model.objects.get(pk=pk) except ValueError: return Response(status=status.HTTP_400_BAD_REQUEST, data={"extra": "Invalid id"}) except self.model.DoesNotExist: return Response(status=status.HTTP_204_NO_CONTENT) if nsp.has_perms(request.user, obj, "delete"): with reversion.create_revision(): if request.user: reversion.set_user(request.user) obj.delete() return Response(status=status.HTTP_204_NO_CONTENT) else: return Response(status=status.HTTP_403_FORBIDDEN) except ProtectedAction as exc: return Response(status=status.HTTP_403_FORBIDDEN, data={"detail": f"{exc}"}) finally: self.get_serializer().finalize_delete(request)
def to_representation(self, instance): """ Apply permissions to serialized data before sending it out for good """ r = super(serializers.ModelSerializer, self).to_representation(instance) req = self.context.get("request", None) user = self.context.get("user") if not user and req: user = req.user if user: # superusers can see everything if user.is_superuser: return r if getattr(instance, "nsp_require_explicit_read", False): if not has_perms(user, instance, 0x01): return None r = permissions_apply_to_serialized_model(instance, user, data=r) return r
def destroy(self, request, pk, format=None): """ Delete object """ try: try: obj = self.model.objects.get(pk=pk) except ValueError: return Response(status=status.HTTP_400_BAD_REQUEST, data={"extra": "Invalid id"}) except self.model.DoesNotExist: return Response(status=status.HTTP_204_NO_CONTENT) if nsp.has_perms(request.user, obj, "delete"): with reversion.create_revision(): if request.user: reversion.set_user(request.user) obj.delete() return Response(status=status.HTTP_204_NO_CONTENT) else: return Response(status=status.HTTP_403_FORBIDDEN) except ProtectedAction as exc: exc_message = f"{exc} - " + _( "Please contact {} to help with the deletion of this object" ).format(settings.DEFAULT_FROM_EMAIL) ticket_queue_deletion_prevented(request.user, exc.protected_object) return Response(status=status.HTTP_403_FORBIDDEN, data={"detail": exc_message}) finally: self.get_serializer().finalize_delete(request)
def view_import_ixlan_ixf_preview(request, ixlan_id): # check if request was blocked by rate limiting was_limited = getattr(request, "limited", False) if was_limited: return JsonResponse({ "non_field_errors": [ _("Please wait a bit before requesting " \ "another ixf import preview.") ] }, status=400) try: ixlan = IXLan.objects.get(id=ixlan_id) except IXLan.DoesNotExist: return JsonResponse({"non_field_errors": [_("Ixlan not found")]}, status=404) if not has_perms(request.user, ixlan, "update"): return JsonResponse({"non_field_errors": [_("Permission denied")]}, status=403) importer = ixf.Importer() importer.update(ixlan, save=False) return HttpResponse(json.dumps(importer.log, indent=2), content_type="application/json")
def test_has_perms_wildcard(self): self.assertEqual( util.has_perms(self.perms, "b.*", constants.PERM_READ), True) self.assertEqual( util.has_perms(self.perms, "a.b.*", constants.PERM_READ, ambiguous=True), True, ) self.assertEqual( util.has_perms(self.perms, "d\..*", constants.PERM_READ, ambiguous=True), False, )
def has_object_permission(self, request, view, obj): self.debug( "Check Object permissions %s, %s, %s" % (request.method, request.user, obj_to_namespace(obj)) ) if request.method in permissions.SAFE_METHODS: return has_perms(request.user, obj, PERM_READ) else: func_name = "nsp_has_perms_%s" % request.method if hasattr(obj, func_name): func = getattr(obj, func_name) return func(request.user, request) else: return has_perms( request.user, obj, get_permission_flag(method_to_permcode(request.method)), )
def test_model_perms(self): obj = ModelTestB() obj.id = 1 obj2 = ModelTestB() obj2.id = 2 self.assertEqual(util.has_perms(self.perms, obj, constants.PERM_WRITE), True) self.assertEqual( util.has_perms(self.perms, obj2, constants.PERM_WRITE), False) self.assertEqual( util.has_perms(self.perms, [obj2, "allowedfield"], constants.PERM_READ), True, ) self.assertEqual( util.has_perms(self.perms, [obj2, "deniedfield"], constants.PERM_READ), False, ) self.assertEqual( util.has_perms(self.perms, [obj2, "allowedfield"], constants.PERM_WRITE), False, )
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 )
def has_module_perms(self, user_obj, obj=None): if hasattr(obj, "nsp_namespace"): fn = getattr(obj, "nsp_namespace") if not isinstance(fn, collections.Callable): raise Exception( "nsp_namespace attribute needs to be callable for %s" % obj) namespace = fn() else: namespace = obj_to_namespace(obj) log.info("Checking module perms: %s" % namespace) perms = self.load_perms(user_obj) return has_perms(perms, namespace, PERM_READ)
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)
def view_import_net_ixf_postmortem(request, net_id): # check if request was blocked by rate limiting was_limited = getattr(request, "limited", False) if was_limited: return error_response( _("Please wait a bit before requesting " "another IX-F import postmortem."), status=400, ) # load net try: net = Network.objects.get(id=net_id, status="ok") except Network.DoesNotExist: return error_response(_("Network not found"), status=404) if not has_perms(request.user, net, "update"): return error_response(_("Permission denied"), status=403) # make sure limit is within bounds and a valid number try: limit = int(request.GET.get("limit", 25)) except: limit = 25 errors = [] if limit < 1: limit = 1 elif limit > settings.IXF_POSTMORTEM_LIMIT: errors.append( _("Postmortem length cannot exceed {} entries").format( settings.IXF_POSTMORTEM_LIMIT ) ) post_mortem = ixf.PostMortem() log = post_mortem.generate(net.asn, limit=limit) return pretty_response({"data": log, "non_field_errors": errors})
def view_import_ixlan_ixf_preview(request, ixlan_id): # check if request was blocked by rate limiting was_limited = getattr(request, "limited", False) if was_limited: return error_response(_("Please wait a bit before requesting " \ "another ixf import preview."), status=400) try: ixlan = IXLan.objects.get(id=ixlan_id) except IXLan.DoesNotExist: return error_response(_("Ixlan not found"), status=404) if not has_perms(request.user, ixlan, "update"): return error_response(_("Permission denied"), status=403) importer = ixf.Importer() importer.update(ixlan, save=False) return pretty_response(importer.log)
def has_perm(self, user_obj, perm, obj=None): # if not user_obj.is_authenticated() or not user.is_active: # FIXME: load guest perms and proceed # return False # super users have access to everything if user_obj.is_superuser: return True namespace, level = permcode_to_namespace(perm) write_ops = ["add", "delete", "change"] if hasattr(obj, "nsp_write_ops") and callable(obj, "nsp_write_ops"): write_ops.extend(getattr(obj, "nsp_write_ops")()) log.info("NSP has_perms %s %s %s" % (namespace, perm, level)) perms = self.load_perms(user_obj) return has_perms(perms, namespace, level)
def destroy(self, request, pk, format=None): """ Delete object """ try: try: obj = self.model.objects.get(pk=pk) except ValueError: return Response(status=status.HTTP_400_BAD_REQUEST, data={"extra": "Invalid id"}) except self.model.DoesNotExist: return Response(status=status.HTTP_204_NO_CONTENT) if nsp.has_perms(request.user, obj, "delete"): with reversion.create_revision(): if request.user: reversion.set_user(request.user) obj.delete() return Response(status=status.HTTP_204_NO_CONTENT) else: return Response(status=status.HTTP_403_FORBIDDEN) finally: self.get_serializer().finalize_delete(request)
def apply_permissions_generic(self, data, explicit=False, join_ids=[], **kwargs): """ Apply permissions to all rows according to rules specified in parameters explicit <function> if explicit is passed as a function it will be called and the result will determine whether or not explicit read perms are required for the row join_ids [(target_id<str>, proxy_id<str>, model<handleref>), ..] Since we are checking permissioning namespaces, and those namespaces may consist of object ids that are not necessarily in the dataset you can join those ids in via the join_ids parameter """ rv = [] joined_ids = collections.OrderedDict() e = {} inst = self.model() # perform id joining if join_ids: for t, p, model in join_ids: joined_ids[t] = { "p": p, "ids": self.join_ids( data, t, p, model, joined_ids.get(p, e).get("ids", e).values() ), } for row in data: # create dict containing ids needed to build the permissioning # namespace init = dict([(k, row.get(v)) for k, v in kwargs.items()]) # joined ids for t, j in joined_ids.items(): if j["p"] in row: init[t] = j["ids"].get(row.get(j["p"])) elif t in joined_ids: init[t] = joined_ids.get(t).get("ids").get(init[j["p"]]) # build permissioning namespace ns = self.model.nsp_namespace_from_id(**init).lower() # apply fields filter if self.fields: for k in row.keys(): if k not in self.fields: del row[k] # determine whether or not read perms for this object need # to be explicitly set if explicit and callable(explicit): expl = explicit(row) else: expl = False # initial read perms check if nsp.has_perms(self.request.user, ns, 0x01, explicit=expl): ruleset = getattr(inst, "nsp_ruleset", {}) # apply permissions to tree row = self.apply_permissions(ns, row, ruleset=ruleset) # if row still has data aftewards, append to results if row: rv.append(row) return rv
def apply_permissions_generic(self, data, explicit=False, join_ids=[], **kwargs): """ Apply permissions to all rows according to rules specified in parameters explicit <function> if explicit is passed as a function it will be called and the result will determine whether or not explicit read perms are required for the row join_ids [(target_id<str>, proxy_id<str>, model<handleref>), ..] Since we are checking permissioning namespaces, and those namespaces may consist of object ids that are not necessarily in the dataset you can join those ids in via the join_ids parameter """ rv = [] joined_ids = collections.OrderedDict() e = {} inst = self.model() # perform id joining if join_ids: for t, p, model in join_ids: joined_ids[t] = { "p": p, "ids": self.join_ids(data, t, p, model, joined_ids.get(p, e).get("ids", e).values()) } for row in data: # create dict containing ids needed to build the permissioning # namespace init = dict([(k, row.get(v)) for k, v in kwargs.items()]) # joined ids for t, j in joined_ids.items(): if j["p"] in row: init[t] = j["ids"].get(row.get(j["p"])) elif t in joined_ids: init[t] = joined_ids.get(t).get("ids").get(init[j["p"]]) # build permissioning namespace ns = self.model.nsp_namespace_from_id(**init).lower() # apply fields filter if self.fields: for k in row.keys(): if k not in self.fields: del row[k] # determine whether or not read perms for this object need # to be explicitly set if explicit and callable(explicit): expl = explicit(row) else: expl = False # initial read perms check if nsp.has_perms(self.request.user, ns, 0x01, explicit=expl): ruleset = getattr(inst, "nsp_ruleset", {}) # apply permissions to tree row = self.apply_permissions(ns, row, ruleset=ruleset) # if row still has data aftewards, append to results if row: rv.append(row) return rv
def nsp_check_write(user, obj): return nsp.has_perms(user, obj, PERM_WRITE)
def nsp_check_read(user, obj): return nsp.has_perms(user, obj, PERM_READ)
def test_has_perms(self): self.assertEqual( util.has_perms(self.perms, "a.b", constants.PERM_READ), True) self.assertEqual( util.has_perms(self.perms, "a.b", constants.PERM_WRITE), False) self.assertEqual( util.has_perms(self.perms, "a.b.c", constants.PERM_WRITE), True) self.assertEqual( util.has_perms(self.perms, "a.b.c", constants.PERM_READ), True) self.assertEqual( util.has_perms(self.perms, "a.b.d", constants.PERM_READ), False) self.assertEqual( util.has_perms(self.perms, "a.b.d", constants.PERM_WRITE), False) self.assertEqual( util.has_perms(self.perms, "e.a.a", constants.PERM_READ, explicit=True), False, ) self.assertEqual( util.has_perms(self.perms, "e.a.b", constants.PERM_READ, explicit=True), True, ) self.assertEqual(util.has_perms(self.perms, "a.b", "read"), True) self.assertEqual(util.has_perms(self.perms, "a.b.d", "read"), False) self.assertEqual(util.has_perms(self.perms, "a.b.d", "write"), False)
def test_has_perms_crud(self): settings.NSP_MODE = "crud" self.assertEqual(util.has_perms(self.perms_crud, "r.a", "read"), True) self.assertEqual(util.has_perms(self.perms_crud, "r.a", "update"), False) self.assertEqual(util.has_perms(self.perms_crud, "r.a", "create"), False) self.assertEqual(util.has_perms(self.perms_crud, "r.a", "delete"), False) self.assertEqual(util.has_perms(self.perms_crud, "r.a.1", "update"), True) self.assertEqual(util.has_perms(self.perms_crud, "r.a.1", "create"), False) self.assertEqual(util.has_perms(self.perms_crud, "r.a.1", "delete"), False) self.assertEqual(util.has_perms(self.perms_crud, "r.a.2", "update"), False) self.assertEqual(util.has_perms(self.perms_crud, "r.a.2", "create"), True) self.assertEqual(util.has_perms(self.perms_crud, "r.a.2", "delete"), False) self.assertEqual(util.has_perms(self.perms_crud, "r.a.3", "update"), False) self.assertEqual(util.has_perms(self.perms_crud, "r.a.3", "create"), False) self.assertEqual(util.has_perms(self.perms_crud, "r.a.3", "delete"), True) self.assertEqual(util.has_perms(self.perms_crud, "r.a.4", "read"), False) self.assertEqual(util.has_perms(self.perms_crud, "r.a.4", "update"), False) self.assertEqual(util.has_perms(self.perms_crud, "r.a.4", "create"), False) self.assertEqual(util.has_perms(self.perms_crud, "r.a.4", "delete"), False) settings.NSP_MODE = "rw"
def has_create_perms(self, user, validated_data): return has_perms( user, self.nsp_namespace_create(validated_data), get_permission_flag("create"), )