Coverage for src/meshadmin/server/networks/views/group.py: 62%
130 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-10 16:08 +0200
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-10 16:08 +0200
1from django.conf import settings
2from django.contrib.auth.mixins import LoginRequiredMixin
3from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
4from django.db import models
5from django.shortcuts import get_object_or_404, render
6from django.urls import reverse_lazy
7from django.views.generic import CreateView, DeleteView, DetailView, UpdateView, View
9from meshadmin.server.networks.forms import GroupForm, RuleForm
10from meshadmin.server.networks.mixins import NetworkPermissionMixin
11from meshadmin.server.networks.models import Group, Network, Rule
14class GroupDetailView(LoginRequiredMixin, NetworkPermissionMixin, DetailView):
15 model = Group
16 template_name = "networks/group/detail.html"
18 def get_network(self):
19 return self.get_object().network
21 def get_context_data(self, **kwargs):
22 context = super().get_context_data(**kwargs)
23 hosts = self.object.host_set.all()
24 search = self.request.GET.get("search", "")
25 if search:
26 hosts = hosts.filter(name__icontains=search)
28 if self.request.GET.get("stale_config"):
29 from datetime import timedelta
31 from django.utils import timezone
33 stale_threshold = timezone.now() - timedelta(hours=24)
34 hosts = hosts.filter(
35 models.Q(last_config_refresh__lt=stale_threshold)
36 | models.Q(last_config_refresh__isnull=True)
37 )
39 per_page = int(self.request.GET.get("per_page", settings.PAGINATION_PER_PAGE))
40 paginator = Paginator(hosts, per_page)
41 page = self.request.GET.get("hosts_page", 1)
43 try:
44 hosts = paginator.page(page)
45 except (PageNotAnInteger, EmptyPage):
46 hosts = paginator.page(1)
48 context.update(
49 {
50 "hosts": hosts,
51 "paginator": paginator,
52 "page_obj": hosts,
53 "per_page": per_page,
54 "per_page_options": [25, 50, 100],
55 "network": self.object.network,
56 "fields": [
57 {
58 "name": field.name,
59 "verbose_name": field.verbose_name,
60 "value": getattr(self.object, field.name),
61 }
62 for field in self.model._meta.fields
63 ],
64 "rules": self.object.rules.all(),
65 }
66 )
67 return context
69 def get_template_names(self):
70 if self.request.htmx:
71 return ["networks/network/_hosts_table.html"]
72 return [self.template_name]
75class GroupCreateView(LoginRequiredMixin, NetworkPermissionMixin, CreateView):
76 model = Group
77 form_class = GroupForm
78 template_name = "networks/group/form.html"
80 def get_network(self):
81 return get_object_or_404(Network, id=self.kwargs.get("network_id"))
83 def form_valid(self, form):
84 response = super().form_valid(form)
85 if self.request.htmx:
86 context = self.get_context_data()
87 context["object"] = self.object
88 context["action"] = "Update"
89 return render(self.request, "networks/group/_form_content.html", context)
90 return response
92 def get_success_url(self):
93 return reverse_lazy("networks:group-detail", kwargs={"pk": self.object.pk})
95 def get_form_kwargs(self):
96 kwargs = super().get_form_kwargs()
97 network_id = self.kwargs.get("network_id")
98 if network_id:
99 network = get_object_or_404(Network, id=network_id)
100 kwargs["network"] = network
101 return kwargs
103 def get_context_data(self, **kwargs):
104 context = super().get_context_data(**kwargs)
105 context.update(
106 {
107 "action": "Create",
108 "model_name": self.model._meta.verbose_name,
109 "network_id": self.kwargs.get("network_id"),
110 }
111 )
112 return context
115class GroupUpdateView(LoginRequiredMixin, NetworkPermissionMixin, UpdateView):
116 model = Group
117 form_class = GroupForm
118 template_name = "networks/group/form.html"
120 def get_network(self):
121 return self.get_object().network
123 def get_context_data(self, **kwargs):
124 context = super().get_context_data(**kwargs)
125 context.update(
126 {
127 "action": "Update",
128 "network_id": self.get_object().network.id,
129 "rules": self.get_object().rules.all(),
130 }
131 )
132 return context
134 def form_valid(self, form):
135 response = super().form_valid(form)
136 if self.request.htmx:
137 context = self.get_context_data()
138 context["object"] = self.object
139 context["action"] = "Update"
140 return render(self.request, "networks/group/_form_content.html", context)
141 return response
143 def get_success_url(self):
144 return reverse_lazy("networks:group-detail", kwargs={"pk": self.object.pk})
147class GroupDeleteView(LoginRequiredMixin, NetworkPermissionMixin, DeleteView):
148 model = Group
149 template_name = "networks/shared/delete.html"
151 def get_network(self):
152 return self.get_object().network
154 def get_success_url(self):
155 return (
156 reverse_lazy(
157 "networks:network-detail", kwargs={"pk": self.object.network.pk}
158 )
159 + "#groups-section"
160 )
162 def get_context_data(self, **kwargs):
163 context = super().get_context_data(**kwargs)
164 context["model_name"] = self.model._meta.verbose_name
165 return context
168class RuleFormModalView(LoginRequiredMixin, NetworkPermissionMixin, View):
169 def get_network(self):
170 group = get_object_or_404(Group, id=self.request.GET.get("group"))
171 return group.network
173 def get(self, request):
174 group_id = request.GET.get("group")
175 rule_id = request.GET.get("rule")
176 security_group = get_object_or_404(Group, id=group_id)
178 if rule_id:
179 rule = get_object_or_404(Rule, id=rule_id)
180 form = RuleForm(instance=rule)
181 else:
182 form = RuleForm(
183 initial={"security_group": security_group},
184 instance=Rule(security_group=security_group),
185 )
187 return render(
188 request,
189 "networks/rule/_form_modal.html",
190 {
191 "form": form,
192 "security_group": security_group,
193 "rule": rule if rule_id else None,
194 },
195 )
198class GroupAddRuleView(LoginRequiredMixin, NetworkPermissionMixin, View):
199 def get_network(self):
200 group_id = self.request.POST.get("security_group")
201 group = get_object_or_404(Group, id=group_id)
202 return group.network
204 def post(self, request):
205 group_id = request.POST.get("security_group")
206 security_group = get_object_or_404(Group, id=group_id)
208 form = RuleForm(request.POST, initial={"security_group_id": group_id})
209 if form.is_valid():
210 rule = form.save(commit=False)
211 rule.security_group = security_group
212 rule.save()
214 if request.POST.getlist("groups"):
215 rule.groups.set(
216 Group.objects.filter(id__in=request.POST.getlist("groups"))
217 )
219 context = {"rules": Rule.objects.filter(security_group=security_group)}
220 return render(
221 request,
222 "networks/group/_rules_list.html",
223 context,
224 )
225 else:
226 response = render(
227 request,
228 "networks/rule/_form_modal.html",
229 {
230 "form": form,
231 "security_group": security_group,
232 },
233 )
234 response["HX-Retarget"] = "#modal-content"
235 return response