nautobot 2.0.5__py3-none-any.whl → 2.1.0b1__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 (376) hide show
  1. nautobot/circuits/navigation.py +0 -25
  2. nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -9
  3. nautobot/circuits/templates/circuits/providernetwork_retrieve.html +0 -2
  4. nautobot/circuits/tests/test_filters.py +1 -0
  5. nautobot/core/api/serializers.py +15 -5
  6. nautobot/core/api/views.py +18 -19
  7. nautobot/core/choices.py +1 -1
  8. nautobot/core/filters.py +12 -4
  9. nautobot/core/jobs/__init__.py +125 -3
  10. nautobot/core/management/commands/generate_test_data.py +4 -1
  11. nautobot/core/models/fields.py +12 -2
  12. nautobot/core/settings.py +8 -7
  13. nautobot/core/templates/base_django.html +2 -2
  14. nautobot/core/templates/buttons/export.html +57 -30
  15. nautobot/core/templates/generic/object_list.html +2 -2
  16. nautobot/core/templates/generic/object_retrieve.html +8 -1
  17. nautobot/core/templates/home.html +5 -5
  18. nautobot/core/templates/inc/created_updated.html +2 -2
  19. nautobot/core/templates/inc/footer.html +2 -2
  20. nautobot/core/templates/inc/javascript.html +0 -10
  21. nautobot/core/templates/inc/media.html +2 -0
  22. nautobot/core/templates/inc/nav_menu.html +66 -68
  23. nautobot/core/templates/inc/object_details_advanced_panel.html +19 -0
  24. nautobot/core/templates/nautobot_config.py.j2 +10 -4
  25. nautobot/core/templates/panel_table.html +1 -1
  26. nautobot/core/templates/template.css +89 -0
  27. nautobot/core/templates/utilities/templatetags/table_config_form.html +1 -0
  28. nautobot/core/templatetags/buttons.py +7 -2
  29. nautobot/core/testing/views.py +34 -4
  30. nautobot/core/tests/integration/test_home.py +1 -43
  31. nautobot/core/tests/integration/test_navbar.py +10 -64
  32. nautobot/core/tests/integration/test_plugin_home.py +4 -5
  33. nautobot/core/tests/integration/test_plugin_navbar.py +20 -16
  34. nautobot/core/tests/integration/test_theme.py +4 -0
  35. nautobot/core/tests/test_api.py +14 -66
  36. nautobot/core/tests/test_filters.py +127 -0
  37. nautobot/core/tests/test_forms.py +1 -1
  38. nautobot/core/tests/test_graphql.py +165 -2
  39. nautobot/core/tests/test_jobs.py +112 -0
  40. nautobot/core/tests/test_openapi.py +6 -0
  41. nautobot/core/tests/test_views.py +11 -85
  42. nautobot/core/urls.py +6 -1
  43. nautobot/core/utils/lookup.py +28 -0
  44. nautobot/core/utils/requests.py +2 -3
  45. nautobot/core/views/__init__.py +3 -4
  46. nautobot/core/views/generic.py +9 -4
  47. nautobot/core/views/mixins.py +4 -2
  48. nautobot/core/views/renderers.py +5 -0
  49. nautobot/dcim/models/device_components.py +1 -0
  50. nautobot/dcim/navigation.py +10 -165
  51. nautobot/dcim/templates/dcim/location.html +1 -1
  52. nautobot/dcim/tests/features/locations.feature +143 -0
  53. nautobot/dcim/tests/test_api.py +1 -1
  54. nautobot/dcim/tests/test_filters.py +11 -3
  55. nautobot/extras/admin.py +1 -1
  56. nautobot/extras/api/serializers.py +33 -0
  57. nautobot/extras/api/urls.py +6 -0
  58. nautobot/extras/api/views.py +45 -6
  59. nautobot/extras/factory.py +28 -2
  60. nautobot/extras/filters/__init__.py +52 -0
  61. nautobot/extras/filters/mixins.py +4 -29
  62. nautobot/extras/forms/forms.py +43 -0
  63. nautobot/extras/jobs.py +31 -9
  64. nautobot/extras/migrations/0100_fileproxy_job_result.py +32 -0
  65. nautobot/extras/migrations/0101_externalintegration.py +61 -0
  66. nautobot/extras/migrations/0102_set_null_objectchange_contenttype.py +32 -0
  67. nautobot/extras/models/__init__.py +2 -0
  68. nautobot/extras/models/change_logging.py +2 -2
  69. nautobot/extras/models/models.py +96 -16
  70. nautobot/extras/navigation.py +17 -29
  71. nautobot/extras/signals.py +15 -0
  72. nautobot/extras/tables.py +27 -0
  73. nautobot/extras/templates/extras/externalintegration_retrieve.html +37 -0
  74. nautobot/extras/templates/extras/inc/jobresult.html +24 -0
  75. nautobot/extras/templates/extras/jobresult.html +24 -0
  76. nautobot/extras/test_jobs/file_output.py +16 -0
  77. nautobot/extras/tests/test_api.py +92 -0
  78. nautobot/extras/tests/test_filters.py +64 -2
  79. nautobot/extras/tests/test_jobs.py +39 -0
  80. nautobot/extras/tests/test_models.py +34 -0
  81. nautobot/extras/tests/test_views.py +22 -2
  82. nautobot/extras/urls.py +1 -0
  83. nautobot/extras/views.py +15 -0
  84. nautobot/ipam/forms.py +16 -0
  85. nautobot/ipam/models.py +3 -0
  86. nautobot/ipam/navigation.py +2 -59
  87. nautobot/ipam/templates/ipam/ipaddress.html +0 -9
  88. nautobot/ipam/templates/ipam/prefix.html +0 -9
  89. nautobot/ipam/tests/features/prefixes.feature +134 -0
  90. nautobot/ipam/tests/test_filters.py +5 -10
  91. nautobot/ipam/tests/test_views.py +8 -1
  92. nautobot/ipam/views.py +3 -0
  93. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.css +191 -191
  94. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.css.map +1 -1
  95. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css +1 -1
  96. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css.map +1 -1
  97. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css +874 -881
  98. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css.map +1 -1
  99. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css +1 -1
  100. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css.map +1 -1
  101. nautobot/project-static/css/base.css +135 -99
  102. nautobot/project-static/css/dark.css +65 -6
  103. nautobot/project-static/docs/404.html +44 -16
  104. nautobot/project-static/docs/apps/index.html +44 -16
  105. nautobot/project-static/docs/apps/nautobot-apps.html +44 -16
  106. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +44 -16
  107. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +44 -16
  108. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +1597 -1457
  109. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +44 -16
  110. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +45 -17
  111. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +44 -16
  112. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +44 -16
  113. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +44 -16
  114. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +44 -16
  115. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +353 -432
  116. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +66 -38
  117. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +44 -16
  118. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2154 -2307
  119. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +807 -691
  120. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +44 -16
  121. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +44 -16
  122. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +58 -30
  123. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +3600 -3456
  124. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +44 -16
  125. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +44 -16
  126. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +101 -75
  127. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +3083 -3019
  128. nautobot/project-static/docs/development/apps/api/configuration-view.html +44 -16
  129. nautobot/project-static/docs/development/apps/api/database-backend-config.html +44 -16
  130. nautobot/project-static/docs/development/apps/api/models/django-admin.html +44 -16
  131. nautobot/project-static/docs/development/apps/api/models/global-search.html +44 -16
  132. nautobot/project-static/docs/development/apps/api/models/graphql.html +44 -16
  133. nautobot/project-static/docs/development/apps/api/models/index.html +44 -16
  134. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +44 -16
  135. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +44 -16
  136. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +44 -16
  137. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +44 -16
  138. nautobot/project-static/docs/development/apps/api/platform-features/index.html +44 -16
  139. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +44 -16
  140. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +44 -16
  141. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +44 -16
  142. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +44 -16
  143. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +44 -16
  144. nautobot/project-static/docs/development/apps/api/prometheus.html +44 -16
  145. nautobot/project-static/docs/development/apps/api/setup.html +44 -16
  146. nautobot/project-static/docs/development/apps/api/testing.html +44 -16
  147. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +44 -16
  148. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +44 -16
  149. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +44 -16
  150. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +44 -16
  151. nautobot/project-static/docs/development/apps/api/ui-extensions/object-detail-views.html +44 -16
  152. nautobot/project-static/docs/development/apps/api/ui-extensions/tabs.html +44 -16
  153. nautobot/project-static/docs/development/apps/api/views/base-template.html +44 -16
  154. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +44 -16
  155. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +44 -16
  156. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +44 -16
  157. nautobot/project-static/docs/development/apps/api/views/index.html +44 -16
  158. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +44 -16
  159. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +44 -16
  160. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +44 -16
  161. nautobot/project-static/docs/development/apps/api/views/notes.html +44 -16
  162. nautobot/project-static/docs/development/apps/api/views/rest-api.html +44 -16
  163. nautobot/project-static/docs/development/apps/api/views/urls.html +44 -16
  164. nautobot/project-static/docs/development/apps/api/views/view-overrides.html +44 -16
  165. nautobot/project-static/docs/development/apps/index.html +44 -16
  166. nautobot/project-static/docs/development/apps/migration/code-updates.html +44 -16
  167. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +44 -16
  168. nautobot/project-static/docs/development/apps/migration/from-v1.html +44 -16
  169. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +44 -16
  170. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +44 -16
  171. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +44 -16
  172. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +44 -16
  173. nautobot/project-static/docs/development/apps/porting-from-netbox.html +44 -16
  174. nautobot/project-static/docs/development/core/application-registry.html +44 -16
  175. nautobot/project-static/docs/development/core/best-practices.html +44 -16
  176. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +44 -16
  177. nautobot/project-static/docs/development/core/extending-models.html +44 -16
  178. nautobot/project-static/docs/development/core/generic-views.html +44 -16
  179. nautobot/project-static/docs/development/core/getting-started.html +44 -16
  180. nautobot/project-static/docs/development/core/homepage.html +44 -16
  181. nautobot/project-static/docs/development/core/index.html +44 -16
  182. nautobot/project-static/docs/development/core/model-features.html +44 -16
  183. nautobot/project-static/docs/development/core/natural-keys.html +44 -16
  184. nautobot/project-static/docs/development/core/navigation-menu.html +44 -21
  185. nautobot/project-static/docs/development/core/react-ui.html +44 -16
  186. nautobot/project-static/docs/development/core/release-checklist.html +44 -16
  187. nautobot/project-static/docs/development/core/role-internals.html +44 -16
  188. nautobot/project-static/docs/development/core/style-guide.html +44 -16
  189. nautobot/project-static/docs/development/core/templates.html +44 -16
  190. nautobot/project-static/docs/development/core/testing.html +44 -16
  191. nautobot/project-static/docs/development/core/user-preferences.html +44 -16
  192. nautobot/project-static/docs/development/index.html +44 -16
  193. nautobot/project-static/docs/development/jobs/index.html +280 -234
  194. nautobot/project-static/docs/development/jobs/migration/from-v1.html +44 -16
  195. nautobot/project-static/docs/index.html +44 -16
  196. nautobot/project-static/docs/objects.inv +0 -0
  197. nautobot/project-static/docs/release-notes/index.html +47 -19
  198. nautobot/project-static/docs/release-notes/version-1.0.html +44 -16
  199. nautobot/project-static/docs/release-notes/version-1.1.html +44 -16
  200. nautobot/project-static/docs/release-notes/version-1.2.html +44 -16
  201. nautobot/project-static/docs/release-notes/version-1.3.html +44 -16
  202. nautobot/project-static/docs/release-notes/version-1.4.html +44 -16
  203. nautobot/project-static/docs/release-notes/version-1.5.html +44 -16
  204. nautobot/project-static/docs/release-notes/version-1.6.html +44 -16
  205. nautobot/project-static/docs/release-notes/version-2.0.html +47 -19
  206. nautobot/project-static/docs/release-notes/version-2.1.html +5724 -0
  207. nautobot/project-static/docs/search/search_index.json +1 -1
  208. nautobot/project-static/docs/sitemap.xml +247 -237
  209. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  210. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +44 -16
  211. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +44 -16
  212. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +44 -16
  213. nautobot/project-static/docs/user-guide/administration/configuration/index.html +44 -16
  214. nautobot/project-static/docs/user-guide/administration/configuration/node-configuration.html +44 -16
  215. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +109 -43
  216. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +44 -16
  217. nautobot/project-static/docs/user-guide/administration/guides/caching.html +44 -16
  218. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +44 -16
  219. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +44 -16
  220. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +44 -16
  221. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +44 -16
  222. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +44 -16
  223. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +48 -19
  224. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +44 -16
  225. nautobot/project-static/docs/user-guide/administration/installation/docker.html +44 -16
  226. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +44 -16
  227. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +44 -16
  228. nautobot/project-static/docs/user-guide/administration/installation/index.html +44 -16
  229. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +44 -16
  230. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +44 -16
  231. nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +44 -16
  232. nautobot/project-static/docs/user-guide/administration/installation/services.html +44 -16
  233. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +44 -16
  234. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +44 -16
  235. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +44 -16
  236. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +44 -16
  237. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +44 -16
  238. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +44 -16
  239. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +44 -16
  240. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +44 -16
  241. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +44 -16
  242. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +44 -16
  243. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +44 -16
  244. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +44 -16
  245. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +44 -16
  246. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +44 -16
  247. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +44 -16
  248. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +44 -16
  249. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +44 -16
  250. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +44 -16
  251. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +44 -16
  252. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +44 -16
  253. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +44 -16
  254. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +44 -16
  255. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +44 -16
  256. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +44 -16
  257. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +44 -16
  258. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +44 -16
  259. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +44 -16
  260. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +44 -16
  261. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +44 -16
  262. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +44 -16
  263. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +44 -16
  264. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +44 -16
  265. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +44 -16
  266. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +44 -16
  267. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +44 -16
  268. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +44 -16
  269. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +44 -16
  270. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +44 -16
  271. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +44 -16
  272. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +44 -16
  273. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +44 -16
  274. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +44 -16
  275. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +44 -16
  276. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +44 -16
  277. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +44 -16
  278. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +44 -16
  279. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +44 -16
  280. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +44 -16
  281. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +44 -16
  282. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +44 -16
  283. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +44 -16
  284. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +44 -16
  285. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +44 -16
  286. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +44 -16
  287. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +44 -16
  288. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +44 -16
  289. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +44 -16
  290. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +44 -16
  291. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +44 -16
  292. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +44 -16
  293. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +44 -16
  294. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +44 -16
  295. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +44 -16
  296. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +44 -16
  297. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +44 -16
  298. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +44 -16
  299. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +44 -16
  300. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +44 -16
  301. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +44 -16
  302. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +44 -16
  303. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +44 -16
  304. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +44 -16
  305. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +44 -16
  306. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +44 -16
  307. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +44 -16
  308. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +44 -16
  309. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +44 -16
  310. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +44 -16
  311. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +44 -16
  312. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +44 -16
  313. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +44 -16
  314. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +44 -16
  315. nautobot/project-static/docs/user-guide/index.html +44 -16
  316. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +110 -16
  317. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +44 -16
  318. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +44 -16
  319. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +44 -16
  320. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +44 -16
  321. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +47 -19
  322. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +5359 -0
  323. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +47 -19
  324. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +44 -16
  325. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +44 -16
  326. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +44 -16
  327. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +44 -16
  328. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +44 -16
  329. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +44 -16
  330. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +44 -16
  331. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +44 -16
  332. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +44 -16
  333. nautobot/project-static/docs/user-guide/platform-functionality/note.html +44 -16
  334. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +44 -16
  335. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +44 -16
  336. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +113 -44
  337. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +44 -16
  338. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +44 -16
  339. nautobot/project-static/docs/user-guide/platform-functionality/role.html +44 -16
  340. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +44 -16
  341. nautobot/project-static/docs/user-guide/platform-functionality/status.html +44 -16
  342. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +44 -16
  343. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +44 -16
  344. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +44 -16
  345. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +44 -16
  346. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +44 -16
  347. nautobot/project-static/fonts/UFL.txt +96 -0
  348. nautobot/project-static/fonts/Ubuntu-Bold.woff2 +0 -0
  349. nautobot/project-static/fonts/Ubuntu-BoldItalic.woff2 +0 -0
  350. nautobot/project-static/fonts/Ubuntu-Italic.woff2 +0 -0
  351. nautobot/project-static/fonts/Ubuntu-Medium.woff2 +0 -0
  352. nautobot/project-static/fonts/Ubuntu-MediumItalic.woff2 +0 -0
  353. nautobot/project-static/fonts/Ubuntu-Regular.woff2 +0 -0
  354. nautobot/project-static/fonts/UbuntuMono-Bold.woff2 +0 -0
  355. nautobot/project-static/fonts/UbuntuMono-BoldItalic.woff2 +0 -0
  356. nautobot/project-static/fonts/UbuntuMono-Italic.woff2 +0 -0
  357. nautobot/project-static/fonts/UbuntuMono-Regular.woff2 +0 -0
  358. nautobot/project-static/img/dark-theme.png +0 -0
  359. nautobot/project-static/img/light-theme.png +0 -0
  360. nautobot/project-static/img/nautobot_chevron.svg +5 -0
  361. nautobot/project-static/img/nautobot_chevron_header.svg +5 -0
  362. nautobot/project-static/img/system-theme.png +0 -0
  363. nautobot/tenancy/navigation.py +0 -13
  364. nautobot/ui/package-lock.json +2 -2
  365. nautobot/ui/package.json +1 -1
  366. nautobot/users/admin.py +44 -0
  367. nautobot/users/migrations/0007_alter_objectpermission_object_types.py +33 -0
  368. nautobot/users/models.py +3 -2
  369. nautobot/virtualization/navigation.py +1 -33
  370. nautobot/virtualization/tests/test_api.py +1 -1
  371. nautobot/virtualization/tests/test_filters.py +1 -1
  372. {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/METADATA +1 -1
  373. {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/RECORD +376 -351
  374. {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/LICENSE.txt +0 -0
  375. {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/WHEEL +0 -0
  376. {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/entry_points.txt +0 -0
@@ -17,14 +17,14 @@
17
17
 
18
18
  {% block content %}
19
19
  {% registry %}
20
- {% if request.user.is_authenticated or not "HIDE_RESTRICTED_UI"|settings_or_config %}
20
+ {% if request.user.is_authenticated %}
21
21
  {% include 'search_form.html' %}
22
22
  {% endif %}
23
23
  <div class="row">
24
24
  <div class="col-sm-12">
25
25
  <div class="homepage_column" style="columns: 4 360px">
26
26
  {% for panel_name, panel_details in registry.homepage_layout.panels.items %}
27
- {% if request.user|has_one_or_more_perms:panel_details.permissions or not "HIDE_RESTRICTED_UI"|settings_or_config %}
27
+ {% if request.user|has_one_or_more_perms:panel_details.permissions %}
28
28
  <div class="panel panel-default" style="break-inside: avoid" data-panel-weight="{{ panel_details.weight }}">
29
29
  <div class="panel-heading">
30
30
  <strong>{{ panel_name }}</strong>
@@ -36,12 +36,12 @@
36
36
  {% for item_name, item_details in panel_details.items.items %}
37
37
  {% if item_details.rendered_html %}
38
38
  <div class="list-group-item" data-item-weight="{{ item_details.weight }}">
39
- {% if request.user|has_one_or_more_perms:item_details.permissions or not "HIDE_RESTRICTED_UI"|settings_or_config %}
39
+ {% if request.user|has_one_or_more_perms:item_details.permissions %}
40
40
  {% autoescape off %}{{ item_details.rendered_html }}{% endautoescape %}
41
41
  {% endif %}
42
42
  </div>
43
43
  {% elif not item_details.items.items %}
44
- {% if request.user|has_one_or_more_perms:item_details.permissions or not "HIDE_RESTRICTED_UI"|settings_or_config %}
44
+ {% if request.user|has_one_or_more_perms:item_details.permissions %}
45
45
  <div class="list-group-item" data-item-weight="{{ item_details.weight }}">
46
46
  {% if request.user|has_perms:item_details.permissions %}
47
47
  <span class="badge pull-right">{{ item_details.count }}</span>
@@ -68,7 +68,7 @@
68
68
  <div class="list-group-item" data-item-weight="{{ item_details.weight }}">
69
69
  <h4 class="list-group-item-heading">{{ item_name }}</h4>
70
70
  {% for group_item_name, group_item_details in item_details.items.items %}
71
- {% if request.user|has_one_or_more_perms:group_item_details.permissions or not "HIDE_RESTRICTED_UI"|settings_or_config %}
71
+ {% if request.user|has_one_or_more_perms:group_item_details.permissions %}
72
72
  {% if request.user|has_perms:group_item_details.permissions %}
73
73
  {% if group_item_details.rendered_html %}
74
74
  {% autoescape off %}
@@ -2,9 +2,9 @@
2
2
  <p>
3
3
  <small class="text-muted">
4
4
  {% if object.created %}
5
- Created {{ object.created }} &middot;
5
+ <span title="{{ object.created }}"><i class="mdi mdi-bookmark-plus"></i> {{ object.created }}</span> |
6
6
  {% endif %}
7
- Updated <span title="{{ object.last_updated }}">{{ object.last_updated|timesince }}</span> ago
7
+ <span title="{{ object.last_updated }}"><i class="mdi mdi-clock"></i> {{ object.last_updated|timesince }}</span> ago
8
8
  </small>
9
9
  </p>
10
10
  {% endif %}
@@ -6,7 +6,7 @@
6
6
  <div class="container-fluid">
7
7
  <div class="row">
8
8
  <div class="col-xs-4">
9
- {% if request.user.is_authenticated or not "HIDE_RESTRICTED_UI"|settings_or_config %}
9
+ {% if request.user.is_authenticated %}
10
10
  <p class="text-muted">
11
11
  {% if settings.BRANDING_FILEPATHS.logo and settings.BRANDING_POWERED_BY_URL %}<a href="{{ settings.BRANDING_POWERED_BY_URL }}"><img src="{% static 'img/nautobot_logo.svg' %}" height="20" /> Powered</a> &middot;{% endif %}
12
12
  {{ settings.HOSTNAME }} {% if request.user.is_authenticated %} (v{{ settings.VERSION }}) {% endif %}
@@ -17,7 +17,7 @@
17
17
  <p class="text-muted">{% now 'Y-m-d H:i:s T' %}</p>
18
18
  </div>
19
19
  <div class="col-xs-4 text-right noprint">
20
- {% if request.user.is_authenticated or not "HIDE_RESTRICTED_UI"|settings_or_config %}
20
+ {% if request.user.is_authenticated %}
21
21
  <p class="text-muted">
22
22
  {% if "ENABLE_ALPHA_UI"|settings_or_config %}
23
23
  {% if request.path|is_new_ui_ready %}
@@ -27,14 +27,4 @@
27
27
  }).ajaxStop(function() {
28
28
  loading.hide();
29
29
  });
30
- /*
31
- this fixes the navbar blocking the main UI from being seen
32
- https://github.com/nautobot/nautobot/issues/1467
33
- */
34
- let setBodyPaddingTop = () => {
35
- document.querySelector('body').style.paddingTop = `${parseInt(window.getComputedStyle(document.querySelector('.navbar')).height)+10}px`
36
- }
37
- window.addEventListener("resize", setBodyPaddingTop);
38
- window.addEventListener("load", setBodyPaddingTop);
39
-
40
30
  </script>
@@ -2,6 +2,8 @@
2
2
  {% load helpers %}
3
3
  {% load plugins %}
4
4
 
5
+ <link rel="stylesheet" id="template-theme"
6
+ href="{% url 'template_css' %}">
5
7
  <link rel="stylesheet"
6
8
  href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}"
7
9
  onerror="window.location='{% url 'media_failure' %}?filename=bootstrap-3.4.1-dist/css/bootstrap.min.css'">
@@ -2,60 +2,92 @@
2
2
  {% load registry %}
3
3
  {% load helpers %}
4
4
  {% registry %}
5
- <nav class="navbar navbar-default navbar-fixed-top">
5
+ <nav class="navbar navbar-default navbar-fixed-left navbar-inverse">
6
6
  <div class="container-fluid">
7
7
  <div class="navbar-header">
8
- <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false">
9
- <span class="sr-only">Toggle navigation</span>
10
- <span class="icon-bar"></span>
11
- <span class="icon-bar"></span>
12
- <span class="icon-bar"></span>
13
- </button>
14
8
  <a class="navbar-brand" href="{% url 'home' %}">
15
9
  <img src="{% custom_branding_or_static 'logo' 'img/nautobot_logo.svg' %}" height="30" />
16
10
  </a>
17
11
  </div>
18
12
 
19
- <div id="navbar" class="navbar-collapse collapse">
13
+ <div id="navbar">
14
+ {% if request.user.is_authenticated %}
15
+ <form action="{% url 'search' %}" method="get" class="navbar-form" id="navbar_search" role="search">
16
+ <div class="input-group">
17
+ <input type="text" name="q" class="form-control" placeholder="Search {{ settings.BRANDING_TITLE }}">
18
+ <span class="input-group-btn">
19
+ <button type="submit" class="btn btn-primary">
20
+ <i class="mdi mdi-magnify"></i>
21
+ </button>
22
+ </span>
23
+ </div>
24
+ </form>
25
+ {% endif %}
26
+
27
+ <ul class="nav navbar-nav">
28
+ {% if request.user.is_authenticated %}
29
+ <li class="dropdown">
30
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown" title="{{ request.user }}" role="button" aria-haspopup="true" aria-expanded="false">
31
+ <i class="mdi mdi-account"></i>
32
+ <span id="navbar_user">{{ request.user }}</span>
33
+ <span class="caret"></span>
34
+ </a>
35
+ <ul class="dropdown-menu">
36
+ <li><a href="{% url 'user:profile' %}"><i class="mdi mdi-account-box"></i> Profile</a></li>
37
+ {% if request.user.is_staff %}
38
+ <li><a href="{% url 'admin:index' %}"><i class="mdi mdi-cogs"></i> Admin</a></li>
39
+ {% endif %}
40
+ <li class="divider"></li>
41
+ <li><a href="{% url 'logout' %}"><i class="mdi mdi-logout"></i> Log out</a></li>
42
+ </ul>
43
+ </li>
44
+ {% else %}
45
+ <li><a href="{% url settings.LOGIN_URL %}?next={{ request.get_full_path | urlencode }}"><i class="mdi mdi-login"></i> Log in</a></li>
46
+ {% endif %}
47
+ </ul>
48
+
20
49
  {% if request.user.is_authenticated %}
21
50
  <ul class="nav navbar-nav">
22
51
  {% for tab_name, tab_details in registry.nav_menu.tabs.items %}
23
- {% if request.user|has_one_or_more_perms:tab_details.permissions or not "HIDE_RESTRICTED_UI"|settings_or_config %}
52
+ {% if request.user|has_one_or_more_perms:tab_details.permissions %}
24
53
  <li class="dropdown">
25
54
  <a href="#" class="dropdown-toggle" data-tab-weight="{{ tab_details.weight }}" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
55
+ <img src="{% custom_branding_or_static 'nav_bullet' 'img/nautobot_chevron.svg' %}" height="20px" />
26
56
  {{ tab_name }} <span class="caret"></span>
27
57
  </a>
28
58
  <ul class="dropdown-menu">
29
59
  {% for group_name, group_details in tab_details.groups.items %}
30
- {% if request.user|has_one_or_more_perms:group_details.permissions or not "HIDE_RESTRICTED_UI"|settings_or_config %}
60
+ {% if request.user|has_one_or_more_perms:group_details.permissions %}
31
61
  <li class="dropdown-header" data-group-weight="{{ group_details.weight }}">{{ group_name }}</li>
32
62
  {% for item_link, item_details in group_details.items.items %}
33
- {% if request.user|has_one_or_more_perms:item_details.permissions or not "HIDE_RESTRICTED_UI"|settings_or_config %}
63
+ {% if request.user|has_one_or_more_perms:item_details.permissions %}
34
64
  <li {% if not request.user|has_perms:item_details.permissions %} class="disabled"{% endif %}>
35
- <div class="buttons pull-right">
36
- {% for button_title, button_details in item_details.buttons.items %}
37
- {% if request.user|has_perms:button_details.permissions %}
38
- {% comment %}
39
- Use 'url xxx as variable' so that an invalid
40
- link doesn't throw a NoReverseMatch exception.
41
- {% endcomment %}
42
- {% url button_details.link as button_url %}
43
- {% if button_url %}
44
- <a href="{{ button_url }}"
45
- data-button-weight="{{ button_details.weight }}"
46
- class="btn btn-xs btn-{{ button_details.button_class }}"
47
- title="{{ button_title }}">
48
- <i class="mdi {{ button_details.icon_class }}"></i>
49
- </a>
50
- {% else %}
51
- <a class="btn btn-xs btn-danger"
52
- title="ERROR: Invalid link!">
53
- <i class="mdi mdi-alert"></i>
54
- </a>
65
+ {% if item_details.buttons.items|length > 0 %}
66
+ <div class="buttons pull-right">
67
+ {% for button_title, button_details in item_details.buttons.items %}
68
+ {% if request.user|has_perms:button_details.permissions %}
69
+ {% comment %}
70
+ Use 'url xxx as variable' so that an invalid
71
+ link doesn't throw a NoReverseMatch exception.
72
+ {% endcomment %}
73
+ {% url button_details.link as button_url %}
74
+ {% if button_url %}
75
+ <a href="{{ button_url }}"
76
+ data-button-weight="{{ button_details.weight }}"
77
+ class="btn btn-xs btn-{{ button_details.button_class }}"
78
+ title="{{ button_title }}">
79
+ <i class="mdi {{ button_details.icon_class }}"></i>
80
+ </a>
81
+ {% else %}
82
+ <a class="btn btn-xs btn-danger"
83
+ title="ERROR: Invalid link!">
84
+ <i class="mdi mdi-alert"></i>
85
+ </a>
86
+ {% endif %}
55
87
  {% endif %}
56
- {% endif %}
57
- {% endfor %}
58
- </div>
88
+ {% endfor %}
89
+ </div>
90
+ {% endif %}
59
91
  <a href="{{ item_link }}"
60
92
  data-item-weight="{{ item_details.weight }}">
61
93
  {{ item_details.name }}
@@ -74,40 +106,6 @@
74
106
  {% endfor %}
75
107
  </ul>
76
108
  {% endif %}
77
-
78
- <ul class="nav navbar-nav navbar-right">
79
- {% if request.user.is_authenticated %}
80
- <li class="dropdown">
81
- <a href="#" class="dropdown-toggle" data-toggle="dropdown" title="{{ request.user }}" role="button" aria-haspopup="true" aria-expanded="false">
82
- <i class="mdi mdi-account"></i>
83
- <span id="navbar_user">{{ request.user|truncatechars:"30" }}</span>
84
- <span class="caret"></span>
85
- </a>
86
- <ul class="dropdown-menu">
87
- <li><a href="{% url 'user:profile' %}"><i class="mdi mdi-account-box"></i> Profile</a></li>
88
- {% if request.user.is_staff %}
89
- <li><a href="{% url 'admin:index' %}"><i class="mdi mdi-cogs"></i> Admin</a></li>
90
- {% endif %}
91
- <li class="divider"></li>
92
- <li><a href="{% url 'logout' %}"><i class="mdi mdi-logout"></i> Log out</a></li>
93
- </ul>
94
- </li>
95
- {% else %}
96
- <li><a href="{% url settings.LOGIN_URL %}?next={{ request.get_full_path | urlencode }}"><i class="mdi mdi-login"></i> Log in</a></li>
97
- {% endif %}
98
- </ul>
99
- {% if request.user.is_authenticated or not "HIDE_RESTRICTED_UI"|settings_or_config %}
100
- <form action="{% url 'search' %}" method="get" class="navbar-form navbar-right" id="navbar_search" role="search">
101
- <div class="input-group">
102
- <input type="text" name="q" class="form-control" placeholder="Search {{ settings.BRANDING_TITLE }}">
103
- <span class="input-group-btn">
104
- <button type="submit" class="btn btn-primary">
105
- <i class="mdi mdi-magnify"></i>
106
- </button>
107
- </span>
108
- </div>
109
- </form>
110
- {% endif %}
111
109
  </div>
112
110
  </div>
113
111
  </nav>
@@ -1,3 +1,5 @@
1
+ {% load helpers %}
2
+
1
3
  {% if object.pk %}
2
4
  <div class="panel panel-default">
3
5
  <div class="panel-heading">
@@ -42,6 +44,15 @@
42
44
  </td>
43
45
  </tr>
44
46
  {% endif %}
47
+ </tbody>
48
+ </table>
49
+ </div>
50
+ <div class="panel panel-default">
51
+ <div class="panel-heading">
52
+ <strong>Data Provenance</strong>
53
+ </div>
54
+ <table class="table table-hover panel-body attr-table">
55
+ <tbody>
45
56
  {% if object.created %}
46
57
  <tr>
47
58
  <td>Created</td>
@@ -54,6 +65,14 @@
54
65
  <td>{{ object.last_updated }}</td>
55
66
  </tr>
56
67
  {% endif %}
68
+ <tr>
69
+ <td>Created By</td>
70
+ <td>{{ created_by | placeholder }}</td>
71
+ </tr>
72
+ <tr>
73
+ <td>Last Updated By</td>
74
+ <td>{{ last_updated_by | placeholder }}</td>
75
+ </tr>
57
76
  </tbody>
58
77
  </table>
59
78
  </div>
@@ -230,6 +230,10 @@ SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "{{ secret_key }}")
230
230
  # "icon_mask": os.getenv(
231
231
  # "NAUTOBOT_BRANDING_FILEPATHS_ICON_MASK", None
232
232
  # ), # mono-chrome icon used for the mask-icon header
233
+ # "header_bullet": os.getenv(
234
+ # "NAUTOBOT_BRANDING_FILEPATHS_HEADER_BULLET", None
235
+ # ), # bullet image used for various view headers
236
+ # "nav_bullet": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_NAV_BULLET", None), # bullet image used for nav menu headers
233
237
  # }
234
238
 
235
239
  # Prepended to CSV, YAML and export template filenames (i.e. `nautobot_device.yml`)
@@ -338,10 +342,6 @@ SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "{{ secret_key }}")
338
342
  # GRAPHQL_CUSTOM_FIELD_PREFIX = "cf"
339
343
  # GRAPHQL_RELATIONSHIP_PREFIX = "rel"
340
344
 
341
- # Set to True to hide rather than disabling UI elements that a user doesn't have permission to access.
342
- #
343
- # HIDE_RESTRICTED_UI = False
344
-
345
345
  # HTTP proxies Nautobot should use when sending outbound HTTP requests (e.g. for webhooks).
346
346
  #
347
347
  # HTTP_PROXIES = {
@@ -353,6 +353,12 @@ SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "{{ secret_key }}")
353
353
  #
354
354
  INSTALLATION_METRICS_ENABLED = is_truthy(os.getenv("NAUTOBOT_INSTALLATION_METRICS_ENABLED", "{{ installation_metrics_enabled | default(True) }}"))
355
355
 
356
+ # Storage backend to use for Job input files and Job output files.
357
+ #
358
+ # Note: the default is for backwards compatibility and it is recommended to change it if possible for your deployment.
359
+ #
360
+ # JOB_FILE_IO_STORAGE = os.getenv("NAUTOBOT_JOB_FILE_IO_STORAGE", "db_file_storage.storage.DatabaseFileStorage")
361
+
356
362
  # Directory where Jobs can be discovered.
357
363
  #
358
364
  # JOBS_ROOT = os.getenv("NAUTOBOT_JOBS_ROOT", os.path.join(NAUTOBOT_ROOT, "jobs").rstrip("/"))
@@ -7,7 +7,7 @@
7
7
  </div>
8
8
  {% endif %}
9
9
  {% if table.rows %}
10
- {% render_table table 'inc/table.html' %}
10
+ {% render_table table table_inc_template|default:'inc/table.html' %}
11
11
  {% else %}
12
12
  <div class="panel-body text-muted">None</div>
13
13
  {% endif %}
@@ -0,0 +1,89 @@
1
+ {% load helpers %}
2
+ {% load static %}
3
+
4
+ @font-face {
5
+ font-family: 'Ubuntu';
6
+ font-style: italic;
7
+ font-weight: 400;
8
+ font-display: swap;
9
+ src: url('{% static 'fonts/Ubuntu-Italic.woff2' %}') format('woff2');
10
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
11
+ }
12
+ @font-face {
13
+ font-family: 'Ubuntu';
14
+ font-style: italic;
15
+ font-weight: 500;
16
+ font-display: swap;
17
+ src: url('{% static 'fonts/Ubuntu-MediumItalic.woff2' %}') format('woff2');
18
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
19
+ }
20
+ @font-face {
21
+ font-family: 'Ubuntu';
22
+ font-style: italic;
23
+ font-weight: 700;
24
+ font-display: swap;
25
+ src: url('{% static 'fonts/Ubuntu-BoldItalic.woff2' %}') format('woff2');
26
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
27
+ }
28
+ @font-face {
29
+ font-family: 'Ubuntu';
30
+ font-style: normal;
31
+ font-weight: 400;
32
+ font-display: swap;
33
+ src: url('{% static 'fonts/Ubuntu-Regular.woff2' %}') format('woff2');
34
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
35
+ }
36
+ @font-face {
37
+ font-family: 'Ubuntu';
38
+ font-style: normal;
39
+ font-weight: 500;
40
+ font-display: swap;
41
+ src: url('{% static 'fonts/Ubuntu-Medium.woff2' %}') format('woff2');
42
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
43
+ }
44
+ @font-face {
45
+ font-family: 'Ubuntu';
46
+ font-style: normal;
47
+ font-weight: 700;
48
+ font-display: swap;
49
+ src: url('{% static 'fonts/Ubuntu-Bold.woff2' %}') format('woff2');
50
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
51
+ }
52
+ @font-face {
53
+ font-family: 'Ubuntu Mono';
54
+ font-style: italic;
55
+ font-weight: 400;
56
+ font-display: swap;
57
+ src: url('{% static 'fonts/UbuntuMono-Italic.woff2' %}') format('woff2');
58
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
59
+ }
60
+ @font-face {
61
+ font-family: 'Ubuntu Mono';
62
+ font-style: italic;
63
+ font-weight: 700;
64
+ font-display: swap;
65
+ src: url('{% static 'fonts/UbuntuMono-BoldItalic.woff2' %}') format('woff2');
66
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
67
+ }
68
+ @font-face {
69
+ font-family: 'Ubuntu Mono';
70
+ font-style: normal;
71
+ font-weight: 400;
72
+ font-display: swap;
73
+ src: url('{% static 'fonts/UbuntuMono-Regular.woff2' %}') format('woff2');
74
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
75
+ }
76
+ @font-face {
77
+ font-family: 'Ubuntu Mono';
78
+ font-style: normal;
79
+ font-weight: 700;
80
+ font-display: swap;
81
+ src: url('{% static 'fonts/UbuntuMono-Bold.woff2' %}') format('woff2');
82
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
83
+ }
84
+ h1::before {
85
+ content: url("{% custom_branding_or_static 'header_bullet' 'img/nautobot_chevron_header.svg' %}");
86
+ position: relative;
87
+ top: 12px;
88
+ padding-right: 7px;
89
+ }
@@ -16,6 +16,7 @@
16
16
  <a class="btn btn-success btn-xs" id="select-all-options" data-target="id_columns"><i class="mdi mdi-expand-all-outline"></i> Select all</a>
17
17
  </div>
18
18
  </div>
19
+ <br />
19
20
  <div class="text-right">
20
21
  <input type="submit" class="btn btn-primary" value="Save" />
21
22
  <input type="submit" class="btn btn-danger reset" value="Reset" />
@@ -114,15 +114,20 @@ def export_button(context, content_type=None):
114
114
  user = context["request"].user
115
115
  export_templates = models.ExportTemplate.objects.restrict(user, "view").filter(content_type=content_type)
116
116
  try:
117
- export_url = reverse(lookup.get_route_for_model(content_type.model_class(), "list", api=True))
117
+ export_url = reverse(
118
+ "extras:job_run_by_class_path", kwargs={"class_path": "nautobot.core.jobs.ExportObjectList"}
119
+ )
118
120
  except NoReverseMatch:
119
121
  export_url = None
122
+ include_yaml_option = hasattr(content_type.model_class(), "to_yaml")
120
123
  else:
121
124
  export_templates = []
122
125
  export_url = None
123
126
 
124
127
  return {
125
128
  "export_url": export_url,
126
- "url_params": context["request"].GET,
129
+ "query_string": context["request"].GET.urlencode(),
130
+ "content_type": content_type,
127
131
  "export_templates": export_templates,
132
+ "include_yaml_option": include_yaml_option,
128
133
  }
@@ -5,8 +5,9 @@ import uuid
5
5
 
6
6
  from django.conf import settings
7
7
  from django.contrib.contenttypes.models import ContentType
8
- from django.core.exceptions import ObjectDoesNotExist
8
+ from django.core.exceptions import ObjectDoesNotExist, ValidationError
9
9
  from django.core.files.uploadedfile import SimpleUploadedFile
10
+ from django.core.validators import URLValidator
10
11
  from django.test import TestCase as _TestCase
11
12
  from django.test import override_settings, tag
12
13
  from django.urls import NoReverseMatch, reverse
@@ -334,7 +335,22 @@ class ViewTestCases:
334
335
  # Verify ObjectChange creation
335
336
  objectchanges = lookup.get_changes_for_model(instance)
336
337
  self.assertEqual(len(objectchanges), 1)
338
+ # Assert that Created By table row is updated with the user that created the object
337
339
  self.assertEqual(objectchanges[0].action, extras_choices.ObjectChangeActionChoices.ACTION_CREATE)
340
+ # Validate if detail view exists
341
+ validate = URLValidator()
342
+ detail_url = instance.get_absolute_url()
343
+ try:
344
+ validate(detail_url)
345
+ response = self.client.get(detail_url)
346
+ response_body = testing.extract_page_body(response.content.decode(response.charset))
347
+ advanced_tab_href = f"{detail_url}#advanced"
348
+ self.assertIn(advanced_tab_href, response_body)
349
+ self.assertIn("<td>Created By</td>", response_body)
350
+ self.assertIn("<td>nautobotuser</td>", response_body)
351
+ except ValidationError:
352
+ # Instance does not have a valid detail view, do nothing here.
353
+ pass
338
354
 
339
355
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
340
356
  def test_create_object_with_constrained_permission(self):
@@ -460,6 +476,20 @@ class ViewTestCases:
460
476
  objectchanges = lookup.get_changes_for_model(instance)
461
477
  self.assertEqual(len(objectchanges), 1)
462
478
  self.assertEqual(objectchanges[0].action, extras_choices.ObjectChangeActionChoices.ACTION_UPDATE)
479
+ # Validate if detail view exists
480
+ validate = URLValidator()
481
+ detail_url = instance.get_absolute_url()
482
+ try:
483
+ validate(detail_url)
484
+ response = self.client.get(detail_url)
485
+ response_body = testing.extract_page_body(response.content.decode(response.charset))
486
+ advanced_tab_href = f"{detail_url}#advanced"
487
+ self.assertIn(advanced_tab_href, response_body)
488
+ self.assertIn("<td>Last Updated By</td>", response_body)
489
+ self.assertIn("<td>nautobotuser</td>", response_body)
490
+ except ValidationError:
491
+ # Instance does not have a valid detail view, do nothing here.
492
+ pass
463
493
 
464
494
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
465
495
  def test_edit_object_with_constrained_permission(self):
@@ -704,7 +734,7 @@ class ViewTestCases:
704
734
  # TODO: it'd make test failures more readable if we strip the page headers/footers from the content
705
735
  self.assertIn("Unknown filter field", content, msg=content)
706
736
  # There should be no table rows displayed except for the empty results row
707
- self.assertIn(f"No {self.model._meta.verbose_name_plural} found", content, msg=content)
737
+ self.assertIn("None", content, msg=content)
708
738
 
709
739
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"], STRICT_FILTERING=False)
710
740
  def test_list_objects_unknown_filter_no_strict_filtering(self):
@@ -729,7 +759,7 @@ class ViewTestCases:
729
759
  content = testing.extract_page_body(response.content.decode(response.charset))
730
760
  # TODO: it'd make test failures more readable if we strip the page headers/footers from the content
731
761
  self.assertNotIn("Unknown filter field", content, msg=content)
732
- self.assertNotIn(f"No {self.model._meta.verbose_name_plural} found", content, msg=content)
762
+ self.assertIn("None", content, msg=content)
733
763
  if hasattr(self.model, "name"):
734
764
  self.assertRegex(content, r">\s*" + re.escape(instance1.name) + r"\s*<", msg=content)
735
765
  self.assertRegex(content, r">\s*" + re.escape(instance2.name) + r"\s*<", msg=content)
@@ -1114,7 +1144,7 @@ class ViewTestCases:
1114
1144
  # Check if the first and second pk is passed into the form.
1115
1145
  self.assertIn(f'<input type="hidden" name="pk" value="{first_pk}"', response_body)
1116
1146
  self.assertIn(f'<input type="hidden" name="pk" value="{second_pk}"', response_body)
1117
- self.assertIn("<h1>Editing 2 ", response_body)
1147
+ self.assertIn("Editing 2 ", response_body)
1118
1148
  # Check if the third pk is not passed into the form.
1119
1149
  self.assertNotIn(f'<input type="hidden" name="pk" value="{third_pk}"', response_body)
1120
1150
 
@@ -1,5 +1,3 @@
1
- from django.test.utils import override_settings
2
-
3
1
  from nautobot.circuits.models import Circuit, Provider
4
2
  from nautobot.core.testing.integration import SeleniumTestCase
5
3
  from nautobot.dcim.models import Location, PowerFeed, PowerPanel
@@ -82,47 +80,7 @@ class HomeTestCase(SeleniumTestCase):
82
80
  counter_html = int(item_html.find_by_xpath("./../../span").first.html)
83
81
  self.assertEqual(counter, counter_html)
84
82
 
85
- @override_settings(HIDE_RESTRICTED_UI=False)
86
- def test_homepage_render_no_permissions(self):
87
- """
88
- Render homepage with no permissions.
89
- """
90
- self.browser.visit(self.live_server_url)
91
-
92
- columns_html = self.browser.find_by_css("div[class='homepage_column']")
93
- for panel_name, panel_details in self.layout.items():
94
- columns_html.first.find_by_xpath(f".//strong[text()='{panel_name}']")
95
- for item_name, _ in panel_details.items():
96
- item_html = columns_html.first.find_by_xpath(f".//h4[contains(text(), '{item_name}')]")
97
- self.assertTrue("mdi mdi-lock" in item_html.find_by_xpath("./../span").html)
98
-
99
- @override_settings(HIDE_RESTRICTED_UI=False)
100
- def test_homepage_render_limit_permissions(self):
101
- """
102
- Render homepage with limited permissions.
103
- """
104
- self.add_permissions("dcim.view_location")
105
- self.add_permissions("circuits.view_circuit")
106
- user_permissions = self.user.get_all_permissions()
107
-
108
- self.browser.visit(self.live_server_url)
109
-
110
- columns_html = self.browser.find_by_css("div[class='homepage_column']")
111
- for panel_name, panel_details in self.layout.items():
112
- columns_html.first.find_by_xpath(f".//*[text()='{panel_name}']")
113
- for item_name, item_details in panel_details.items():
114
- if item_details["permission"] in user_permissions:
115
- item_html = columns_html.first.find_by_xpath(f".//a[contains(text(), '{item_name}')]")
116
- if item_details.get("model"):
117
- counter = item_details["model"].objects.count()
118
- counter_html = int(item_html.find_by_xpath("./../../span").html)
119
- self.assertEqual(counter, counter_html)
120
- else:
121
- item_html = columns_html.first.find_by_xpath(f".//h4[contains(text(), '{item_name}')]")
122
- self.assertTrue("mdi mdi-lock" in item_html.find_by_xpath("./../span").html)
123
-
124
- @override_settings(HIDE_RESTRICTED_UI=True)
125
- def test_homepage_render_limit_permissions_with_restricted_ui(self):
83
+ def test_homepage_render_with_limit_permissions(self):
126
84
  """
127
85
  Render homepage with limited permissions and restricted UI.
128
86
  This restricts the user to be able to view ONLY locations and circuits.