Skip to content
Snippets Groups Projects
Commit 498ece49 authored by James Graham's avatar James Graham
Browse files

Refactor permission granting views

parent 8e5813a4
No related branches found
No related tags found
1 merge request!60Merge dev pre-hackday
...@@ -85,7 +85,7 @@ class Application(BaseAppDataModel): ...@@ -85,7 +85,7 @@ class Application(BaseAppDataModel):
def has_view_permission(self, user: settings.AUTH_USER_MODEL) -> bool: def has_view_permission(self, user: settings.AUTH_USER_MODEL) -> bool:
""" """
Does a user have permission to use this data source? Does a user have permission to use this application?
:param user: User to check :param user: User to check
:return: User has permission? :return: User has permission?
......
...@@ -113,6 +113,29 @@ class DataSource(BaseAppDataModel): ...@@ -113,6 +113,29 @@ class DataSource(BaseAppDataModel):
return super().save(**kwargs) return super().save(**kwargs)
def has_view_permission(self, user: settings.AUTH_USER_MODEL) -> bool:
"""
Does a user have permission to view this data source in the PEDASI UI?
:param user: User to check
:return: User has permission?
"""
if not self.access_control:
return True
if self.owner == user:
return True
try:
permission = UserPermissionLink.objects.get(
user=user,
datasource=self
)
except UserPermissionLink.DoesNotExist:
return False
return permission.granted >= UserPermissionLevels.VIEW
@property @property
def is_catalogue(self) -> bool: def is_catalogue(self) -> bool:
return self.data_connector_class.is_catalogue return self.data_connector_class.is_catalogue
......
...@@ -43,21 +43,21 @@ ...@@ -43,21 +43,21 @@
</thead> </thead>
<tbody> <tbody>
{% for user in datasource.users_group_requested.user_set.all %} {% for permission in permissions_requested.all %}
<tr id="requested-user-{{ user.pk }}"> <tr id="requested-user-{{ permission.user.pk }}">
<td>{{ user.username }}</td> <td>{{ permission.user.username }}</td>
<td> <td>
<button onclick="userGrantAccess( <button onclick="userGrantAccess(
'{% url 'datasources:datasource.manage-access.user' pk=datasource.pk user_pk=user.pk %}', '{% url 'datasources:datasource.manage-access.user' pk=datasource.pk user_pk=permission.user.pk %}',
{{ user.pk }} {{ permission.user.pk }}
)" )"
class="btn btn-success" class="btn btn-success"
role="button">Approve</button> role="button">Approve</button>
</td> </td>
<td> <td>
<button onclick="userRemoveAccess( <button onclick="userRemoveAccess(
'{% url 'datasources:datasource.manage-access.user' pk=datasource.pk user_pk=user.pk %}', '{% url 'datasources:datasource.manage-access.user' pk=datasource.pk user_pk=permission.user.pk %}',
{{ user.pk }} {{ permission.user.pk }}
)" )"
class="btn btn-danger" class="btn btn-danger"
role="button">Reject</button> role="button">Reject</button>
...@@ -83,14 +83,14 @@ ...@@ -83,14 +83,14 @@
</thead> </thead>
<tbody> <tbody>
{% for user in datasource.users_group.user_set.all %} {% for permission in permissions_granted %}
<tr id="approved-user-{{ user.pk }}"> <tr id="approved-user-{{ permission.user.pk }}">
<td>{{ user.username }}</td> <td>{{ permission.user.username }}</td>
<td></td> <td></td>
<td> <td>
<button onclick="userRemoveAccess( <button onclick="userRemoveAccess(
'{% url 'datasources:datasource.manage-access.user' pk=datasource.pk user_pk=user.pk %}', '{% url 'datasources:datasource.manage-access.user' pk=datasource.pk user_pk=permission.user.pk %}',
{{ user.pk }} {{ permission.user.pk }}
)" )"
class="btn btn-danger" class="btn btn-danger"
role="button">Remove</button> role="button">Remove</button>
......
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.db.models import F
from django.http import JsonResponse, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden from django.http import JsonResponse, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
from django.views.generic import View from django.views.generic import View
from django.views.generic.detail import DetailView, SingleObjectMixin from django.views.generic.detail import DetailView, SingleObjectMixin
...@@ -87,6 +88,16 @@ class DataSourceManageAccessView(OwnerPermissionRequiredMixin, DetailView): ...@@ -87,6 +88,16 @@ class DataSourceManageAccessView(OwnerPermissionRequiredMixin, DetailView):
context['all_users'] = get_user_model().objects context['all_users'] = get_user_model().objects
context['permissions_requested'] = models.UserPermissionLink.objects.filter(
datasource=self.object,
requested__gt=F('granted')
)
context['permissions_granted'] = models.UserPermissionLink.objects.filter(
datasource=self.object,
requested__lte=F('granted'),
granted__gt=models.UserPermissionLevels.NONE
)
return context return context
...@@ -99,6 +110,74 @@ class DataSourceRequestAccessView(SingleObjectMixin, View): ...@@ -99,6 +110,74 @@ class DataSourceRequestAccessView(SingleObjectMixin, View):
""" """
model = models.DataSource model = models.DataSource
def _set_permission(self, user, level=models.UserPermissionLevels.VIEW):
if level == models.UserPermissionLevels.NONE:
try:
permission = models.UserPermissionLink.objects.get(
user=user,
datasource=self.object,
)
permission.delete()
except models.UserPermissionLink.DoesNotExist:
pass
return None
try:
permission = models.UserPermissionLink.objects.get(
user=user,
datasource=self.object,
)
permission.granted = level
permission.requested = max(permission.requested, level)
permission.save()
except models.UserPermissionLink.DoesNotExist:
permission = models.UserPermissionLink.objects.create(
user=user,
datasource=self.object,
granted=level,
requested=level
)
return permission
def _request_permission(self, user, level=models.UserPermissionLevels.VIEW):
try:
permission = models.UserPermissionLink.objects.get(
user=user,
datasource=self.object
)
if permission.granted >= level:
return HttpResponseBadRequest(
JsonResponse({
'status': 'fail',
'message': 'You already have access to this resource',
})
)
if permission.requested >= level:
return HttpResponseBadRequest(
JsonResponse({
'status': 'fail',
'message': 'You have already requested access to this resource',
})
)
permission.requested = max(permission.requested, level)
permission.save()
except models.UserPermissionLink.DoesNotExist:
# If user is requesting for themselves, mark them as 'permission requested'
permission = models.UserPermissionLink.objects.create(
user=user,
datasource=self.object,
requested=level
)
def put(self, request, *args, **kwargs): def put(self, request, *args, **kwargs):
""" """
Add a user to the access group for a DataSource. Add a user to the access group for a DataSource.
...@@ -116,25 +195,14 @@ class DataSourceRequestAccessView(SingleObjectMixin, View): ...@@ -116,25 +195,14 @@ class DataSourceRequestAccessView(SingleObjectMixin, View):
self.object = self.get_object() self.object = self.get_object()
user = get_user_model().objects.get(pk=kwargs['user_pk']) user = get_user_model().objects.get(pk=kwargs['user_pk'])
access_group = self.object.users_group level = self.request.GET.get('level', models.UserPermissionLevels.VIEW)
request_group = self.object.users_group_requested
if self.request.user == self.object.owner or self.request.user.is_staff: if self.request.user == self.object.owner or self.request.user.is_superuser:
# If request is from DataSource owner or staff, add user to access group # If request is from DataSource owner or superuser, add user to access group
access_group.user_set.add(user) permission = self._set_permission(user, level=level)
request_group.user_set.remove(user)
elif self.request.user == user: elif self.request.user == user:
if access_group.user_set.filter(id=user.id).exists(): permission = self._request_permission(user, level=level)
return HttpResponseBadRequest(
JsonResponse({
'status': 'fail',
'message': 'You already have access to this resource',
})
)
# If user is requesting for themselves, add them to 'access requested' group
request_group.user_set.add(user)
else: else:
return HttpResponseForbidden( return HttpResponseForbidden(
...@@ -147,8 +215,12 @@ class DataSourceRequestAccessView(SingleObjectMixin, View): ...@@ -147,8 +215,12 @@ class DataSourceRequestAccessView(SingleObjectMixin, View):
return JsonResponse({ return JsonResponse({
'status': 'success', 'status': 'success',
'data': { 'data': {
'user': { 'permission': {
'pk': user.pk 'pk': permission.pk,
'user': permission.user_id,
'datasource': permission.datasource_id,
'granted': permission.granted,
'requested': permission.requested,
}, },
}, },
}) })
...@@ -158,13 +230,14 @@ class DataSourceRequestAccessView(SingleObjectMixin, View): ...@@ -158,13 +230,14 @@ class DataSourceRequestAccessView(SingleObjectMixin, View):
self.object = self.get_object() self.object = self.get_object()
user = get_user_model().objects.get(pk=kwargs['user_pk']) user = get_user_model().objects.get(pk=kwargs['user_pk'])
access_group = self.object.users_group
request_group = self.object.users_group_requested
if self.request.user == user or self.request.user == self.object.owner or self.request.user.is_staff: if self.request.user == user or self.request.user == self.object.owner or self.request.user.is_superuser:
# Users can remove themselves, be removed by the DataSource owner, or by staff # Users can remove themselves, be removed by the DataSource owner, or by staff
access_group.user_set.remove(user) permission = models.UserPermissionLink.objects.get(
request_group.user_set.remove(user) user=user,
datasource=self.object
)
permission.delete()
else: else:
return HttpResponseForbidden( return HttpResponseForbidden(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment