Skip to content
Snippets Groups Projects
Commit 0bae79cf authored by David Schmitz's avatar David Schmitz
Browse files

feature/admin_user_delete_with_owned_rule_reassigning: allow admin deletion of...

feature/admin_user_delete_with_owned_rule_reassigning: allow admin deletion of users which are assigned as applier to some rules by re-assigning the rules to another remaining user of the same peer the user to be deleted pertains (only if the user is assigned to exactly 1 peer)
parent 64cdf404
No related branches found
No related tags found
No related merge requests found
...@@ -21,7 +21,16 @@ from django.db import models ...@@ -21,7 +21,16 @@ from django.db import models
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import AbstractBaseUser, User, BaseUserManager from django.contrib.auth.models import AbstractBaseUser, User, BaseUserManager
from peers.models import Peer from peers.models import Peer
from flowspec.models import Route
# TODO: dependency issue: move logging_utils to general package
import flowspec.logging_utils
logger = flowspec.logging_utils.logger_init_default(__name__, "accounts_model.log", False)
#
#
class UserProfile(models.Model): class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE) user = models.OneToOneField(User, on_delete=models.CASCADE)
...@@ -46,8 +55,54 @@ class UserProfile(models.Model): ...@@ -46,8 +55,54 @@ class UserProfile(models.Model):
return False return False
return networks return networks
# deleting of rules by this account is allowed
def is_delete_allowed(self): def is_delete_allowed(self):
user_is_admin = self.user.is_superuser user_is_admin = self.user.is_superuser
username = self.username username = self.username
return (user_is_admin and settings.ALLOW_DELETE_FULL_FOR_ADMIN) or settings.ALLOW_DELETE_FULL_FOR_USER_ALL or (username in settings.ALLOW_DELETE_FULL_FOR_USER_LIST) return (user_is_admin and settings.ALLOW_DELETE_FULL_FOR_ADMIN) or settings.ALLOW_DELETE_FULL_FOR_USER_ALL or (username in settings.ALLOW_DELETE_FULL_FOR_USER_LIST)
#
from django.dispatch import receiver
from django.db.models.signals import pre_delete
#@receiver(pre_delete, sender=UserProfile)
@receiver(pre_delete, sender=User)
def user_pre_delete_handler(sender, instance, **kwargs):
logger.info("user_pre_delete_handler(): pre_delete instance="+str(instance))
user_owned_rules_adopt_to_related_user(instance)
def user_owned_rules_adopt_to_related_user(user):
routes_owned = Route.objects.filter(applier=user)
logger.info("user_owned_rules_adopt_to_related_user(): => routes_owned="+str(routes_owned))
users_peers = user.userprofile.peers.all()
users_peers1 = None
logger.info("user_owned_rules_adopt_to_related_user(): => users_peers="+str(users_peers))
if len(users_peers)==1:
users_peers1 = users_peers[0]
logger.info("user_owned_rules_adopt_to_related_user(): => users_peers[0]="+str(users_peers1))
#peers1_userprofiles = users_peers[0].user_profile
#logger.info("user_owned_rules_adopt_to_related_user(): => peers1_userprofiles="+str(peers1_userprofiles))
users_related = User.objects.filter(userprofile__peers__in=users_peers)
logger.info("user_owned_rules_adopt_to_related_user(): => users_related="+str(users_related))
user_related1 = None
for user2 in users_related:
if user2 != user:
user_related1=user2
break
logger.info("user_owned_rules_adopt_to_related_user(): => user_related1="+str(user_related1))
if user_related1!=None:
if len(routes_owned)>0:
logger.info("user_owned_rules_adopt_to_related_user(): len="+str(len(routes_owned)))
for route in routes_owned:
logger.info("user_owned_rules_adopt_to_related_user(): owned route="+str(route))
route.applier = user_related1
logger.info("user_owned_rules_adopt_to_related_user(): reassigning owned route="+str(route)+" by user to be deleted ("+str(user)+") to new owner "+str(user_related1))
route.save()
return (routes_owned, user_related1, users_peers1)
...@@ -27,6 +27,14 @@ from django.contrib.auth.admin import UserAdmin ...@@ -27,6 +27,14 @@ from django.contrib.auth.admin import UserAdmin
from peers.models import * from peers.models import *
from longerusername.forms import UserCreationForm, UserChangeForm from longerusername.forms import UserCreationForm, UserChangeForm
from django.contrib import messages
from accounts.models import user_owned_rules_adopt_to_related_user
# TODO: dependency issue: move logging_utils to general package
import flowspec.logging_utils
logger = flowspec.logging_utils.logger_init_default(__name__, "flowspec_admin.log", False)
#
class RouteAdmin(admin.ModelAdmin): class RouteAdmin(admin.ModelAdmin):
form = RouteForm form = RouteForm
...@@ -83,6 +91,21 @@ class UserProfileAdmin(UserAdmin): ...@@ -83,6 +91,21 @@ class UserProfileAdmin(UserAdmin):
queryset = queryset.update(is_active=True) queryset = queryset.update(is_active=True)
activate.short_description = "Activate Selected Users" activate.short_description = "Activate Selected Users"
def delete_model(self, request, client):
if False:
messages.set_level(request, messages.ERROR)
messages.error(request, 'Blocking deletion')
else:
(adopted_rules, adoting_user, users_peer1) = user_owned_rules_adopt_to_related_user(client) # before actually calling the super.delete_model clean-up owned rules in order to get info about the cleanup which can be used for extra message to the admin UI
logger.info("delete_model() => adoting_user="+str(adoting_user))
logger.info("delete_model() => adopted_rules="+str(adopted_rules))
if len(adopted_rules)>0:
messages.set_level(request, messages.INFO)
messages.error(request, 'additional info: the rules '+str(adopted_rules)+' were re-assigned to remaining user '+str(adoting_user)+' of peer '+str(users_peer1))
super().delete_model(request, client)
def get_userprofile_peers(self, instance): def get_userprofile_peers(self, instance):
# instance is User instance # instance is User instance
peers = instance.userprofile.peers.all() peers = instance.userprofile.peers.all()
......
...@@ -45,8 +45,13 @@ def get_matching_related_peer_for_rule_destination(ivaltrees_per_version, route) ...@@ -45,8 +45,13 @@ def get_matching_related_peer_for_rule_destination(ivaltrees_per_version, route)
peer_name_tmp = None peer_name_tmp = None
peer_name_tmp_not_applier_related = None peer_name_tmp_not_applier_related = None
try: try:
if route.applier!=None: applier = route.applier
route_applier__peers_related = set(route.applier.userprofile.peers.select_related()) except:
applier = None
try:
if applier!=None:
route_applier__peers_related = set(applier.userprofile.peers.select_related())
else: else:
route_applier__peers_related = None route_applier__peers_related = None
......
...@@ -157,7 +157,8 @@ class ThenAction(models.Model): ...@@ -157,7 +157,8 @@ class ThenAction(models.Model):
class Route(models.Model): class Route(models.Model):
name = models.SlugField(max_length=128, verbose_name=_("Name")) name = models.SlugField(max_length=128, verbose_name=_("Name"))
applier = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE) #applier = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)
applier = models.ForeignKey(User, blank=True, null=True, on_delete=models.DO_NOTHING)
source = models.CharField(max_length=45+4, help_text=_("Network address. Use address/CIDR notation"), verbose_name=_("Source Address")) source = models.CharField(max_length=45+4, help_text=_("Network address. Use address/CIDR notation"), verbose_name=_("Source Address"))
sourceport = models.TextField(blank=True, null=True, verbose_name=_("Source Port")) sourceport = models.TextField(blank=True, null=True, verbose_name=_("Source Port"))
destination = models.CharField(max_length=45+4, help_text=_("Network address. Use address/CIDR notation"), verbose_name=_("Destination Address")) destination = models.CharField(max_length=45+4, help_text=_("Network address. Use address/CIDR notation"), verbose_name=_("Destination Address"))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment