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

Add access control groups to DataSource

parent b8aeebf7
No related branches found
No related tags found
No related merge requests found
...@@ -8,6 +8,7 @@ db.sqlite3 ...@@ -8,6 +8,7 @@ db.sqlite3
# Python environments and run time # Python environments and run time
/env /env
/venv
*.pyc *.pyc
__pycache__/ __pycache__/
......
# Generated by Django 2.0.8 on 2018-08-21 09:41
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('applications', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='application',
name='owner',
field=models.ForeignKey(limit_choices_to={'groups__name': 'Application providers'}, on_delete=django.db.models.deletion.PROTECT, related_name='applications', to=settings.AUTH_USER_MODEL),
),
]
# Generated by Django 2.0.8 on 2018-08-21 09:41
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('auth', '0009_alter_user_last_name_max_length'),
('datasources', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='datasource',
name='access_control',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='datasource',
name='users_group',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='datasource', to='auth.Group'),
),
migrations.AddField(
model_name='datasource',
name='users_group_requested',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='datasource_requested', to='auth.Group'),
),
migrations.AlterField(
model_name='datasource',
name='owner',
field=models.ForeignKey(limit_choices_to={'groups__name': 'Data providers'}, on_delete=django.db.models.deletion.PROTECT, related_name='datasources', to=settings.AUTH_USER_MODEL),
),
]
# Generated by Django 2.0.8 on 2018-08-21 09:53
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('datasources', '0002_add_access_control_groups'),
]
operations = [
migrations.AlterField(
model_name='datasource',
name='users_group',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='datasource', to='auth.Group'),
),
migrations.AlterField(
model_name='datasource',
name='users_group_requested',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='datasource_requested', to='auth.Group'),
),
]
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import Group
from django.db import models from django.db import models
from django.urls import reverse from django.urls import reverse
...@@ -28,6 +29,7 @@ class DataSource(models.Model): ...@@ -28,6 +29,7 @@ class DataSource(models.Model):
#: Address at which the API may be accessed #: Address at which the API may be accessed
url = models.URLField(blank=False, null=False) url = models.URLField(blank=False, null=False)
# TODO replace this with an admin group
#: User who has responsibility for this data source #: User who has responsibility for this data source
owner = models.ForeignKey(settings.AUTH_USER_MODEL, owner = models.ForeignKey(settings.AUTH_USER_MODEL,
limit_choices_to={ limit_choices_to={
...@@ -37,6 +39,46 @@ class DataSource(models.Model): ...@@ -37,6 +39,46 @@ class DataSource(models.Model):
related_name='datasources', related_name='datasources',
blank=False, null=False) blank=False, null=False)
#: Group of users who have explicit permission to use (query) this data source
users_group = models.ForeignKey(Group,
on_delete=models.SET_NULL,
related_name='datasource',
blank=True, null=True)
#: Groups of users who have requested explicit permission to use this data source
users_group_requested = models.ForeignKey(Group,
on_delete=models.SET_NULL,
related_name='datasource_requested',
blank=True, null=True)
#: Do users require explicit permission to use this data source?
access_control = models.BooleanField(default=False,
blank=False, null=False)
def has_permission(self, user: settings.AUTH_USER_MODEL) -> bool:
"""
Does a user have permission to use this data source?
:param user: User to check
:return: User has permission?
"""
if not self.access_control:
return True
return user.groups.exists(self.users_group)
def save(self, **kwargs):
if self.access_control:
# Create access control groups if they do not exist
self.users_group, created = Group.objects.get_or_create(
name=self.name + ' Users'
)
self.users_group_requested, created = Group.objects.get_or_create(
name=self.name + ' Users Requested'
)
super().save(**kwargs)
def get_absolute_url(self): def get_absolute_url(self):
return reverse('datasources:datasource.detail', return reverse('datasources:datasource.detail',
kwargs={'pk': self.pk}) kwargs={'pk': self.pk})
......
...@@ -23,5 +23,9 @@ ...@@ -23,5 +23,9 @@
class="btn btn-success" role="button">Edit</a> class="btn btn-success" role="button">Edit</a>
<a href="{% url 'datasources:datasource.delete' pk=datasource.pk %}" <a href="{% url 'datasources:datasource.delete' pk=datasource.pk %}"
class="btn btn-danger" role="button">Delete</a> class="btn btn-danger" role="button">Delete</a>
{% if datasource.access_control %}
<a href="{% url 'datasources:datasource.manage-access' pk=datasource.pk %}"
class="btn btn-primary" role="button">Manage Access</a>
{% endif %}
{% endblock %} {% endblock %}
\ No newline at end of file
{% extends "base.html" %}
{% load bootstrap4 %}
{% block content %}
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item" aria-current="page">
<a href="{% url 'datasources:datasource.list' %}">Data Sources</a>
</li>
<li class="breadcrumb-item" aria-current="page">
<a href="{% url 'datasources:datasource.detail' pk=datasource.pk %}">{{ datasource.name }}</a>
</li>
<li class="breadcrumb-item active" aria-current="page">
Manage Access
</li>
</ol>
</nav>
<h2>View Data Source - {{ datasource.name }}</h2>
{% if datasource.description %}
<p>{{ datasource.description }}</p>
{% endif %}
<hr/>
<h2>Requests for Access</h2>
<table class="table">
<thead class="thead">
<tr>
<th>Username</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{% for user in datasource.users_group_requested.users.all %}
<tr>
<td>user.username</td>
<td>
<a href="#" class="btn btn-success" role="button">Approve</a>
</td>
<td>
<a href="#" class="btn btn-danger" role="button">Reject</a>
</td>
</tr>
{% empty %}
<tr><td>No requests</td></tr>
{% endfor %}
</tbody>
</table>
<hr/>
<h2>Approved Users</h2>
<table class="table">
<thead class="thead">
<tr>
<th>Username</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{% for user in datasource.users_group.users.all %}
<tr>
<td>user.username</td>
<td>
<a href="#" class="btn btn-success" role="button">Approve</a>
</td>
<td>
<a href="#" class="btn btn-danger" role="button">Reject</a>
</td>
</tr>
{% empty %}
<tr><td>No approved users</td></tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
\ No newline at end of file
...@@ -24,4 +24,8 @@ urlpatterns = [ ...@@ -24,4 +24,8 @@ urlpatterns = [
path('<int:pk>/delete', path('<int:pk>/delete',
views.DataSourceDeleteView.as_view(), views.DataSourceDeleteView.as_view(),
name='datasource.delete'), name='datasource.delete'),
path('<int:pk>/manage-access',
views.DataSourceManageAccessView.as_view(),
name='datasource.manage-access'),
] ]
...@@ -45,3 +45,11 @@ class DataSourceDeleteView(OwnerPermissionRequiredMixin, DeleteView): ...@@ -45,3 +45,11 @@ class DataSourceDeleteView(OwnerPermissionRequiredMixin, DeleteView):
success_url = reverse_lazy('datasources:datasource.list') success_url = reverse_lazy('datasources:datasource.list')
permission_required = 'datasources.delete_datasource' permission_required = 'datasources.delete_datasource'
class DataSourceManageAccessView(OwnerPermissionRequiredMixin, DetailView):
model = models.DataSource
template_name = 'datasources/datasource/manage_access.html'
context_object_name = 'datasource'
permission_required = 'datasources.change_datasource'
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment