1 from django.urls import resolve, reverse

2

3 from meshadmin.server.networks.models import (

4 CA,

5 ConfigRollout,

6 Group,

7 Host,

8 Network,

9 Rule,

10 Template,

11)

12

13

14 class BreadcrumbMiddleware:

15 def __init__(self, get_response):

16 self.get_response = get_response

17

18 def __call__(self, request):

19 response = self.get_response(request)

20 return response

21

22 def process_template_response(self, request, response):

23 if request.htmx:

24 return response

25

26 if not hasattr(response, "context_data"):

27 return response

28

29 # Start with the base networks link

30 breadcrumbs = [{"label": "Networks", "url": reverse("networks:network-list")}]

31

32 # Get resolved URL info

33 resolved = resolve(request.path_info)

34 url_name = resolved.url_name

35 kwargs = resolved.kwargs

36 context = response.context_data

37

38 # Handle network-specific paths

39 if "pk" in kwargs and url_name in [

40 "network-detail",

41 "network-edit",

42 "network-delete",

43 ]:

44 network_id = kwargs["pk"]

45 network = self._get_network_by_id(network_id, context)

46 if network:

47 breadcrumbs.append(

48 {

49 "label": network.name,

50 "url": reverse(

51 "networks:network-detail", kwargs={"pk": network.pk}

52 ),

53 }

54 )

55 if url_name == "network-edit":

56 breadcrumbs.append({"label": "Edit", "url": "#"})

57 elif url_name == "network-delete":

58 breadcrumbs.append({"label": "Delete", "url": "#"})

59

60 # Handle network creation

61 elif url_name == "network-create":

62 breadcrumbs.append({"label": "Create Network", "url": "#"})

63

64 # Handle network-related entities (host, template, group, ca, rollout, membership)

65 elif "network_id" in kwargs:

66 network_id = kwargs["network_id"]

67 network = self._get_network_by_id(network_id, context)

68

69 if network:

70 # Add network link with appropriate section anchor

71 section_anchor = ""

72 if "host" in url_name:

73 section_anchor = "#hosts-section"

74 elif "template" in url_name:

75 section_anchor = "#templates-section"

76 elif "group" in url_name or "security-group" in url_name:

77 section_anchor = "#groups-section"

78 elif "ca" in url_name:

79 section_anchor = "#cas-section"

80 elif "rollout" in url_name:

81 section_anchor = "#rollouts-section"

82 elif "member" in url_name or "member" in url_name:

83 section_anchor = "#members-section"

84

85 breadcrumbs.append(

86 {

87 "label": network.name,

88 "url": reverse(

89 "networks:network-detail", kwargs={"pk": network.pk}

90 )

91 + section_anchor,

92 }

93 )

94

95 # Add entity-specific breadcrumbs based on URL pattern

96 if "host" in url_name:

97 breadcrumbs.append({"label": "Create Host", "url": "#"})

98 elif "template" in url_name:

99 breadcrumbs.append({"label": "Create Template", "url": "#"})

100 elif "group" in url_name:

101 breadcrumbs.append({"label": "Create Group", "url": "#"})

102 elif "ca" in url_name:

103 breadcrumbs.append({"label": "Create CA", "url": "#"})

104 elif "rollout" in url_name:

105 breadcrumbs.append({"label": "Create Rollout", "url": "#"})

106 elif "add" in url_name:

107 breadcrumbs.append({"label": "Add Member", "url": "#"})

108

109 # Handle entity-specific paths (without network_id in URL)

110 elif "pk" in kwargs:

111 entity_id = kwargs["pk"]

112

113 # Handle Host

114 if url_name in [

115 "host-detail",

116 "host-edit",

117 "host-delete",

118 ]:

119 host = self._get_object_by_id(Host, entity_id, context)

120 if host:

121 network = host.network

122 breadcrumbs.append(

123 {

124 "label": network.name,

125 "url": reverse(

126 "networks:network-detail", kwargs={"pk": network.pk}

127 )

128 + "#hosts-section",

129 }

130 )

131 breadcrumbs.append(

132 {

133 "label": host.name,

134 "url": reverse(

135 "networks:host-detail", kwargs={"pk": host.pk}

136 ),

137 }

138 )

139

140 # Add action breadcrumb

141 if "edit" in url_name:

142 breadcrumbs.append({"label": "Edit", "url": "#"})

143 elif "delete" in url_name:

144 breadcrumbs.append({"label": "Delete", "url": "#"})

145

146 # Handle Template

147 elif url_name in ["template-detail", "template-edit", "template-delete"]:

148 template = self._get_object_by_id(Template, entity_id, context)

149 if template:

150 network = template.network

151 breadcrumbs.append(

152 {

153 "label": network.name,

154 "url": reverse(

155 "networks:network-detail", kwargs={"pk": network.pk}

156 )

157 + "#templates-section",

158 }

159 )

160 breadcrumbs.append(

161 {

162 "label": template.name,

163 "url": reverse(

164 "networks:template-detail", kwargs={"pk": template.pk}

165 ),

166 }

167 )

168

169 # Add action breadcrumb

170 if "edit" in url_name:

171 breadcrumbs.append({"label": "Edit", "url": "#"})

172 elif "delete" in url_name:

173 breadcrumbs.append({"label": "Delete", "url": "#"})

174

175 # Handle Group

176 elif url_name in ["group-detail", "group-edit", "group-delete"]:

177 group = self._get_object_by_id(Group, entity_id, context)

178 if group:

179 network = group.network

180 breadcrumbs.append(

181 {

182 "label": network.name,

183 "url": reverse(

184 "networks:network-detail", kwargs={"pk": network.pk}

185 )

186 + "#groups-section",

187 }

188 )

189 breadcrumbs.append(

190 {

191 "label": group.name,

192 "url": reverse(

193 "networks:group-detail", kwargs={"pk": group.pk}

194 ),

195 }

196 )

197

198 # Add action breadcrumb

199 if "edit" in url_name:

200 breadcrumbs.append({"label": "Edit", "url": "#"})

201 elif "delete" in url_name:

202 breadcrumbs.append({"label": "Delete", "url": "#"})

203

204 # Handle CA

205 elif url_name in ["ca-detail", "ca-edit", "ca-delete"]:

206 ca = self._get_object_by_id(CA, entity_id, context)

207 if ca:

208 network = ca.network

209 breadcrumbs.append(

210 {

211 "label": network.name,

212 "url": reverse(

213 "networks:network-detail", kwargs={"pk": network.pk}

214 )

215 + "#cas-section",

216 }

217 )

218 breadcrumbs.append(

219 {

220 "label": ca.name,

221 "url": reverse("networks:ca-detail", kwargs={"pk": ca.pk}),

222 }

223 )

224

225 # Add action breadcrumb

226 if "edit" in url_name:

227 breadcrumbs.append({"label": "Edit", "url": "#"})

228 elif "delete" in url_name:

229 breadcrumbs.append({"label": "Delete", "url": "#"})

230

231 # Handle Rule

232 elif url_name in ["rule-detail", "rule-edit", "rule-delete"]:

233 rule = self._get_object_by_id(Rule, entity_id, context)

234 if rule:

235 security_group = rule.security_group

236 network = security_group.network

237 breadcrumbs.append(

238 {

239 "label": network.name,

240 "url": reverse(

241 "networks:network-detail", kwargs={"pk": network.pk}

242 )

243 + "#groups-section",

244 }

245 )

246 if security_group:

247 breadcrumbs.append(

248 {

249 "label": security_group.name,

250 "url": reverse(

251 "networks:group-detail",

252 kwargs={"pk": security_group.pk},

253 ),

254 }

255 )

256 breadcrumbs.append(

257 {

258 "label": f"Rule {rule.pk}",

259 "url": reverse(

260 "networks:rule-detail", kwargs={"pk": rule.pk}

261 ),

262 }

263 )

264

265 # Add action breadcrumb

266 if "edit" in url_name:

267 breadcrumbs.append({"label": "Edit", "url": "#"})

268 elif "delete" in url_name:

269 breadcrumbs.append({"label": "Delete", "url": "#"})

270

271 # Handle Rollout

272 elif url_name in [

273 "rollout-detail",

274 "rollout-edit",

275 "rollout-delete",

276 ]:

277 rollout = self._get_object_by_id(ConfigRollout, entity_id, context)

278 if rollout:

279 network = rollout.network

280 breadcrumbs.append(

281 {

282 "label": network.name,

283 "url": reverse(

284 "networks:network-detail", kwargs={"pk": network.pk}

285 )

286 + "#rollouts-section",

287 }

288 )

289 breadcrumbs.append(

290 {

291 "label": f"Rollout {rollout.pk}",

292 "url": reverse(

293 "networks:rollout-detail", kwargs={"pk": rollout.pk}

294 ),

295 }

296 )

297

298 # Add action breadcrumb

299 if "edit" in url_name:

300 breadcrumbs.append({"label": "Edit", "url": "#"})

301 elif "delete" in url_name:

302 breadcrumbs.append({"label": "Delete", "url": "#"})

303

304 # Add breadcrumbs to context

305 response.context_data["breadcrumbs"] = breadcrumbs

306 return response

307

308 def _get_network_by_id(self, network_id, context):

309 """

310 Helper to get a network by ID from context or database

311 """

312 if (

313 "network" in context

314 and hasattr(context["network"], "pk")

315 and context["network"].pk == network_id

316 ):

317 return context["network"]

318

319 if (

320 "object" in context

321 and isinstance(context["object"], Network)

322 and context["object"].pk == network_id

323 ):

324 return context["object"]

325

326 try:

327 return Network.objects.get(id=network_id)

328 except Network.DoesNotExist:

329 return None

330

331 def _get_object_by_id(self, model_class, object_id, context):

332 """

333 Helper to get an object by ID from context or database

334 """

335 if (

336 "object" in context

337 and isinstance(context["object"], model_class)

338 and context["object"].pk == object_id

339 ):

340 return context["object"]

341

342 try:

343 return model_class.objects.get(id=object_id)

344 except model_class.DoesNotExist:

345 return None