Works almost
This commit is contained in:
19
abac/forms.py
Normal file
19
abac/forms.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from django import forms
|
||||
|
||||
from .models import File, RuleAttribute, AttributeType
|
||||
|
||||
class FileUploadForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = File
|
||||
fields = ['name', 'file']
|
||||
|
||||
|
||||
class UploadCertificateForm(forms.Form):
|
||||
certificate = forms.FileField()
|
||||
|
||||
class RuleAttributeForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = RuleAttribute
|
||||
fields = ['attribute_type', 'operator', 'value']
|
||||
|
||||
attribute_type = forms.ModelChoiceField(queryset=AttributeType.objects.all())
|
||||
@@ -1,4 +1,4 @@
|
||||
# Generated by Django 4.2.5 on 2023-09-21 17:15
|
||||
# Generated by Django 4.2.5 on 2023-09-28 12:45
|
||||
|
||||
from django.conf import settings
|
||||
import django.contrib.auth.models
|
||||
@@ -43,49 +43,61 @@ class Migration(migrations.Migration):
|
||||
('objects', django.contrib.auth.models.UserManager()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Attribute',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('value', models.IntegerField()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AttributeType',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('is_secret', models.BooleanField(default=False)),
|
||||
('is_private', models.BooleanField(default=False)),
|
||||
('datatype', models.CharField(max_length=15)),
|
||||
('significant_digits', models.PositiveIntegerField(blank=True, null=True)),
|
||||
('name', models.CharField(max_length=40)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Rule',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('rule_type', models.CharField(choices=[('and', 'AND'), ('or', 'OR')], max_length=3)),
|
||||
('attributes', models.ManyToManyField(to='abac.attribute')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='File',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255)),
|
||||
('file', models.FileField(upload_to='uploads/')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('last_modified', models.DateTimeField(auto_now=True)),
|
||||
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
('rules', models.ManyToManyField(to='abac.rule')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['name', 'created_at'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Rule',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255)),
|
||||
('file', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='abac.file')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='attribute',
|
||||
name='attribute_type',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='abac.attributetype'),
|
||||
migrations.CreateModel(
|
||||
name='Attribute',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('value', models.IntegerField()),
|
||||
('last_modified', models.DateTimeField(auto_now=True)),
|
||||
('attribute_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='abac.attributetype')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='attribute',
|
||||
name='user',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||
migrations.CreateModel(
|
||||
name='UserAttribute',
|
||||
fields=[
|
||||
('attribute_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='abac.attribute')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
bases=('abac.attribute',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='RuleAttribute',
|
||||
fields=[
|
||||
('attribute_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='abac.attribute')),
|
||||
('rule', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='abac.rule')),
|
||||
],
|
||||
bases=('abac.attribute',),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# Generated by Django 4.2.5 on 2023-09-28 13:51
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('abac', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='attribute',
|
||||
name='last_modified',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='rule',
|
||||
name='delete',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='rule',
|
||||
name='read',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='rule',
|
||||
name='write',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ruleattribute',
|
||||
name='option',
|
||||
field=models.CharField(choices=[('EQ', 'Equals'), ('NEQ', "Doesn't Equal"), ('GT', 'Greater Than'), ('LT', 'Less Than')], default='EQ', max_length=3),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='userattribute',
|
||||
name='last_modified',
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
]
|
||||
18
abac/migrations/0003_rename_option_ruleattribute_operator.py
Normal file
18
abac/migrations/0003_rename_option_ruleattribute_operator.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.5 on 2023-09-28 14:49
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('abac', '0002_remove_attribute_last_modified_rule_delete_rule_read_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='ruleattribute',
|
||||
old_name='option',
|
||||
new_name='operator',
|
||||
),
|
||||
]
|
||||
@@ -2,6 +2,7 @@ import pickle
|
||||
from base64 import b64encode, b64decode
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
|
||||
|
||||
class User(AbstractUser):
|
||||
@@ -37,7 +38,7 @@ class AttributeType(models.Model):
|
||||
('integer', 'Integer'),
|
||||
]
|
||||
|
||||
is_secret = models.BooleanField(default=False)
|
||||
is_private = models.BooleanField(default=False)
|
||||
datatype = models.CharField(max_length=15)
|
||||
significant_digits = models.PositiveIntegerField(null=True, blank=True)
|
||||
name = models.CharField(max_length=40)
|
||||
@@ -51,24 +52,52 @@ class AttributeType(models.Model):
|
||||
raise ValueError('significant_digits must be None for non-float datatype')
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
|
||||
class Attribute(models.Model):
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
|
||||
attribute_type = models.ForeignKey(AttributeType, on_delete=models.CASCADE)
|
||||
value = models.IntegerField() # assuming value is always stored as an integer
|
||||
value = models.IntegerField()
|
||||
|
||||
|
||||
class Rule(models.Model):
|
||||
TYPE_CHOICES = [
|
||||
('and', 'AND'),
|
||||
('or', 'OR'),
|
||||
]
|
||||
rule_type = models.CharField(max_length=3, choices=TYPE_CHOICES)
|
||||
attributes = models.ManyToManyField(Attribute)
|
||||
|
||||
class UserAttribute(Attribute):
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
last_modified = models.DateTimeField(auto_now=True)
|
||||
|
||||
class File(models.Model):
|
||||
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
name = models.CharField(max_length=255)
|
||||
file = models.FileField(upload_to='uploads/') # assuming you are using FileField to store the file
|
||||
rules = models.ManyToManyField(Rule)
|
||||
file = models.FileField(upload_to='uploads/')
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
last_modified = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
ordering = ['name', 'created_at']
|
||||
|
||||
class Rule(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
file = models.ForeignKey(File, on_delete=models.CASCADE)
|
||||
read = models.BooleanField(default=False)
|
||||
write = models.BooleanField(default=False)
|
||||
delete = models.BooleanField(default=False)
|
||||
|
||||
class RuleAttribute(Attribute):
|
||||
OPTION_EQUALS = 'EQ'
|
||||
OPTION_DOES_NOT_EQUAL = 'NEQ'
|
||||
OPTION_GREATER_THAN = 'GT'
|
||||
OPTION_LESS_THAN = 'LT'
|
||||
|
||||
OPTION_CHOICES = [
|
||||
('EQ', 'Equals'),
|
||||
('NEQ', "Doesn't Equal"),
|
||||
('GT', 'Greater Than'),
|
||||
('LT', 'Less Than'),
|
||||
]
|
||||
|
||||
rule = models.ForeignKey(Rule, on_delete=models.CASCADE)
|
||||
operator = models.CharField(max_length=3, choices=OPTION_CHOICES, default=OPTION_EQUALS)
|
||||
7
abac/static/abac/main.js
Normal file
7
abac/static/abac/main.js
Normal file
@@ -0,0 +1,7 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.querySelectorAll('tr[data-url]').forEach(row => {
|
||||
row.addEventListener('click', function() {
|
||||
window.location.href = row.dataset.url;
|
||||
});
|
||||
});
|
||||
});
|
||||
4
abac/static/abac/styles.css
Normal file
4
abac/static/abac/styles.css
Normal file
@@ -0,0 +1,4 @@
|
||||
tr[data-url]:hover {
|
||||
cursor: pointer;
|
||||
background-color: #e8e8e8; /* Or any other color you prefer */
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<!-- abac/templates/base.html -->
|
||||
{% load static %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
@@ -8,29 +8,32 @@
|
||||
<title>{% block title %}Privacy Preserving ABAC{% endblock %}</title>
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="{% static 'abac/styles.css' %}"> <!-- Include CSS file -->
|
||||
|
||||
</head>
|
||||
|
||||
<body class="d-flex flex-column min-vh-100">
|
||||
<header>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<a class="navbar-brand" href="{% url 'home' %}">Privacy Preserving ABAC</a>
|
||||
<a class="navbar-brand" href="{% url 'abac:home' %}">Privacy Preserving ABAC</a>
|
||||
<span class="navbar-text ml-auto">
|
||||
{% if user.is_authenticated %}
|
||||
{{ user.username }}
|
||||
<a class="btn btn-outline-light ml-3" href="{% url 'logout' %}">Logout</a>
|
||||
<a href="{% url 'abac:user_details' username=user.username %}"> {{ user.username }}</a>
|
||||
<a class="btn btn-outline-light ml-3" href="{% url 'abac:logout' %}">Logout</a>
|
||||
{% else %}
|
||||
<a class="btn btn-outline-light" href="{% url 'login' %}">Login</a>
|
||||
<a class="btn btn-outline-light" href="{% url 'abac:login' %}">Login</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
</nav>
|
||||
{% if user.is_authenticated %}
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<button class="btn btn-primary">Upload File</button>
|
||||
<button class="btn btn-primary" onclick="window.location.href='{% url 'abac:upload_file' %}'">Upload File</button>
|
||||
{% if perms.abac.can_create_users %}
|
||||
<button class="btn btn-primary ml-2">Create User</button>
|
||||
<button class="btn btn-primary ml-2">User Management</button>
|
||||
{% endif %}
|
||||
<span class="ml-auto">
|
||||
<button class="btn btn-primary">Upload Certificate</button>
|
||||
<button class="btn btn-primary" onclick="window.location.href='{% url 'abac:upload_certificate' %}'">Upload Certificate</button>
|
||||
</span>
|
||||
</nav>
|
||||
{% endif %}
|
||||
@@ -44,7 +47,7 @@
|
||||
|
||||
<footer class="footer mt-auto py-3 bg-dark text-white">
|
||||
<div class="container text-center">
|
||||
<span>© 2023 Privacy Preserving ABAC</span>
|
||||
<span>© 2023 Masterthesis Malte Kerl – Applications of Homomorphic Encryption in Attribute Based Access Control (ABAC) Systems </span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
26
abac/templates/file_detail.html
Normal file
26
abac/templates/file_detail.html
Normal file
@@ -0,0 +1,26 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-3">
|
||||
<h2>{{ file.name }}</h2>
|
||||
<p>Created At: {{ file.created_at|date:"F d, Y H:i" }}</p>
|
||||
<p>Last Modified: {{ file.last_modified|date:"F d, Y H:i" }}</p>
|
||||
|
||||
<form method="post" action="{% url 'abac:create_rule' file.id %}">
|
||||
{% csrf_token %}
|
||||
<label for="rule_name">Rule Name:</label>
|
||||
<input type="text" name="rule_name" required>
|
||||
<button type="submit" class="btn btn-primary">Add Rule</button>
|
||||
</form>
|
||||
|
||||
|
||||
{% for rule in rules %}
|
||||
<div class="bg-light p-3 my-2">
|
||||
<h4>{{ rule.name }}</h4>
|
||||
<a href="{% url 'abac:rule_detail' file_id=file.id rule_id=rule.id %}">View Details</a>
|
||||
</div>
|
||||
{% empty %}
|
||||
<p>No rules have been added yet.</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
12
abac/templates/file_upload.html
Normal file
12
abac/templates/file_upload.html
Normal file
@@ -0,0 +1,12 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<h2>Upload File</h2>
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<button type="submit" class="btn btn-primary">Upload</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,14 +1,42 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}ABAC Home{% endblock %}
|
||||
|
||||
{% block title %}Landing Page{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>All Files</h2>
|
||||
<ul>
|
||||
{% for file in files %}
|
||||
<li>{{ file.name }}</li>
|
||||
{% empty %}
|
||||
<li>No files have been uploaded yet.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
<div class="container mt-3">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">File Name</th>
|
||||
<th scope="col">Owner</th>
|
||||
<th scope="col">Created At</th>
|
||||
<th scope="col">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for file in files %}
|
||||
<tr data-url="{% url 'abac:file_detail' file_id=file.id %}"> <!-- Add data-url attribute here -->
|
||||
<td>{{ file.name }}</td>
|
||||
<td>{{ file.owner.username }}</td>
|
||||
<td>{{ file.created_at|date:"F d, Y H:i" }}</td>
|
||||
<td>
|
||||
<a href="{{ file.file.url }}" download="{{ file.name }}" class="btn btn-outline-primary btn-sm">
|
||||
<i class="bi bi-download"></i> Download
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="4" class="text-center">No files have been uploaded yet.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script src="{% static 'abac/main.js' %}"></script>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
48
abac/templates/rule_detail.html
Normal file
48
abac/templates/rule_detail.html
Normal file
@@ -0,0 +1,48 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<header>
|
||||
<h1>{{ rule.name }}</h1>
|
||||
<p>File Owner: {{ rule.file.owner.username }}</p>
|
||||
<a href="{% url 'abac:file_detail' file_id=rule.file.id %}">Back to {{ rule.file.name }}</a>
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
<div class="container">
|
||||
<h2>{{ rule.name }} Details</h2>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Attribute Name</th>
|
||||
<th>Operator</th>
|
||||
<th>Value</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for rule_attribute in rule_attributes %}
|
||||
<tr>
|
||||
<td>{{ rule_attribute.attribute_type.name }}</td>
|
||||
<td>{{ rule_attribute.operator }}</td>
|
||||
<td>{{ rule_attribute.value }}</td>
|
||||
<td>
|
||||
<a href="{% url 'abac:delete_rule_attribute' file_id=file.id rule_id=rule.id rule_attribute_id=rule_attribute.id %}" class="btn btn-danger">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<!-- Form to add new RuleAttribute -->
|
||||
<form method="post" action="{% url 'abac:rule_detail' file_id=file.id rule_id=rule.id %}">
|
||||
{% csrf_token %}
|
||||
<td>{{ form.attribute_type }}</td>
|
||||
<td>{{ form.operator }}</td>
|
||||
<td>{{ form.value }}</td>
|
||||
<td><input type="submit" class="btn btn-success" value="Add"></td>
|
||||
</form>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
9
abac/templates/upload_certificate.html
Normal file
9
abac/templates/upload_certificate.html
Normal file
@@ -0,0 +1,9 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<button type="submit">Upload</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
33
abac/templates/user_detail.html
Normal file
33
abac/templates/user_detail.html
Normal file
@@ -0,0 +1,33 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<h2>{{ user.username }}'s Attributes</h2>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Attribute Name</th>
|
||||
<th scope="col">Last Modified</th>
|
||||
<th scope="col">Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for attribute in attributes %}
|
||||
<tr>
|
||||
<td>{{ attribute.attribute_type.name }}</td>
|
||||
<td>{{ attribute.last_modified|date:"F d, Y H:i" }}</td>
|
||||
<td>
|
||||
{% if not attribute.attribute_type.is_private %}
|
||||
{{ attribute.value }}
|
||||
{% else %}
|
||||
<i>Private</i>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="3">This user has no attributes.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
29
abac/urls.py
29
abac/urls.py
@@ -3,9 +3,32 @@
|
||||
from django.contrib.auth import views as auth_views
|
||||
from django.urls import path
|
||||
|
||||
from .views import landing_page
|
||||
from .views import (
|
||||
landing_page,
|
||||
login_view,
|
||||
logout_view,
|
||||
upload_file_view,
|
||||
create_user_view,
|
||||
upload_certificate_view,
|
||||
file_detail,
|
||||
create_rule,
|
||||
rule_detail,
|
||||
user_detail_view,
|
||||
delete_rule_attribute,
|
||||
)
|
||||
|
||||
app_name = 'abac'
|
||||
|
||||
urlpatterns = [
|
||||
path('login/', auth_views.LoginView.as_view(template_name='login.html'), name='login'),
|
||||
path('', landing_page, name='home'),
|
||||
]
|
||||
path('login/', auth_views.LoginView.as_view(template_name='login.html', success_url='/'), name='login'),
|
||||
path('logout/', logout_view, name='logout'),
|
||||
path('upload-file/', upload_file_view, name='upload_file'),
|
||||
path('create-user/', create_user_view, name='create_user'),
|
||||
path('upload-certificate/', upload_certificate_view, name='upload_certificate'),
|
||||
path('files/<int:file_id>/', file_detail, name='file_detail'),
|
||||
path('files/<int:file_id>/create_rule/', create_rule, name='create_rule'),
|
||||
path('rules/<int:file_id>/<int:rule_id>/',rule_detail, name='rule_detail'),
|
||||
path('user/<str:username>/', user_detail_view, name='user_details'),
|
||||
path('rules/<int:file_id>/<int:rule_id>/delete/<int:rule_attribute_id>/', delete_rule_attribute, name='delete_rule_attribute'),
|
||||
]
|
||||
165
abac/views.py
165
abac/views.py
@@ -1,9 +1,19 @@
|
||||
from django.shortcuts import render
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.http.response import HttpResponseNotAllowed
|
||||
from django.contrib.auth.decorators import permission_required
|
||||
from django.http import HttpResponse
|
||||
from django.contrib.auth.decorators import permission_required, login_required
|
||||
from django.http import HttpResponse, JsonResponse, HttpResponseForbidden, HttpResponseBadRequest, HttpResponseNotAllowed
|
||||
from django.contrib.auth import logout
|
||||
from django.urls import reverse
|
||||
from django.views.generic.detail import SingleObjectMixin, DetailView
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils import timezone
|
||||
|
||||
from .models import File
|
||||
import json
|
||||
|
||||
from .forms import FileUploadForm, UploadCertificateForm, RuleAttributeForm
|
||||
from .models import File, Rule, UserAttribute, RuleAttribute, AttributeType, User
|
||||
|
||||
def create_user(request):
|
||||
special_user = request.user
|
||||
@@ -18,7 +28,150 @@ def create_user_view(request):
|
||||
# Your view logic here
|
||||
return HttpResponse('New user created')
|
||||
|
||||
|
||||
@login_required
|
||||
def landing_page(request):
|
||||
files = File.objects.all()
|
||||
return render(request, 'landing_page.html', {'files': files})
|
||||
return render(request, 'landing_page.html', {'files': files})
|
||||
|
||||
def login_view(request):
|
||||
return HttpResponse('Login View')
|
||||
|
||||
def logout_view(request):
|
||||
logout(request)
|
||||
return redirect('abac:login')
|
||||
|
||||
@login_required
|
||||
def upload_file_view(request):
|
||||
if request.method == 'POST':
|
||||
form = FileUploadForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
file_instance = form.save(commit=False)
|
||||
file_instance.owner = request.user # Assign the logged-in user as the owner of the uploaded file.
|
||||
file_instance.save()
|
||||
return redirect('abac:home') # Redirect to the landing page after a successful file upload.
|
||||
else:
|
||||
form = FileUploadForm()
|
||||
return render(request, 'file_upload.html', {'form': form})
|
||||
|
||||
def create_user_view(request):
|
||||
return HttpResponse('Create User View')
|
||||
|
||||
@login_required
|
||||
def upload_certificate_view(request):
|
||||
if request.method == 'POST':
|
||||
uploaded_file = request.FILES.get('certificate')
|
||||
|
||||
if not uploaded_file:
|
||||
return HttpResponseBadRequest('No file uploaded.')
|
||||
|
||||
certificate_data = json.load(uploaded_file)
|
||||
|
||||
for attribute_data in certificate_data:
|
||||
name = attribute_data.get('name')
|
||||
value = attribute_data.get('value')
|
||||
|
||||
# Assuming you have a method to get or create AttributeType
|
||||
attribute_type = get_or_create_attribute_type(name, value, private=True)
|
||||
|
||||
attribute, created = UserAttribute.objects.update_or_create(
|
||||
user=request.user,
|
||||
attribute_type=attribute_type,
|
||||
defaults={'value': value, 'last_modified': timezone.now()}
|
||||
)
|
||||
|
||||
messages.success(request, 'Certificate uploaded successfully.')
|
||||
return redirect('abac:user_details', username=request.user.username)
|
||||
else:
|
||||
form = UploadCertificateForm()
|
||||
|
||||
return render(request, 'upload_certificate.html', {'form': form})
|
||||
|
||||
@login_required
|
||||
def file_detail(request, file_id):
|
||||
file = get_object_or_404(File, id=file_id)
|
||||
rules = Rule.objects.filter(file=file)
|
||||
return render(request, 'file_detail.html', {'file': file, 'rules': rules})
|
||||
|
||||
@login_required
|
||||
def create_rule(request, file_id):
|
||||
file = get_object_or_404(File, id=file_id)
|
||||
|
||||
if request.method == "POST":
|
||||
rule_name = request.POST.get('rule_name')
|
||||
if rule_name:
|
||||
rule = Rule.objects.create(name=rule_name, file=file)
|
||||
url = reverse('abac:rule_detail', args=[file_id, rule.id])
|
||||
return redirect(url)
|
||||
|
||||
# If the rule_name is not provided or if the method is GET, redirect to file_detail view.
|
||||
return redirect('abac:file_detail', file_id=file_id)
|
||||
|
||||
|
||||
@login_required
|
||||
def rule_detail(request, file_id, rule_id=None):
|
||||
file = get_object_or_404(File, id=file_id)
|
||||
rule = get_object_or_404(Rule, id=rule_id) if rule_id else None
|
||||
|
||||
if request.method == "POST":
|
||||
form = RuleAttributeForm(request.POST)
|
||||
if form.is_valid():
|
||||
rule_attribute = form.save(commit=False)
|
||||
rule_attribute.rule = rule
|
||||
rule_attribute.save()
|
||||
return redirect('abac:rule_detail', file_id=file_id, rule_id=rule_id)
|
||||
else:
|
||||
form = RuleAttributeForm()
|
||||
|
||||
rule_attributes = RuleAttribute.objects.filter(rule=rule) if rule else []
|
||||
|
||||
return render(request, 'rule_detail.html', {
|
||||
'file': file,
|
||||
'rule': rule,
|
||||
'form': form,
|
||||
'rule_attributes': rule_attributes
|
||||
})
|
||||
|
||||
@login_required
|
||||
def delete_rule_attribute(request, file_id, rule_id, rule_attribute_id):
|
||||
rule_attribute = get_object_or_404(RuleAttribute, id=rule_attribute_id)
|
||||
rule_attribute.delete()
|
||||
return redirect('abac:rule_detail', file_id=file_id, rule_id=rule_id)
|
||||
|
||||
@login_required
|
||||
def user_detail_view(request, username):
|
||||
user = get_object_or_404(User, username=username)
|
||||
|
||||
# Check if the requested user is the same as the logged-in user or the logged-in user has the required permission
|
||||
if user != request.user and not request.user.has_perm('abac.can_create_users'):
|
||||
return HttpResponseForbidden('You do not have permission to view this page.')
|
||||
|
||||
attributes = UserAttribute.objects.filter(user=user)
|
||||
return render(request, 'user_detail.html', {'user': user, 'attributes': attributes})
|
||||
|
||||
|
||||
|
||||
|
||||
def get_or_create_attribute_type(name, value, private=False):
|
||||
# Determine the datatype from the value
|
||||
if isinstance(value, int):
|
||||
datatype = 'INTEGER'
|
||||
elif isinstance(value, float):
|
||||
datatype = 'FLOAT'
|
||||
elif isinstance(value, bool):
|
||||
datatype = 'BOOLEAN'
|
||||
elif isinstance(value, str):
|
||||
datatype = 'STRING'
|
||||
else:
|
||||
raise ValidationError('Invalid data type in certificate for attribute: {}'.format(name))
|
||||
|
||||
# Try to get the existing AttributeType object with matching name and datatype.
|
||||
attribute_type, created = AttributeType.objects.get_or_create(
|
||||
name=name,
|
||||
datatype=datatype
|
||||
)
|
||||
|
||||
if not created and attribute_type.datatype != datatype:
|
||||
# If an AttributeType with the same name but different datatype exists, create a new one.
|
||||
attribute_type = AttributeType.objects.create(name=name, datatype=datatype, is_private=private)
|
||||
|
||||
return attribute_type
|
||||
|
||||
Reference in New Issue
Block a user