from django.contrib.auth import get_user_model
from django.shortcuts import get_object_or_404
from django.core.cache import cache
from django.core.exceptions import PermissionDenied
from django.db.models import Q
from aristotle_mdr.utils import fetch_aristotle_settings
from aristotle_mdr.utils.utils import item_is_visible_to_user
from aristotle_mdr.contrib.reviews.const import REVIEW_STATES
import logging
logger = logging.getLogger(__name__)
VIEW_CACHE_SECONDS = 60
EDIT_CACHE_SECONDS = 60
def user_can(user, item, method_name):
"""When custom methods are required"""
if user.is_superuser:
return True
if user.is_anonymous:
return False
method = getattr(item, method_name)
if callable(method):
return method(user)
return False
def get_item_if_user_can(obj_type, user, iid, permission_type):
"""
The purpose of this function is to get an item if the user has a particular permission type.
If the user does not have the permission specified in permission_type, a PermissionDenied error is raised.
usage:
get_item_if_user_can(MDR._concept, request.user, kwargs.get("iid"), perms.user_can_supersede)
:param obj_type: Class or model of the item to be checked.
:param user: User instance.
:param iid: String or Int ID of the object instance.
:param permission_type: Function. Permission type function.
:return: Item
"""
item = get_object_or_404(obj_type, pk=iid)
if permission_type(user, item):
return item
else:
raise PermissionDenied
def user_can_alter_comment(user, comment):
return user.is_superuser or user == comment.author or user_is_workgroup_manager(user, comment.post.workgroup)
def user_can_alter_post(user, post):
return user.is_superuser or user == post.author or user_is_workgroup_manager(user, post.workgroup)
def can_post_discussion(user):
return user.is_active and user.profile.myWorkgroups.count() > 0
def can_comment_on_post(user, post):
return user_in_workgroup(user, post.workgroup)
def can_delete_comment(user, comment):
return user_can_alter_comment(user, comment)
def can_delete_discussion_post(user, post):
return user_can_alter_post(user, post)
def user_can_publish_object(user, obj):
if user.is_superuser:
return True
if user.is_anonymous:
return False
stewardship_organisation = obj.stewardship_organisation
if not stewardship_organisation:
# Can't publish "un-owned" objects
return False
if not getattr(obj, 'publication_details', None):
# There is no reverse relation, don't allow publication
return False
return stewardship_organisation.user_has_permission(user, "publish_objects")
def can_delete_metadata(user, item):
if item.submitter == user and item.workgroup is None:
if not item.statuses.exists():
return True
return False
[docs]def user_can_view(user, item):
"""Can the user view the item?"""
if user.is_superuser:
return True
if item.__class__ == get_user_model(): # -- Sometimes duck-typing fails --
return user == item # A user can edit their own details
if user.is_anonymous:
user_key = "anonymous"
else:
user_key = str(user.id)
can_use_cache = False
# If the item was not modified recently, use cache
if hasattr(item, "was_modified_very_recently") and not item.was_modified_very_recently():
can_use_cache = True
key = 'user_can_view_%s|%s:%s|%s' % (user_key, item._meta.app_label, item._meta.app_label, str(item.id))
cached_can_view = cache.get(key)
if can_use_cache and cached_can_view is not None:
return cached_can_view
_can_view = False
_can_view = item.can_view(user)
cache.set(key, _can_view, VIEW_CACHE_SECONDS)
return _can_view
[docs]def user_can_edit(user, item):
"""Can the user edit the item?"""
# Superusers can edit everything
if user.is_superuser:
return True
# Anonymous users can edit nothing
if user.is_anonymous:
return False
# A user can edit their own details
if item.__class__ == get_user_model(): # -- Sometimes duck-typing fails --
return user == item
can_use_cache = False
# If the item was not modified recently, use cache
if hasattr(item, "was_modified_very_recently") and not item.was_modified_very_recently():
can_use_cache = True
user_key = str(user.id)
key = 'user_can_edit_%s|%s:%s|%s' % (user_key, item._meta.app_label, item._meta.app_label, str(item.id))
cached_can_edit = cache.get(key)
if can_use_cache and cached_can_edit is not None:
return cached_can_edit
_can_edit = False
if not user_can_view(user, item):
_can_edit = False
else:
_can_edit = item.can_edit(user)
cache.set(key, _can_edit, VIEW_CACHE_SECONDS)
return _can_edit
def user_is_authenticated_and_active(user):
return user.is_authenticated and user.is_active
def user_can_submit_to_workgroup(user, workgroup):
return workgroup.has_role(["submitter", "steward"], user)
def user_is_registrar(user, ra=None):
"""
This function can be used to check whether a user is associated with ANY Registration Authority or associated with a
specific Registration Authority.
:param user: User object.
:param ra: (Optional) Registration Authority object.
:return: Boolean
"""
if user.is_anonymous:
return False
if user.is_superuser:
return True
elif ra is None:
return user.registrar_in.count() > 0
else:
return user in ra.registrars.all()
def user_is_registation_authority_manager(user, ra=None):
if user.is_anonymous:
return False
if user.is_superuser:
return True
elif ra is None:
return user.organization_manager_in.count() > 0
else:
return user in ra.managers.all()
[docs]def user_can_add_status(user, item):
"""Can the user add a status to this item in some RA"""
if user.is_anonymous:
return False
if user.is_superuser:
return True
if user.profile.registrar_count < 1: # If the user is not associated with any Registration Authority.
return False
if user.profile.is_registrar and item_is_visible_to_user(user, item):
return True
return False
def user_can_add_ra_status(user, ra, item):
"""Can the user add a status to this item in this RA"""
if user.is_anonymous:
return False
if user.is_superuser:
return True
# Must be a registrar in this ra
if user not in ra.registrars.all():
return False
# If this item has any requested reviews in this ra
if item.rr_review_requests.filter(registration_authority=ra).visible(user):
return True
# Get proposed supersedes in this ra involving this item
ss_items = item.superseded_by_items_relation_set.filter(
Q(proposed=True),
Q(registration_authority=ra)
)
# If these exist user can change status on the item
if ss_items.exists():
return True
return False
def user_can_view_statuses_revisions(user, ra):
# TODO: We need to implement the user permissions to check the statuses version history.
if user.is_anonymous:
return False
if user.is_superuser:
return True
return False
def user_can_supersede(user, item):
if user.is_anonymous:
return False
if user.is_superuser:
return True
if not user_can_view(user, item):
return False
if user.profile.is_registrar:
return True
return False
def user_can_view_review(user, review):
if user.is_anonymous:
return False
# A user can see all their requests
if review.requester == user:
return True
if user.is_superuser:
return True
# No-one else can see a cancelled request
if review.status == REVIEW_STATES.revoked:
return False
# If a registrar is in the registration authority for the request they can see it.
if user.registrar_in.filter(pk=review.registration_authority.pk).exists():
return True
# If the user is a manager in the registration authority for the request they can view it.
if user in review.registration_authority.managers.all():
return True
return False
def user_can_edit_review(user, review):
if user.is_anonymous:
return False
# A user can edit all their requests
if review.requester == user:
return True
if user.is_superuser:
return True
# None else can see a cancelled request
if review.status == REVIEW_STATES.revoked:
return False
# If the user is a manager in the registration authority for the request they can edit it.
return user in review.registration_authority.managers.all()
def user_can_edit_review_comment(user, reviewcomment):
if user.is_anonymous:
return False
# A user can edit all their requests
if reviewcomment.author == user:
return True
if user.is_superuser:
return True
# None else can see a cancelled request
if reviewcomment.review.status == REVIEW_STATES.revoked:
return False
# If a registrar is in the registration authority for the request they can see it.
return user in reviewcomment.request.registration_authority.managers.all()
def user_can_view_review_comment(user, reviewcomment):
return user_can_view_review(user, reviewcomment.review)
def user_can_revoke_review(user, review):
if user.is_anonymous:
return False
# A user can see all their requests
if review.requester == user:
return True
if user.is_superuser:
return True
return False
def user_can_close_or_reopen_review(user, review):
if user.is_anonymous:
return False
# A user can see all their requests
if review.requester == user:
return True
if user.is_superuser:
return True
# If you arent the requester or a super user, you can reopen a revoked request
if review.status == REVIEW_STATES.revoked:
return False
# If a registrar is in the registration authority for the request they can see it.
return user.registrar_in.filter(pk=review.registration_authority.pk).exists()
def user_can_approve_review(user, review):
if user.is_anonymous:
return False
# Can't approve a closed request
if review.status != REVIEW_STATES.open:
return False
if user.is_superuser:
return True
# If a registrar is in the registration authority for the request they can see it.
return user.registrar_in.filter(pk=review.registration_authority.pk).exists()
def user_can_view_workgroup(user, wg):
return wg.can_view(user)
def user_can_manage_workgroup(user, workgroup):
if user.is_superuser:
return True
elif workgroup is None:
return user.workgroupmembership_set.filter(role='manager').exists()
if not workgroup.stewardship_organisation.is_active():
return False
if workgroup.stewardship_organisation.user_has_permission(user, "manage_workgroups"):
return True
else:
return workgroup.has_role('manager', user)
def user_is_workgroup_manager(user, workgroup):
return user_can_manage_workgroup(user, workgroup)
def user_in_workgroup(user, wg):
if user.is_anonymous:
return False
if user.is_superuser:
return True
return user in wg.member_list.all()
def user_can_move_any_workgroup(user):
"""Checks if a user can move an item from any of their workgroups"""
workgroup_change_access = fetch_aristotle_settings().get('WORKGROUP_CHANGES', [])
if user.is_anonymous:
return False
if user.is_superuser:
return True
if 'admin' in workgroup_change_access and user.is_staff:
return True
if 'manager' in workgroup_change_access and user.profile.is_workgroup_manager():
return True
if 'submitter' in workgroup_change_access and user.workgroupmembership_set.filter(role="submitter").exists():
return True
return False
def user_can_move_any_stewardship_organisation(user):
"""Checks if a user can move an item from any of their stewardship organisations"""
from aristotle_mdr.models import StewardOrganisation
if user.is_anonymous:
return False
if user.is_superuser:
return True
else:
if user.profile.stewardship_organisations.filter(members__role=StewardOrganisation.roles.admin).count() > 0:
return True
return False
def user_can_add_or_remove_workgroup(user, workgroup):
workgroup_change_access = fetch_aristotle_settings().get('WORKGROUP_CHANGES', [])
if user.is_anonymous:
return False
if user.is_superuser:
return True
if 'admin' in workgroup_change_access and user.has_perm("aristotle_mdr.is_registry_administrator"):
return True
if workgroup:
if 'manager' in workgroup_change_access and workgroup.has_role('manager', user):
return True
if 'submitter' in workgroup_change_access and workgroup.has_role('submitter', user):
return True
return False
def user_can_remove_from_workgroup(user, workgroup):
return user_can_add_or_remove_workgroup(user, workgroup)
def user_can_move_to_workgroup(user, workgroup):
return user_can_add_or_remove_workgroup(user, workgroup)
def user_can_move_between_workgroups(user, workgroup_a, workgroup_b):
"""checks if a user can move an item from A to B"""
return user_can_remove_from_workgroup(user, workgroup_a) and user_can_move_to_workgroup(user, workgroup_b)
def user_can_query_user_list(user):
if user.is_anonymous:
return False
user_visbility = fetch_aristotle_settings().get('USER_VISIBILITY', 'owner')
return (
user.has_perm("aristotle_mdr.is_registry_administrator") or
user.profile.is_stewardship_organisation_admin() or
('workgroup_manager' in user_visbility and user.profile.is_workgroup_manager()) or
('registation_authority_manager' in user_visbility and user.profile.is_registrar)
)
def edit_other_users_account(viewing_user, viewed_user):
return view_other_users_account(viewing_user, viewed_user)
def view_other_users_account(viewing_user, viewed_user):
from aristotle_mdr.models import StewardOrganisation
user = viewing_user
if user.is_anonymous:
return False
if user.is_superuser:
return True
allowed_roles = [
StewardOrganisation.roles.admin,
]
return StewardOrganisation.objects.filter(
members__user=viewed_user
).filter(
members__user=viewing_user, members__role__in=allowed_roles
).active().exists()
def user_can_create_workgroup(user, steward_org=None):
return user_is_superuser_or_has_admin_role_in_steward_organisation(user, steward_org)
def user_can_create_registration_authority(user, steward_org=None):
return user_is_superuser_or_has_admin_role_in_steward_organisation(user, steward_org)
def user_is_superuser_or_has_admin_role_in_steward_organisation(user, steward_org=None):
from aristotle_mdr.models import StewardOrganisation
if user.is_superuser:
return True
allowed_roles = [
StewardOrganisation.roles.admin,
]
kwargs = {"members__user": user, "members__role__in": allowed_roles}
if steward_org:
kwargs["pk"] = steward_org.pk
return StewardOrganisation.objects.filter(**kwargs).active().exists()
def user_can_remove_from_stewardship_organisation(user, steward_org=None):
return user_is_superuser_or_has_admin_role_in_steward_organisation(user, steward_org=steward_org)
def user_can_move_to_stewardship_organisation(user, steward_org=None):
return user_is_superuser_or_has_admin_role_in_steward_organisation(user, steward_org=steward_org)
def user_can_move_between_stewardship_organisations(user, stewardorg_a, stewardorg_b):
"""Checks if user can move metadata from a to b """
return user_is_superuser_or_has_admin_role_in_steward_organisation(user, steward_org=stewardorg_a) and \
user_is_superuser_or_has_admin_role_in_steward_organisation(user, steward_org=stewardorg_b)
def user_can_edit_issue_label(user, label):
if user.is_superuser:
return True
if label.stewardship_organisation is None:
return False
from aristotle_mdr.models import StewardOrganisation
return label.stewardship_organisation.has_role(
user=user, role=StewardOrganisation.roles.admin
)
def can_alter_any_issue_labels(user):
if user.is_superuser:
return True
from aristotle_mdr.models import StewardOrganisation, StewardOrganisationMembership
return StewardOrganisationMembership.user_has_role_for_any_group(
user=user, role=StewardOrganisation.roles.admin
)