Initial commit

This commit is contained in:
Felix Baumann
2026-06-27 17:07:34 +00:00
commit fb47c53d52
256 changed files with 21270 additions and 0 deletions
View File
+34
View File
@@ -0,0 +1,34 @@
from django.contrib import admin
from .models import Role, UserProfile
@admin.register(Role)
class RoleAdmin(admin.ModelAdmin):
list_display = [
"name",
]
search_fields = [
"name",
]
@admin.register(UserProfile)
class UserProfileAdmin(admin.ModelAdmin):
list_display = [
"user",
"role",
]
list_filter = [
"role",
]
search_fields = [
"user__username",
"user__first_name",
"user__last_name",
"user__email",
]
+5
View File
@@ -0,0 +1,5 @@
from django.apps import AppConfig
class AccountsConfig(AppConfig):
name = 'accounts'
+50
View File
@@ -0,0 +1,50 @@
from functools import wraps
from django.shortcuts import redirect
from django.contrib import messages
def permission_required(permission):
def decorator(view_func):
@wraps(view_func)
def wrapper(request, *args, **kwargs):
# Superuser haben alles
if request.user.is_superuser:
return view_func(
request,
*args,
**kwargs
)
profile = getattr(
request.user,
"profile",
None
)
if profile and profile.has_permission(permission):
return view_func(
request,
*args,
**kwargs
)
messages.error(
request,
"Keine Berechtigung für diese Aktion!"
)
return redirect("core:dashboard")
return wrapper
return decorator
+61
View File
@@ -0,0 +1,61 @@
from django import forms
from django.contrib.auth.models import User
from .models import Role
from core.forms.base import BaseForm
class UserAddForm(BaseForm):
password = forms.CharField(
label="Passwort",
widget=forms.PasswordInput
)
role = forms.ModelChoiceField(
queryset=Role.objects.order_by("name"),
required=False,
label="Rolle"
)
class Meta:
model = User
fields = [
"username",
"first_name",
"last_name",
"email",
]
labels = {
"username": "Benutzername",
"first_name": "Vorname",
"last_name": "Nachname",
"email": "E-Mail",
}
help_texts = {
"username": "",
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.apply_style()
class RoleForm(BaseForm):
class Meta:
model = Role
fields = [
"name",
]
labels = {
"name": "Rollenname",
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.apply_style()
+97
View File
@@ -0,0 +1,97 @@
# Generated by Django 6.0.6 on 2026-06-23 22:12
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='Role',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, unique=True, verbose_name='Rolle')),
('projects_view', models.BooleanField(default=False, help_text='Benutzer darf Projekte einsehen.', verbose_name='Projekte anzeigen')),
('projects_archived_view', models.BooleanField(default=False, help_text='Benutzer darf archivierte Projekte einsehen.', verbose_name='Archivierte Projekte anzeigen')),
('projects_detail_view', models.BooleanField(default=False, help_text='Benutzer darf Details des Projekts einsehen.', verbose_name='Projektdetails anzeigen')),
('projects_add', models.BooleanField(default=False, help_text='Benutzer darf neue Projekte anlegen.', verbose_name='Projekt erstellen')),
('projects_contact_add', models.BooleanField(default=False, help_text='Benutzer darf Kontakte mit dem Projekt verknüpfen.', verbose_name='Projektkontakt verknüpfen')),
('projects_contact_delete', models.BooleanField(default=False, help_text='Benutzer darf Kontakte aus dem Projekt entfernen.', verbose_name='Projektkontakt entfernen')),
('projects_location_add', models.BooleanField(default=False, help_text='Benutzer darf Standorte mit dem Projekt verknüpfen.', verbose_name='Projektstandort verknüpfen')),
('projects_location_delete', models.BooleanField(default=False, help_text='Benutzer darf Standorte aus dem Projekt entfernen.', verbose_name='Projektstandort entfernen')),
('projects_edit', models.BooleanField(default=False, help_text='Benutzer darf Projekte ändern.', verbose_name='Projekte bearbeiten')),
('projects_user_add', models.BooleanField(default=False, help_text='Benutzer darf Mitarbeiter im Projekt hinzufügen.', verbose_name='Projektmitarbeiter erstellen')),
('projects_user_delete', models.BooleanField(default=False, help_text='Benutzer darf Mitarbeiter aus dem Projekt entfernen.', verbose_name='Projektmitarbeiter entfernen')),
('projects_finance_view', models.BooleanField(default=False, help_text='Benutzer darf Projektfinanzen einsehen.', verbose_name='Projektfinanzen anzeigen')),
('projects_finance_income_add', models.BooleanField(default=False, help_text='Benutzer darf Einnahmen hinzufügen.', verbose_name='Projekteinnahmen erfassen')),
('projects_finance_expense_add', models.BooleanField(default=False, help_text='Benutzer darf Ausgaben hinzufügen.', verbose_name='Projektausgaben erfassen')),
('projects_time_tracking_view', models.BooleanField(default=False, help_text='Benutzer darf Projektzeiten sehen.', verbose_name='Projektzeiten anzeigen')),
('projects_time_tracking_edit', models.BooleanField(default=False, help_text='Benutzer darf Projektzeiten ändern.', verbose_name='Projektzeiten bearbeiten')),
('projects_time_tracking_delete', models.BooleanField(default=False, help_text='Benutzer darf Projektzeiten löschen.', verbose_name='Projektzeiten löschen')),
('projects_documents_view', models.BooleanField(default=False, help_text='Benutzer darf Dokumente sehen.', verbose_name='Projektdokumente anzeigen')),
('projects_documents_add', models.BooleanField(default=False, help_text='Benutzer darf Dokumente hochladen.', verbose_name='Projektdokumente hinzufügen')),
('projects_documents_delete', models.BooleanField(default=False, help_text='Benutzer darf Dokumente löschen.', verbose_name='Projektdokumente löschen')),
('projects_inventory_inventory_view', models.BooleanField(default=False, help_text='Benutzer darf Projektinventar sehen.', verbose_name='Projektinventar anzeigen')),
('projects_inventory_inventory_add', models.BooleanField(default=False, help_text='Benutzer darf Inventar hinzufügen.', verbose_name='Projektinventar hinzufügen')),
('projects_inventory_inventory_edit', models.BooleanField(default=False, help_text='Benutzer darf Inventar ändern.', verbose_name='Projektinventar bearbeiten')),
('projects_inventory_inventory_delete', models.BooleanField(default=False, help_text='Benutzer darf Inventar löschen.', verbose_name='Projektinventar löschen')),
('projects_inventory_shopping_add', models.BooleanField(default=False, help_text='Benutzer darf Einkaufspositionen erstellen.', verbose_name='Einkauf hinzufügen')),
('projects_inventory_shopping_edit', models.BooleanField(default=False, help_text='Benutzer darf Einkaufspositionen ändern.', verbose_name='Einkauf bearbeiten')),
('projects_inventory_shopping_delete', models.BooleanField(default=False, help_text='Benutzer darf Einkaufspositionen löschen.', verbose_name='Einkauf löschen')),
('inventory_view', models.BooleanField(default=False, help_text='Benutzer darf Inventar einsehen.', verbose_name='Inventar anzeigen')),
('inventory_add', models.BooleanField(default=False, help_text='Benutzer darf Inventareinträge erstellen.', verbose_name='Inventar hinzufügen')),
('inventory_edit', models.BooleanField(default=False, help_text='Benutzer darf Inventareinträge ändern.', verbose_name='Inventar bearbeiten')),
('inventory_delete', models.BooleanField(default=False, help_text='Benutzer darf Inventareinträge löschen.', verbose_name='Inventar löschen')),
('invoices_view', models.BooleanField(default=False, help_text='Benutzer darf Rechnungen verwalten.', verbose_name='Rechnungsbereich anzeigen')),
('invoices_customers_view', models.BooleanField(default=False, help_text='Benutzer darf Kunden sehen.', verbose_name='Kunden anzeigen')),
('invoices_customers_detail_view', models.BooleanField(default=False, help_text='Benutzer darf Details des Kunden sehen.', verbose_name='Kundendetails anzeigen')),
('invoices_customers_add', models.BooleanField(default=False, help_text='Benutzer darf Kunden anlegen.', verbose_name='Kunden erstellen')),
('invoices_customers_edit', models.BooleanField(default=False, help_text='Benutzer darf Kunden ändern.', verbose_name='Kunden bearbeiten')),
('invoices_customers_archive', models.BooleanField(default=False, help_text='Benutzer darf Kunden archivieren.', verbose_name='Kunden archivieren')),
('invoices_customers_activate', models.BooleanField(default=False, help_text='Benutzer darf Kunden wieder aktivieren.', verbose_name='Kunden reaktivieren')),
('invoices_items_view', models.BooleanField(default=False, help_text='Benutzer darf Artikel sehen.', verbose_name='Artikel anzeigen')),
('invoices_items_add', models.BooleanField(default=False, help_text='Benutzer darf Artikel erstellen.', verbose_name='Artikel erstellen')),
('invoices_items_edit', models.BooleanField(default=False, help_text='Benutzer darf Artikel ändern.', verbose_name='Artikel bearbeiten')),
('invoices_items_delete', models.BooleanField(default=False, help_text='Benutzer darf Artikel löschen.', verbose_name='Artikel löschen')),
('invoices_invoices_view', models.BooleanField(default=False, help_text='Benutzer darf Rechnungen sehen.', verbose_name='Rechnungen anzeigen')),
('invoices_invoices_project_add', models.BooleanField(default=False, help_text='Benutzer darf Rechnungen aus Projekten erstellen.', verbose_name='Projekt-Rechnung erstellen')),
('invoices_invoices_customer_add', models.BooleanField(default=False, help_text='Benutzer darf Rechnungen für Kunden erstellen.', verbose_name='Kunden-Rechnung erstellen')),
('invoices_invoices_invoices_view', models.BooleanField(default=False, help_text='Benutzer darf Rechnungsdetails sehen.', verbose_name='Rechnungsdetails anzeigen')),
('invoices_invoices_invoices_item_add', models.BooleanField(default=False, help_text='Benutzer darf Positionen hinzufügen.', verbose_name='Rechnungsposition hinzufügen')),
('invoices_invoices_invoices_item_delete', models.BooleanField(default=False, help_text='Benutzer darf Positionen löschen.', verbose_name='Rechnungsposition löschen')),
('invoices_invoices_invoices_preview', models.BooleanField(default=False, help_text='Benutzer darf Vorschauen öffnen.', verbose_name='Rechnungsvorschau anzeigen')),
('users_view', models.BooleanField(default=False, help_text='Benutzer darf Mitarbeiter sehen.', verbose_name='Benutzer anzeigen')),
('users_add', models.BooleanField(default=False, help_text='Benutzer darf neue Mitarbeiter anlegen.', verbose_name='Benutzer erstellen')),
('users_edit', models.BooleanField(default=False, help_text='Benutzer darf Mitarbeiter bearbeiten.', verbose_name='Benutzer bearbeiten')),
('users_archive', models.BooleanField(default=False, help_text='Benutzer darf Mitarbeiter deaktivieren.', verbose_name='Benutzer archivieren')),
('users_activate', models.BooleanField(default=False, help_text='Benutzer darf Mitarbeiter aktivieren.', verbose_name='Benutzer aktivieren')),
('users_groups_add', models.BooleanField(default=False, help_text='Benutzer darf neue Rollen erstellen.', verbose_name='Rollen erstellen')),
('users_groups_edit', models.BooleanField(default=False, help_text='Benutzer darf Rollen und Berechtigungen ändern.', verbose_name='Rollen bearbeiten')),
('users_groups_delete', models.BooleanField(default=False, help_text='Benutzer darf Rollen entfernen.', verbose_name='Rollen löschen')),
('settings_view', models.BooleanField(default=False, help_text='Benutzer darf Einstellungskategorien sehen.', verbose_name='Einstellungsübersicht anzeigen')),
('settings_detail_view', models.BooleanField(default=False, help_text='Benutzer darf Systemeinstellungen sehen.', verbose_name='Einstellungen anzeigen')),
('settings_add', models.BooleanField(default=False, help_text='Benutzer darf neue Einstellungen hinzufügen.', verbose_name='Einstellungen erstellen')),
('settings_delete', models.BooleanField(default=False, help_text='Benutzer darf Einstellungen entfernen.', verbose_name='Einstellungen löschen')),
],
options={
'verbose_name': 'Rolle',
'verbose_name_plural': 'Rollen',
},
),
migrations.CreateModel(
name='UserProfile',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('role', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='accounts.role')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)),
],
),
]
@@ -0,0 +1,18 @@
# Generated by Django 6.0.6 on 2026-06-23 23:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='role',
name='invoices_invoices_invoices_download',
field=models.BooleanField(default=False, help_text='Benutzer darf Rechnungen herunterladen.', verbose_name='Rechnung herunterladen'),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 6.0.6 on 2026-06-24 08:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0002_role_invoices_invoices_invoices_download'),
]
operations = [
migrations.AddField(
model_name='role',
name='invoices_invoices_invoices_cancel',
field=models.BooleanField(default=False, help_text='Benutzer darf Rechnungen stornieren.', verbose_name='Rechnung stornieren'),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 6.0.6 on 2026-06-24 09:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0003_role_invoices_invoices_invoices_cancel'),
]
operations = [
migrations.AddField(
model_name='role',
name='invoices_invoices_invoices_cancel_download',
field=models.BooleanField(default=False, help_text='Benutzer darf Stornorechnungen herunterladen.', verbose_name='Stornorechnung Download'),
),
]
@@ -0,0 +1,22 @@
# Generated by Django 6.0.6 on 2026-06-24 13:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0004_role_invoices_invoices_invoices_cancel_download'),
]
operations = [
migrations.RemoveField(
model_name='role',
name='invoices_invoices_invoices_cancel_download',
),
migrations.AddField(
model_name='role',
name='invoices_invoices_invoices_paid',
field=models.BooleanField(default=False, help_text='Benutzer darf Rechnungsstatus ändern.', verbose_name='Rechnung auf bezahlt setzen'),
),
]
@@ -0,0 +1,53 @@
# Generated by Django 6.0.6 on 2026-06-25 16:29
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0005_remove_role_invoices_invoices_invoices_cancel_download_and_more'),
]
operations = [
migrations.AddField(
model_name='role',
name='invoices_offers_add',
field=models.BooleanField(default=False, help_text='Benutzer darf Angebote für Kunden erstellen.', verbose_name='Angebot erstellen'),
),
migrations.AddField(
model_name='role',
name='invoices_offers_offers_download',
field=models.BooleanField(default=False, help_text='Benutzer darf Angebote herunterladen.', verbose_name='Angebot herunterladen'),
),
migrations.AddField(
model_name='role',
name='invoices_offers_offers_item_add',
field=models.BooleanField(default=False, help_text='Benutzer darf Positionen hinzufügen.', verbose_name='Angebotsposition hinzufügen'),
),
migrations.AddField(
model_name='role',
name='invoices_offers_offers_item_delete',
field=models.BooleanField(default=False, help_text='Benutzer darf Positionen löschen.', verbose_name='Angebotsposition löschen'),
),
migrations.AddField(
model_name='role',
name='invoices_offers_offers_preview',
field=models.BooleanField(default=False, help_text='Benutzer darf Vorschauen öffnen.', verbose_name='Angebotsvorschau anzeigen'),
),
migrations.AddField(
model_name='role',
name='invoices_offers_offers_status',
field=models.BooleanField(default=False, help_text='Benutzer darf Angebotsstatus ändern.', verbose_name='Angebotsstatus bearbeiten'),
),
migrations.AddField(
model_name='role',
name='invoices_offers_offers_view',
field=models.BooleanField(default=False, help_text='Benutzer darf Angebotsdetails sehen.', verbose_name='Angebotsdetails anzeigen'),
),
migrations.AddField(
model_name='role',
name='invoices_offers_view',
field=models.BooleanField(default=False, help_text='Benutzer darf Angebote sehen.', verbose_name='Angebote anzeigen'),
),
]
View File
+193
View File
@@ -0,0 +1,193 @@
from django.db import models
from django.contrib.auth.models import User
class Role(models.Model):
name = models.CharField(
max_length=100,
unique=True,
verbose_name="Rolle"
)
projects_view = models.BooleanField(default=False, verbose_name="Projekte anzeigen", help_text="Benutzer darf Projekte einsehen.")
projects_archived_view = models.BooleanField(default=False, verbose_name="Archivierte Projekte anzeigen", help_text="Benutzer darf archivierte Projekte einsehen.")
projects_detail_view = models.BooleanField(default=False, verbose_name="Projektdetails anzeigen", help_text="Benutzer darf Details des Projekts einsehen.")
projects_add = models.BooleanField(default=False, verbose_name="Projekt erstellen", help_text="Benutzer darf neue Projekte anlegen.")
projects_contact_add = models.BooleanField(default=False, verbose_name="Projektkontakt verknüpfen", help_text="Benutzer darf Kontakte mit dem Projekt verknüpfen.")
projects_contact_delete = models.BooleanField(default=False, verbose_name="Projektkontakt entfernen", help_text="Benutzer darf Kontakte aus dem Projekt entfernen.")
projects_location_add = models.BooleanField(default=False, verbose_name="Projektstandort verknüpfen", help_text="Benutzer darf Standorte mit dem Projekt verknüpfen.")
projects_location_delete = models.BooleanField(default=False, verbose_name="Projektstandort entfernen", help_text="Benutzer darf Standorte aus dem Projekt entfernen.")
projects_edit = models.BooleanField(default=False, verbose_name="Projekte bearbeiten", help_text="Benutzer darf Projekte ändern.")
projects_user_add = models.BooleanField(default=False, verbose_name="Projektmitarbeiter erstellen", help_text="Benutzer darf Mitarbeiter im Projekt hinzufügen.")
projects_user_delete = models.BooleanField(default=False, verbose_name="Projektmitarbeiter entfernen", help_text="Benutzer darf Mitarbeiter aus dem Projekt entfernen.")
projects_finance_view = models.BooleanField(default=False, verbose_name="Projektfinanzen anzeigen", help_text="Benutzer darf Projektfinanzen einsehen.")
projects_finance_income_add = models.BooleanField(default=False, verbose_name="Projekteinnahmen erfassen", help_text="Benutzer darf Einnahmen hinzufügen.")
projects_finance_expense_add = models.BooleanField(default=False, verbose_name="Projektausgaben erfassen", help_text="Benutzer darf Ausgaben hinzufügen.")
projects_time_tracking_view = models.BooleanField(default=False, verbose_name="Projektzeiten anzeigen", help_text="Benutzer darf Projektzeiten sehen.")
projects_time_tracking_edit = models.BooleanField(default=False, verbose_name="Projektzeiten bearbeiten", help_text="Benutzer darf Projektzeiten ändern.")
projects_time_tracking_delete = models.BooleanField(default=False, verbose_name="Projektzeiten löschen", help_text="Benutzer darf Projektzeiten löschen.")
projects_documents_view = models.BooleanField(default=False, verbose_name="Projektdokumente anzeigen", help_text="Benutzer darf Dokumente sehen.")
projects_documents_add = models.BooleanField(default=False, verbose_name="Projektdokumente hinzufügen", help_text="Benutzer darf Dokumente hochladen.")
projects_documents_delete = models.BooleanField(default=False, verbose_name="Projektdokumente löschen", help_text="Benutzer darf Dokumente löschen.")
projects_inventory_inventory_view = models.BooleanField(default=False, verbose_name="Projektinventar anzeigen", help_text="Benutzer darf Projektinventar sehen.")
projects_inventory_inventory_add = models.BooleanField(default=False, verbose_name="Projektinventar hinzufügen", help_text="Benutzer darf Inventar hinzufügen.")
projects_inventory_inventory_edit = models.BooleanField(default=False, verbose_name="Projektinventar bearbeiten", help_text="Benutzer darf Inventar ändern.")
projects_inventory_inventory_delete = models.BooleanField(default=False, verbose_name="Projektinventar löschen", help_text="Benutzer darf Inventar löschen.")
projects_inventory_shopping_add = models.BooleanField(default=False, verbose_name="Einkauf hinzufügen", help_text="Benutzer darf Einkaufspositionen erstellen.")
projects_inventory_shopping_edit = models.BooleanField(default=False, verbose_name="Einkauf bearbeiten", help_text="Benutzer darf Einkaufspositionen ändern.")
projects_inventory_shopping_delete = models.BooleanField(default=False, verbose_name="Einkauf löschen", help_text="Benutzer darf Einkaufspositionen löschen.")
#projects_inventory_shopping_buy = models.BooleanField(default=False, verbose_name="Einkäufe durchführen", help_text="Benutzer darf Einkäufe als erledigt markieren.")
# =====================
# Inventar
# =====================
inventory_view = models.BooleanField(default=False, verbose_name="Inventar anzeigen", help_text="Benutzer darf Inventar einsehen.")
inventory_add = models.BooleanField(default=False, verbose_name="Inventar hinzufügen", help_text="Benutzer darf Inventareinträge erstellen.")
inventory_edit = models.BooleanField(default=False, verbose_name="Inventar bearbeiten", help_text="Benutzer darf Inventareinträge ändern.")
inventory_delete = models.BooleanField(default=False, verbose_name="Inventar löschen", help_text="Benutzer darf Inventareinträge löschen.")
# =====================
# Rechnungen
# =====================
invoices_view = models.BooleanField(default=False, verbose_name="Rechnungsbereich anzeigen", help_text="Benutzer darf Rechnungen verwalten.")
invoices_customers_view = models.BooleanField(default=False, verbose_name="Kunden anzeigen", help_text="Benutzer darf Kunden sehen.")
invoices_customers_detail_view = models.BooleanField(default=False, verbose_name="Kundendetails anzeigen", help_text="Benutzer darf Details des Kunden sehen.")
invoices_customers_add = models.BooleanField(default=False, verbose_name="Kunden erstellen", help_text="Benutzer darf Kunden anlegen.")
invoices_customers_edit = models.BooleanField(default=False, verbose_name="Kunden bearbeiten", help_text="Benutzer darf Kunden ändern.")
invoices_customers_archive = models.BooleanField(default=False, verbose_name="Kunden archivieren", help_text="Benutzer darf Kunden archivieren.")
invoices_customers_activate = models.BooleanField(default=False, verbose_name="Kunden reaktivieren", help_text="Benutzer darf Kunden wieder aktivieren.")
invoices_items_view = models.BooleanField(default=False, verbose_name="Artikel anzeigen", help_text="Benutzer darf Artikel sehen.")
invoices_items_add = models.BooleanField(default=False, verbose_name="Artikel erstellen", help_text="Benutzer darf Artikel erstellen.")
invoices_items_edit = models.BooleanField(default=False, verbose_name="Artikel bearbeiten", help_text="Benutzer darf Artikel ändern.")
invoices_items_delete = models.BooleanField(default=False, verbose_name="Artikel löschen", help_text="Benutzer darf Artikel löschen.")
invoices_invoices_view = models.BooleanField(default=False, verbose_name="Rechnungen anzeigen", help_text="Benutzer darf Rechnungen sehen.")
invoices_invoices_project_add = models.BooleanField(default=False, verbose_name="Projekt-Rechnung erstellen", help_text="Benutzer darf Rechnungen aus Projekten erstellen.")
invoices_invoices_customer_add = models.BooleanField(default=False, verbose_name="Kunden-Rechnung erstellen", help_text="Benutzer darf Rechnungen für Kunden erstellen.")
invoices_invoices_invoices_view = models.BooleanField(default=False, verbose_name="Rechnungsdetails anzeigen", help_text="Benutzer darf Rechnungsdetails sehen.")
invoices_invoices_invoices_item_add = models.BooleanField(default=False, verbose_name="Rechnungsposition hinzufügen", help_text="Benutzer darf Positionen hinzufügen.")
invoices_invoices_invoices_item_delete = models.BooleanField(default=False, verbose_name="Rechnungsposition löschen", help_text="Benutzer darf Positionen löschen.")
invoices_invoices_invoices_preview = models.BooleanField(default=False, verbose_name="Rechnungsvorschau anzeigen", help_text="Benutzer darf Vorschauen öffnen.")
invoices_invoices_invoices_download = models.BooleanField(default=False, verbose_name="Rechnung herunterladen", help_text="Benutzer darf Rechnungen herunterladen.")
invoices_invoices_invoices_cancel = models.BooleanField(default=False, verbose_name="Rechnung stornieren", help_text="Benutzer darf Rechnungen stornieren.")
invoices_invoices_invoices_paid = models.BooleanField(default=False, verbose_name="Rechnung auf bezahlt setzen", help_text="Benutzer darf Rechnungsstatus ändern.")
invoices_offers_view = models.BooleanField(default=False, verbose_name="Angebote anzeigen", help_text="Benutzer darf Angebote sehen.")
invoices_offers_add = models.BooleanField(default=False, verbose_name="Angebot erstellen", help_text="Benutzer darf Angebote für Kunden erstellen.")
invoices_offers_offers_view = models.BooleanField(default=False, verbose_name="Angebotsdetails anzeigen", help_text="Benutzer darf Angebotsdetails sehen.")
invoices_offers_offers_item_add = models.BooleanField(default=False, verbose_name="Angebotsposition hinzufügen", help_text="Benutzer darf Positionen hinzufügen.")
invoices_offers_offers_item_delete = models.BooleanField(default=False, verbose_name="Angebotsposition löschen", help_text="Benutzer darf Positionen löschen.")
invoices_offers_offers_preview = models.BooleanField(default=False, verbose_name="Angebotsvorschau anzeigen", help_text="Benutzer darf Vorschauen öffnen.")
invoices_offers_offers_download = models.BooleanField(default=False, verbose_name="Angebot herunterladen", help_text="Benutzer darf Angebote herunterladen.")
invoices_offers_offers_status = models.BooleanField(default=False, verbose_name="Angebotsstatus bearbeiten", help_text="Benutzer darf Angebotsstatus ändern.")
# =====================
# Benutzerverwaltung
# =====================
users_view = models.BooleanField(default=False, verbose_name="Benutzer anzeigen", help_text="Benutzer darf Mitarbeiter sehen.")
users_add = models.BooleanField(default=False, verbose_name="Benutzer erstellen", help_text="Benutzer darf neue Mitarbeiter anlegen.")
users_edit = models.BooleanField(default=False, verbose_name="Benutzer bearbeiten", help_text="Benutzer darf Mitarbeiter bearbeiten.")
users_archive = models.BooleanField(default=False, verbose_name="Benutzer archivieren", help_text="Benutzer darf Mitarbeiter deaktivieren.")
users_activate = models.BooleanField(default=False, verbose_name="Benutzer aktivieren", help_text="Benutzer darf Mitarbeiter aktivieren.")
users_groups_add = models.BooleanField(default=False, verbose_name="Rollen erstellen", help_text="Benutzer darf neue Rollen erstellen.")
users_groups_edit = models.BooleanField(default=False, verbose_name="Rollen bearbeiten", help_text="Benutzer darf Rollen und Berechtigungen ändern.")
users_groups_delete = models.BooleanField(default=False, verbose_name="Rollen löschen", help_text="Benutzer darf Rollen entfernen.")
# =====================
# Einstellungen
# =====================
settings_view = models.BooleanField(default=False, verbose_name="Einstellungsübersicht anzeigen", help_text="Benutzer darf Einstellungskategorien sehen.")
settings_detail_view = models.BooleanField(default=False, verbose_name="Einstellungen anzeigen", help_text="Benutzer darf Systemeinstellungen sehen.")
settings_add = models.BooleanField(default=False, verbose_name="Einstellungen erstellen", help_text="Benutzer darf neue Einstellungen hinzufügen.")
#settings_edit = models.BooleanField(default=False, verbose_name="Einstellungen bearbeiten", help_text="Benutzer darf Einstellungen ändern.")
settings_delete = models.BooleanField(default=False, verbose_name="Einstellungen löschen", help_text="Benutzer darf Einstellungen entfernen.")
# =====================
# Zeiterfassung
# =====================
#time_tracking_own_view = models.BooleanField(default=False, verbose_name="Eigene Zeiten anzeigen", help_text="Benutzer darf eigene Arbeitszeiten sehen.")
#time_tracking_own_add = models.BooleanField(default=False, verbose_name="Eigene Zeiten erfassen", help_text="Benutzer darf eigene Arbeitszeiten hinzufügen.")
#time_tracking_own_edit = models.BooleanField(default=False, verbose_name="Eigene Zeiten bearbeiten", help_text="Benutzer darf eigene Arbeitszeiten ändern.")
#time_tracking_own_delete = models.BooleanField(default=False, verbose_name="Eigene Zeiten löschen", help_text="Benutzer darf eigene Arbeitszeiten löschen.")
#time_tracking_all_view = models.BooleanField(default=False, verbose_name="Alle Zeiten anzeigen", help_text="Benutzer darf Arbeitszeiten aller Benutzer sehen.")
#time_tracking_all_add = models.BooleanField(default=False, verbose_name="Alle Zeiten erfassen", help_text="Benutzer darf Arbeitszeiten für andere Benutzer hinzufügen.")
#time_tracking_all_edit = models.BooleanField(default=False, verbose_name="Alle Zeiten bearbeiten", help_text="Benutzer darf Arbeitszeiten anderer Benutzer ändern.")
#time_tracking_all_delete = models.BooleanField(default=False, verbose_name="Alle Zeiten löschen", help_text="Benutzer darf Arbeitszeiten anderer Benutzer löschen.")
# =====================
# Finanzen
# =====================
#finance_view = models.BooleanField(default=False, verbose_name="Finanzen anzeigen", help_text="Benutzer darf Finanzdaten sehen.")
#finance_export = models.BooleanField(default=False, verbose_name="Finanzen exportieren", help_text="Benutzer darf Finanzdaten exportieren.")
# =====================
# Investments
# =====================
#invests_view = models.BooleanField(default=False, verbose_name="Investitionen anzeigen", help_text="Benutzer darf Investitionen sehen.")
#invests_add = models.BooleanField(default=False, verbose_name="Investitionen erstellen", help_text="Benutzer darf neue Investitionen anlegen.")
#invests_edit = models.BooleanField(default=False, verbose_name="Investitionen bearbeiten", help_text="Benutzer darf Investitionen ändern.")
#invests_delete = models.BooleanField(default=False, verbose_name="Investitionen löschen", help_text="Benutzer darf Investitionen entfernen.")
class Meta:
verbose_name = "Rolle"
verbose_name_plural = "Rollen"
def __str__(self):
return self.name
class UserProfile(models.Model):
user = models.OneToOneField(
User,
on_delete=models.CASCADE,
related_name="profile"
)
role = models.ForeignKey(
Role,
on_delete=models.SET_NULL,
null=True,
blank=True
)
def has_permission(self, permission):
if self.user.is_superuser:
return True
if not self.role:
return False
return getattr(
self.role,
permission.replace(".", "_"),
False
)
def __str__(self):
return self.user.username
+102
View File
@@ -0,0 +1,102 @@
import django_tables2 as tables
from django.contrib.auth.models import User
from .models import Role
class RoleTable(tables.Table):
toggle_prefix = "role"
detail_template = "accounts/tables/user/role_edit_form.html"
name = tables.Column(
verbose_name="Rolle"
)
class Meta:
model = Role
template_name = "django_tables2/table_toggle.html"
fields = (
"name",
)
attrs = {
"class": "w-full text-sm min-w-[700px]"
}
class ArchivedUserTable(tables.Table):
toggle_prefix = "user"
detail_template = "accounts/tables/user/archive_edit_form.html"
username = tables.Column(
verbose_name="Benutzername"
)
first_name = tables.Column(
verbose_name="Vorname"
)
last_name = tables.Column(
verbose_name="Nachname"
)
email = tables.Column(
verbose_name="E-Mail"
)
role = tables.TemplateColumn(
template_name="accounts/tables/user/role.html",
verbose_name="Rolle",
orderable=False
)
superuser = tables.TemplateColumn(
template_name="accounts/tables/user/superuser.html",
verbose_name="Superuser",
orderable=False
)
class Meta:
model = User
template_name = "django_tables2/table_toggle.html"
fields = (
"username",
"first_name",
"last_name",
"email",
"role",
"superuser",
)
attrs = {
"class": "w-full text-sm min-w-[700px]"
}
class UserTable(tables.Table):
toggle_prefix = "user"
detail_template = "accounts/tables/user/edit_form.html"
username = tables.Column(
verbose_name="Benutzername"
)
first_name = tables.Column(
verbose_name="Vorname"
)
last_name = tables.Column(
verbose_name="Nachname"
)
email = tables.Column(
verbose_name="E-Mail"
)
role = tables.TemplateColumn(
template_name="accounts/tables/user/role.html",
verbose_name="Rolle",
orderable=False
)
superuser = tables.TemplateColumn(
template_name="accounts/tables/user/superuser.html",
verbose_name="Superuser",
orderable=False
)
class Meta:
model = User
template_name = "django_tables2/table_toggle.html"
fields = (
"username",
"first_name",
"last_name",
"email",
"role",
"superuser",
)
attrs = {
"class": "w-full text-sm min-w-[700px]"
}
+36
View File
@@ -0,0 +1,36 @@
{% extends "base.html" %}
{% block title %}
Mitarbeiter
{% endblock %}
{% block header_title %}
Mitarbeiter hinzufügen
{% endblock %}
{% block header_description %}
Neuen Mitarbeiter anlegen
{% endblock %}
{% block content %}
<div class="p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors mb-8">
<form method="post" enctype="multipart/form-data" class="space-y-4">
{% csrf_token %}
<div class="grid grid-cols-1 gap-4">
{{ form.as_p }}
</div>
<button
type="submit"
class="btn mt-4 btn-save">
Speichern
</button>
</form>
</div>
{% endblock %}
+68
View File
@@ -0,0 +1,68 @@
{% extends "base.html" %}
{% block title %}
Login
{% endblock %}
{% block header_title %}
<div class="flex justify-center">
{% if company_settings.logo %}
<img src="{{ company_settings.logo.url }}" alt="" class="h-32">
{% elif company_settings.companyname %}
{{ company_settings.companyname }}
{% else %}
Projektverwaltung
{% endif %}
</div>
{% endblock %}
{% block header_description %}
{% endblock %}
{% block content %}
<div class="flex justify-center items-center min-h-[80vh]">
<div class="p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors w-full max-w-md">
<h1 class="text-3xl font-bold text-center mb-6">
Anmelden
</h1>
<form method="post" class="space-y-4">
{% csrf_token %}
{% for field in form %}
<div class="space-y-1">
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300">
{{ field.label }}
</label>
<input
type="{{ field.field.widget.input_type }}"
name="{{ field.html_name }}"
id="{{ field.id_for_label }}"
{% if field.value %}value="{{ field.value }}"{% endif %}
class="w-full px-4 py-3 rounded-lg border border-slate-300 dark:border-slate-600 bg-slate-50 dark:bg-slate-700 text-slate-900 dark:text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition"
placeholder="{{ field.label }}"
>
{% if field.errors %}
<p class="text-sm text-red-500">{{ field.errors|join:", " }}</p>
{% endif %}
</div>
{% endfor %}
<button
type="submit"
class="btn w-full btn-action"
>
Anmelden
</button>
</form>
</div>
</div>
{% endblock %}
+100
View File
@@ -0,0 +1,100 @@
{% extends "base.html" %}
{% block title %}
Mitarbeiter
{% endblock %}
{% block header_title %}
Mitarbeiter
{% endblock %}
{% block header_description %}
Mitarbeiter, Rollen und Berechtigungen verwalten
{% endblock %}
{% block content %}
{% load django_tables2 %}
<div class="mb-8">
<div class="p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4">
<div>
<h2 class="text-xl font-bold">Aktionen</h2>
<p class="text-slate-400 text-sm mt-1">Mitarbeiter oder Rollen hinzufügen</p>
</div>
<div class="flex flex-col sm:flex-row gap-2">
<a href="{% url 'accounts:user_add' %}" class="btn btn-add">+ Mitarbeiter</a>
<a href="{% url 'accounts:role_add' %}" class="btn btn-add">+ Rolle</a>
</div>
</div>
</div>
</div>
<div class="p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors mb-8">
<div class="mb-6">
<h2 class="text-xl font-bold">
Benutzer
</h2>
<p class="text-slate-400 text-sm mt-1">
Aktive Benutzer mit Rollen und Berechtigungen
</p>
</div>
<div class="overflow-x-auto rounded-xl">
{% render_table table %}
</div>
</div>
<div class="p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors mb-8">
<div class="mb-6">
<h2 class="text-xl font-bold">
Archivierte Benutzer
</h2>
<p class="text-slate-400 text-sm mt-1">
Deaktivierte Benutzer
</p>
</div>
<div class="overflow-x-auto rounded-xl">
{% render_table archived_table %}
</div>
</div>
<div class="p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors mt-8">
<div class="mb-6">
<h2 class="text-xl font-bold">
Rollen
</h2>
<p class="text-slate-400 text-sm mt-1">
Rollen und Berechtigungen verwalten
</p>
</div>
<div class="overflow-x-auto rounded-xl">
{% render_table role_table %}
</div>
</div>
{% endblock %}
+36
View File
@@ -0,0 +1,36 @@
{% extends "base.html" %}
{% block title %}
Mitarbeiter
{% endblock %}
{% block header_title %}
Rolle hinzufügen
{% endblock %}
{% block header_description %}
Neue Rolle anlegen
{% endblock %}
{% block content %}
<div class="p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors mb-8">
<form method="post" enctype="multipart/form-data" class="space-y-4">
{% csrf_token %}
<div class="grid grid-cols-1 gap-4">
{{ form.as_p }}
</div>
<button
type="submit"
class="btn mt-4 btn-save">
Speichern
</button>
</form>
</div>
{% endblock %}
@@ -0,0 +1,121 @@
<form method="post" action="{% url 'accounts:user_edit' item.id %}">
{% csrf_token %}
<div>
<div class="grid md:grid-cols-2 xl:grid-cols-3 gap-4">
<div>
<label class="block text-sm mb-1">
Benutzername
</label>
<input
type="text"
name="username"
value="{{ item.username }}"
class="border rounded px-3 py-2 w-full">
</div>
<div>
<label class="block text-sm mb-1">
Vorname
</label>
<input
type="text"
name="first_name"
value="{{ item.first_name }}"
class="border rounded px-3 py-2 w-full">
</div>
<div>
<label class="block text-sm mb-1">
Nachname
</label>
<input
type="text"
name="last_name"
value="{{ item.last_name }}"
class="border rounded px-3 py-2 w-full">
</div>
<div>
<label class="block text-sm mb-1">
E-Mail
</label>
<input
type="email"
name="email"
value="{{ item.email }}"
class="border rounded px-3 py-2 w-full">
</div>
<div>
<label class="block text-sm mb-1">
Rolle
</label>
<select
name="role"
class="border rounded px-3 py-2 w-full">
<option value="">
---
</option>
{% for role in table.roles %}
<option
value="{{ role.id }}"
{% if item.profile.role_id == role.id %}selected{% endif %}>
{{ role.name }}
</option>
{% endfor %}
</select>
</div>
<div>
<label class="block text-sm mb-1">
Letzter Login
</label>
<input
type="text"
disabled
value="{{ item.last_login|date:'d.m.Y H:i' }}"
class="border rounded px-3 py-2 w-full bg-slate-100">
</div>
</div>
<div class="mt-5 flex gap-2">
<button
type="submit"
class="btn btn-save">
Speichern
</button>
<button
type="submit"
formaction="{% url 'accounts:user_reactivate' item.id %}"
class="btn btn-action">
Aktivieren
</button>
</div>
</div>
</form>
@@ -0,0 +1,121 @@
<form method="post" action="{% url 'accounts:user_edit' item.id %}">
{% csrf_token %}
<div>
<div class="grid md:grid-cols-2 xl:grid-cols-3 gap-4">
<div>
<label class="block text-sm mb-1">
Benutzername
</label>
<input
type="text"
name="username"
value="{{ item.username }}"
class="border rounded px-3 py-2 w-full">
</div>
<div>
<label class="block text-sm mb-1">
Vorname
</label>
<input
type="text"
name="first_name"
value="{{ item.first_name }}"
class="border rounded px-3 py-2 w-full">
</div>
<div>
<label class="block text-sm mb-1">
Nachname
</label>
<input
type="text"
name="last_name"
value="{{ item.last_name }}"
class="border rounded px-3 py-2 w-full">
</div>
<div>
<label class="block text-sm mb-1">
E-Mail
</label>
<input
type="email"
name="email"
value="{{ item.email }}"
class="border rounded px-3 py-2 w-full">
</div>
<div>
<label class="block text-sm mb-1">
Rolle
</label>
<select
name="role"
class="border rounded px-3 py-2 w-full">
<option value="">
---
</option>
{% for role in table.roles %}
<option
value="{{ role.id }}"
{% if item.profile.role_id == role.id %}selected{% endif %}>
{{ role.name }}
</option>
{% endfor %}
</select>
</div>
<div>
<label class="block text-sm mb-1">
Letzter Login
</label>
<input
type="text"
disabled
value="{{ item.last_login|date:'d.m.Y H:i' }}"
class="border rounded px-3 py-2 w-full bg-slate-100">
</div>
</div>
<div class="mt-5 flex gap-2">
<button
type="submit"
class="btn btn-save">
Speichern
</button>
<button
type="submit"
formaction="{% url 'accounts:user_archive' item.id %}"
class="btn btn-action">
Archivieren
</button>
</div>
</div>
</form>
@@ -0,0 +1 @@
{{ record.profile.role.name|default:"-" }}
@@ -0,0 +1,63 @@
<form method="post" action="{% url 'accounts:role_edit' item.id %}">
{% csrf_token %}
<div>
<h3 class="font-bold mb-4">
Berechtigungen
</h3>
<div class="grid md:grid-cols-2 xl-grid-cols-3 gap-4">
{% for permission in item.permissions %}
<label class="
bg-slate-100 dark:bg-slate-700
rounded-xl
p-3
flex
items-center
gap-3
">
<input
type="checkbox"
name="{{ permission.name }}"
{% if permission.value %}
checked
{% endif %}
class="w-4 h-4">
<span>
{{ permission.verbose_name }}
</span>
</label>
{% endfor %}
</div>
<div class="mt-5 flex gap-2">
<button
type="submit"
class="btn btn-save">
Speichern
</button>
<button
type="submit"
formaction="{% url 'accounts:role_delete' item.id %}"
class="btn btn-delete">
Löschen
</button>
</div>
</div>
</form>
@@ -0,0 +1,5 @@
{% if record.is_superuser %}
Ja
{% else %}
Nein
{% endif %}
+3
View File
@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.
+19
View File
@@ -0,0 +1,19 @@
from django.urls import path
from . import views
app_name = "accounts"
urlpatterns = [
path("login/", views.CustomLoginView.as_view(), name="login"),
path("logout/", views.CustomLogoutView.as_view(), name="logout"),
path("", views.overview, name="overview"),
path("add/",views.user_add,name="user_add"),
path("<int:user_id>/edit/",views.user_edit,name="user_edit"),
path("<int:user_id>/archive/",views.user_archive,name="user_archive"),
path("<int:user_id>/reactivate/",views.user_reactivate,name="user_reactivate"),
path("role/add/",views.role_add,name="role_add"),
path("role/<int:role_id>/edit/",views.role_edit,name="role_edit"),
path("role/<int:role_id>/delete/",views.role_delete,name="role_delete"),
]
+398
View File
@@ -0,0 +1,398 @@
from django.contrib.auth.views import LoginView, LogoutView
from django.contrib.auth.decorators import login_required
from accounts.decorators import permission_required
from django.contrib.auth.models import User
from django.shortcuts import render, redirect, get_object_or_404
from .forms import UserAddForm, RoleForm
from .models import Role, UserProfile
from .tables import UserTable, ArchivedUserTable, RoleTable
from django_tables2 import RequestConfig
class CustomLoginView(LoginView):
template_name = "accounts/login.html"
redirect_authenticated_user = True
class CustomLogoutView(LogoutView):
pass
@login_required
@permission_required("users_view")
def overview(request):
users = (
User.objects
.filter(is_active=True)
.select_related(
"profile",
"profile__role"
)
.order_by("username")
)
archived_users = (
User.objects
.filter(is_active=False)
.select_related(
"profile",
"profile__role"
)
.order_by("username")
)
roles = list(
Role.objects.order_by("name")
)
# ==================================================
# ROLE PERMISSIONS FÜR CHECKBOXEN
# ==================================================
permission_fields = []
for field in Role._meta.fields:
if field.get_internal_type() == "BooleanField":
permission_fields.append({
"name": field.name,
"verbose_name": field.verbose_name or field.name
})
for role in roles:
role.permissions = []
for permission in permission_fields:
role.permissions.append({
"name": permission["name"],
"verbose_name": permission["verbose_name"],
"value": getattr(
role,
permission["name"]
)
})
# ==================================================
# USER ROLLEN-PERMISSIONS
# ==================================================
for user in list(users) + list(archived_users):
role = getattr(
getattr(user, "profile", None),
"role",
None
)
user.role_permissions = []
if role:
for permission in permission_fields:
if getattr(
role,
permission["name"]
):
user.role_permissions.append(
permission["verbose_name"]
)
# ==================================================
# TABLES
# ==================================================
table = UserTable(users)
table.roles = roles
RequestConfig(
request,
paginate=False
).configure(table)
archived_table = ArchivedUserTable(archived_users)
archived_table.roles = roles
RequestConfig(
request,
paginate=False
).configure(archived_table)
role_table = RoleTable(roles)
role_table.roles = roles
RequestConfig(
request,
paginate=False
).configure(role_table)
return render(
request,
"accounts/overview.html",
{
"table": table,
"archived_table": archived_table,
"role_table": role_table,
}
)
@login_required
@permission_required("users_edit")
def user_edit(request, user_id):
user = get_object_or_404(
User.objects.select_related(
"profile"
),
id=user_id
)
if user.is_superuser:
return redirect("accounts:overview")
if request.method != "POST":
return redirect("accounts:overview")
# -------------------------
# USER
# -------------------------
user.username = request.POST.get(
"username",
user.username
)
user.first_name = request.POST.get(
"first_name",
user.first_name
)
user.last_name = request.POST.get(
"last_name",
user.last_name
)
user.email = request.POST.get(
"email",
user.email
)
user.save()
# -------------------------
# PROFILE / ROLE
# -------------------------
profile, _ = UserProfile.objects.get_or_create(
user=user
)
role_id = request.POST.get("role")
if role_id:
profile.role_id = role_id
else:
profile.role = None
profile.save()
return redirect(
"accounts:overview"
)
@login_required
@permission_required("users_archive")
def user_archive(request, user_id):
user = get_object_or_404(
User,
id=user_id
)
if user.is_superuser:
return redirect("accounts:overview")
if request.method == "POST":
user.is_active = False
user.save()
return redirect("accounts:overview")
@login_required
@permission_required("users_activate")
def user_reactivate(request, user_id):
user = get_object_or_404(
User,
id=user_id
)
if user.is_superuser:
return redirect("accounts:overview")
if request.method == "POST":
user.is_active = True
user.save()
return redirect("accounts:overview")
@login_required
@permission_required("users_add")
def user_add(request):
form = UserAddForm(
request.POST or None
)
if form.is_valid():
user = form.save(commit=False)
password = form.cleaned_data["password"]
user.set_password(password)
user.save()
UserProfile.objects.create(
user=user,
role=form.cleaned_data["role"]
)
return redirect(
"accounts:overview"
)
return render(
request,
"accounts/add.html",
{
"form": form
}
)
def get_role_permissions():
fields = []
for field in Role._meta.fields:
if field.get_internal_type() == "BooleanField":
fields.append({
"name": field.name,
"label": field.verbose_name or field.name
})
return fields
@login_required
@permission_required("users_groups_edit")
def role_edit(request, role_id):
role = get_object_or_404(
Role,
id=role_id
)
if request.method == "POST":
for field in Role._meta.fields:
if (
field.get_internal_type()
== "BooleanField"
):
setattr(
role,
field.name,
field.name in request.POST
)
role.name = request.POST.get(
"name",
role.name
)
role.save()
return redirect(
"accounts:overview"
)
@login_required
@permission_required("users_groups_delete")
def role_delete(request, role_id):
role = get_object_or_404(
Role,
id=role_id
)
if request.method == "POST":
role.delete()
return redirect(
"accounts:overview"
)
@login_required
@permission_required("users_groups_add")
def role_add(request):
if request.method == "POST":
form = RoleForm(
request.POST
)
if form.is_valid():
form.save()
return redirect(
"accounts:overview"
)
else:
form = RoleForm()
return render(
request,
"accounts/role_add.html",
{
"form": form
}
)