nautobot 2.3.10__py3-none-any.whl → 2.3.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of nautobot might be problematic. Click here for more details.

Files changed (524) hide show
  1. nautobot/apps/utils.py +2 -0
  2. nautobot/cloud/tables.py +1 -0
  3. nautobot/core/forms/forms.py +5 -1
  4. nautobot/core/settings.py +26 -0
  5. nautobot/core/settings.yaml +31 -0
  6. nautobot/core/tables.py +88 -22
  7. nautobot/core/templates/generic/object_bulk_destroy.html +12 -3
  8. nautobot/core/templates/generic/object_bulk_update.html +4 -2
  9. nautobot/core/templates/generic/object_create.html +1 -1
  10. nautobot/core/templates/generic/object_notes.html +1 -1
  11. nautobot/core/templates/generic/object_retrieve.html +1 -1
  12. nautobot/core/templates/rest_framework/api.html +3 -0
  13. nautobot/core/testing/api.py +3 -1
  14. nautobot/core/testing/integration.py +64 -0
  15. nautobot/core/testing/views.py +48 -31
  16. nautobot/core/tests/integration/test_app_navbar.py +3 -3
  17. nautobot/core/tests/integration/test_navbar.py +1 -1
  18. nautobot/core/tests/test_csv.py +3 -0
  19. nautobot/core/tests/test_utils.py +25 -5
  20. nautobot/core/utils/lookup.py +35 -0
  21. nautobot/core/views/generic.py +50 -39
  22. nautobot/core/views/mixins.py +97 -43
  23. nautobot/core/views/renderers.py +8 -5
  24. nautobot/dcim/choices.py +6 -0
  25. nautobot/dcim/tables/devices.py +5 -6
  26. nautobot/dcim/templates/dcim/controller_retrieve.html +1 -1
  27. nautobot/dcim/templates/dcim/device/base.html +1 -1
  28. nautobot/dcim/templates/dcim/device_component_add.html +8 -8
  29. nautobot/dcim/templates/dcim/virtualchassis_add_member.html +2 -2
  30. nautobot/dcim/templates/dcim/virtualchassis_edit.html +2 -2
  31. nautobot/dcim/tests/integration/test_create_device.py +86 -0
  32. nautobot/extras/group_sync.py +42 -0
  33. nautobot/extras/models/metadata.py +1 -0
  34. nautobot/extras/models/models.py +1 -1
  35. nautobot/extras/plugins/__init__.py +2 -1
  36. nautobot/extras/tables.py +1 -0
  37. nautobot/extras/templates/extras/inc/job_table.html +1 -1
  38. nautobot/extras/tests/test_relationships.py +1 -0
  39. nautobot/extras/tests/test_views.py +0 -2
  40. nautobot/extras/views.py +1 -2
  41. nautobot/ipam/factory.py +3 -0
  42. nautobot/ipam/filters.py +5 -0
  43. nautobot/ipam/forms.py +17 -0
  44. nautobot/ipam/models.py +2 -1
  45. nautobot/ipam/signals.py +2 -2
  46. nautobot/ipam/tables.py +6 -13
  47. nautobot/ipam/templates/ipam/ipaddress_assign.html +2 -2
  48. nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +1 -1
  49. nautobot/ipam/tests/test_models.py +113 -1
  50. nautobot/ipam/tests/test_views.py +39 -5
  51. nautobot/project-static/docs/404.html +10 -10
  52. nautobot/project-static/docs/additional-features/caching.html +1 -2
  53. nautobot/project-static/docs/additional-features/change-logging.html +1 -2
  54. nautobot/project-static/docs/additional-features/config-contexts.html +1 -2
  55. nautobot/project-static/docs/additional-features/healthcheck.html +1 -2
  56. nautobot/project-static/docs/additional-features/jobs.html +1 -2
  57. nautobot/project-static/docs/additional-features/prometheus-metrics.html +1 -2
  58. nautobot/project-static/docs/administration/celery-queues.html +1 -2
  59. nautobot/project-static/docs/administration/nautobot-server.html +1 -2
  60. nautobot/project-static/docs/administration/nautobot-shell.html +1 -2
  61. nautobot/project-static/docs/administration/permissions.html +1 -2
  62. nautobot/project-static/docs/administration/replicating-nautobot.html +1 -2
  63. nautobot/project-static/docs/apps/index.html +10 -10
  64. nautobot/project-static/docs/apps/migrating-jobs-from-nautobot-v1.html +1 -2
  65. nautobot/project-static/docs/apps/nautobot-apps.html +10 -10
  66. nautobot/project-static/docs/assets/stylesheets/main.6f8fc17f.min.css +1 -0
  67. nautobot/project-static/docs/assets/stylesheets/main.6f8fc17f.min.css.map +1 -0
  68. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +10 -10
  69. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +10 -10
  70. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +10 -10
  71. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +10 -10
  72. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +10 -10
  73. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +10 -10
  74. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +10 -10
  75. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +10 -10
  76. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +10 -10
  77. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +10 -10
  78. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +10 -10
  79. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +10 -10
  80. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +10 -10
  81. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +10 -10
  82. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +10 -10
  83. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +10 -10
  84. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +10 -10
  85. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +141 -16
  86. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +185 -10
  87. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +10 -10
  88. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +10 -10
  89. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +104 -10
  90. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +14 -14
  91. nautobot/project-static/docs/configuration/authentication/ldap.html +1 -2
  92. nautobot/project-static/docs/configuration/authentication/remote.html +1 -2
  93. nautobot/project-static/docs/configuration/authentication/sso.html +1 -2
  94. nautobot/project-static/docs/configuration/index.html +1 -2
  95. nautobot/project-static/docs/configuration/optional-settings.html +1 -2
  96. nautobot/project-static/docs/configuration/required-settings.html +1 -2
  97. nautobot/project-static/docs/core-functionality/circuits.html +1 -2
  98. nautobot/project-static/docs/core-functionality/device-types.html +1 -2
  99. nautobot/project-static/docs/core-functionality/devices.html +1 -2
  100. nautobot/project-static/docs/core-functionality/ipam.html +1 -2
  101. nautobot/project-static/docs/core-functionality/power.html +1 -2
  102. nautobot/project-static/docs/core-functionality/secrets.html +1 -2
  103. nautobot/project-static/docs/core-functionality/services.html +1 -2
  104. nautobot/project-static/docs/core-functionality/sites-and-racks.html +1 -2
  105. nautobot/project-static/docs/core-functionality/tenancy.html +1 -2
  106. nautobot/project-static/docs/core-functionality/virtualization.html +1 -2
  107. nautobot/project-static/docs/core-functionality/vlans.html +1 -2
  108. nautobot/project-static/docs/development/application-registry.html +1 -2
  109. nautobot/project-static/docs/development/apps/api/configuration-view.html +10 -10
  110. nautobot/project-static/docs/development/apps/api/database-backend-config.html +10 -10
  111. nautobot/project-static/docs/development/apps/api/models/django-admin.html +10 -10
  112. nautobot/project-static/docs/development/apps/api/models/global-search.html +10 -10
  113. nautobot/project-static/docs/development/apps/api/models/graphql.html +10 -10
  114. nautobot/project-static/docs/development/apps/api/models/index.html +10 -10
  115. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +10 -10
  116. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +10 -10
  117. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +10 -10
  118. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +10 -10
  119. nautobot/project-static/docs/development/apps/api/platform-features/index.html +10 -10
  120. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +10 -10
  121. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +10 -10
  122. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +10 -10
  123. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +10 -10
  124. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +10 -10
  125. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +10 -10
  126. nautobot/project-static/docs/development/apps/api/prometheus.html +10 -10
  127. nautobot/project-static/docs/development/apps/api/setup.html +10 -10
  128. nautobot/project-static/docs/development/apps/api/testing.html +10 -10
  129. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +10 -10
  130. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +10 -10
  131. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +10 -10
  132. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +10 -10
  133. nautobot/project-static/docs/development/apps/api/ui-extensions/object-detail-views.html +1 -2
  134. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +10 -10
  135. nautobot/project-static/docs/development/apps/api/ui-extensions/tabs.html +1 -2
  136. nautobot/project-static/docs/development/apps/api/views/base-template.html +10 -10
  137. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +10 -10
  138. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +10 -10
  139. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +10 -10
  140. nautobot/project-static/docs/development/apps/api/views/index.html +10 -10
  141. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +10 -10
  142. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +10 -10
  143. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +10 -10
  144. nautobot/project-static/docs/development/apps/api/views/notes.html +10 -10
  145. nautobot/project-static/docs/development/apps/api/views/rest-api.html +10 -10
  146. nautobot/project-static/docs/development/apps/api/views/urls.html +10 -10
  147. nautobot/project-static/docs/development/apps/api/views/view-overrides.html +1 -2
  148. nautobot/project-static/docs/development/apps/index.html +10 -10
  149. nautobot/project-static/docs/development/apps/migration/code-updates.html +10 -10
  150. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +10 -10
  151. nautobot/project-static/docs/development/apps/migration/from-v1.html +10 -10
  152. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +10 -10
  153. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +10 -10
  154. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +10 -10
  155. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +10 -10
  156. nautobot/project-static/docs/development/apps/porting-from-netbox.html +10 -10
  157. nautobot/project-static/docs/development/best-practices.html +1 -2
  158. nautobot/project-static/docs/development/core/application-registry.html +10 -10
  159. nautobot/project-static/docs/development/core/best-practices.html +10 -10
  160. nautobot/project-static/docs/development/core/bootstrap-ui.html +10 -10
  161. nautobot/project-static/docs/development/core/caching.html +10 -10
  162. nautobot/project-static/docs/development/core/controllers.html +10 -10
  163. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +10 -10
  164. nautobot/project-static/docs/development/core/extending-models.html +1 -2
  165. nautobot/project-static/docs/development/core/generic-views.html +10 -10
  166. nautobot/project-static/docs/development/core/getting-started.html +10 -10
  167. nautobot/project-static/docs/development/core/homepage.html +10 -10
  168. nautobot/project-static/docs/development/core/index.html +10 -10
  169. nautobot/project-static/docs/development/core/model-checklist.html +10 -10
  170. nautobot/project-static/docs/development/core/model-features.html +10 -10
  171. nautobot/project-static/docs/development/core/natural-keys.html +10 -10
  172. nautobot/project-static/docs/development/core/navigation-menu.html +10 -10
  173. nautobot/project-static/docs/development/core/react-ui.html +1 -2
  174. nautobot/project-static/docs/development/core/release-checklist.html +10 -10
  175. nautobot/project-static/docs/development/core/role-internals.html +10 -10
  176. nautobot/project-static/docs/development/core/settings.html +10 -10
  177. nautobot/project-static/docs/development/core/style-guide.html +10 -10
  178. nautobot/project-static/docs/development/core/templates.html +10 -10
  179. nautobot/project-static/docs/development/core/testing.html +12 -12
  180. nautobot/project-static/docs/development/core/user-preferences.html +10 -10
  181. nautobot/project-static/docs/development/docker-compose-advanced-use-cases.html +1 -2
  182. nautobot/project-static/docs/development/extending-models.html +1 -2
  183. nautobot/project-static/docs/development/generic-views.html +1 -2
  184. nautobot/project-static/docs/development/getting-started.html +1 -2
  185. nautobot/project-static/docs/development/homepage.html +1 -2
  186. nautobot/project-static/docs/development/index.html +10 -10
  187. nautobot/project-static/docs/development/jobs/index.html +10 -10
  188. nautobot/project-static/docs/development/jobs/migration/from-v1.html +10 -10
  189. nautobot/project-static/docs/development/model-features.html +1 -2
  190. nautobot/project-static/docs/development/natural-keys.html +1 -2
  191. nautobot/project-static/docs/development/navigation-menu.html +1 -2
  192. nautobot/project-static/docs/development/react-ui.html +1 -2
  193. nautobot/project-static/docs/development/release-checklist.html +1 -2
  194. nautobot/project-static/docs/development/role-internals.html +1 -2
  195. nautobot/project-static/docs/development/style-guide.html +1 -2
  196. nautobot/project-static/docs/development/templates.html +1 -2
  197. nautobot/project-static/docs/development/testing.html +1 -2
  198. nautobot/project-static/docs/development/user-preferences.html +1 -2
  199. nautobot/project-static/docs/docker/index.html +1 -2
  200. nautobot/project-static/docs/index.html +10 -10
  201. nautobot/project-static/docs/installation/centos.html +1 -2
  202. nautobot/project-static/docs/installation/external-authentication.html +1 -2
  203. nautobot/project-static/docs/installation/http-server.html +1 -2
  204. nautobot/project-static/docs/installation/index.html +1 -2
  205. nautobot/project-static/docs/installation/migrating-from-netbox.html +1 -2
  206. nautobot/project-static/docs/installation/migrating-from-postgresql.html +1 -2
  207. nautobot/project-static/docs/installation/nautobot.html +1 -2
  208. nautobot/project-static/docs/installation/region-and-site-data-migration-guide.html +1 -2
  209. nautobot/project-static/docs/installation/selinux-troubleshooting.html +1 -2
  210. nautobot/project-static/docs/installation/services.html +1 -2
  211. nautobot/project-static/docs/installation/ubuntu.html +1 -2
  212. nautobot/project-static/docs/installation/upgrading-from-nautobot-v1.html +1 -2
  213. nautobot/project-static/docs/installation/upgrading.html +1 -2
  214. nautobot/project-static/docs/models/circuits/circuit.html +1 -2
  215. nautobot/project-static/docs/models/circuits/circuittermination.html +1 -2
  216. nautobot/project-static/docs/models/circuits/circuittype.html +1 -2
  217. nautobot/project-static/docs/models/circuits/provider.html +1 -2
  218. nautobot/project-static/docs/models/circuits/providernetwork.html +1 -2
  219. nautobot/project-static/docs/models/cloud/cloudaccount.html +1 -2
  220. nautobot/project-static/docs/models/cloud/cloudnetwork.html +1 -2
  221. nautobot/project-static/docs/models/cloud/cloudnetworkprefixassignment.html +1 -2
  222. nautobot/project-static/docs/models/cloud/cloudresourcetype.html +1 -2
  223. nautobot/project-static/docs/models/cloud/cloudservice.html +1 -2
  224. nautobot/project-static/docs/models/cloud/cloudservicenetworkassignment.html +1 -2
  225. nautobot/project-static/docs/models/dcim/cable.html +1 -2
  226. nautobot/project-static/docs/models/dcim/consoleport.html +1 -2
  227. nautobot/project-static/docs/models/dcim/consoleporttemplate.html +1 -2
  228. nautobot/project-static/docs/models/dcim/consoleserverport.html +1 -2
  229. nautobot/project-static/docs/models/dcim/consoleserverporttemplate.html +1 -2
  230. nautobot/project-static/docs/models/dcim/controller.html +1 -2
  231. nautobot/project-static/docs/models/dcim/controllermanageddevicegroup.html +1 -2
  232. nautobot/project-static/docs/models/dcim/device.html +1 -2
  233. nautobot/project-static/docs/models/dcim/devicebay.html +1 -2
  234. nautobot/project-static/docs/models/dcim/devicebaytemplate.html +1 -2
  235. nautobot/project-static/docs/models/dcim/devicefamily.html +1 -2
  236. nautobot/project-static/docs/models/dcim/deviceredundancygroup.html +1 -2
  237. nautobot/project-static/docs/models/dcim/devicetype.html +1 -2
  238. nautobot/project-static/docs/models/dcim/frontport.html +1 -2
  239. nautobot/project-static/docs/models/dcim/frontporttemplate.html +1 -2
  240. nautobot/project-static/docs/models/dcim/interface.html +1 -2
  241. nautobot/project-static/docs/models/dcim/interfacetemplate.html +1 -2
  242. nautobot/project-static/docs/models/dcim/inventoryitem.html +1 -2
  243. nautobot/project-static/docs/models/dcim/location.html +1 -2
  244. nautobot/project-static/docs/models/dcim/locationtype.html +1 -2
  245. nautobot/project-static/docs/models/dcim/manufacturer.html +1 -2
  246. nautobot/project-static/docs/models/dcim/module.html +1 -2
  247. nautobot/project-static/docs/models/dcim/modulebay.html +1 -2
  248. nautobot/project-static/docs/models/dcim/modulebaytemplate.html +1 -2
  249. nautobot/project-static/docs/models/dcim/moduletype.html +1 -2
  250. nautobot/project-static/docs/models/dcim/platform.html +1 -2
  251. nautobot/project-static/docs/models/dcim/powerfeed.html +1 -2
  252. nautobot/project-static/docs/models/dcim/poweroutlet.html +1 -2
  253. nautobot/project-static/docs/models/dcim/poweroutlettemplate.html +1 -2
  254. nautobot/project-static/docs/models/dcim/powerpanel.html +1 -2
  255. nautobot/project-static/docs/models/dcim/powerport.html +1 -2
  256. nautobot/project-static/docs/models/dcim/powerporttemplate.html +1 -2
  257. nautobot/project-static/docs/models/dcim/rack.html +1 -2
  258. nautobot/project-static/docs/models/dcim/rackgroup.html +1 -2
  259. nautobot/project-static/docs/models/dcim/rackreservation.html +1 -2
  260. nautobot/project-static/docs/models/dcim/rearport.html +1 -2
  261. nautobot/project-static/docs/models/dcim/rearporttemplate.html +1 -2
  262. nautobot/project-static/docs/models/dcim/softwareimagefile.html +1 -2
  263. nautobot/project-static/docs/models/dcim/softwareversion.html +1 -2
  264. nautobot/project-static/docs/models/dcim/virtualchassis.html +1 -2
  265. nautobot/project-static/docs/models/extras/computedfield.html +1 -2
  266. nautobot/project-static/docs/models/extras/configcontext.html +1 -2
  267. nautobot/project-static/docs/models/extras/configcontextschema.html +1 -2
  268. nautobot/project-static/docs/models/extras/contact.html +1 -2
  269. nautobot/project-static/docs/models/extras/customfield.html +1 -2
  270. nautobot/project-static/docs/models/extras/customlink.html +1 -2
  271. nautobot/project-static/docs/models/extras/dynamicgroup.html +1 -2
  272. nautobot/project-static/docs/models/extras/exporttemplate.html +1 -2
  273. nautobot/project-static/docs/models/extras/gitrepository.html +1 -2
  274. nautobot/project-static/docs/models/extras/jobhook.html +1 -2
  275. nautobot/project-static/docs/models/extras/joblogentry.html +1 -2
  276. nautobot/project-static/docs/models/extras/jobresult.html +1 -2
  277. nautobot/project-static/docs/models/extras/metadatachoice.html +1 -2
  278. nautobot/project-static/docs/models/extras/metadatatype.html +1 -2
  279. nautobot/project-static/docs/models/extras/objectmetadata.html +1 -2
  280. nautobot/project-static/docs/models/extras/role.html +1 -2
  281. nautobot/project-static/docs/models/extras/savedview.html +1 -2
  282. nautobot/project-static/docs/models/extras/secret.html +1 -2
  283. nautobot/project-static/docs/models/extras/secretsgroup.html +1 -2
  284. nautobot/project-static/docs/models/extras/staticgroupassociation.html +1 -2
  285. nautobot/project-static/docs/models/extras/status.html +1 -2
  286. nautobot/project-static/docs/models/extras/team.html +1 -2
  287. nautobot/project-static/docs/models/ipam/ipaddress.html +1 -2
  288. nautobot/project-static/docs/models/ipam/prefix.html +1 -2
  289. nautobot/project-static/docs/models/ipam/rir.html +1 -2
  290. nautobot/project-static/docs/models/ipam/routetarget.html +1 -2
  291. nautobot/project-static/docs/models/ipam/service.html +1 -2
  292. nautobot/project-static/docs/models/ipam/vlan.html +1 -2
  293. nautobot/project-static/docs/models/ipam/vlangroup.html +1 -2
  294. nautobot/project-static/docs/models/ipam/vrf.html +1 -2
  295. nautobot/project-static/docs/models/tenancy/tenant.html +1 -2
  296. nautobot/project-static/docs/models/tenancy/tenantgroup.html +1 -2
  297. nautobot/project-static/docs/models/virtualization/cluster.html +1 -2
  298. nautobot/project-static/docs/models/virtualization/clustergroup.html +1 -2
  299. nautobot/project-static/docs/models/virtualization/clustertype.html +1 -2
  300. nautobot/project-static/docs/models/virtualization/virtualmachine.html +1 -2
  301. nautobot/project-static/docs/models/virtualization/vminterface.html +1 -2
  302. nautobot/project-static/docs/objects.inv +0 -0
  303. nautobot/project-static/docs/overview/application_stack.html +10 -10
  304. nautobot/project-static/docs/overview/design_philosophy.html +10 -10
  305. nautobot/project-static/docs/overview/index.html +1 -2
  306. nautobot/project-static/docs/plugins/development.html +1 -2
  307. nautobot/project-static/docs/plugins/index.html +1 -2
  308. nautobot/project-static/docs/plugins/porting-from-netbox.html +1 -2
  309. nautobot/project-static/docs/release-notes/index.html +15 -15
  310. nautobot/project-static/docs/release-notes/version-1.0.html +10 -10
  311. nautobot/project-static/docs/release-notes/version-1.1.html +10 -10
  312. nautobot/project-static/docs/release-notes/version-1.2.html +10 -10
  313. nautobot/project-static/docs/release-notes/version-1.3.html +10 -10
  314. nautobot/project-static/docs/release-notes/version-1.4.html +10 -10
  315. nautobot/project-static/docs/release-notes/version-1.5.html +10 -10
  316. nautobot/project-static/docs/release-notes/version-1.6.html +10 -10
  317. nautobot/project-static/docs/release-notes/version-2.0.html +10 -10
  318. nautobot/project-static/docs/release-notes/version-2.1.html +10 -10
  319. nautobot/project-static/docs/release-notes/version-2.2.html +10 -10
  320. nautobot/project-static/docs/release-notes/version-2.3.html +491 -182
  321. nautobot/project-static/docs/requirements.txt +2 -2
  322. nautobot/project-static/docs/rest-api/overview.html +1 -2
  323. nautobot/project-static/docs/search/search_index.json +1 -1
  324. nautobot/project-static/docs/sitemap.xml +270 -270
  325. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  326. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +10 -10
  327. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +10 -10
  328. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +65 -12
  329. nautobot/project-static/docs/user-guide/administration/configuration/index.html +10 -10
  330. nautobot/project-static/docs/user-guide/administration/configuration/node-configuration.html +1 -2
  331. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +1 -2
  332. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +10 -10
  333. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +1 -2
  334. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +122 -10
  335. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +10 -10
  336. nautobot/project-static/docs/user-guide/administration/guides/caching.html +1 -2
  337. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +10 -10
  338. nautobot/project-static/docs/user-guide/administration/guides/docker.html +10 -10
  339. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +10 -10
  340. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +1 -2
  341. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +10 -10
  342. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +10 -10
  343. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +10 -10
  344. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +49 -10
  345. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +10 -10
  346. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +10 -10
  347. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +10 -10
  348. nautobot/project-static/docs/user-guide/administration/installation/docker.html +1 -2
  349. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +10 -10
  350. nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +1 -2
  351. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +10 -10
  352. nautobot/project-static/docs/user-guide/administration/installation/index.html +10 -10
  353. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +10 -10
  354. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +10 -10
  355. nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +1 -2
  356. nautobot/project-static/docs/user-guide/administration/installation/services.html +10 -10
  357. nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +1 -2
  358. nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +1 -2
  359. nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +1 -2
  360. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +10 -10
  361. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +10 -10
  362. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +10 -10
  363. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +10 -10
  364. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +10 -10
  365. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +10 -10
  366. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +10 -10
  367. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +10 -10
  368. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +10 -10
  369. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +10 -10
  370. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +10 -10
  371. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +10 -10
  372. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +10 -10
  373. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +10 -10
  374. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +10 -10
  375. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +10 -10
  376. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +10 -10
  377. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +10 -10
  378. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +10 -10
  379. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +10 -10
  380. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +10 -10
  381. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +10 -10
  382. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +10 -10
  383. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +10 -10
  384. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +10 -10
  385. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +10 -10
  386. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +10 -10
  387. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +10 -10
  388. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +10 -10
  389. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +10 -10
  390. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +10 -10
  391. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +10 -10
  392. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +10 -10
  393. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +10 -10
  394. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +10 -10
  395. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +10 -10
  396. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +10 -10
  397. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +10 -10
  398. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +10 -10
  399. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +10 -10
  400. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +10 -10
  401. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +10 -10
  402. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +10 -10
  403. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +10 -10
  404. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +10 -10
  405. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +10 -10
  406. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +10 -10
  407. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +10 -10
  408. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +10 -10
  409. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +10 -10
  410. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +10 -10
  411. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +10 -10
  412. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +10 -10
  413. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +10 -10
  414. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +10 -10
  415. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +10 -10
  416. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +10 -10
  417. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +10 -10
  418. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +10 -10
  419. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +10 -10
  420. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +10 -10
  421. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +10 -10
  422. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +10 -10
  423. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +10 -10
  424. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +10 -10
  425. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +10 -10
  426. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +10 -10
  427. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +10 -10
  428. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +10 -10
  429. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +10 -10
  430. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +10 -10
  431. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +10 -10
  432. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +10 -10
  433. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +10 -10
  434. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +10 -10
  435. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +10 -10
  436. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +10 -10
  437. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +10 -10
  438. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +10 -10
  439. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +10 -10
  440. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +10 -10
  441. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +10 -10
  442. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +10 -10
  443. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +10 -10
  444. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +10 -10
  445. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +10 -10
  446. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +10 -10
  447. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +10 -10
  448. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +10 -10
  449. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +10 -10
  450. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +10 -10
  451. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +10 -10
  452. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +10 -10
  453. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +10 -10
  454. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +10 -10
  455. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +10 -10
  456. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +10 -10
  457. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +10 -10
  458. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +10 -10
  459. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +10 -10
  460. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +10 -10
  461. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +10 -10
  462. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +10 -10
  463. nautobot/project-static/docs/user-guide/index.html +10 -10
  464. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +10 -10
  465. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +10 -10
  466. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +10 -10
  467. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +10 -10
  468. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +10 -10
  469. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +10 -10
  470. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +10 -10
  471. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +10 -10
  472. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +10 -10
  473. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +10 -10
  474. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +10 -10
  475. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +10 -10
  476. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +10 -10
  477. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +10 -10
  478. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +10 -10
  479. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +10 -10
  480. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +10 -10
  481. nautobot/project-static/docs/user-guide/platform-functionality/note.html +10 -10
  482. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +10 -10
  483. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +10 -10
  484. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +10 -10
  485. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +10 -10
  486. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +10 -10
  487. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +10 -10
  488. nautobot/project-static/docs/user-guide/platform-functionality/role.html +10 -10
  489. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +10 -10
  490. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +10 -10
  491. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +10 -10
  492. nautobot/project-static/docs/user-guide/platform-functionality/status.html +10 -10
  493. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +10 -10
  494. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +10 -10
  495. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +10 -10
  496. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +10 -10
  497. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +10 -10
  498. nautobot/project-static/docs/user-guides/custom-fields.html +1 -2
  499. nautobot/project-static/docs/user-guides/getting-started/creating-devices.html +1 -2
  500. nautobot/project-static/docs/user-guides/getting-started/index.html +1 -2
  501. nautobot/project-static/docs/user-guides/getting-started/interfaces.html +1 -2
  502. nautobot/project-static/docs/user-guides/getting-started/ipam.html +1 -2
  503. nautobot/project-static/docs/user-guides/getting-started/platforms.html +1 -2
  504. nautobot/project-static/docs/user-guides/getting-started/search-bar.html +1 -2
  505. nautobot/project-static/docs/user-guides/getting-started/tenants.html +1 -2
  506. nautobot/project-static/docs/user-guides/getting-started/vlans-and-vlan-groups.html +1 -2
  507. nautobot/project-static/docs/user-guides/git-data-source.html +1 -2
  508. nautobot/project-static/docs/user-guides/graphql.html +1 -2
  509. nautobot/project-static/docs/user-guides/ip-address-merge-tool.html +1 -2
  510. nautobot/project-static/docs/user-guides/relationships.html +1 -2
  511. nautobot/project-static/docs/user-guides/s3-django-storage.html +1 -2
  512. nautobot/project-static/js/forms.js +10 -0
  513. nautobot/virtualization/forms.py +24 -0
  514. nautobot/virtualization/templates/virtualization/vminterface.html +4 -0
  515. nautobot/virtualization/templates/virtualization/vminterface_edit.html +1 -0
  516. nautobot/virtualization/tests/test_views.py +7 -2
  517. {nautobot-2.3.10.dist-info → nautobot-2.3.12.dist-info}/METADATA +2 -2
  518. {nautobot-2.3.10.dist-info → nautobot-2.3.12.dist-info}/RECORD +522 -520
  519. nautobot/project-static/docs/assets/stylesheets/main.0253249f.min.css +0 -1
  520. nautobot/project-static/docs/assets/stylesheets/main.0253249f.min.css.map +0 -1
  521. {nautobot-2.3.10.dist-info → nautobot-2.3.12.dist-info}/LICENSE.txt +0 -0
  522. {nautobot-2.3.10.dist-info → nautobot-2.3.12.dist-info}/NOTICE +0 -0
  523. {nautobot-2.3.10.dist-info → nautobot-2.3.12.dist-info}/WHEEL +0 -0
  524. {nautobot-2.3.10.dist-info → nautobot-2.3.12.dist-info}/entry_points.txt +0 -0
nautobot/apps/utils.py CHANGED
@@ -30,6 +30,7 @@ from nautobot.core.utils.lookup import (
30
30
  get_form_for_model,
31
31
  get_model_from_name,
32
32
  get_related_class_for_model,
33
+ get_related_field_for_models,
33
34
  get_route_for_model,
34
35
  get_table_for_model,
35
36
  get_url_for_url_pattern,
@@ -111,6 +112,7 @@ __all__ = (
111
112
  "get_only_new_ui_ready_routes",
112
113
  "get_permission_for_model",
113
114
  "get_related_class_for_model",
115
+ "get_related_field_for_models",
114
116
  "get_route_for_model",
115
117
  "get_settings_or_config",
116
118
  "get_table_for_model",
nautobot/cloud/tables.py CHANGED
@@ -55,6 +55,7 @@ class CloudNetworkTable(BaseTable):
55
55
  circuit_count = LinkedCountColumn(
56
56
  viewname="circuits:circuit_list",
57
57
  url_params={"cloud_network": "name"},
58
+ # lookup="circuit_terminations__circuit", # TODO: not currently supported
58
59
  verbose_name="Circuits",
59
60
  reverse_lookup="circuit_terminations__cloud_network",
60
61
  )
@@ -113,7 +113,7 @@ class BulkEditForm(forms.Form):
113
113
  a more powerful subclass and should be used instead of directly inheriting from this class.
114
114
  """
115
115
 
116
- def __init__(self, model, *args, **kwargs):
116
+ def __init__(self, model, *args, edit_all=False, **kwargs):
117
117
  super().__init__(*args, **kwargs)
118
118
  self.model = model
119
119
  self.nullable_fields = []
@@ -122,6 +122,10 @@ class BulkEditForm(forms.Form):
122
122
  if hasattr(self.Meta, "nullable_fields"):
123
123
  self.nullable_fields = self.Meta.nullable_fields
124
124
 
125
+ if edit_all:
126
+ self.fields["pk"].required = False
127
+ self.fields["_all"] = forms.BooleanField(widget=forms.HiddenInput(), required=True, initial=True)
128
+
125
129
 
126
130
  class BulkRenameForm(forms.Form):
127
131
  """
nautobot/core/settings.py CHANGED
@@ -212,6 +212,32 @@ SOCIAL_AUTH_POSTGRES_JSONFIELD = False
212
212
  # Nautobot related - May be overridden if using custom social auth backend
213
213
  SOCIAL_AUTH_BACKEND_PREFIX = "social_core.backends"
214
214
 
215
+ # Enables adding the OAuth2/OIDC group sync module to the authentication pipeline
216
+ SSO_ENABLE_GROUP_SYNC = is_truthy(os.getenv("NAUTOBOT_SSO_ENABLE_GROUP_SYNC", "false"))
217
+ if SSO_ENABLE_GROUP_SYNC:
218
+ SOCIAL_AUTH_PIPELINE = (
219
+ "social_core.pipeline.social_auth.social_details",
220
+ "social_core.pipeline.social_auth.social_uid",
221
+ "social_core.pipeline.social_auth.auth_allowed",
222
+ "social_core.pipeline.social_auth.social_user",
223
+ "social_core.pipeline.user.get_username",
224
+ "social_core.pipeline.user.create_user",
225
+ "social_core.pipeline.social_auth.associate_user",
226
+ "social_core.pipeline.social_auth.load_extra_data",
227
+ "social_core.pipeline.user.user_details",
228
+ "nautobot.extras.group_sync",
229
+ )
230
+ # OAuth2/OIDC claim where the list of groups the authenticating user is a part of
231
+ SSO_CLAIMS_GROUP = os.getenv("NAUTOBOT_SSO_CLAIMS_GROUP", "groups")
232
+ # list of groups that an authenticating user can be a part of to get the Django staff permission
233
+ SSO_STAFF_GROUPS = [
234
+ group for group in os.getenv("NAUTOBOT_SSO_STAFF_GROUPS", "").split(_CONFIG_SETTING_SEPARATOR) if group != ""
235
+ ]
236
+ # list of groups that an authenticating user can be a part of to be a Django super user
237
+ SSO_SUPERUSER_GROUPS = [
238
+ group for group in os.getenv("NAUTOBOT_SSO_SUPERUSER_GROUPS", "").split(_CONFIG_SETTING_SEPARATOR) if group != ""
239
+ ]
240
+
215
241
  # Job log entry sanitization and similar
216
242
  SANITIZER_PATTERNS = [
217
243
  # General removal of username-like and password-like tokens
@@ -1705,6 +1705,37 @@ properties:
1705
1705
  "Single Sign On": "./authentication/sso.md"
1706
1706
  "`social-auth-app-django`": "https://python-social-auth.readthedocs.io/en/latest/configuration/django.html"
1707
1707
  type: "string"
1708
+ SSO_CLAIMS_GROUP:
1709
+ default: "groups"
1710
+ description: "OAuth2/OIDC claim which will contain the groups which the authenticated user is a member of."
1711
+ environment_variable: "NAUTOBOT_SSO_CLAIMS_GROUP"
1712
+ see_also:
1713
+ "Single Sign On": "./authentication/sso.md"
1714
+ SSO_ENABLE_GROUP_SYNC:
1715
+ default: false
1716
+ type: "boolean"
1717
+ description: "Enables the group syncing authentication module."
1718
+ environment_variable: "NAUTOBOT_SSO_ENABLE_GROUP_SYNC"
1719
+ see_also:
1720
+ "Single Sign On": "./authentication/sso.md"
1721
+ SSO_STAFF_GROUPS:
1722
+ default: []
1723
+ description: "List of groups that a user can be a member of to get the Django Staff permission."
1724
+ environment_variable: "NAUTOBOT_SSO_STAFF_GROUPS"
1725
+ see_also:
1726
+ "Single Sign On": "./authentication/sso.md"
1727
+ items:
1728
+ type: "string"
1729
+ type: "array"
1730
+ SSO_SUPERUSER_GROUPS:
1731
+ default: []
1732
+ description: "List of groups that a user can be a member of to be a Django Super User."
1733
+ environment_variable: "NAUTOBOT_SSO_SUPERUSER_GROUPS"
1734
+ see_also:
1735
+ "Single Sign On": "./authentication/sso.md"
1736
+ items:
1737
+ type: "string"
1738
+ type: "array"
1708
1739
  STATIC_ROOT:
1709
1740
  "$ref": "#/definitions/absolute_path"
1710
1741
  default: "~/.nautobot/static"
nautobot/core/tables.py CHANGED
@@ -5,10 +5,12 @@ from django.contrib.auth.models import AnonymousUser
5
5
  from django.contrib.contenttypes.fields import GenericForeignKey
6
6
  from django.core.exceptions import FieldDoesNotExist, FieldError
7
7
  from django.db import NotSupportedError
8
+ from django.db.models import Prefetch
8
9
  from django.db.models.fields.related import ForeignKey, RelatedField
9
10
  from django.db.models.fields.reverse_related import ManyToOneRel
10
11
  from django.urls import reverse
11
12
  from django.utils.html import escape, format_html, format_html_join
13
+ from django.utils.http import urlencode
12
14
  from django.utils.safestring import mark_safe
13
15
  from django.utils.text import Truncator
14
16
  import django_tables2
@@ -18,7 +20,7 @@ from tree_queries.models import TreeNode
18
20
 
19
21
  from nautobot.core.models.querysets import count_related
20
22
  from nautobot.core.templatetags import helpers
21
- from nautobot.core.utils import lookup
23
+ from nautobot.core.utils.lookup import get_model_for_view_name, get_related_field_for_models, get_route_for_model
22
24
  from nautobot.extras import choices, models
23
25
 
24
26
  logger = logging.getLogger(__name__)
@@ -154,12 +156,25 @@ class BaseTable(django_tables2.Table):
154
156
  if not column.visible:
155
157
  continue
156
158
  if isinstance(column.column, LinkedCountColumn):
157
- column_model = lookup.get_model_for_view_name(column.column.viewname)
159
+ column_model = get_model_for_view_name(column.column.viewname)
158
160
  if column_model is None:
159
161
  logger.error("Couldn't find model for %s", column.column.viewname)
160
162
  continue
161
163
  reverse_lookup = column.column.reverse_lookup or next(iter(column.column.url_params.keys()))
162
164
  count_fields.append((column.name, column_model, reverse_lookup))
165
+ try:
166
+ lookup = column.column.lookup or get_related_field_for_models(model, column_model).name
167
+ # For some reason get_related_field_for_models(Tag, DynamicGroup) gives a M2M with the name
168
+ # `dynamicgroup`, which isn't actually a field on Tag. May be a django-taggit issue?
169
+ # Workaround for now: make sure the field actually exists on the model under this name:
170
+ getattr(model, lookup)
171
+ except AttributeError:
172
+ lookup = None
173
+ if lookup is not None:
174
+ # Also attempt to prefetch the first matching record for display - see LinkedCountColumn
175
+ prefetch_fields.append(
176
+ Prefetch(lookup, column_model.objects.all()[:1], to_attr=f"{lookup}_list")
177
+ )
163
178
  continue
164
179
 
165
180
  column_model = model
@@ -233,7 +248,7 @@ class BaseTable(django_tables2.Table):
233
248
  # Belt and suspenders - we should have avoided any error cases above, but be safe anyway:
234
249
  try:
235
250
  queryset = queryset.prefetch_related(*prefetch_fields)
236
- except (TypeError, ValueError, NotSupportedError) as exc:
251
+ except (AttributeError, TypeError, ValueError, NotSupportedError) as exc:
237
252
  logger.warning(
238
253
  "Unexpected error when trying to .prefetch_related() on %s QuerySet: %s",
239
254
  model.__name__,
@@ -395,9 +410,9 @@ class ButtonsColumn(django_tables2.TemplateColumn):
395
410
  self.template_code = prepend_template + self.template_code
396
411
 
397
412
  app_label = model._meta.app_label
398
- changelog_route = lookup.get_route_for_model(model, "changelog")
399
- edit_route = lookup.get_route_for_model(model, "edit")
400
- delete_route = lookup.get_route_for_model(model, "delete")
413
+ changelog_route = get_route_for_model(model, "changelog")
414
+ edit_route = get_route_for_model(model, "edit")
415
+ delete_route = get_route_for_model(model, "delete")
401
416
 
402
417
  template_code = self.template_code.format(
403
418
  app_label=app_label,
@@ -462,29 +477,80 @@ class ColoredLabelColumn(django_tables2.TemplateColumn):
462
477
 
463
478
  class LinkedCountColumn(django_tables2.Column):
464
479
  """
465
- Render a count of related objects linked to a filtered URL.
466
-
467
- :param viewname: The view name to use for URL resolution
468
- :param view_kwargs: Additional kwargs to pass for URL resolution (optional)
469
- :param url_params: A dict of query parameters to append to the URL (e.g. ?foo=bar) (optional)
470
- :param reverse_lookup: The reverse lookup parameter to use to derive the count. If not specified, the first key
471
- in `url_params` will be implicitly used as the `reverse_lookup` value.
480
+ Render a count of related objects linked to a filtered URL, or if a single related object is present, the object.
481
+
482
+ Args:
483
+ viewname (str): The list view name to use for URL resolution, for example `"dcim:location_list"`
484
+ url_params (dict, optional): Query parameters to apply to filter the list URL (e.g. `{"vlans": "pk"}` will add
485
+ `?vlans=<record.pk>` to the linked list URL)
486
+ view_kwargs (dict, optional): Additional kwargs to pass to `reverse()` for list URL resolution. Rarely used.
487
+ lookup (str, optional): The field name on the base record that can be used to query the related objects.
488
+ If not specified, `nautobot.core.utils.lookup.get_related_field_for_models()` will be called at render time
489
+ to attempt to intelligently find the appropriate field.
490
+ TODO: this currently does *not* support nested lookups via `__`. That may be solvable in the future.
491
+ reverse_lookup (str, optional): The reverse lookup parameter to use to derive the count.
492
+ If not specified, the first key in `url_params` will be implicitly used as the `reverse_lookup` value.
493
+ **kwargs (dict, optional): As the parent Column class.
494
+
495
+ Examples:
496
+ ```py
497
+ class VLANTable(..., BaseTable):
498
+ ...
499
+ location_count = LinkedCountColumn(
500
+ # Link for N related locations will be reverse("dcim:location_list") + "?vlans=<record.pk>"
501
+ viewname="dcim:location_list",
502
+ url_params={"vlans": "pk"},
503
+ verbose_name="Locations",
504
+ )
505
+ ```
506
+
507
+ ```py
508
+ class CloudNetworkTable(BaseTable):
509
+ ...
510
+ circuit_count = LinkedCountColumn(
511
+ # Link for N related circuits will be reverse("circuits:circuit_list") + "?cloud_network=<record.name>"
512
+ viewname="circuits:circuit_list",
513
+ url_params={"cloud_network": "name"},
514
+ # We'd like to do the below but this module isn't currently smart enough to build the right Prefetch()
515
+ # for a nested lookup:
516
+ # lookup="circuit_terminations__circuit",
517
+ # For the count, .annotate(circuit_count=count_related(Circuit, "circuit_terminations__cloud_network"))
518
+ reverse_lookup="circuit_terminations__cloud_network",
519
+ verbose_name="Circuits",
520
+ )
521
+ ```
472
522
  """
473
523
 
474
- def __init__(self, viewname, *args, view_kwargs=None, url_params=None, reverse_lookup=None, default=0, **kwargs):
524
+ def __init__(
525
+ self, viewname, *args, view_kwargs=None, url_params=None, lookup=None, reverse_lookup=None, default=0, **kwargs
526
+ ):
475
527
  self.viewname = viewname
528
+ self.lookup = lookup
476
529
  self.view_kwargs = view_kwargs or {}
477
530
  self.url_params = url_params
478
- self.reverse_lookup = reverse_lookup
531
+ self.reverse_lookup = reverse_lookup or next(iter(url_params.keys()))
532
+ self.model = get_model_for_view_name(self.viewname)
479
533
  super().__init__(*args, default=default, **kwargs)
480
534
 
481
- def render(self, record, value): # pylint: disable=arguments-differ
482
- if value:
483
- url = reverse(self.viewname, kwargs=self.view_kwargs)
484
- if self.url_params:
485
- url += "?" + "&".join([f"{k}={getattr(record, v)}" for k, v in self.url_params.items()])
486
- return format_html('<a href="{}">{}</a>', url, value)
487
- return value
535
+ def render(self, bound_column, record, value): # pylint: disable=arguments-differ
536
+ related_record = None
537
+ try:
538
+ lookup = self.lookup or get_related_field_for_models(bound_column._table._meta.model, self.model).name
539
+ except AttributeError:
540
+ lookup = None
541
+ if lookup:
542
+ if related_records := getattr(record, f"{lookup}_list", None):
543
+ related_record = related_records[0]
544
+ url = reverse(self.viewname, kwargs=self.view_kwargs)
545
+ if self.url_params:
546
+ url += "?" + urlencode({k: getattr(record, v) for k, v in self.url_params.items()})
547
+ if value > 1:
548
+ return format_html('<a href="{}" class="badge">{}</a>', url, value)
549
+ if related_record is not None:
550
+ return helpers.hyperlinked_object(related_record)
551
+ if value == 1:
552
+ return format_html('<a href="{}" class="badge">{}</a>', url, value)
553
+ return helpers.placeholder(value)
488
554
 
489
555
 
490
556
  class TagColumn(django_tables2.TemplateColumn):
@@ -2,7 +2,7 @@
2
2
  {% load helpers %}
3
3
  {% load render_table from django_tables2 %}
4
4
 
5
- {% block title %}Delete {{ table.rows|length }} {{ obj_type_plural|bettertitle }}?{% endblock %}
5
+ {% block title %}Delete {{ total_objs_to_delete }} {{ obj_type_plural|bettertitle }}?{% endblock %}
6
6
 
7
7
  {% block content %}
8
8
  <div class="row">
@@ -10,12 +10,14 @@
10
10
  <div class="panel panel-danger">
11
11
  <div class="panel-heading"><strong>Confirm Bulk Deletion</strong></div>
12
12
  <div class="panel-body">
13
- <p><strong>Warning:</strong> The following operation will delete {{ table.rows|length }} {{ obj_type_plural }}. Please carefully review the {{ obj_type_plural }} to be deleted and confirm below.</p>
13
+ <p><strong>Warning:</strong> The following operation will delete {{ total_objs_to_delete }} {{ obj_type_plural }}. {% if not delete_all %}Please carefully review the {{ obj_type_plural }} to be deleted and confirm below.{% endif %}</p>
14
14
  {% block message_extra %}{% endblock %}
15
15
  </div>
16
16
  </div>
17
17
  </div>
18
18
  </div>
19
+
20
+ {% if table %}
19
21
  <div class="row">
20
22
  <div class="col-md-8 col-md-offset-2">
21
23
  <div class="panel panel-default">
@@ -25,15 +27,22 @@
25
27
  </div>
26
28
  </div>
27
29
  </div>
30
+ {% endif %}
31
+
28
32
  <div class="row">
29
33
  <div class="col-md-6 col-md-offset-3">
30
34
  <form action="" method="post" class="form">
35
+
31
36
  {% csrf_token %}
37
+ {% if delete_all %}
38
+ <input type="hidden" name="_all" value="true" />
39
+ {% endif %}
32
40
  {% for field in form.hidden_fields %}
33
41
  {{ field }}
34
42
  {% endfor %}
43
+
35
44
  <div class="text-center">
36
- <button type="submit" name="_confirm" class="btn btn-danger">Delete these {{ table.rows|length }} {{ obj_type_plural }}</button>
45
+ <button type="submit" name="_confirm" class="btn btn-danger">Delete these {{ total_objs_to_delete }} {{ obj_type_plural }}</button>
37
46
  <a href="{{ return_url }}" class="btn btn-default">Cancel</a>
38
47
  </div>
39
48
  </form>
@@ -4,7 +4,7 @@
4
4
  {% load render_table from django_tables2 %}
5
5
 
6
6
  {% block content %}
7
- <h1>{% block title %}Editing {{ table.rows|length }} {{ obj_type_plural|bettertitle }}{% endblock %}</h1>
7
+ <h1>{% block title %}Editing {{ objs_count }} {{ obj_type_plural|bettertitle }}{% endblock %}</h1>
8
8
  {% if form.errors %}
9
9
  <div class="panel panel-danger">
10
10
  <div class="panel-heading"><strong>Errors</strong></div>
@@ -27,6 +27,7 @@
27
27
  {{ field }}
28
28
  {% endfor %}
29
29
  <div class="row">
30
+ {% if table %}
30
31
  <div class="col-md-8">
31
32
  <div class="panel panel-default">
32
33
  <div class="table-responsive">
@@ -34,7 +35,8 @@
34
35
  </div>
35
36
  </div>
36
37
  </div>
37
- <div class="col-md-4">
38
+ {% endif %}
39
+ <div class="{% if table %} col-md-4 {% else %} col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1 {% endif %}">
38
40
  <div class="panel panel-default">
39
41
  <div class="panel-heading"><strong>{% block form_title %}Attributes{% endblock %}</strong></div>
40
42
  <div class="panel-body">
@@ -50,7 +50,7 @@
50
50
  </div>
51
51
  </div>
52
52
  <div class="row">
53
- <div class="col-md-6 col-md-offset-3 text-right">
53
+ <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1 text-right">
54
54
  {% block buttons %}
55
55
  {% if editing %}
56
56
  <button type="submit" name="_update" class="btn btn-primary">Update</button>
@@ -21,7 +21,7 @@
21
21
  </div>
22
22
  </div>
23
23
  <div class="col-md-6 col-md-offset-3 text-right" style="margin-bottom: 20px;">
24
- <button type="submit" class="btn btn-primary">Create</button>
24
+ <button id="createNote" type="submit" class="btn btn-primary">Create</button>
25
25
  <a href="{{ object.get_absolute_url }}" class="btn btn-default">Cancel</a>
26
26
  </div>
27
27
  </div>
@@ -54,7 +54,7 @@
54
54
  <h1>
55
55
  <span class="hover_copy">
56
56
  <span id="copy_title">{% block title %}{{object.display|default:object}}{% endblock %}</span>
57
- <button type="button" class="btn btn-inline btn-default hover_copy_button" data-clipboard-target="#copy_title">
57
+ <button type="button" class="btn btn-inline btn-default hover_copy_button" data-clipboard-text="{{ object.display | default:object }}">
58
58
  <span class="mdi mdi-content-copy"></span>
59
59
  </button>
60
60
  </span>
@@ -20,6 +20,9 @@
20
20
  #main-content {
21
21
  min-height: calc(100vh - 70px);
22
22
  }
23
+ .request-info {
24
+ clear: both; /* Fix description floating issue */
25
+ }
23
26
  </style>
24
27
  {% endblock body %}
25
28
 
@@ -699,13 +699,15 @@ class APIViewTestCases:
699
699
  serializer_class = get_serializer_for_model(self.model)
700
700
  old_serializer = serializer_class(instance, context={"request": None})
701
701
  old_data = old_serializer.data
702
+ # save the pk because .delete() will clear it, making the test below always pass
703
+ orig_pk = instance.pk
702
704
  instance.delete()
703
705
 
704
706
  response = self.client.post(self._get_list_url(), csv_data, content_type="text/csv", **self.header)
705
707
  self.assertHttpStatus(response, status.HTTP_201_CREATED, csv_data)
706
708
  # Note that create via CSV is always treated as a bulk-create, and so the response is always a list of dicts
707
709
  new_instance = self._get_queryset().get(pk=response.data[0]["id"])
708
- self.assertNotEqual(new_instance.pk, instance.pk)
710
+ self.assertNotEqual(new_instance.pk, orig_pk)
709
711
 
710
712
  new_serializer = serializer_class(new_instance, context={"request": None})
711
713
  new_data = new_serializer.data
@@ -5,6 +5,7 @@ from django.contrib.staticfiles.testing import StaticLiveServerTestCase
5
5
  from django.test import override_settings, tag
6
6
  from django.urls import reverse
7
7
  from django.utils.functional import classproperty
8
+ from selenium.webdriver.common.keys import Keys
8
9
  from splinter.browser import Browser
9
10
 
10
11
  from nautobot.core import testing
@@ -74,3 +75,66 @@ class SeleniumTestCase(StaticLiveServerTestCase, testing.NautobotTestCaseMixin):
74
75
 
75
76
  def logout(self):
76
77
  self.browser.visit(f"{self.live_server_url}/logout")
78
+
79
+ def click_navbar_entry(self, parent_menu_name, child_menu_name):
80
+ """
81
+ Helper function to click on a parent menu and child menu in the navigation bar.
82
+ """
83
+
84
+ parent_menu_xpath = f"//*[@id='navbar']//a[@class='dropdown-toggle' and normalize-space()='{parent_menu_name}']"
85
+ parent_menu = self.browser.find_by_xpath(parent_menu_xpath, wait_time=5)
86
+ if not parent_menu["aria-expanded"] == "true":
87
+ parent_menu.click()
88
+ child_menu_xpath = f"{parent_menu_xpath}/following-sibling::ul//li[.//a[normalize-space()='{child_menu_name}']]"
89
+ child_menu = self.browser.find_by_xpath(child_menu_xpath, wait_time=5)
90
+ child_menu.click()
91
+
92
+ # Wait for body element to appear
93
+ self.assertTrue(self.browser.is_element_present_by_tag("body", wait_time=5), "Page failed to load")
94
+
95
+ def click_list_view_add_button(self):
96
+ """
97
+ Helper function to click the "Add" button on a list view.
98
+ """
99
+ add_button = self.browser.find_by_xpath("//a[@id='add-button']", wait_time=5)
100
+ add_button.click()
101
+
102
+ # Wait for body element to appear
103
+ self.assertTrue(self.browser.is_element_present_by_tag("body", wait_time=5), "Page failed to load")
104
+
105
+ def click_edit_form_create_button(self):
106
+ """
107
+ Helper function to click the "Create" button on a form.
108
+ """
109
+ add_button = self.browser.find_by_xpath("//button[@name='_create']", wait_time=5)
110
+ add_button.click()
111
+
112
+ # Wait for body element to appear
113
+ self.assertTrue(self.browser.is_element_present_by_tag("body", wait_time=5), "Page failed to load")
114
+
115
+ def fill_select2_field(self, field_name, value):
116
+ """
117
+ Helper function to fill a Select2 single selection field.
118
+ """
119
+ self.browser.find_by_xpath(f"//select[@id='id_{field_name}']//following-sibling::span").click()
120
+ search_box = self.browser.find_by_xpath(
121
+ "//*[@class='select2-search select2-search--dropdown']//input", wait_time=5
122
+ )
123
+ for _ in search_box.first.type(value, slowly=True):
124
+ pass
125
+
126
+ # wait for "searching" to disappear
127
+ self.browser.is_element_not_present_by_css(".loading-results", wait_time=5)
128
+ search_box.first.type(Keys.ENTER)
129
+
130
+ def fill_select2_multiselect_field(self, field_name, value):
131
+ """
132
+ Helper function to fill a Select2 multi-selection field.
133
+ """
134
+ search_box = self.browser.find_by_xpath(f"//select[@id='id_{field_name}']//following-sibling::span//input")
135
+ for _ in search_box.first.type(value, slowly=True):
136
+ pass
137
+
138
+ # wait for "searching" to disappear
139
+ self.browser.is_element_not_present_by_css(".loading-results", wait_time=5)
140
+ search_box.first.type(Keys.ENTER)