mirror of
https://github.com/eduardogsilva/wireguard_webadmin.git
synced 2025-04-19 00:45:16 +00:00
User and permission management
This commit is contained in:
parent
3177eb2b8d
commit
f036daf779
@ -3,6 +3,7 @@ from django.contrib.auth.models import User
|
||||
from django.contrib import auth
|
||||
from .forms import CreateUserForm, LoginForm
|
||||
from django.http import HttpResponse
|
||||
from user_manager.models import UserAcl
|
||||
|
||||
|
||||
def view_create_first_user(request):
|
||||
@ -13,7 +14,8 @@ def view_create_first_user(request):
|
||||
if form.is_valid():
|
||||
username = form.cleaned_data['username']
|
||||
password = form.cleaned_data['password']
|
||||
User.objects.create_superuser(username=username, password=password)
|
||||
new_user = User.objects.create_superuser(username=username, password=password)
|
||||
UserAcl.objects.create(user=new_user, user_level=50)
|
||||
return render(request, 'accounts/superuser_created.html')
|
||||
else:
|
||||
form = CreateUserForm()
|
||||
|
@ -1,5 +1,25 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
this page is just a placeholder for the moment
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Username</th>
|
||||
<th>User Level</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user_acl in user_acl_list %}
|
||||
<tr>
|
||||
<td>{{ user_acl.user.username }}</td>
|
||||
<td>{{ user_acl.get_user_level_display }}</td>
|
||||
<td style="width: 1%; white-space: nowrap;">
|
||||
<a href="/user/manage/?uuid={{ user_acl.uuid }}" ><i class="far fa-edit"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
||||
|
97
templates/user_manager/manage_user.html
Normal file
97
templates/user_manager/manage_user.html
Normal file
@ -0,0 +1,97 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-3">
|
||||
<div class="card card-primary card-outline">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">{{ form.instance.pk|yesno:"Edit User,Create New User" }}</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
<!-- Username -->
|
||||
<div class="form-group">
|
||||
<label for="{{ form.username.id_for_label }}">Username</label>
|
||||
<input type="text" class="form-control" id="{{ form.username.id_for_label }}" name="{{ form.username.html_name }}" placeholder="Enter Username" value="{{ form.username.value|default_if_none:'' }}" {% if form.instance.pk %}readonly{% endif %}>
|
||||
</div>
|
||||
<!-- Password -->
|
||||
<div class="form-group">
|
||||
<label for="{{ form.password1.id_for_label }}">Password</label>
|
||||
<input type="password" class="form-control" id="{{ form.password1.id_for_label }}" name="{{ form.password1.html_name }}" placeholder="Password">
|
||||
</div>
|
||||
|
||||
<!-- Retype Password -->
|
||||
<div class="form-group">
|
||||
<label for="{{ form.password2.id_for_label }}">Retype Password</label>
|
||||
<input type="password" class="form-control" id="{{ form.password2.id_for_label }}" name="{{ form.password2.html_name }}" placeholder="Retype Password">
|
||||
</div>
|
||||
<!-- User Level -->
|
||||
<div class="form-group">
|
||||
<label for="{{ form.user_level.id_for_label }}">{{ form.user_level.label }}</label>
|
||||
<select class="form-control" id="{{ form.user_level.id_for_label }}" name="{{ form.user_level.html_name }}">
|
||||
{% for value, display in form.user_level.field.choices %}
|
||||
<option value="{{ value }}" {% if form.user_level.value|stringformat:"s" == value|stringformat:"s" %}selected{% endif %}>{{ display }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
<a href="/user/list/" class="btn btn-outline-secondary">Back</a>
|
||||
{% if user_acl %}<a href='javascript:void(0)' class='btn btn-outline-danger' data-command='delete' onclick='openCommandDialog(this)'>Delete User</a>{% endif %}
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-md-8">
|
||||
|
||||
<h5>Debugging Analyst</h5>
|
||||
<p>Access to basic system information and logs for troubleshooting. No access to modify settings or view sensitive data such as peer keys.</p>
|
||||
|
||||
<h5>View Only User</h5>
|
||||
<p>Full view access, including peer keys and configuration files. Cannot modify any settings or configurations.</p>
|
||||
|
||||
<h5>Peer Manager</h5>
|
||||
<p>Permissions to add, edit, and remove peers and IP addresses. Does not include access to modify WireGuard instance configurations or higher-level settings.</p>
|
||||
|
||||
<h5>Wireguard Manager</h5>
|
||||
<p>Authority to add, edit, and remove configurations of WireGuard instances.</p>
|
||||
|
||||
<h5>Administrator</h5>
|
||||
<p>Full access across the system. Can view and modify all settings, configurations and manage users. </p>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block custom_page_scripts %}
|
||||
|
||||
<script>
|
||||
function openCommandDialog(element) {
|
||||
var command = element.getAttribute('data-command');
|
||||
var confirmation = prompt("Please type '{{ user_acl.user.username }}' to remove this user.");
|
||||
if (confirmation) {
|
||||
var url = "?uuid={{ user_acl.uuid }}&action=delete&confirmation=" + encodeURIComponent(confirmation);
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
@ -1,3 +1,9 @@
|
||||
from django.contrib import admin
|
||||
from user_manager.models import UserAcl
|
||||
|
||||
# Register your models here.
|
||||
|
||||
class UserAclAdmin(admin.ModelAdmin):
|
||||
list_display = ('user', 'user_level', 'created', 'updated')
|
||||
search_fields = ('user__username', 'user__email')
|
||||
|
||||
admin.site.register(UserAcl, UserAclAdmin)
|
||||
|
46
user_manager/forms.py
Normal file
46
user_manager/forms.py
Normal file
@ -0,0 +1,46 @@
|
||||
from django import forms
|
||||
from django.contrib.auth.forms import UserCreationForm
|
||||
from django.contrib.auth.models import User
|
||||
from .models import UserAcl
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
class UserAclForm(UserCreationForm):
|
||||
user_level = forms.ChoiceField(choices=UserAcl.user_level.field.choices, required=True, label="User Level")
|
||||
|
||||
class Meta(UserCreationForm.Meta):
|
||||
model = User
|
||||
fields = UserCreationForm.Meta.fields + ('user_level',)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.user_id = kwargs.pop('user_id', None)
|
||||
super().__init__(*args, **kwargs)
|
||||
if self.instance and self.instance.pk:
|
||||
self.fields['password1'].required = False
|
||||
self.fields['password2'].required = False
|
||||
self.fields['username'].widget.attrs['readonly'] = True
|
||||
|
||||
def clean_username(self):
|
||||
username = self.cleaned_data.get('username')
|
||||
if User.objects.filter(username=username).exclude(pk=self.user_id).exists():
|
||||
raise ValidationError("A user with that username already exists.")
|
||||
return username
|
||||
|
||||
def save(self, commit=True):
|
||||
user = super().save(commit=False)
|
||||
new_password = self.cleaned_data.get("password1")
|
||||
|
||||
if new_password:
|
||||
user.set_password(new_password)
|
||||
user.save()
|
||||
else:
|
||||
if not user.id:
|
||||
user.save()
|
||||
|
||||
if commit:
|
||||
user_acl, created = UserAcl.objects.update_or_create(
|
||||
user=user,
|
||||
defaults={'user_level': self.cleaned_data.get('user_level')}
|
||||
)
|
||||
|
||||
return user
|
25
user_manager/migrations/0001_initial.py
Normal file
25
user_manager/migrations/0001_initial.py
Normal file
@ -0,0 +1,25 @@
|
||||
# Generated by Django 5.0.1 on 2024-02-14 20:54
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='UserAcl',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('user_level', models.PositiveIntegerField(choices=[(10, 'Debugging Analyst'), (20, 'View Only User'), (30, 'Peer Manager'), (40, 'Wireguard Manager'), (50, 'Administrator')], default=0)),
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
]
|
@ -0,0 +1,35 @@
|
||||
# Generated by Django 5.0.1 on 2024-02-14 21:23
|
||||
|
||||
import django.utils.timezone
|
||||
import uuid
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('user_manager', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='useracl',
|
||||
name='id',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='useracl',
|
||||
name='created',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='useracl',
|
||||
name='updated',
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='useracl',
|
||||
name='uuid',
|
||||
field=models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
@ -1,6 +1,6 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
# Create your models here.
|
||||
import uuid
|
||||
|
||||
|
||||
class UserAcl(models.Model):
|
||||
@ -11,8 +11,11 @@ class UserAcl(models.Model):
|
||||
(30, 'Peer Manager'),
|
||||
(40, 'Wireguard Manager'),
|
||||
(50, 'Administrator'),
|
||||
|
||||
))
|
||||
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
uuid = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4)
|
||||
|
||||
def __str__(self):
|
||||
return self.user.username
|
||||
|
@ -1,9 +1,60 @@
|
||||
from django.shortcuts import render
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from user_manager.models import UserAcl
|
||||
from .forms import UserAclForm
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib import messages
|
||||
from django.contrib.sessions.models import Session
|
||||
|
||||
@login_required
|
||||
def view_user_list(request):
|
||||
page_title = 'User Manager'
|
||||
context = {'page_title': page_title}
|
||||
user_acl_list = UserAcl.objects.all().order_by('user__username')
|
||||
context = {'page_title': page_title, 'user_acl_list': user_acl_list}
|
||||
return render(request, 'user_manager/list.html', context)
|
||||
|
||||
|
||||
@login_required
|
||||
def view_manage_user(request):
|
||||
user_acl = None
|
||||
user = None
|
||||
if 'uuid' in request.GET:
|
||||
user_acl = get_object_or_404(UserAcl, uuid=request.GET['uuid'])
|
||||
user = user_acl.user
|
||||
form = UserAclForm(instance=user, initial={'user_level': user_acl.user_level}, user_id=user.id)
|
||||
page_title = 'Edit User '+ user.username
|
||||
if request.GET.get('action') == 'delete':
|
||||
username = user.username
|
||||
if request.GET.get('confirm') == user.username:
|
||||
user.delete()
|
||||
messages.success(request, 'User deleted|The user '+ username +' has been deleted.')
|
||||
return redirect('/user/list/')
|
||||
user_acl.delete()
|
||||
return redirect('/user/list/')
|
||||
else:
|
||||
form = UserAclForm()
|
||||
page_title = 'Add User'
|
||||
|
||||
if request.method == 'POST':
|
||||
if user_acl:
|
||||
form = UserAclForm(request.POST, instance=user, user_id=user.id)
|
||||
else:
|
||||
form = UserAclForm(request.POST)
|
||||
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
if form.cleaned_data.get('password1'):
|
||||
user_disconnected = False
|
||||
for session in Session.objects.all():
|
||||
if str(user.id) == session.get_decoded().get('_auth_user_id'):
|
||||
session.delete()
|
||||
if not user_disconnected:
|
||||
messages.warning(request, 'User Disconnected|The user '+ user.username +' has been disconnected.')
|
||||
user_disconnected = True
|
||||
if user_acl:
|
||||
messages.success(request, 'User updated|The user '+ form.cleaned_data['username'] +' has been updated.')
|
||||
else:
|
||||
messages.success(request, 'User added|The user '+ form.cleaned_data['username'] +' has been added.')
|
||||
return redirect('/user/list/')
|
||||
|
||||
return render(request, 'user_manager/manage_user.html', {'form': form, 'page_title': page_title, 'user_acl': user_acl})
|
||||
|
@ -19,7 +19,7 @@ from django.urls import path
|
||||
from wireguard.views import view_welcome, view_wireguard_status, view_wireguard_manage_instance
|
||||
from wireguard_peer.views import view_wireguard_peer_list, view_wireguard_peer_manage, view_manage_ip_address
|
||||
from console.views import view_console
|
||||
from user_manager.views import view_user_list
|
||||
from user_manager.views import view_user_list, view_manage_user
|
||||
from accounts.views import view_create_first_user, view_login, view_logout
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@ urlpatterns = [
|
||||
path('peer/manage_ip_address/', view_manage_ip_address, name='manage_ip_address'),
|
||||
path('console/', view_console, name='console'),
|
||||
path('user/list/', view_user_list, name='user_list'),
|
||||
path('user/manage/', view_manage_user, name='manage_user'),
|
||||
path('server/manage/', view_wireguard_manage_instance, name='wireguard_manage_instance'),
|
||||
path('accounts/create_first_user/', view_create_first_user, name='create_first_user'),
|
||||
path('accounts/login/', view_login, name='login'),
|
||||
|
Loading…
x
Reference in New Issue
Block a user