nautobot 2.2.3__py3-none-any.whl → 2.2.4__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 (301) hide show
  1. nautobot/core/settings.py +6 -4
  2. nautobot/core/settings.yaml +51 -16
  3. nautobot/core/templates/admin/base.html +2 -2
  4. nautobot/core/templates/base_django.html +2 -2
  5. nautobot/core/templates/buttons/export.html +47 -47
  6. nautobot/core/templates/inc/javascript.html +3 -0
  7. nautobot/core/templates/inc/media.html +3 -0
  8. nautobot/core/templates/login.html +2 -2
  9. nautobot/core/templates/nautobot_config.py.j2 +2 -0
  10. nautobot/core/tests/test_jobs.py +79 -2
  11. nautobot/core/tests/test_views.py +33 -0
  12. nautobot/core/views/mixins.py +4 -0
  13. nautobot/dcim/tests/test_views.py +239 -55
  14. nautobot/dcim/views.py +23 -20
  15. nautobot/extras/api/serializers.py +17 -6
  16. nautobot/extras/tests/test_context_managers.py +18 -0
  17. nautobot/extras/utils.py +2 -1
  18. nautobot/extras/views.py +35 -21
  19. nautobot/ipam/views.py +6 -6
  20. nautobot/project-static/docs/404.html +107 -51
  21. nautobot/project-static/docs/apps/index.html +107 -51
  22. nautobot/project-static/docs/apps/nautobot-apps.html +107 -51
  23. nautobot/project-static/docs/assets/_mkdocstrings.css +6 -1
  24. nautobot/project-static/docs/assets/extra.css +7 -0
  25. nautobot/project-static/docs/assets/javascripts/bundle.3220b9d7.min.js +29 -0
  26. nautobot/project-static/docs/assets/javascripts/bundle.3220b9d7.min.js.map +7 -0
  27. nautobot/project-static/docs/assets/stylesheets/main.66ac8b77.min.css +1 -0
  28. nautobot/project-static/docs/assets/stylesheets/main.66ac8b77.min.css.map +1 -0
  29. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +107 -51
  30. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +107 -51
  31. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +107 -51
  32. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +107 -51
  33. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +107 -51
  34. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +107 -51
  35. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +107 -51
  36. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +107 -51
  37. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +107 -51
  38. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +107 -51
  39. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +107 -51
  40. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +107 -51
  41. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +107 -51
  42. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +107 -51
  43. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +107 -51
  44. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +107 -51
  45. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +107 -51
  46. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +107 -51
  47. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +107 -51
  48. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +107 -51
  49. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +107 -51
  50. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +107 -51
  51. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +107 -51
  52. nautobot/project-static/docs/development/apps/api/configuration-view.html +110 -54
  53. nautobot/project-static/docs/development/apps/api/database-backend-config.html +110 -54
  54. nautobot/project-static/docs/development/apps/api/models/django-admin.html +107 -51
  55. nautobot/project-static/docs/development/apps/api/models/global-search.html +110 -54
  56. nautobot/project-static/docs/development/apps/api/models/graphql.html +113 -57
  57. nautobot/project-static/docs/development/apps/api/models/index.html +107 -51
  58. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +113 -57
  59. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +107 -51
  60. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +110 -54
  61. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +107 -51
  62. nautobot/project-static/docs/development/apps/api/platform-features/index.html +107 -51
  63. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +110 -54
  64. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +110 -54
  65. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +110 -54
  66. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +110 -54
  67. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +107 -51
  68. nautobot/project-static/docs/development/apps/api/prometheus.html +110 -54
  69. nautobot/project-static/docs/development/apps/api/setup.html +107 -51
  70. nautobot/project-static/docs/development/apps/api/testing.html +113 -57
  71. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +110 -54
  72. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +110 -54
  73. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +107 -51
  74. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +107 -51
  75. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +113 -57
  76. nautobot/project-static/docs/development/apps/api/views/base-template.html +107 -51
  77. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +110 -54
  78. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +107 -51
  79. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +110 -54
  80. nautobot/project-static/docs/development/apps/api/views/index.html +107 -51
  81. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +113 -57
  82. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +122 -66
  83. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +110 -54
  84. nautobot/project-static/docs/development/apps/api/views/notes.html +110 -54
  85. nautobot/project-static/docs/development/apps/api/views/rest-api.html +107 -51
  86. nautobot/project-static/docs/development/apps/api/views/urls.html +107 -51
  87. nautobot/project-static/docs/development/apps/index.html +128 -72
  88. nautobot/project-static/docs/development/apps/migration/code-updates.html +107 -51
  89. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +107 -51
  90. nautobot/project-static/docs/development/apps/migration/from-v1.html +107 -51
  91. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +107 -51
  92. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +107 -51
  93. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +107 -51
  94. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +107 -51
  95. nautobot/project-static/docs/development/apps/porting-from-netbox.html +110 -54
  96. nautobot/project-static/docs/development/core/application-registry.html +119 -63
  97. nautobot/project-static/docs/development/core/best-practices.html +122 -66
  98. nautobot/project-static/docs/development/core/bootstrap-ui.html +107 -51
  99. nautobot/project-static/docs/development/core/caching.html +107 -51
  100. nautobot/project-static/docs/development/core/controllers.html +107 -51
  101. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +113 -57
  102. nautobot/project-static/docs/development/core/generic-views.html +110 -54
  103. nautobot/project-static/docs/development/core/getting-started.html +135 -79
  104. nautobot/project-static/docs/development/core/homepage.html +110 -54
  105. nautobot/project-static/docs/development/core/index.html +107 -51
  106. nautobot/project-static/docs/development/core/model-checklist.html +107 -51
  107. nautobot/project-static/docs/development/core/model-features.html +107 -51
  108. nautobot/project-static/docs/development/core/natural-keys.html +110 -54
  109. nautobot/project-static/docs/development/core/navigation-menu.html +107 -51
  110. nautobot/project-static/docs/development/core/release-checklist.html +107 -51
  111. nautobot/project-static/docs/development/core/role-internals.html +107 -51
  112. nautobot/project-static/docs/development/core/settings.html +107 -51
  113. nautobot/project-static/docs/development/core/style-guide.html +110 -54
  114. nautobot/project-static/docs/development/core/templates.html +113 -57
  115. nautobot/project-static/docs/development/core/testing.html +125 -69
  116. nautobot/project-static/docs/development/core/user-preferences.html +107 -51
  117. nautobot/project-static/docs/development/index.html +107 -51
  118. nautobot/project-static/docs/development/jobs/index.html +173 -117
  119. nautobot/project-static/docs/development/jobs/migration/from-v1.html +110 -54
  120. nautobot/project-static/docs/docker/index.html +3 -3
  121. nautobot/project-static/docs/index.html +125 -69
  122. nautobot/project-static/docs/installation/selinux-troubleshooting.html +3 -3
  123. nautobot/project-static/docs/release-notes/index.html +107 -51
  124. nautobot/project-static/docs/release-notes/version-1.0.html +107 -51
  125. nautobot/project-static/docs/release-notes/version-1.1.html +107 -51
  126. nautobot/project-static/docs/release-notes/version-1.2.html +107 -51
  127. nautobot/project-static/docs/release-notes/version-1.3.html +107 -51
  128. nautobot/project-static/docs/release-notes/version-1.4.html +107 -51
  129. nautobot/project-static/docs/release-notes/version-1.5.html +116 -60
  130. nautobot/project-static/docs/release-notes/version-1.6.html +107 -51
  131. nautobot/project-static/docs/release-notes/version-2.0.html +110 -54
  132. nautobot/project-static/docs/release-notes/version-2.1.html +107 -51
  133. nautobot/project-static/docs/release-notes/version-2.2.html +321 -117
  134. nautobot/project-static/docs/requirements.txt +2 -2
  135. nautobot/project-static/docs/search/search_index.json +1 -1
  136. nautobot/project-static/docs/sitemap.xml +262 -262
  137. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  138. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +107 -51
  139. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +107 -51
  140. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +107 -51
  141. nautobot/project-static/docs/user-guide/administration/configuration/index.html +107 -51
  142. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +251 -164
  143. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +113 -57
  144. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +107 -51
  145. nautobot/project-static/docs/user-guide/administration/guides/caching.html +113 -57
  146. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +107 -51
  147. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +107 -51
  148. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +107 -51
  149. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +113 -57
  150. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +107 -51
  151. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +107 -51
  152. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +107 -51
  153. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +171 -112
  154. nautobot/project-static/docs/user-guide/administration/installation/docker.html +13 -8626
  155. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +117 -61
  156. nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +13 -8614
  157. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +252 -165
  158. nautobot/project-static/docs/user-guide/administration/installation/index.html +165 -192
  159. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +411 -691
  160. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +248 -229
  161. nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +13 -8118
  162. nautobot/project-static/docs/user-guide/administration/installation/services.html +350 -240
  163. nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +8684 -0
  164. nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +8672 -0
  165. nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +8176 -0
  166. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +110 -54
  167. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +110 -54
  168. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +155 -99
  169. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +107 -51
  170. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +109 -53
  171. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +107 -51
  172. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +107 -51
  173. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +107 -51
  174. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +107 -51
  175. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +107 -51
  176. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +107 -51
  177. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +113 -57
  178. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +113 -57
  179. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +107 -51
  180. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +107 -51
  181. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +107 -51
  182. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +107 -51
  183. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +110 -54
  184. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +107 -51
  185. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +110 -54
  186. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +110 -54
  187. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +110 -54
  188. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +110 -54
  189. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +107 -51
  190. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +107 -51
  191. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +113 -57
  192. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +110 -54
  193. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +110 -54
  194. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +110 -54
  195. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +110 -54
  196. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +116 -60
  197. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +110 -54
  198. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +110 -54
  199. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +119 -63
  200. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +110 -54
  201. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +110 -54
  202. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +113 -57
  203. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +113 -57
  204. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +113 -57
  205. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +107 -51
  206. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +113 -57
  207. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +107 -51
  208. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +110 -54
  209. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +110 -54
  210. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +107 -51
  211. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +110 -54
  212. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +110 -54
  213. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +107 -51
  214. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +107 -51
  215. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +107 -51
  216. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +110 -54
  217. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +110 -54
  218. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +110 -54
  219. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +110 -54
  220. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +107 -51
  221. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +113 -57
  222. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +110 -54
  223. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +110 -54
  224. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +110 -54
  225. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +125 -69
  226. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +113 -57
  227. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +128 -72
  228. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +110 -54
  229. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +107 -51
  230. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +110 -54
  231. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +116 -60
  232. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +107 -51
  233. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +113 -57
  234. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +107 -51
  235. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +110 -54
  236. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +107 -51
  237. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +107 -51
  238. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +107 -51
  239. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +107 -51
  240. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +113 -57
  241. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +113 -57
  242. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +107 -51
  243. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +113 -57
  244. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +107 -51
  245. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +107 -51
  246. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +107 -51
  247. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +107 -51
  248. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +107 -51
  249. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +107 -51
  250. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +107 -51
  251. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +107 -51
  252. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +107 -51
  253. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +110 -54
  254. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +113 -57
  255. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +107 -51
  256. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +110 -54
  257. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +107 -51
  258. nautobot/project-static/docs/user-guide/index.html +109 -53
  259. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +107 -51
  260. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +113 -57
  261. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +128 -72
  262. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +107 -51
  263. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +125 -69
  264. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +107 -51
  265. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +110 -54
  266. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +125 -69
  267. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +110 -54
  268. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +107 -51
  269. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +107 -51
  270. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +128 -72
  271. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +113 -57
  272. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +113 -57
  273. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +110 -54
  274. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +119 -63
  275. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +107 -51
  276. nautobot/project-static/docs/user-guide/platform-functionality/note.html +110 -54
  277. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +116 -60
  278. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +110 -54
  279. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +131 -75
  280. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +149 -93
  281. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +110 -54
  282. nautobot/project-static/docs/user-guide/platform-functionality/role.html +107 -51
  283. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +116 -60
  284. nautobot/project-static/docs/user-guide/platform-functionality/status.html +119 -63
  285. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +110 -54
  286. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +137 -81
  287. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +110 -54
  288. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +107 -51
  289. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +110 -54
  290. nautobot/tenancy/views.py +2 -6
  291. nautobot/virtualization/views.py +5 -9
  292. {nautobot-2.2.3.dist-info → nautobot-2.2.4.dist-info}/METADATA +2 -2
  293. {nautobot-2.2.3.dist-info → nautobot-2.2.4.dist-info}/RECORD +297 -294
  294. nautobot/project-static/docs/assets/javascripts/bundle.bd41221c.min.js +0 -29
  295. nautobot/project-static/docs/assets/javascripts/bundle.bd41221c.min.js.map +0 -7
  296. nautobot/project-static/docs/assets/stylesheets/main.bcfcd587.min.css +0 -1
  297. nautobot/project-static/docs/assets/stylesheets/main.bcfcd587.min.css.map +0 -1
  298. {nautobot-2.2.3.dist-info → nautobot-2.2.4.dist-info}/LICENSE.txt +0 -0
  299. {nautobot-2.2.3.dist-info → nautobot-2.2.4.dist-info}/NOTICE +0 -0
  300. {nautobot-2.2.3.dist-info → nautobot-2.2.4.dist-info}/WHEEL +0 -0
  301. {nautobot-2.2.3.dist-info → nautobot-2.2.4.dist-info}/entry_points.txt +0 -0
nautobot/core/settings.py CHANGED
@@ -69,7 +69,7 @@ ALLOWED_URL_SCHEMES = [
69
69
  "xmpp",
70
70
  ]
71
71
 
72
- # Banners to display to users. HTML is allowed.
72
+ # Banners to display to users. Markdown and limited HTML are allowed.
73
73
  if "NAUTOBOT_BANNER_BOTTOM" in os.environ and os.environ["NAUTOBOT_BANNER_BOTTOM"] != "":
74
74
  BANNER_BOTTOM = os.environ["NAUTOBOT_BANNER_BOTTOM"]
75
75
  if "NAUTOBOT_BANNER_LOGIN" in os.environ and os.environ["NAUTOBOT_BANNER_LOGIN"] != "":
@@ -686,15 +686,15 @@ CONSTANCE_CONFIG = {
686
686
  ),
687
687
  "BANNER_BOTTOM": ConstanceConfigItem(
688
688
  default="",
689
- help_text="Custom HTML to display in a banner at the bottom of all pages.",
689
+ help_text="Custom Markdown or limited HTML to display in a banner at the bottom of all pages.",
690
690
  ),
691
691
  "BANNER_LOGIN": ConstanceConfigItem(
692
692
  default="",
693
- help_text="Custom HTML to display in a banner at the top of the login page.",
693
+ help_text="Custom Markdown or limited HTML to display in a banner at the top of the login page.",
694
694
  ),
695
695
  "BANNER_TOP": ConstanceConfigItem(
696
696
  default="",
697
- help_text="Custom HTML to display in a banner at the top of all pages.",
697
+ help_text="Custom Markdown or limited HTML to display in a banner at the top of all pages.",
698
698
  ),
699
699
  "CHANGELOG_RETENTION": ConstanceConfigItem(
700
700
  default=90,
@@ -972,6 +972,8 @@ BRANDING_FILEPATHS = {
972
972
  "NAUTOBOT_BRANDING_FILEPATHS_HEADER_BULLET", None
973
973
  ), # bullet image used for various view headers
974
974
  "nav_bullet": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_NAV_BULLET", None), # bullet image used for nav menu headers
975
+ "css": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_CSS", None), # Custom global CSS
976
+ "javascript": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_JAVASCRIPT", None), # Custom global JavaScript
975
977
  }
976
978
 
977
979
  # Title to use in place of "Nautobot"
@@ -128,24 +128,40 @@ properties:
128
128
  type: "array"
129
129
  BANNER_BOTTOM:
130
130
  default: ""
131
- description: "Custom content to be displayed in a banner at the bottom of the page. HTML is allowed."
131
+ description: >-
132
+ Custom content to be displayed in a banner at the bottom of all Nautobot pages.
133
+ details: |-
134
+ +/- 2.2.4
135
+ Markdown formatting is supported within this message, as well as
136
+ [a limited subset of HTML](../../platform-functionality/template-filters.md#render_markdown).
132
137
  environment_variable: "NAUTOBOT_BANNER_BOTTOM"
133
138
  is_constance_config: true
134
139
  type: "string"
135
140
  BANNER_LOGIN:
136
141
  default: ""
137
- description: "Custom content to be displayed on the login page above the login form. HTML is allowed."
142
+ description: >-
143
+ Custom content to be displayed in a banner on the login page above the login form.
144
+ details: |-
145
+ +/- 2.2.4
146
+ Markdown formatting is supported within this message, as well as
147
+ [a limited subset of HTML](../../platform-functionality/template-filters.md#render_markdown).
138
148
  environment_variable: "NAUTOBOT_BANNER_LOGIN"
139
149
  is_constance_config: true
140
150
  type: "string"
141
151
  BANNER_TOP:
142
152
  default: ""
143
- description: "Custom content to be displayed in a banner at the top of the page. HTML is allowed."
153
+ description: >-
154
+ Custom content to be displayed in a banner at the top of all Nautobot pages.
155
+ details: |-
156
+ +/- 2.2.4
157
+ Markdown formatting is supported within this message, as well as
158
+ [a limited subset of HTML](../../platform-functionality/template-filters.md#render_markdown).
144
159
  environment_variable: "NAUTOBOT_BANNER_TOP"
145
160
  is_constance_config: true
146
161
  type: "string"
147
162
  BRANDING_FILEPATHS:
148
163
  default:
164
+ css: null
149
165
  favicon: null
150
166
  header_bullet: null
151
167
  icon_16: null
@@ -153,57 +169,76 @@ properties:
153
169
  icon_180: null
154
170
  icon_192: null
155
171
  icon_mask: null
172
+ javascript: null
156
173
  logo: null
157
174
  nav_bullet: null
158
175
  description: >-
159
- A set of filepaths relative to the [`MEDIA_ROOT`](#media_root) which locate image assets used for
160
- custom branding. Each of these assets takes the place of the corresponding stock Nautobot asset.
176
+ A set of filepaths relative to the [`MEDIA_ROOT`](#media_root) which locate assets used for
177
+ custom branding of your Nautobot instance.
178
+ With the exception of `css` and `javascript`, which provide the option to add an _additional_ file to Nautobot
179
+ page content, each of the other assets takes the place of the corresponding stock Nautobot asset.
161
180
  This allows for, for instance, providing your own navbar logo and favicon.
162
- If a custom image asset is not provided for any of the above options, the stock Nautobot asset is used.
181
+ If a custom asset is not provided for any of the above options, the stock Nautobot asset is used.
182
+ details: |-
183
+ +++ 2.1.0
184
+ The `header_bullet` and `nav_bullet` assets were added as options.
185
+
186
+ +++ 2.2.4
187
+ The `css` and `javascript` assets were added as options.
163
188
  properties:
189
+ css:
190
+ "$ref": "#/definitions/relative_path"
191
+ default: null
192
+ description: "Custom global CSS file"
193
+ environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_CSS"
164
194
  favicon:
165
195
  "$ref": "#/definitions/relative_path"
166
- default: ""
196
+ default: null
167
197
  description: "Browser favicon"
168
198
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_FAVICON"
169
199
  header_bullet:
170
200
  "$ref": "#/definitions/relative_path"
171
- default: ""
201
+ default: null
172
202
  description: "Bullet image used for various view headers"
173
203
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_HEADER_BULLET"
174
204
  icon_16:
175
205
  "$ref": "#/definitions/relative_path"
176
- default: ""
206
+ default: null
177
207
  description: "16x16px icon"
178
208
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_ICON_16"
179
209
  icon_180:
180
210
  "$ref": "#/definitions/relative_path"
181
- default: ""
211
+ default: null
182
212
  description: "180x180px icon - used for the apple-touch-icon header"
183
213
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_ICON_180"
184
214
  icon_192:
185
215
  "$ref": "#/definitions/relative_path"
186
- default: ""
216
+ default: null
187
217
  description: "192x192px icon"
188
218
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_ICON_192"
189
219
  icon_32:
190
220
  "$ref": "#/definitions/relative_path"
191
- default: ""
221
+ default: null
192
222
  description: "32x32px icon"
193
223
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_ICON_32"
194
224
  icon_mask:
195
225
  "$ref": "#/definitions/relative_path"
196
- default: ""
226
+ default: null
197
227
  description: "Mono-chrome icon used for the mask-icon header"
198
228
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_ICON_MASK"
229
+ javascript:
230
+ "$ref": "#/definitions/relative_path"
231
+ default: null
232
+ description: "Custom global JavaScript file"
233
+ environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_JAVASCRIPT"
199
234
  logo:
200
235
  "$ref": "#/definitions/relative_path"
201
- default: ""
236
+ default: null
202
237
  description: "Navbar logo"
203
238
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_LOGO"
204
239
  nav_bullet:
205
240
  "$ref": "#/definitions/relative_path"
206
- default: ""
241
+ default: null
207
242
  description: "Bullet image used for nav menu headers"
208
243
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_NAV_BULLET"
209
244
  type: "object"
@@ -1135,7 +1170,7 @@ properties:
1135
1170
  !!! note
1136
1171
  The Docker container normally attempts to run migrations on startup; however, if the database is
1137
1172
  in a read-only state the Docker container will fail to start. Setting the environment variable
1138
- [`NAUTOBOT_DOCKER_SKIP_INIT`](../installation/docker.md#nautobot_docker_skip_init) to `true`
1173
+ [`NAUTOBOT_DOCKER_SKIP_INIT`](../installation-extras/docker.md#nautobot_docker_skip_init) to `true`
1139
1174
  will prevent the migrations from occurring.
1140
1175
 
1141
1176
  !!! note
@@ -56,7 +56,7 @@
56
56
  {% if not is_popup %}
57
57
  {% if "BANNER_TOP"|settings_or_config %}
58
58
  <div class="alert alert-info text-center" role="alert">
59
- {{ "BANNER_TOP"|settings_or_config|safe }}
59
+ {{ "BANNER_TOP"|settings_or_config|render_markdown }}
60
60
  </div>
61
61
  {% endif %}
62
62
  {% if settings.MAINTENANCE_MODE %}
@@ -107,7 +107,7 @@
107
107
  <div class="push"></div>
108
108
  {% if "BANNER_BOTTOM"|settings_or_config %}
109
109
  <div class="alert alert-info text-center banner-bottom" role="alert">
110
- {{ "BANNER_BOTTOM"|settings_or_config|safe }}
110
+ {{ "BANNER_BOTTOM"|settings_or_config|render_markdown }}
111
111
  </div>
112
112
  {% endif %}
113
113
  </div>
@@ -16,7 +16,7 @@
16
16
  {% if request.user.is_authenticated %}
17
17
  {% if "BANNER_TOP"|settings_or_config %}
18
18
  <div class="alert alert-info text-center" role="alert">
19
- {{ "BANNER_TOP"|settings_or_config|safe }}
19
+ {{ "BANNER_TOP"|settings_or_config|render_markdown }}
20
20
  </div>
21
21
  {% endif %}
22
22
  {% endif %}
@@ -42,7 +42,7 @@
42
42
  {% if request.user.is_authenticated %}
43
43
  {% if "BANNER_BOTTOM"|settings_or_config %}
44
44
  <div class="alert alert-info text-center banner-bottom" role="alert">
45
- {{ "BANNER_BOTTOM"|settings_or_config|safe }}
45
+ {{ "BANNER_BOTTOM"|settings_or_config|render_markdown }}
46
46
  </div>
47
47
  {% endif %}
48
48
  {% endif %}
@@ -1,60 +1,60 @@
1
1
  {% if export_url %}
2
2
  {% if export_templates or include_yaml_option %}
3
- <form style="display: inline-block" action="{{ export_url }}" method="post">
4
- {% csrf_token %}
5
- <input type="hidden" name="content_type" value="{{ content_type.pk }}">
6
- <input type="hidden" name="query_string" value="{{ query_string }}">
7
- <input type="hidden" name="export_format"
8
- value="{% if include_yaml_option %}yaml{% else %}csv{% endif %}">
9
- <input type="hidden" name="_schedule_type" value="immediately">
10
- <div class="btn-group">
11
- <button type="submit" class="btn btn-success">
12
- <span class="mdi mdi-database-export" aria-hidden="true"></span>
13
- Export
14
- </button>
15
- <button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
16
- <span class="caret"></span>
17
- <span class="sr-only">Toggle Dropdown</span>
18
- </button>
19
- <ul class="dropdown-menu dropdown-menu-right">
20
- {% if include_yaml_option %}
21
- <li>
22
- <button type="submit" class="btn btn-link">YAML format</button>
23
- </li>
3
+ <div class="btn-group">
4
+ <button type="submit" class="btn btn-success" form="export_default">
5
+ <span class="mdi mdi-database-export" aria-hidden="true"></span>
6
+ Export
7
+ </button>
8
+ <form id="export_default" style="display: inline-block" action="{{ export_url }}" method="post">
9
+ {% csrf_token %}
10
+ <input type="hidden" name="content_type" value="{{ content_type.pk }}">
11
+ <input type="hidden" name="query_string" value="{{ query_string }}">
12
+ <input type="hidden" name="export_format"
13
+ value="{% if include_yaml_option %}yaml{% else %}csv{% endif %}">
14
+ <input type="hidden" name="_schedule_type" value="immediately">
15
+ </form>
16
+ <button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
17
+ <span class="caret"></span>
18
+ <span class="sr-only">Toggle Dropdown</span>
19
+ </button>
20
+ <ul class="dropdown-menu dropdown-menu-right">
21
+ {% if include_yaml_option %}
22
+ <li>
23
+ <button type="submit" class="btn btn-link" form="export_default">YAML format</button>
24
+ </li>
25
+ <li>
26
+ <form action="{{ export_url }}" method="post">
27
+ {% csrf_token %}
28
+ <input type="hidden" name="content_type" value="{{ content_type.pk }}">
29
+ <input type="hidden" name="query_string" value="{{ query_string }}">
30
+ <input type="hidden" name="_schedule_type" value="immediately">
31
+ <button type="submit" class="btn btn-link">CSV format</button>
32
+ </form>
33
+ </li>
34
+ {% else %}
35
+ <li>
36
+ <button type="submit" class="btn btn-link" form="export_default">CSV format</button>
37
+ </li>
38
+ {% endif %}
39
+ {% if export_templates %}
40
+ <li class="divider"></li>
41
+ {% for et in export_templates %}
24
42
  <li>
25
43
  <form action="{{ export_url }}" method="post">
26
44
  {% csrf_token %}
27
45
  <input type="hidden" name="content_type" value="{{ content_type.pk }}">
46
+ <input type="hidden" name="export_template" value="{{ et.pk }}">
28
47
  <input type="hidden" name="query_string" value="{{ query_string }}">
29
48
  <input type="hidden" name="_schedule_type" value="immediately">
30
- <button type="submit" class="btn btn-link">CSV format</button>
49
+ <button type="submit" class="btn btn-link"
50
+ {% if et.description %}title="{{ et.description }}"{% endif %}
51
+ >{{ et.name }}</button>
31
52
  </form>
32
53
  </li>
33
- {% else %}
34
- <li>
35
- <button type="submit" class="btn btn-link">CSV format</button>
36
- </li>
37
- {% endif %}
38
- {% if export_templates %}
39
- <li class="divider"></li>
40
- {% for et in export_templates %}
41
- <li>
42
- <form action="{{ export_url }}" method="post">
43
- {% csrf_token %}
44
- <input type="hidden" name="content_type" value="{{ content_type.pk }}">
45
- <input type="hidden" name="export_template" value="{{ et.pk }}">
46
- <input type="hidden" name="query_string" value="{{ query_string }}">
47
- <input type="hidden" name="_schedule_type" value="immediately">
48
- <button type="submit" class="btn btn-link"
49
- {% if et.description %}title="{{ et.description }}"{% endif %}
50
- >{{ et.name }}</button>
51
- </form>
52
- </li>
53
- {% endfor %}
54
- {% endif %}
55
- </ul>
56
- </div>
57
- </form>
54
+ {% endfor %}
55
+ {% endif %}
56
+ </ul>
57
+ </div>
58
58
  {% else %}
59
59
  <form style="display: inline-block" action="{{ export_url }}" method="post">
60
60
  {% csrf_token %}
@@ -40,3 +40,6 @@
40
40
  hljs.configure({ cssSelector: '.language-graphql, .language-json, .language-xml, .language-yaml' });
41
41
  hljs.highlightAll();
42
42
  </script>
43
+ {% if settings.BRANDING_FILEPATHS.javascript %}
44
+ <script src="{% custom_branding_or_static 'javascript' None %}"></script>
45
+ {% endif %}
@@ -34,6 +34,9 @@
34
34
  <link rel="stylesheet" id="base-theme"
35
35
  href="{% versioned_static 'css/base.css' %}"
36
36
  onerror="window.location='{% url 'media_failure' %}?filename=css/base.css'">
37
+ {% if settings.BRANDING_FILEPATHS.css %}
38
+ <link rel="stylesheet" id="custom-css" href="{% custom_branding_or_static 'css' None %}">
39
+ {% endif %}
37
40
  <link rel="apple-touch-icon" sizes="180x180" href="{% custom_branding_or_static 'icon_180' 'img/nautobot_icon_180x180.png' %}">
38
41
  <link rel="icon" type="image/png" sizes="32x32" href="{% custom_branding_or_static 'icon_32' 'img/nautobot_icon_32x32.png' %}">
39
42
  <link rel="icon" type="image/png" sizes="16x16" href="{% custom_branding_or_static 'icon_16' 'img/nautobot_icon_16x16.png' %}">
@@ -53,8 +53,8 @@
53
53
  <div class="row" style="margin-top: {% if 'BANNER_LOGIN'|settings_or_config %}100{% else %}150{% endif %}px;">
54
54
  <div class="col-sm-4 col-sm-offset-4">
55
55
  {% if "BANNER_LOGIN"|settings_or_config %}
56
- <div style="margin-bottom: 25px">
57
- {{ "BANNER_LOGIN"|settings_or_config|safe }}
56
+ <div class="alert alert-info text-center" role="alert">
57
+ {{ "BANNER_LOGIN"|settings_or_config|render_markdown }}
58
58
  </div>
59
59
  {% endif %}
60
60
  {% if form.non_field_errors %}
@@ -248,6 +248,8 @@ SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "{{ secret_key }}")
248
248
  # "NAUTOBOT_BRANDING_FILEPATHS_HEADER_BULLET", None
249
249
  # ), # bullet image used for various view headers
250
250
  # "nav_bullet": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_NAV_BULLET", None), # bullet image used for nav menu headers
251
+ # "css": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_CSS", None), # Custom global CSS
252
+ # "javascript": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_JAVASCRIPT", None), # Custom global JavaScript
251
253
  # }
252
254
 
253
255
  # Prepended to CSV, YAML and export template filenames (i.e. `nautobot_device.yml`)
@@ -4,9 +4,9 @@ from django.contrib.contenttypes.models import ContentType
4
4
  import yaml
5
5
 
6
6
  from nautobot.core.testing import create_job_result_and_run_job, TransactionTestCase
7
- from nautobot.dcim.models import DeviceType, Manufacturer
7
+ from nautobot.dcim.models import DeviceType, Location, LocationType, Manufacturer
8
8
  from nautobot.extras.choices import JobResultStatusChoices, LogLevelChoices
9
- from nautobot.extras.models import ExportTemplate, JobLogEntry, Status
9
+ from nautobot.extras.models import Contact, ContactAssociation, ExportTemplate, JobLogEntry, Role, Status
10
10
  from nautobot.users.models import ObjectPermission
11
11
 
12
12
 
@@ -256,3 +256,80 @@ class ImportObjectsTestCase(TransactionTestCase):
256
256
  self.assertEqual(log_successes[3].message, 'Row 5: Created record "test_status4"')
257
257
  self.assertTrue(Status.objects.filter(name="test_status4").exists())
258
258
  self.assertEqual(log_successes[4].message, "Created 4 status object(s) from 5 row(s) of data")
259
+
260
+ def test_csv_import_contact_assignment(self):
261
+ location_types_csv = "\n".join(["name", "ContactAssignmentImportTestLocationType"])
262
+ locations_csv = "\n".join(
263
+ [
264
+ "location_type__name,name,status__name",
265
+ "ContactAssignmentImportTestLocationType,ContactAssignmentImportTestLocation1,Active",
266
+ "ContactAssignmentImportTestLocationType,ContactAssignmentImportTestLocation2,Active",
267
+ ]
268
+ )
269
+ roles_csv = "\n".join(
270
+ [
271
+ "name,content_types",
272
+ "ContactAssignmentImportTestLocation-On Site,extras.contactassociation",
273
+ ]
274
+ )
275
+ contacts_csv = "\n".join(["name,email", "Bob-ContactAssignmentImportTestLocation,bob@example.com"])
276
+
277
+ location_types_job_result = create_job_result_and_run_job(
278
+ "nautobot.core.jobs",
279
+ "ImportObjects",
280
+ content_type=ContentType.objects.get_for_model(LocationType).pk,
281
+ csv_data=location_types_csv,
282
+ )
283
+ self.assertEqual(location_types_job_result.status, JobResultStatusChoices.STATUS_SUCCESS)
284
+
285
+ location_type_count = LocationType.objects.filter(name="ContactAssignmentImportTestLocationType").count()
286
+ self.assertEqual(location_type_count, 1, f"Unexpected count of LocationTypes {location_type_count}")
287
+
288
+ locations_job_result = create_job_result_and_run_job(
289
+ "nautobot.core.jobs",
290
+ "ImportObjects",
291
+ content_type=ContentType.objects.get_for_model(Location).pk,
292
+ csv_data=locations_csv,
293
+ )
294
+ self.assertEqual(locations_job_result.status, JobResultStatusChoices.STATUS_SUCCESS)
295
+
296
+ location_count = Location.objects.filter(location_type__name="ContactAssignmentImportTestLocationType").count()
297
+ self.assertEqual(location_count, 2, f"Unexpected count of Locations {location_count}")
298
+
299
+ contacts_job_result = create_job_result_and_run_job(
300
+ "nautobot.core.jobs",
301
+ "ImportObjects",
302
+ content_type=ContentType.objects.get_for_model(Contact).pk,
303
+ csv_data=contacts_csv,
304
+ )
305
+ self.assertEqual(contacts_job_result.status, JobResultStatusChoices.STATUS_SUCCESS)
306
+
307
+ contact_count = Contact.objects.filter(name="Bob-ContactAssignmentImportTestLocation").count()
308
+ self.assertEqual(contact_count, 1, f"Unexpected number of contacts {contact_count}")
309
+
310
+ roles_job_result = create_job_result_and_run_job(
311
+ "nautobot.core.jobs",
312
+ "ImportObjects",
313
+ content_type=ContentType.objects.get_for_model(Role).pk,
314
+ csv_data=roles_csv,
315
+ )
316
+ self.assertEqual(roles_job_result.status, JobResultStatusChoices.STATUS_SUCCESS)
317
+
318
+ role_count = Role.objects.filter(name="ContactAssignmentImportTestLocation-On Site").count()
319
+ self.assertEqual(role_count, 1, f"Unexpected number of role values {role_count}")
320
+
321
+ associations = ["associated_object_id,associated_object_type,status__name,role__name,contact__name"]
322
+ for location in Location.objects.filter(location_type__name="ContactAssignmentImportTestLocationType"):
323
+ associations.append(
324
+ f"{location.pk},dcim.location,Active,ContactAssignmentImportTestLocation-On Site,Bob-ContactAssignmentImportTestLocation"
325
+ )
326
+ associations_csv = "\n".join(associations)
327
+
328
+ associations_job_result = create_job_result_and_run_job(
329
+ "nautobot.core.jobs",
330
+ "ImportObjects",
331
+ content_type=ContentType.objects.get_for_model(ContactAssociation).pk,
332
+ csv_data=associations_csv,
333
+ )
334
+
335
+ self.assertEqual(associations_job_result.status, JobResultStatusChoices.STATUS_SUCCESS)
@@ -146,6 +146,39 @@ class HomeViewTestCase(TestCase):
146
146
  response_content = response.content.decode(response.charset).replace("\n", "")
147
147
  self.assertNotRegex(response_content, footer_hostname_version_pattern)
148
148
 
149
+ def test_banners_markdown(self):
150
+ url = reverse("home")
151
+ with override_settings(
152
+ BANNER_TOP="# Hello world",
153
+ BANNER_BOTTOM="[info](https://nautobot.com)",
154
+ ):
155
+ response = self.client.get(url)
156
+ self.assertInHTML("<h1>Hello world</h1>", response.content.decode(response.charset))
157
+ self.assertInHTML(
158
+ '<a href="https://nautobot.com" rel="noopener noreferrer">info</a>',
159
+ response.content.decode(response.charset),
160
+ )
161
+
162
+ with override_settings(BANNER_LOGIN="_Welcome to Nautobot!_"):
163
+ self.client.logout()
164
+ response = self.client.get(reverse("login"))
165
+ self.assertInHTML("<em>Welcome to Nautobot!</em>", response.content.decode(response.charset))
166
+
167
+ def test_banners_no_xss(self):
168
+ url = reverse("home")
169
+ with override_settings(
170
+ BANNER_TOP='<script>alert("Hello from above!");</script>',
171
+ BANNER_BOTTOM='<script>alert("Hello from below!");</script>',
172
+ ):
173
+ response = self.client.get(url)
174
+ self.assertNotIn("Hello from above", response.content.decode(response.charset))
175
+ self.assertNotIn("Hello from below", response.content.decode(response.charset))
176
+
177
+ with override_settings(BANNER_LOGIN='<script>alert("Welcome to Nautobot!");</script>'):
178
+ self.client.logout()
179
+ response = self.client.get(reverse("login"))
180
+ self.assertNotIn("Welcome to Nautobot!", response.content.decode(response.charset))
181
+
149
182
 
150
183
  @override_settings(BRANDING_TITLE="Nautobot")
151
184
  class SearchFieldsTestCase(TestCase):
@@ -485,6 +485,10 @@ class NautobotViewSetMixin(GenericViewSet, AccessMixin, GetReturnURLMixin, FormV
485
485
  request: The current request
486
486
  instance: The object being viewed
487
487
  """
488
+ if instance is not None:
489
+ return {
490
+ "active_tab": request.GET.get("tab", "main"),
491
+ }
488
492
  return {}
489
493
 
490
494
  def get_template_name(self):