Semaine 11

This commit is contained in:
gauvainboiche
2026-07-11 21:38:00 +02:00
parent d3d2416dea
commit 0d071d2843
281 changed files with 54412 additions and 0 deletions
View File
+4
View File
@@ -0,0 +1,4 @@
from django.contrib import admin
from .models import Equipment
admin.site.register(Equipment)
+5
View File
@@ -0,0 +1,5 @@
from django.apps import AppConfig
class ParcConfig(AppConfig):
name = 'parc'
+12
View File
@@ -0,0 +1,12 @@
from django import forms
from .models import Equipment
class EquipmentForm(forms.ModelForm):
class Meta:
model = Equipment
fields = ["hostname", "ip", "is_active"]
widgets = {
"hostname": forms.TextInput(attrs={"class": "form-control"}),
"ip": forms.TextInput(attrs={"class": "form-control"}),
"is_active": forms.CheckboxInput(attrs={"class": "form-check-input"}),
}
@@ -0,0 +1,28 @@
# Generated by Django 6.0.7 on 2026-07-10 10:25
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='Equipment',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('hostname', models.CharField(max_length=200)),
('ip', models.GenericIPAddressField()),
('is_active', models.BooleanField(default=True)),
('internal_notes', models.TextField(blank=True, default='')),
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
+15
View File
@@ -0,0 +1,15 @@
from django.db import models
from django.conf import settings
class Equipment(models.Model):
hostname = models.CharField(max_length=200)
ip = models.GenericIPAddressField()
is_active = models.BooleanField(default=True)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
internal_notes = models.TextField(blank=True, default="")
def __str__(self):
if self.is_active:
return f"{self.hostname} - {self.ip}"
else:
return f"{self.hostname} is DOWN."
+5
View File
@@ -0,0 +1,5 @@
from rest_framework import permissions
class IsOwner(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
return obj.owner == request.user
+8
View File
@@ -0,0 +1,8 @@
from rest_framework import serializers
from .models import Equipment
class EquipmentSerializer(serializers.ModelSerializer):
class Meta:
model = Equipment
fields = ["id", "hostname", "ip", "is_active", "owner"]
read_only_fields = ["owner"]
+3
View File
@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.
+15
View File
@@ -0,0 +1,15 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views
router = DefaultRouter()
router.register(r'equipments', views.EquipmentViewSet, basename='equipment')
urlpatterns = [
path("api/", include(router.urls)),
path("equipments/", views.EquipmentListView.as_view(), name="equipment_list"),
path("equipments/create/", views.EquipmentCreateView.as_view(), name="equipment_create"),
path("equipments/<int:pk>/", views.EquipmentDetailView.as_view(), name="equipment_detail"),
path("equipments/<int:pk>/update/", views.EquipmentUpdateView.as_view(), name="equipment_update"),
path("equipments/<int:pk>/delete/", views.EquipmentDeleteView.as_view(), name="equipment_delete"),
]
+120
View File
@@ -0,0 +1,120 @@
from django.shortcuts import render
from django.urls import reverse_lazy
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
from rest_framework import viewsets, status, permissions
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Equipment
from .serializers import EquipmentSerializer
from .forms import EquipmentForm
from .permissions import IsOwner
@login_required
def list_active_equipments(request):
equipments = Equipment.objects.filter(is_active=True)
return render(request, "parc/list.html", {"equipments": equipments})
@method_decorator(login_required, name="dispatch")
class EquipmentListView(ListView):
model = Equipment
template_name = "parc/list.html"
context_object_name = "equipments"
def get_queryset(self):
return Equipment.objects.filter(is_active=True)
@method_decorator(login_required, name="dispatch")
class EquipmentDetailView(DetailView):
model = Equipment
template_name = "parc/detail.html"
context_object_name = "equipment"
@method_decorator(login_required, name="dispatch")
class EquipmentCreateView(CreateView):
model = Equipment
form_class = EquipmentForm
template_name = "parc/form.html"
success_url = reverse_lazy("equipment_list")
@method_decorator(login_required, name="dispatch")
class EquipmentUpdateView(UpdateView):
model = Equipment
form_class = EquipmentForm
template_name = "parc/form.html"
success_url = reverse_lazy("equipment_list")
@method_decorator(login_required, name="dispatch")
class EquipmentDeleteView(DeleteView):
model = Equipment
template_name = "parc/delete_confirm.html"
success_url = reverse_lazy("equipment_list")
class EquipmentListAPIView(APIView):
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def get(self, request):
equipments = Equipment.objects.all()
serializer = EquipmentSerializer(equipments, many=True)
return Response(serializer.data)
def post(self, request):
serializer = EquipmentSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class EquipmentViewSet(viewsets.ModelViewSet):
"""
Ce ViewSet fournit automatiquement les actions :
- 'list' (GET /equipments/)
- 'retrieve' (GET /equipments/{id}/)
- 'create' (POST /equipments/)
- 'update' (PUT /equipments/{id}/)
- 'destroy' (DELETE /equipments/{id}/)
"""
permission_classes = [permissions.IsAuthenticated, IsOwner]
def get_queryset(self):
return Equipment.objects.filter(owner=self.request.user)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
# queryset = Equipment.objects.all()
serializer_class = EquipmentSerializer
import logging
logger = logging.getLogger("parc.auth")
class EquipmentViewSet(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticated, IsOwner]
def get_queryset(self):
return Equipment.objects.filter(owner=self.request.user)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
def handle_exception(self, exc):
response = super().handle_exception(exc)
if response.status_code in (401, 403):
logger.warning(
"Authentication failure: user=%s path=%s method=%s status=%s",
getattr(self.request.user, "username", "anonymous"),
self.request.path,
self.request.method,
response.status_code,
)
return response
serializer_class = EquipmentSerializer