This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
veridic/acs/deletion_view.py

565 lines
24 KiB
Python

'''
VERIDIC - Towards a centralized access control system
Copyright (C) 2011 Mikael Ates
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
'''
import logging
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.contrib import messages
from django.conf import settings
from django.contrib.auth.models import User
from django.views.decorators.csrf import csrf_exempt
from django.utils.translation import ugettext as _
from django.template import RequestContext
from django.contrib.contenttypes.models import ContentType
from core import isAuthorizedRBAC2, \
set_default_alias, is_user_administrator, \
is_policy_root_administrator, is_policy_user_administrator, \
check_permission, return_all_derived_delegated_permissions
from views import list_any
from alias_mgmt_views import list_aliases
from utils_views import get_policy_from_session
from models import UserAlias, Role, AcsObject, View, Action, Activity, \
Namespace, AcsPermission, Policy, AcsAbacPermission
from abac.models import Source, PredicateRequired, PredicateComparison
from acs.abac.core import remove_rule
from decorators import prevent_access_to_normal_users
logger = logging.getLogger('acs')
login_url = settings.LOGIN_URL
root_url = settings.ROOT_URL
@csrf_exempt
@prevent_access_to_normal_users
def del_any(request):
backlink = root_url
if request.method == 'POST':
logger.debug('del_any: POST')
if 'Cancel' in request.POST:
messages.add_message(request, messages.INFO,
_('Operation canceled'))
if 'type_entity' in request.POST:
return list_any(request, request.POST['type_entity'])
elif 'back_url' in request.POST:
return HttpResponseRedirect(request.POST['back_url'])
else:
return HttpResponseRedirect(root_url)
if not 'Delete' in request.POST:
messages.add_message(request, messages.ERROR,
_('Unknown action requested'))
return HttpResponseRedirect(root_url)
if not 'id' in request.POST or not 'type_entity' in request.POST:
messages.add_message(request, messages.ERROR,
_('Unable to find the object'))
return HttpResponseRedirect(root_url)
type_entity = request.POST['type_entity']
pk = request.POST['id']
item = None
p = []
p_admin = []
administration = Action.objects.get(name='administration')
admin_deletion=[]
policy = get_policy_from_session(request)
default_ns = Namespace.objects.get(name='Default')
if type_entity == 'user':
try:
item = User.objects.get(id=pk)
except:
messages.add_message(request, messages.ERROR,
_('Unable to find the object'))
return list_any(request, type_entity)
'''
Check authorization to delete this item
The special user administrator role is needed because here we
manage users even if they are not declared in ACS (empowered)
'''
if not is_user_administrator(request.user):
messages.add_message(request, messages.ERROR,
_('You are not authorized to delete the user %s') %item)
return list_any(request, type_entity)
'''
Even if users can administrate themselves,
we do not want hem to delete themselves
'''
if request.user.id == item.id:
messages.add_message(request, messages.ERROR,
_('You are not authorized to delete yourself Mister or Miss \
%s') %item)
return list_any(request, type_entity)
elif type_entity == 'alias':
try:
item = UserAlias.objects.get(id=pk)
except:
messages.add_message(request, messages.ERROR,
_('Unable to find the object'))
return list_aliases(request)
'''Check authorization to delete this item'''
policy = None
try:
policy = Policy.objects.get(namespace=item.namespace)
except:
pass
back_url = root_url
if 'back_url' in request.POST:
back_url = request.POST['back_url']
if item.namespace.id == default_ns.id:
messages.add_message(request, messages.ERROR,
_('Default user alias cannot be deleted'))
return HttpResponseRedirect(back_url)
if not is_policy_user_administrator(request.user, policy):
messages.add_message(request, messages.ERROR,
_('You are not authorized to delete the user alias %s') %item)
return HttpResponseRedirect(back_url)
'''
The permissions that should be removed, only aliases not in
default, so no admin permission with this alias as who
'''
p = list(AcsPermission.objects.\
filter(content_type_who__pk=\
ContentType.objects.get_for_model(item).id,
object_id_who=item.id))
'''This alias may be what of an administration permission'''
p_admin = list(AcsPermission.objects.\
filter(content_type_what__pk=\
ContentType.objects.get_for_model(item).id,
object_id_what=item.id, content_type_how__pk=\
ContentType.objects.get_for_model(administration).id,
object_id_how=administration.id))
elif type_entity == 'role':
if not policy:
messages.add_message(request, messages.ERROR,
_('Missing policy'))
return list_any(request, type_entity)
try:
item = Role.objects.get(id=pk)
except:
messages.add_message(request, messages.ERROR,
_('Unable to find the object'))
return list_any(request, type_entity)
if item in policy.admin_roles.all():
messages.add_message(request, messages.ERROR,
_('%s is an administration role and cannot be deleted here')
%item)
return list_any(request, type_entity)
'''Check authorization to delete this item'''
p = isAuthorizedRBAC2(set_default_alias(request.user), item,
administration)
if not p:
messages.add_message(request, messages.ERROR,
_('You are not authorized to delete the role %s') %item)
return list_any(request, type_entity)
'''
The permissions that should be removed, only not admin role,
so no admin permission with this alias as who
'''
p = list(AcsPermission.objects.\
filter(content_type_who__pk=\
ContentType.objects.get_for_model(item).id,
object_id_who=item.id))
'''This alias may be what of an administration permission'''
p_admin = list(AcsPermission.objects.\
filter(content_type_what__pk=\
ContentType.objects.get_for_model(item).id,
object_id_what=item.id, content_type_how__pk=\
ContentType.objects.get_for_model(administration).id,
object_id_how=administration.id))
elif type_entity == 'admin_role':
if not policy:
messages.add_message(request, messages.ERROR,
_('Missing policy'))
return list_any(request, type_entity)
try:
item = Role.objects.get(id=pk)
except:
messages.add_message(request, messages.ERROR,
_('Unable to find the object'))
return list_any(request, type_entity)
if not item in policy.admin_roles.all():
messages.add_message(request, messages.ERROR,
_('%s is not an administration role') %item)
return list_any(request, type_entity)
'''Check authorization to delete this item'''
if not is_policy_root_administrator(request.user, policy):
messages.add_message(request, messages.ERROR,
_('You are not authorized to delete the role %s') %item)
return list_any(request, type_entity)
'''The permissions that should be removed'''
p = list(AcsPermission.objects.\
filter(content_type_who__pk=\
ContentType.objects.get_for_model(item).id,
object_id_who=item.id, content_type_how__pk=\
ContentType.objects.get_for_model(administration).id,
object_id_how=administration.id))
'''
No administration permission with an administration role as what
'''
elif type_entity == 'object':
if not policy:
messages.add_message(request, messages.ERROR,
_('Missing policy'))
return list_any(request, type_entity)
try:
item = AcsObject.objects.get(id=pk)
except:
messages.add_message(request, messages.ERROR,
_('Unable to find the object'))
return list_any(request, type_entity)
'''Check authorization to delete this item'''
p = isAuthorizedRBAC2(set_default_alias(request.user), item,
administration)
if not p:
messages.add_message(request, messages.ERROR,
_('You are not authorized to delete the object %s') %item)
return list_any(request, type_entity)
'''
The permissions that should be removed, object of a normal
permission and objects of administration permission
'''
p = list(AcsPermission.objects.\
filter(content_type_what__pk=\
ContentType.objects.get_for_model(item).id,
object_id_what=item.id))
for it in p:
if it.how.id == administration.id:
p_admin.append(it)
p.remove(it)
elif type_entity == 'view':
if not policy:
messages.add_message(request, messages.ERROR,
_('Missing policy'))
return list_any(request, type_entity)
try:
item = View.objects.get(id=pk)
except:
messages.add_message(request, messages.ERROR,
_('Unable to find the object'))
return list_any(request, type_entity)
if item in policy.admin_views.all():
messages.add_message(request, messages.ERROR,
_('%s is an administration view and cannot be deleted here')
%item)
return list_any(request, type_entity)
'''Check authorization to delete this item'''
p = isAuthorizedRBAC2(set_default_alias(request.user), item,
administration)
if not p:
messages.add_message(request, messages.ERROR,
_('You are not authorized to delete the view %s') %item)
return list_any(request, type_entity)
'''
The permissions that should be removed, view of a normal
permission and objects of administration permission
'''
p = list(AcsPermission.objects.\
filter(content_type_what__pk=\
ContentType.objects.get_for_model(item).id,
object_id_what=item.id))
for it in p:
if it.how.id == administration.id:
p_admin.append(it)
p.remove(it)
elif type_entity == 'admin_view':
if not policy:
messages.add_message(request, messages.ERROR,
_('Missing policy'))
return list_any(request, type_entity)
try:
item = View.objects.get(id=pk)
except:
messages.add_message(request, messages.ERROR,
_('Unable to find the object'))
return list_any(request, type_entity)
if not item in policy.admin_views.all():
messages.add_message(request, messages.ERROR,
_('%s is not an administration role') %item)
return list_any(request, type_entity)
'''Check authorization to delete this item'''
if not is_policy_root_administrator(request.user, policy):
messages.add_message(request, messages.ERROR,
_('You are not authorized to delete the role %s') %item)
return list_any(request, type_entity)
'''
The permissions that should be removed, only administration
permission on admin views
'''
p_admin = list(AcsPermission.objects.\
filter(content_type_what__pk=\
ContentType.objects.get_for_model(item).id,
object_id_what=item.id, content_type_how__pk=\
ContentType.objects.get_for_model(administration).id,
object_id_how=administration.id))
elif type_entity == 'action':
if not policy:
messages.add_message(request, messages.ERROR,
_('Missing policy'))
return list_any(request, type_entity)
try:
item = Action.objects.get(id=pk)
except:
messages.add_message(request, messages.ERROR,
_('Unable to find the object'))
return list_any(request, type_entity)
if item.namespace.id == default_ns.id:
messages.add_message(request, messages.ERROR,
_('Default action cannot be deleted'))
return list_any(request, type_entity)
'''Check authorization to delete this item'''
p = isAuthorizedRBAC2(set_default_alias(request.user), item,
administration)
if not p:
messages.add_message(request, messages.ERROR,
_('You are not authorized to delete the action %s') %item)
return list_any(request, type_entity)
'''The permissions that should be removed'''
p = list(AcsPermission.objects.\
filter(content_type_how__pk=\
ContentType.objects.get_for_model(item).id,
object_id_how=item.id))
p_admin = list(AcsPermission.objects.\
filter(content_type_what__pk=\
ContentType.objects.get_for_model(item).id,
object_id_what=item.id, content_type_how__pk=\
ContentType.objects.get_for_model(administration).id,
object_id_how=administration.id))
elif type_entity == 'activity':
if not policy:
messages.add_message(request, messages.ERROR,
_('Missing policy'))
return list_any(request, type_entity)
try:
item = Activity.objects.get(id=pk)
except:
messages.add_message(request, messages.ERROR,
_('Unable to find the object'))
return list_any(request, type_entity)
if item.namespace.id == default_ns.id:
messages.add_message(request, messages.ERROR,
_('Default activity cannot be deleted'))
return list_any(request, type_entity)
'''Check authorization to delete this item'''
p = isAuthorizedRBAC2(set_default_alias(request.user), item,
administration)
if not p:
messages.add_message(request, messages.ERROR,
_('You are not authorized to delete the activity %s') %item)
return list_any(request, type_entity)
'''The permissions that should be removed'''
p = list(AcsPermission.objects.\
filter(content_type_how__pk=\
ContentType.objects.get_for_model(item).id,
object_id_how=item.id))
p_admin = list(AcsPermission.objects.\
filter(content_type_what__pk=\
ContentType.objects.get_for_model(item).id,
object_id_what=item.id, content_type_how__pk=\
ContentType.objects.get_for_model(administration).id,
object_id_how=administration.id))
elif type_entity == 'source':
if not is_user_administrator(request.user):
messages.add_message(request, messages.ERROR,
_('You are not authorized to delete a source of attributes'))
return list_any(request, type_entity)
try:
item = Source.objects.get(id=pk)
except:
messages.add_message(request, messages.ERROR,
_('Unable to find the source'))
return list_any(request, type_entity)
'''
Grab all ABAC permissions that have a predicate with that
source
'''
ats = item.attachedsource_set.all()
preds_req = []
for at in ats:
tmp = \
PredicateRequired.objects.filter(definition=at.assertion)
for t in tmp:
if t not in preds_req:
preds_req.append(t)
preds_cmp = []
for at in ats:
tmp = \
PredicateComparison.objects.filter(operand1=at.assertion)
for t in tmp:
if t not in preds_cmp:
preds_cmp.append(t)
tmp = \
PredicateComparison.objects.filter(operand2=at.assertion)
for t in tmp:
if t not in preds_cmp:
preds_cmp.append(t)
p = []
for it in preds_req:
tmp = AcsAbacPermission.objects.filter(rule=it.rule)
for t in tmp:
if t not in p:
p.append(t)
for it in preds_cmp:
tmp = AcsAbacPermission.objects.filter(rule=it.rule)
for t in tmp:
if t not in p:
p.append(t)
'''
Here we should remove assertionData of profile on such a
source
'''
else:
messages.add_message(request, messages.ERROR,
_('Unable to find the object'))
return list_any(request, type_entity)
collateral_damages = []
denied = []
'''The permissions that should be removed'''
if p_admin and not is_policy_root_administrator(request.user, policy):
messages.add_message(request, messages.ERROR,
_('You are not authorized to perform this deletion because \
you have not the administration right to delete the \
following administration permissions that should be removed \
if this object is removed:'))
for it in p_admin:
messages.add_message(request, messages.ERROR,
'%s' %it)
return list_any(request, type_entity)
for it in p:
collateral_damages.append(it)
'''
We check here that the user has the permission to delete the
permissions that should be removed if the object is removed
'''
if type_entity != 'source':
if not check_permission(request.user, policy, it):
if not it in denied:
denied.append(it)
else:
delegateds = return_all_derived_delegated_permissions(it)
if len(delegateds) > 1:
logger.debug('del_permission: delegated permissions \
%s' % delegateds)
for i in delegateds:
if not i in collateral_damages:
collateral_damages.append(i)
else:
logger.debug('del_permission: no delegated \
permissions')
if not it in collateral_damages:
collateral_damages.append(it)
if denied:
messages.add_message(request, messages.ERROR,
_('You are not authorized to perform this deletion because \
you have not the rights to delete the following permissions \
that should be removed if this object is removed:'))
for it in denied:
messages.add_message(request, messages.ERROR,
'%s' %it)
return list_any(request, type_entity)
if p_admin:
for it in p_admin:
collateral_damages.append(it)
if not 'consent' in request.POST:
tpl_parameters = {'item': item,
'type_entity': type_entity,
'admin_deletion': admin_deletion,
'collateral_damages': collateral_damages}
if 'back_url' in request.POST:
tpl_parameters['back_url'] = request.POST['back_url']
return render_to_response('deletion_confirmation.html',
tpl_parameters, context_instance=RequestContext(request))
'''Here we remove the permissions by hand'''
for it in collateral_damages:
try:
if type_entity == 'source':
remove_rule(it.rule)
it.delete()
messages.add_message(request, messages.INFO,
_('Object %s successfully deleted') %it)
except:
logger.error('del_any_final: \
Unable to delete the object: %s' %it)
messages.add_message(request, messages.ERROR,
_('Unable to delete the the object: %s') %it)
try:
if type_entity == 'user':
for u in UserAlias.objects.filter(user=item):
logger.debug('del_any_final: User %s will be \
deleted - deletion of alias: %s' % (item, u))
u.delete()
elif type_entity == 'source':
try:
ns = Namespace.objects.get(name=item.name)
for u in UserAlias.objects.filter(namespace=ns):
logger.debug('del_any_final: Source %s will be \
deleted - deletion of alias: %s' % (item, u))
u.delete()
logger.debug('del_any_final: Source %s will be \
deleted - deletion of namespace: %s' % (item, ns))
ns.delete()
except Exception, err:
logger.error('del_any_final: \
Error removing a source due to: %s' % err)
pass
item.delete()
except:
logger.error('del_any_final: \
Unable to delete the object: %s' %item)
messages.add_message(request, messages.ERROR,
_('Unable to delete the the object: %s') %item)
return list_any(request, type_entity)
messages.add_message(request, messages.INFO,
_('Object %s successfully deleted') %item)
if 'back_url' in request.POST:
return HttpResponseRedirect(request.POST['back_url'])
return list_any(request, type_entity)
return HttpResponseRedirect(backlink)