nautobot 2.1.8__py3-none-any.whl → 2.1.9__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 (296) hide show
  1. nautobot/apps/api.py +1 -2
  2. nautobot/apps/utils.py +4 -0
  3. nautobot/apps/views.py +2 -0
  4. nautobot/circuits/api/urls.py +1 -2
  5. nautobot/circuits/api/views.py +0 -12
  6. nautobot/core/api/routers.py +25 -3
  7. nautobot/core/api/utils.py +4 -0
  8. nautobot/core/api/views.py +21 -15
  9. nautobot/core/settings.py +1 -0
  10. nautobot/core/templates/admin/base.html +23 -94
  11. nautobot/core/templates/graphene/graphiql.html +18 -47
  12. nautobot/core/templates/inc/footer.html +5 -5
  13. nautobot/core/templates/inc/nav_menu.html +0 -7
  14. nautobot/core/templates/rest_framework/api.html +12 -5
  15. nautobot/core/tests/integration/test_view_authentication.py +67 -0
  16. nautobot/core/tests/test_graphql.py +2 -14
  17. nautobot/core/tests/test_views.py +22 -16
  18. nautobot/core/utils/lookup.py +124 -0
  19. nautobot/core/views/__init__.py +3 -7
  20. nautobot/core/views/generic.py +9 -0
  21. nautobot/dcim/api/urls.py +1 -2
  22. nautobot/dcim/api/views.py +1 -12
  23. nautobot/dcim/models/racks.py +1 -3
  24. nautobot/dcim/templates/dcim/device/lldp_neighbors.html +67 -43
  25. nautobot/dcim/tests/test_api.py +3 -0
  26. nautobot/dcim/views.py +5 -2
  27. nautobot/extras/api/urls.py +1 -2
  28. nautobot/extras/api/views.py +0 -10
  29. nautobot/extras/plugins/views.py +6 -9
  30. nautobot/extras/tests/test_views.py +101 -0
  31. nautobot/extras/views.py +10 -10
  32. nautobot/ipam/api/urls.py +1 -2
  33. nautobot/ipam/api/views.py +0 -11
  34. nautobot/ipam/tables.py +0 -1
  35. nautobot/ipam/tests/test_graphql.py +2 -3
  36. nautobot/ipam/views.py +9 -9
  37. nautobot/project-static/css/base.css +1 -0
  38. nautobot/project-static/docs/404.html +14 -0
  39. nautobot/project-static/docs/apps/index.html +14 -0
  40. nautobot/project-static/docs/apps/nautobot-apps.html +14 -0
  41. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +14 -0
  42. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +14 -0
  43. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +394 -408
  44. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +14 -0
  45. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +14 -0
  46. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +14 -0
  47. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +14 -0
  48. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +14 -0
  49. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +14 -0
  50. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +14 -0
  51. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +14 -0
  52. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +14 -0
  53. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +14 -0
  54. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +14 -0
  55. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +14 -0
  56. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +14 -0
  57. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +14 -0
  58. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +14 -0
  59. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +14 -0
  60. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +14 -0
  61. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +649 -183
  62. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +1811 -1744
  63. nautobot/project-static/docs/development/apps/api/configuration-view.html +14 -0
  64. nautobot/project-static/docs/development/apps/api/database-backend-config.html +14 -0
  65. nautobot/project-static/docs/development/apps/api/models/django-admin.html +14 -0
  66. nautobot/project-static/docs/development/apps/api/models/global-search.html +14 -0
  67. nautobot/project-static/docs/development/apps/api/models/graphql.html +14 -0
  68. nautobot/project-static/docs/development/apps/api/models/index.html +14 -0
  69. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +14 -0
  70. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +14 -0
  71. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +14 -0
  72. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +14 -0
  73. nautobot/project-static/docs/development/apps/api/platform-features/index.html +14 -0
  74. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +14 -0
  75. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +14 -0
  76. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +14 -0
  77. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +14 -0
  78. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +14 -0
  79. nautobot/project-static/docs/development/apps/api/prometheus.html +14 -0
  80. nautobot/project-static/docs/development/apps/api/setup.html +14 -0
  81. nautobot/project-static/docs/development/apps/api/testing.html +14 -0
  82. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +14 -0
  83. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +14 -0
  84. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +14 -0
  85. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +14 -0
  86. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +14 -0
  87. nautobot/project-static/docs/development/apps/api/views/base-template.html +14 -0
  88. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +28 -9
  89. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +31 -12
  90. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +14 -0
  91. nautobot/project-static/docs/development/apps/api/views/index.html +14 -0
  92. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +14 -0
  93. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +14 -0
  94. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +14 -0
  95. nautobot/project-static/docs/development/apps/api/views/notes.html +14 -0
  96. nautobot/project-static/docs/development/apps/api/views/rest-api.html +14 -0
  97. nautobot/project-static/docs/development/apps/api/views/urls.html +14 -0
  98. nautobot/project-static/docs/development/apps/index.html +14 -0
  99. nautobot/project-static/docs/development/apps/migration/code-updates.html +14 -0
  100. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +14 -0
  101. nautobot/project-static/docs/development/apps/migration/from-v1.html +14 -0
  102. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +14 -0
  103. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +14 -0
  104. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +14 -0
  105. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +14 -0
  106. nautobot/project-static/docs/development/apps/porting-from-netbox.html +14 -0
  107. nautobot/project-static/docs/development/core/application-registry.html +14 -0
  108. nautobot/project-static/docs/development/core/best-practices.html +14 -0
  109. nautobot/project-static/docs/development/core/bootstrap-ui.html +14 -0
  110. nautobot/project-static/docs/development/core/caching.html +14 -0
  111. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +14 -0
  112. nautobot/project-static/docs/development/core/extending-models.html +14 -0
  113. nautobot/project-static/docs/development/core/generic-views.html +14 -0
  114. nautobot/project-static/docs/development/core/getting-started.html +33 -10
  115. nautobot/project-static/docs/development/core/homepage.html +14 -0
  116. nautobot/project-static/docs/development/core/index.html +14 -0
  117. nautobot/project-static/docs/development/core/model-features.html +14 -0
  118. nautobot/project-static/docs/development/core/natural-keys.html +14 -0
  119. nautobot/project-static/docs/development/core/navigation-menu.html +14 -0
  120. nautobot/project-static/docs/development/core/release-checklist.html +14 -0
  121. nautobot/project-static/docs/development/core/role-internals.html +14 -0
  122. nautobot/project-static/docs/development/core/style-guide.html +14 -0
  123. nautobot/project-static/docs/development/core/templates.html +14 -0
  124. nautobot/project-static/docs/development/core/testing.html +14 -0
  125. nautobot/project-static/docs/development/core/user-preferences.html +14 -0
  126. nautobot/project-static/docs/development/index.html +14 -0
  127. nautobot/project-static/docs/development/jobs/index.html +14 -0
  128. nautobot/project-static/docs/development/jobs/migration/from-v1.html +14 -0
  129. nautobot/project-static/docs/index.html +14 -0
  130. nautobot/project-static/docs/objects.inv +0 -0
  131. nautobot/project-static/docs/release-notes/index.html +14 -0
  132. nautobot/project-static/docs/release-notes/version-1.0.html +14 -0
  133. nautobot/project-static/docs/release-notes/version-1.1.html +14 -0
  134. nautobot/project-static/docs/release-notes/version-1.2.html +14 -0
  135. nautobot/project-static/docs/release-notes/version-1.3.html +14 -0
  136. nautobot/project-static/docs/release-notes/version-1.4.html +14 -0
  137. nautobot/project-static/docs/release-notes/version-1.5.html +14 -0
  138. nautobot/project-static/docs/release-notes/version-1.6.html +14 -0
  139. nautobot/project-static/docs/release-notes/version-2.0.html +14 -0
  140. nautobot/project-static/docs/release-notes/version-2.1.html +365 -159
  141. nautobot/project-static/docs/search/search_index.json +1 -1
  142. nautobot/project-static/docs/sitemap.xml +245 -240
  143. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  144. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +14 -0
  145. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +14 -0
  146. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +14 -0
  147. nautobot/project-static/docs/user-guide/administration/configuration/index.html +14 -0
  148. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +14 -0
  149. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +14 -0
  150. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +14 -0
  151. nautobot/project-static/docs/user-guide/administration/guides/caching.html +14 -0
  152. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +14 -0
  153. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +14 -0
  154. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +14 -0
  155. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +14 -0
  156. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +14 -0
  157. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +14 -0
  158. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +14 -0
  159. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +14 -0
  160. nautobot/project-static/docs/user-guide/administration/installation/docker.html +21 -3
  161. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +14 -0
  162. nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +6019 -0
  163. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +14 -0
  164. nautobot/project-static/docs/user-guide/administration/installation/index.html +14 -0
  165. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +14 -0
  166. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +14 -0
  167. nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +17 -3
  168. nautobot/project-static/docs/user-guide/administration/installation/services.html +14 -0
  169. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +14 -0
  170. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +14 -0
  171. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +14 -0
  172. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +14 -0
  173. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +14 -0
  174. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +14 -0
  175. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +14 -0
  176. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +14 -0
  177. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +14 -0
  178. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +14 -0
  179. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +14 -0
  180. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +14 -0
  181. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +14 -0
  182. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +14 -0
  183. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +14 -0
  184. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +14 -0
  185. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +14 -0
  186. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +14 -0
  187. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +14 -0
  188. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +14 -0
  189. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +14 -0
  190. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +14 -0
  191. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +14 -0
  192. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +14 -0
  193. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +14 -0
  194. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +14 -0
  195. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +14 -0
  196. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +14 -0
  197. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +14 -0
  198. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +14 -0
  199. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +14 -0
  200. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +14 -0
  201. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +14 -0
  202. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +14 -0
  203. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +14 -0
  204. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +14 -0
  205. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +14 -0
  206. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +14 -0
  207. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +14 -0
  208. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +14 -0
  209. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +14 -0
  210. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +14 -0
  211. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +14 -0
  212. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +14 -0
  213. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +14 -0
  214. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +14 -0
  215. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +14 -0
  216. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +14 -0
  217. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +14 -0
  218. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +14 -0
  219. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +14 -0
  220. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +14 -0
  221. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +14 -0
  222. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +14 -0
  223. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +14 -0
  224. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +14 -0
  225. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +14 -0
  226. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +14 -0
  227. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +14 -0
  228. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +14 -0
  229. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +14 -0
  230. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +14 -0
  231. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +14 -0
  232. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +14 -0
  233. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +14 -0
  234. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +14 -0
  235. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +14 -0
  236. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +14 -0
  237. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +14 -0
  238. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +14 -0
  239. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +14 -0
  240. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +14 -0
  241. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +14 -0
  242. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +14 -0
  243. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +14 -0
  244. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +14 -0
  245. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +14 -0
  246. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +14 -0
  247. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +14 -0
  248. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +14 -0
  249. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +14 -0
  250. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +14 -0
  251. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +14 -0
  252. nautobot/project-static/docs/user-guide/index.html +14 -0
  253. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +14 -0
  254. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +14 -0
  255. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +14 -0
  256. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +14 -0
  257. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +14 -0
  258. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +14 -0
  259. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +14 -0
  260. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +14 -0
  261. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +14 -0
  262. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +14 -0
  263. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +14 -0
  264. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +14 -0
  265. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +14 -0
  266. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +14 -0
  267. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +14 -0
  268. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +14 -0
  269. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +14 -0
  270. nautobot/project-static/docs/user-guide/platform-functionality/note.html +14 -0
  271. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +14 -0
  272. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +14 -0
  273. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +14 -0
  274. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +14 -0
  275. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +14 -0
  276. nautobot/project-static/docs/user-guide/platform-functionality/role.html +14 -0
  277. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +14 -0
  278. nautobot/project-static/docs/user-guide/platform-functionality/status.html +14 -0
  279. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +14 -0
  280. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +14 -0
  281. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +14 -0
  282. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +14 -0
  283. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +14 -0
  284. nautobot/tenancy/api/urls.py +1 -2
  285. nautobot/tenancy/api/views.py +0 -12
  286. nautobot/users/api/urls.py +1 -2
  287. nautobot/users/api/views.py +2 -65
  288. nautobot/users/views.py +8 -8
  289. nautobot/virtualization/api/urls.py +1 -2
  290. nautobot/virtualization/api/views.py +0 -12
  291. {nautobot-2.1.8.dist-info → nautobot-2.1.9.dist-info}/METADATA +2 -2
  292. {nautobot-2.1.8.dist-info → nautobot-2.1.9.dist-info}/RECORD +296 -294
  293. {nautobot-2.1.8.dist-info → nautobot-2.1.9.dist-info}/LICENSE.txt +0 -0
  294. {nautobot-2.1.8.dist-info → nautobot-2.1.9.dist-info}/NOTICE +0 -0
  295. {nautobot-2.1.8.dist-info → nautobot-2.1.9.dist-info}/WHEEL +0 -0
  296. {nautobot-2.1.8.dist-info → nautobot-2.1.9.dist-info}/entry_points.txt +0 -0
nautobot/apps/api.py CHANGED
@@ -19,7 +19,7 @@ from nautobot.core.api.fields import (
19
19
  )
20
20
  from nautobot.core.api.mixins import WritableSerializerMixin
21
21
  from nautobot.core.api.parsers import NautobotCSVParser
22
- from nautobot.core.api.routers import OrderedDefaultRouter
22
+ from nautobot.core.api.routers import AuthenticatedAPIRootView as APIRootView, OrderedDefaultRouter
23
23
  from nautobot.core.api.schema import NautobotAutoSchema
24
24
  from nautobot.core.api.serializers import (
25
25
  OptInFieldsMixin,
@@ -36,7 +36,6 @@ from nautobot.core.api.utils import (
36
36
  versioned_serializer_selector,
37
37
  )
38
38
  from nautobot.core.api.views import (
39
- APIRootView,
40
39
  BulkDestroyModelMixin,
41
40
  BulkUpdateModelMixin,
42
41
  GetObjectCountsView,
nautobot/apps/utils.py CHANGED
@@ -32,6 +32,8 @@ from nautobot.core.utils.lookup import (
32
32
  get_related_class_for_model,
33
33
  get_route_for_model,
34
34
  get_table_for_model,
35
+ get_url_for_url_pattern,
36
+ get_url_patterns,
35
37
  )
36
38
  from nautobot.core.utils.navigation import (
37
39
  get_all_new_ui_ready_routes,
@@ -110,6 +112,8 @@ __all__ = (
110
112
  "get_route_for_model",
111
113
  "get_settings_or_config",
112
114
  "get_table_for_model",
115
+ "get_url_for_url_pattern",
116
+ "get_url_patterns",
113
117
  "get_worker_count",
114
118
  "GitRepo",
115
119
  "hex_to_rgb",
nautobot/apps/views.py CHANGED
@@ -8,6 +8,7 @@ from nautobot.core.views.generic import (
8
8
  BulkImportView,
9
9
  BulkRenameView,
10
10
  ComponentCreateView,
11
+ GenericView,
11
12
  ObjectDeleteView,
12
13
  ObjectEditView,
13
14
  ObjectImportView,
@@ -57,6 +58,7 @@ __all__ = (
57
58
  "csv_format",
58
59
  "EnhancedPage",
59
60
  "EnhancedPaginator",
61
+ "GenericView",
60
62
  "get_csv_form_fields_from_serializer_class",
61
63
  "get_paginate_count",
62
64
  "GetReturnURLMixin",
@@ -2,8 +2,7 @@ from nautobot.core.api.routers import OrderedDefaultRouter
2
2
 
3
3
  from . import views
4
4
 
5
- router = OrderedDefaultRouter()
6
- router.APIRootView = views.CircuitsRootView
5
+ router = OrderedDefaultRouter(view_name="Circuits")
7
6
 
8
7
  # Providers
9
8
  router.register("providers", views.ProviderViewSet)
@@ -1,5 +1,3 @@
1
- from rest_framework.routers import APIRootView
2
-
3
1
  from nautobot.circuits import filters
4
2
  from nautobot.circuits.models import Circuit, CircuitTermination, CircuitType, Provider, ProviderNetwork
5
3
  from nautobot.core.models.querysets import count_related
@@ -8,16 +6,6 @@ from nautobot.extras.api.views import NautobotModelViewSet
8
6
 
9
7
  from . import serializers
10
8
 
11
-
12
- class CircuitsRootView(APIRootView):
13
- """
14
- Circuits API root view
15
- """
16
-
17
- def get_view_name(self):
18
- return "Circuits"
19
-
20
-
21
9
  #
22
10
  # Providers
23
11
  #
@@ -1,12 +1,23 @@
1
- from collections import OrderedDict
1
+ import logging
2
2
 
3
3
  from rest_framework.routers import DefaultRouter
4
4
 
5
+ from nautobot.core.api.views import AuthenticatedAPIRootView
6
+
7
+ logger = logging.getLogger(__name__)
8
+
5
9
 
6
10
  class OrderedDefaultRouter(DefaultRouter):
7
- def __init__(self, *args, **kwargs):
11
+ APIRootView = AuthenticatedAPIRootView
12
+
13
+ def __init__(self, *args, view_name=None, view_description=None, **kwargs):
8
14
  super().__init__(*args, **kwargs)
9
15
 
16
+ self.view_name = view_name
17
+ if view_name and not view_description:
18
+ view_description = f"{view_name} API root view"
19
+ self.view_description = view_description
20
+
10
21
  # Extend the list view mappings to support the DELETE operation
11
22
  self.routes[0].mapping.update(
12
23
  {
@@ -20,9 +31,20 @@ class OrderedDefaultRouter(DefaultRouter):
20
31
  """
21
32
  Wrap DRF's DefaultRouter to return an alphabetized list of endpoints.
22
33
  """
23
- api_root_dict = OrderedDict()
34
+ api_root_dict = {}
24
35
  list_name = self.routes[0].name
36
+
25
37
  for prefix, _viewset, basename in sorted(self.registry, key=lambda x: x[0]):
26
38
  api_root_dict[prefix] = list_name.format(basename=basename)
27
39
 
40
+ if issubclass(self.APIRootView, AuthenticatedAPIRootView):
41
+ return self.APIRootView.as_view(
42
+ api_root_dict=api_root_dict, name=self.view_name, description=self.view_description
43
+ )
44
+ # Fallback for the established practice of overriding self.APIRootView with a custom class
45
+ logger.warning(
46
+ "Something has changed an OrderedDefaultRouter's APIRootView attribute to a custom class. "
47
+ "Please verify that class %s implements appropriate authentication controls.",
48
+ self.APIRootView.__name__,
49
+ )
28
50
  return self.APIRootView.as_view(api_root_dict=api_root_dict)
@@ -178,6 +178,10 @@ def get_view_name(view, suffix=None):
178
178
 
179
179
  else:
180
180
  # Replicate DRF's built-in behavior.
181
+ name = getattr(view, "name", None)
182
+ if name is not None:
183
+ return view.name
184
+
181
185
  name = view.__class__.__name__
182
186
  name = formatting.remove_trailing_string(name, "View")
183
187
  name = formatting.remove_trailing_string(name, "ViewSet")
@@ -22,9 +22,9 @@ from graphql import get_default_backend
22
22
  from graphql.execution import ExecutionResult
23
23
  from graphql.execution.middleware import MiddlewareManager
24
24
  from graphql.type.schema import GraphQLSchema
25
- from rest_framework import status
25
+ from rest_framework import routers, status
26
26
  from rest_framework.exceptions import ParseError, PermissionDenied
27
- from rest_framework.permissions import AllowAny, IsAuthenticated
27
+ from rest_framework.permissions import IsAuthenticated
28
28
  from rest_framework.response import Response
29
29
  from rest_framework.reverse import reverse
30
30
  from rest_framework.views import APIView
@@ -341,15 +341,25 @@ class ReadOnlyModelViewSet(NautobotAPIVersionMixin, ModelViewSetMixin, ReadOnlyM
341
341
  #
342
342
 
343
343
 
344
- class APIRootView(NautobotAPIVersionMixin, APIView):
344
+ class AuthenticatedAPIRootView(NautobotAPIVersionMixin, routers.APIRootView):
345
345
  """
346
- This is the root of the REST API. API endpoints are arranged by app and model name; e.g. `/api/dcim/locations/`.
346
+ Extends DRF's base APIRootView class to enforce user authentication.
347
347
  """
348
348
 
349
- _ignore_model_permissions = True
349
+ permission_classes = [IsAuthenticated]
350
+
351
+ name = None
352
+ description = None
353
+
354
+
355
+ class APIRootView(AuthenticatedAPIRootView):
356
+ """
357
+ This is the root of the REST API.
350
358
 
351
- def get_view_name(self):
352
- return "API Root"
359
+ API endpoints are arranged by app and model name; e.g. `/api/dcim/locations/`.
360
+ """
361
+
362
+ name = "API Root"
353
363
 
354
364
  @extend_schema(exclude=True)
355
365
  def get(self, request, format=None): # pylint: disable=redefined-builtin
@@ -492,11 +502,6 @@ class NautobotSpectacularSwaggerView(APIVersioningGetSchemaURLMixin, Spectacular
492
502
  @extend_schema(exclude=True)
493
503
  def get(self, request, *args, **kwargs):
494
504
  """Fix up the rendering of the Swagger UI to work with Nautobot's UI."""
495
- if not request.user.is_authenticated:
496
- doc_url = reverse("api_docs")
497
- login_url = reverse(settings.LOGIN_URL)
498
- return redirect(f"{login_url}?next={doc_url}")
499
-
500
505
  # For backward compatibility wtih drf-yasg, `/api/docs/?format=openapi` is a redirect to the JSON schema.
501
506
  if request.GET.get("format") == "openapi":
502
507
  return redirect("schema_json", permanent=True)
@@ -525,11 +530,12 @@ class NautobotSpectacularRedocView(APIVersioningGetSchemaURLMixin, SpectacularRe
525
530
  class GraphQLDRFAPIView(NautobotAPIVersionMixin, APIView):
526
531
  """
527
532
  API View for GraphQL to integrate properly with DRF authentication mechanism.
528
- The code is a stripped down version of graphene-django default View
529
- https://github.com/graphql-python/graphene-django/blob/main/graphene_django/views.py#L57
530
533
  """
531
534
 
532
- permission_classes = [AllowAny]
535
+ # The code is a stripped down version of graphene-django default View
536
+ # https://github.com/graphql-python/graphene-django/blob/main/graphene_django/views.py#L57
537
+
538
+ permission_classes = [IsAuthenticated]
533
539
  graphql_schema = None
534
540
  executor = None
535
541
  backend = None
nautobot/core/settings.py CHANGED
@@ -242,6 +242,7 @@ SPECTACULAR_SETTINGS = {
242
242
  # trim it from all of the individual paths correspondingly.
243
243
  # See also https://github.com/nautobot/nautobot-ansible/pull/135 for an example of why this is desirable.
244
244
  "SERVERS": [{"url": "/api"}],
245
+ "SERVE_PERMISSIONS": ["rest_framework.permissions.IsAuthenticated"],
245
246
  "SCHEMA_PATH_PREFIX": "/api",
246
247
  "SCHEMA_PATH_PREFIX_TRIM": True,
247
248
  # use sidecar - locally packaged UI files, not CDN
@@ -8,55 +8,7 @@
8
8
  <html lang="en"{% if request.COOKIES|get_item:"theme" == 'dark' %} data-theme="dark"{% endif %}>
9
9
  <head>
10
10
  <title>{% block title %}Admin Home{% endblock %} - Nautobot</title>
11
- <link rel="stylesheet"
12
- href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}"
13
- onerror="window.location='{% url 'media_failure' %}?filename=bootstrap-3.4.1-dist/css/bootstrap.min.css'">
14
- <link rel="stylesheet"
15
- href="{% static 'materialdesignicons-6.5.95/css/materialdesignicons.min.css' %}"
16
- onerror="window.location='{% url 'media_failure' %}?filename=materialdesignicons-6.5.95/css/materialdesignicons.min.css'">
17
- <link rel="stylesheet"
18
- href="{% static 'jquery-ui-1.13.1/jquery-ui.min.css' %}"
19
- onerror="window.location='{% url 'media_failure' %}?filename=jquery-ui-1.13.1/jquery-ui.min.css'">
20
- <link rel="stylesheet"
21
- href="{% static 'select2-4.0.13/select2.min.css' %}"
22
- onerror="window.location='{% url 'media_failure' %}?filename=select2-4.0.13/select2.min.css'">
23
- <link rel="stylesheet"
24
- href="{% static 'select2-bootstrap-0.1.0-beta.10/select2-bootstrap.min.css' %}"
25
- onerror="window.location='{% url 'media_failure' %}?filename=select2-bootstrap-0.1.0-beta.10/select2-bootstrap.min.css'">
26
- <link rel="stylesheet"
27
- href="{% static 'flatpickr-4.6.9/themes/light.min.css' %}"
28
- onerror="window.location='{% url 'media_failure' %}?filename=flatpickr-4.6.9/themes/light.min.css'">
29
- <link rel="stylesheet" id="dark-theme"
30
- href="{% versioned_static 'css/dark.css' %}"
31
- onerror="window.location='{% url 'media_failure' %}?filename=css/dark.css'"{% if request.COOKIES|get_item:"theme" != 'dark' %} disabled="disabled"{% endif %} />
32
- <link rel="stylesheet" id="base-theme"
33
- href="{% versioned_static 'css/base.css' %}"
34
- onerror="window.location='{% url 'media_failure' %}?filename=css/base.css'">
35
- <link rel="apple-touch-icon" sizes="180x180" href="{% custom_branding_or_static 'icon_180' 'img/nautobot_icon_180x180.png' %}">
36
- <link rel="icon" type="image/png" sizes="32x32" href="{% custom_branding_or_static 'icon_32' 'img/nautobot_icon_32x32.png' %}">
37
- <link rel="icon" type="image/png" sizes="16x16" href="{% custom_branding_or_static 'icon_16' 'img/nautobot_icon_16x16.png' %}">
38
- <link rel="icon" type="image/png" href="{% custom_branding_or_static 'icon_192' 'img/nautobot_icon_192x192.png' %}" sizes="192x192">
39
- <link rel="mask-icon" href="{% custom_branding_or_static 'icon_mask' 'img/nautobot_icon_monochrome.svg' %}" color="#0097ff">
40
- <link rel="shortcut icon" href="{% custom_branding_or_static 'favicon' 'img/favicon.ico' %}">
41
-
42
- <script src="{% static 'jquery/jquery-3.6.0.min.js' %}"
43
- onerror="window.location='{% url 'media_failure' %}?filename=jquery/jquery-3.6.0.min.js'"></script>
44
- <script src="{% static 'jquery-ui-1.13.1/jquery-ui.min.js' %}"
45
- onerror="window.location='{% url 'media_failure' %}?filename=jquery-ui-1.13.1/jquery-ui.min.js'"></script>
46
- <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"
47
- onerror="window.location='{% url 'media_failure' %}?filename=bootstrap-3.4.1-dist/js/bootstrap.min.js'"></script>
48
- <script src="{% static 'select2-4.0.13/select2.min.js' %}"
49
- onerror="window.location='{% url 'media_failure' %}?filename=select2-4.0.13/select2.min.js'"></script>
50
- <script src="{% static 'flatpickr-4.6.9/flatpickr.min.js' %}"
51
- onerror="window.location='{% url 'media_failure' %}?filename=flatpickr-4.6.9/flatpickr.min.js'"></script>
52
- <script src="{% static 'js/forms.js' %}"
53
- onerror="window.location='{% url 'media_failure' %}?filename=js/forms.js'"></script>
54
-
55
- <meta name="msapplication-TileColor" content="#2d89ef">
56
- <meta name="theme-color" content="#ffffff">
57
- <meta charset="UTF-8">
58
- <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
59
-
11
+ {% include 'inc/media.html' %}
60
12
  {% block extrahead %}{% endblock %}
61
13
  {% block extrastyle %}{% endblock %}
62
14
 
@@ -94,23 +46,27 @@
94
46
  }
95
47
  </style>
96
48
  </head>
97
- <body {% if is_popup %}style="padding-top: 0px;"{% endif %}>
49
+ <body {% if is_popup %}style="padding-left: 0px;"{% endif %}>
50
+
98
51
  {% if not is_popup %}
99
52
  {% include 'inc/nav_menu.html' %}
100
53
  {% endif %}
101
- <div class="container-fluid wrapper" {% if is_popup %}style="padding-bottom: 0px;"{% endif %}>
102
- {% if "BANNER_TOP"|settings_or_config %}
103
- <div class="alert alert-info text-center" role="alert">
104
- {{ "BANNER_TOP"|settings_or_config|safe }}
105
- </div>
106
- {% endif %}
107
- {% if settings.MAINTENANCE_MODE %}
108
- <div class="alert alert-warning text-center" role="alert">
109
- <h4><i class="mdi mdi-alert"></i> Maintenance Mode</h4>
110
- <p>Nautobot is currently in maintenance mode. Functionality may be limited.</p>
111
- </div>
54
+
55
+ <div class="container-fluid wrapper" id="main-content" {% if is_popup %}style="padding-bottom: 0px;"{% endif %}>
56
+ {% if not is_popup %}
57
+ {% if "BANNER_TOP"|settings_or_config %}
58
+ <div class="alert alert-info text-center" role="alert">
59
+ {{ "BANNER_TOP"|settings_or_config|safe }}
60
+ </div>
61
+ {% endif %}
62
+ {% if settings.MAINTENANCE_MODE %}
63
+ <div class="alert alert-warning text-center" role="alert">
64
+ <h4><i class="mdi mdi-alert"></i> Maintenance Mode</h4>
65
+ <p>Nautobot is currently in maintenance mode. Functionality may be limited.</p>
66
+ </div>
67
+ {% endif %}
68
+ {% plugin_banners %}
112
69
  {% endif %}
113
- {% plugin_banners %}
114
70
  {% for message in messages %}
115
71
  <div class="alert alert-{{ message.tags }} alert-dismissable" role="alert">
116
72
  <button type="button" class="close" data-dismiss="alert" aria-label="Close">
@@ -148,8 +104,6 @@
148
104
  {% block content %}{{ content }}{% endblock %}
149
105
  </div>
150
106
  </div>
151
-
152
- {% block footer %}<footer id="footer"></footer>{% endblock %}
153
107
  <div class="push"></div>
154
108
  {% if "BANNER_BOTTOM"|settings_or_config %}
155
109
  <div class="alert alert-info text-center banner-bottom" role="alert">
@@ -158,37 +112,12 @@
158
112
  {% endif %}
159
113
  </div>
160
114
  {% if not is_popup %}
161
- <footer class="footer">
162
- <div class="container-fluid">
163
- <div class="row">
164
- <div class="col-xs-4">
165
- <p class="text-muted">{{ settings.HOSTNAME }} (v{{ settings.VERSION }})</p>
166
- </div>
167
- <div class="col-xs-4 text-center">
168
- <p class="text-muted">{% now 'Y-m-d H:i:s T' %}</p>
169
- </div>
170
- <div class="col-xs-4 text-right noprint">
171
- <p class="text-muted">
172
- <a href="#theme_modal" data-toggle="modal" data-target="#theme_modal" id="btn-theme-modal"><i class="mdi mdi-theme-light-dark text-primary"></i>Theme</a> &middot;
173
- <i class="mdi mdi-book-open-page-variant text-primary"></i>
174
- {% if settings.BRANDING_URLS.docs %}
175
- <a href="{{ settings.BRANDING_URLS.docs }}">Docs</a>
176
- {% else %}
177
- <a href="{% static 'docs/index.html' %}">Docs</a>
178
- {% endif %}
179
- &middot;
180
- <i class="mdi mdi-cloud-braces text-primary"></i> <a href="{% url 'api_docs' %}">API</a> &middot;
181
- <i class="mdi mdi-graphql text-primary"></i> <a href="{% url 'graphql' %}">GraphQL</a> &middot;
182
- <i class="mdi mdi-xml text-primary"></i> <a href="{{ settings.BRANDING_URLS.code }}">Code</a> &middot;
183
- <i class="mdi mdi-lifebuoy text-primary"></i> <a href="{{ settings.BRANDING_URLS.help }}">Help</a>
184
- </p>
185
- </div>
186
- </div>
187
- </div>
188
- </footer>
115
+ {% include 'inc/footer.html' %}
189
116
  {% endif %}
190
117
  {% include 'modals/modal_theme.html' with name='theme'%}
191
- <script src="{% versioned_static 'js/theme.js' %}"></script>
192
- {% block javascript %}{% endblock %}
118
+
119
+ {% block javascript %}
120
+ {% include 'inc/javascript.html' %}
121
+ {% endblock %}
193
122
  </body>
194
123
  </html>
@@ -10,53 +10,31 @@ add "&raw" to the end of the URL within a browser.
10
10
  <!DOCTYPE html>
11
11
  <html>
12
12
  <head>
13
+ {% include 'inc/media.html' %}
14
+ {% block extra_styles %}{% endblock %}
13
15
  <!-- Nautobot template requirements -->
14
16
  <title>{% block title %}GraphiQL{% endblock %} - {{ settings.BRANDING_TITLE }}</title>
15
- <link rel="stylesheet"
16
- href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}"
17
- onerror="window.location='{% url 'media_failure' %}?filename=bootstrap-3.4.1-dist/css/bootstrap.min.css'">
18
- <link rel="stylesheet"
19
- href="{% static 'materialdesignicons-6.5.95/css/materialdesignicons.min.css' %}"
20
- onerror="window.location='{% url 'media_failure' %}?filename=materialdesignicons-6.5.95/css/materialdesignicons.min.css'">
21
- <link rel="stylesheet"
22
- href="{% static 'jquery-ui-1.13.1/jquery-ui.min.css' %}"
23
- onerror="window.location='{% url 'media_failure' %}?filename=jquery-ui-1.13.1/jquery-ui.min.css'">
24
- <link rel="stylesheet"
25
- href="{% static 'select2-4.0.13/select2.min.css' %}"
26
- onerror="window.location='{% url 'media_failure' %}?filename=select2-4.0.13/select2.min.css'">
27
- <link rel="stylesheet"
28
- href="{% static 'select2-bootstrap-0.1.0-beta.10/select2-bootstrap.min.css' %}"
29
- onerror="window.location='{% url 'media_failure' %}?filename=select2-bootstrap-0.1.0-beta.10/select2-bootstrap.min.css'">
30
- <link rel="stylesheet"
31
- href="{% static 'flatpickr-4.6.9/themes/light.min.css' %}"
32
- onerror="window.location='{% url 'media_failure' %}?filename=flatpickr-4.6.9/themes/light.min.css'">
33
- <link rel="stylesheet" id="dark-theme"
34
- href="{% versioned_static 'css/dark.css' %}"
35
- onerror="window.location='{% url 'media_failure' %}?filename=css/dark.css'" disabled="disabled" />
36
- <link rel="stylesheet"
37
- href="{% versioned_static 'css/base.css' %}"
38
- onerror="window.location='{% url 'media_failure' %}?filename=css/base.css'">
39
- <link rel="apple-touch-icon" sizes="180x180" href="{% custom_branding_or_static 'icon_180' 'img/nautobot_icon_180x180.png' %}">
40
- <link rel="icon" type="image/png" sizes="32x32" href="{% custom_branding_or_static 'icon_32' 'img/nautobot_icon_32x32.png' %}">
41
- <link rel="icon" type="image/png" sizes="16x16" href="{% custom_branding_or_static 'icon_16' 'img/nautobot_icon_16x16.png' %}">
42
- <link rel="icon" type="image/png" sizes="192x192" href="{% custom_branding_or_static 'icon_192' 'img/nautobot_icon_192x192.png' %}">
43
- <link rel="mask-icon" type="image/png" color="#0097ff" href="{% custom_branding_or_static 'icon_mask' 'img/nautobot_icon_monochrome.png' %}">
44
- <link rel="shortcut icon" href="{% custom_branding_or_static 'favicon' 'img/favicon.ico' %}">
45
- <meta name="msapplication-TileColor" content="#2d89ef">
46
- <meta name="theme-color" content="#ffffff">
47
- <meta charset="UTF-8">
48
- <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
17
+
49
18
  <!-- GraphiQL template requirements -->
50
19
  <style>
51
- html, body, #editor {
52
- height: 100%;
20
+ #editor {
53
21
  margin: 0;
54
22
  width: 100%;
23
+ height: calc(100vh - 56px - 3rem);
55
24
  }
56
25
  .toolbar .dropdown-menu > li > a {
57
26
  clear: left;
58
27
  margin-right: 120px; /* leave room for the "Save Changes" button if present */
59
28
  }
29
+ .graphiql-container .doc-explorer-title-bar {
30
+ box-sizing: content-box;
31
+ }
32
+ .graphiql-container .history-title-bar {
33
+ box-sizing: content-box;
34
+ }
35
+ .graphiql-container .docExplorerShow {
36
+ white-space: nowrap;
37
+ }
60
38
  </style>
61
39
  <!-- As Nautobot may be run without internet access, we source these files locally rather than from an online CDN -->
62
40
  <link rel="stylesheet"
@@ -72,23 +50,16 @@ add "&raw" to the end of the URL within a browser.
72
50
  onerror="window.location='{% url 'media_failure' %}?filename=graphiql-1.5.16/graphiql.min.js'"></script>
73
51
  <script src="{% static 'subscriptions-transport-ws-0.9.18/client.min.js' %}"
74
52
  onerror="window.location='{% url 'media_failure' %}?filename=subscriptions-transport-ws-0.9.18/client.min.js'"></script>
75
- <!-- Custom CSS to address some conflicts between the two -->
76
- <style>
77
- body {
78
- padding-top: 54px;
79
- }
80
- .graphiql-container .doc-explorer-title-bar {
81
- box-sizing: content-box;
82
- }
83
- </style>
84
53
  </head>
85
54
  <body>
86
55
  <!-- Nautobot page contents -->
87
56
  {% include 'inc/nav_menu.html' %}
88
57
  {% include 'modals/modal_theme.html' with name='theme'%}
89
58
  {% include 'inc/javascript.html' %}
90
- <!-- GraphiQL page contents -->
91
- <div id="editor"></div>
59
+ <div class="container-fluid wrapper" id="main-content">
60
+ <!-- GraphiQL page contents -->
61
+ <div id="editor"></div>
62
+ </div>
92
63
  {% include 'inc/footer.html' %}
93
64
  {% csrf_token %}
94
65
  <script type="application/javascript">
@@ -3,8 +3,8 @@
3
3
  {% load plugins %}
4
4
 
5
5
  <style>
6
- /* Styles for viewports narrower than 1007px */
7
- @media (max-width: 1007px) {
6
+ /* Styles for viewports narrower than 1232px, i.e. bootstrap 'xs' and 'sm' layouts */
7
+ @media (max-width: 1232px) {
8
8
  .footer-col-1, .footer-col-2, .footer-col-3 {
9
9
  text-align: center !important;
10
10
  }
@@ -19,7 +19,7 @@
19
19
  <footer class="footer" id="footer">
20
20
  <div class="container-fluid">
21
21
  <div class="row">
22
- <div class="col-xl-4 col-lg-4 col-md-4 col-sm-3 col-xs-12 text-left footer-col-1 no-wrap">
22
+ <div class="col-xl-4 col-lg-4 col-md-3 col-sm-12 col-xs-12 text-left footer-col-1 no-wrap">
23
23
  {% if request.user.is_authenticated %}
24
24
  <p class="text-muted">
25
25
  {% 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 %}
@@ -27,10 +27,10 @@
27
27
  </p>
28
28
  {% endif %}
29
29
  </div>
30
- <div class="col-xl-4 col-lg-4 col-md-4 col-sm-3 col-xs-12 text-center footer-col-2">
30
+ <div class="col-xl-4 col-lg-3 col-md-3 col-sm-12 col-xs-12 text-center footer-col-2">
31
31
  <p class="text-muted">{% now 'Y-m-d H:i:s T' %}</p>
32
32
  </div>
33
- <div class="col-xl-4 col-lg-4 col-md-4 col-sm-6 col-xs-12 text-right footer-col-3 noprint">
33
+ <div class="col-xl-4 col-lg-5 col-md-6 col-sm-12 col-xs-12 text-right footer-col-3 noprint">
34
34
  {% if request.user.is_authenticated %}
35
35
  <p class="text-muted footer-links">
36
36
  <a href="#theme_modal" data-toggle="modal" data-target="#theme_modal" id="btn-theme-modal"><i class="mdi mdi-theme-light-dark text-primary"></i>Theme</a> &middot;
@@ -121,9 +121,6 @@
121
121
  document.addEventListener('DOMContentLoaded', function() {
122
122
  const navbar = document.querySelector('.navbar-fixed-left');
123
123
  const navbarHeader = document.querySelector('.navbar-header');
124
- const breadcrumb = document.querySelector('.breadcrumb');
125
- const bannerAlertArea = document.querySelector('.banner-alert-area');
126
- const bannerAlert = document.querySelector('.plugin-banner') !== null;
127
124
  const mainContent = document.querySelector('#main-content');
128
125
  const footer = document.querySelector('#footer');
129
126
  const dropdownToggles = document.querySelectorAll('.navbar-fixed-left .navbar-nav > .dropdown > a[data-toggle="collapse"]');
@@ -180,10 +177,6 @@
180
177
  function adjustElementsForNavbarState(isCollapsed) {
181
178
  const marginLeftValue = isCollapsed ? '-240px' : '0px';
182
179
  mainContent.style.marginLeft = marginLeftValue;
183
- bannerAlertArea.classList.toggle('collapsed', isCollapsed);
184
- if(!bannerAlert && breadcrumb) {
185
- breadcrumb.classList.toggle('collapsed', isCollapsed);
186
- };
187
180
  if(footer) footer.style.marginLeft = marginLeftValue;
188
181
  toggler.style.left = isCollapsed ? '-5px' : '225px';
189
182
  }
@@ -7,13 +7,20 @@
7
7
  {% include 'inc/media.html' %}
8
8
  {% endblock bootstrap_theme %}
9
9
 
10
- {% block navbar %}
11
- {% include 'inc/nav_menu.html' %}
12
- {% endblock navbar %}
13
-
14
10
  {% block body %}
15
- {{ block.super }}
11
+ {% include 'inc/nav_menu.html' %}
12
+ <div class="container-fluid" id="main-content">
13
+ {{ block.super }}
14
+ </div>
16
15
  {% include 'inc/footer.html' %}
16
+ <style>
17
+ .navbar-static-top {
18
+ display: none;
19
+ }
20
+ #main-content {
21
+ min-height: calc(100vh - 70px);
22
+ }
23
+ </style>
17
24
  {% endblock body %}
18
25
 
19
26
  {% block script %}
@@ -0,0 +1,67 @@
1
+ from django.test import tag
2
+
3
+ from nautobot.core.testing import TestCase
4
+ from nautobot.core.utils.lookup import get_url_for_url_pattern, get_url_patterns
5
+
6
+
7
+ @tag("integration")
8
+ class AuthenticationEnforcedTestCase(TestCase):
9
+ r"""
10
+ Test that all\* registered views require authentication to access.
11
+
12
+ \* with a very small number of known exceptions such as login and logout views.
13
+ """
14
+
15
+ def test_all_views_require_authentication(self):
16
+ self.client.logout()
17
+ url_patterns = get_url_patterns()
18
+
19
+ for url_pattern in url_patterns:
20
+ with self.subTest(url_pattern=url_pattern):
21
+ url = get_url_for_url_pattern(url_pattern)
22
+ response = self.client.get(url, follow=True)
23
+
24
+ if response.status_code == 405: # Method not allowed
25
+ response = self.client.post(url, follow=True)
26
+
27
+ # Is a view that *should* be open to unauthenticated users?
28
+ if url in [
29
+ "/admin/login/",
30
+ "/api/plugins/example-plugin/webhook/",
31
+ "/health/",
32
+ "/login/",
33
+ "/media-failure/",
34
+ "/template.css",
35
+ ]:
36
+ self.assertHttpStatus(response, 200, msg=url)
37
+ elif response.status_code == 200:
38
+ # UI views generally should redirect unauthenticated users to the appropriate login page
39
+ if url.startswith("/admin"):
40
+ if "logout" in url:
41
+ # /admin/logout/ sets next=/admin/ because having login redirect to logout would be silly
42
+ redirect_url = "/admin/login/?next=/admin/"
43
+ else:
44
+ redirect_url = f"/admin/login/?next={url}"
45
+ else:
46
+ if "logout" in url:
47
+ # /logout/ sets next=/ because having login redirect back to logout would be silly
48
+ redirect_url = "/login/?next=/"
49
+ else:
50
+ redirect_url = f"/login/?next={url}"
51
+ self.assertRedirects(response, redirect_url)
52
+ elif response.status_code != 403:
53
+ if any(
54
+ url.startswith(path)
55
+ for path in [
56
+ "/complete/", # social auth
57
+ "/login/", # social auth
58
+ "/media/", # MEDIA_ROOT
59
+ "/plugins/example-plugin/docs/", # STATIC_ROOT
60
+ ]
61
+ ):
62
+ self.assertEqual(response.status_code, 404)
63
+ else:
64
+ self.fail(
65
+ f"Unexpected {response.status_code} response at {url}: "
66
+ + response.content.decode(response.charset)
67
+ )
@@ -630,21 +630,9 @@ class GraphQLAPIPermissionTest(GraphQLTestCaseBase):
630
630
  self.assertEqual(names, ["Rack 1-1", "Rack 1-2", "Rack 2-1", "Rack 2-2"])
631
631
 
632
632
  def test_graphql_api_no_token(self):
633
- """Validate unauthenticated users are not able to query anything by default."""
633
+ """Validate unauthenticated users are not able to query anything."""
634
634
  response = self.client.post(self.api_url, {"query": self.get_racks_query}, format="json")
635
- self.assertEqual(response.status_code, status.HTTP_200_OK)
636
- self.assertIsInstance(response.data["data"]["racks"], list)
637
- names = [item["name"] for item in response.data["data"]["racks"]]
638
- self.assertEqual(names, [])
639
-
640
- @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
641
- def test_graphql_api_no_token_exempt(self):
642
- """Validate unauthenticated users are able to query based on the exempt permissions."""
643
- response = self.client.post(self.api_url, {"query": self.get_racks_query}, format="json")
644
- self.assertEqual(response.status_code, status.HTTP_200_OK)
645
- self.assertIsInstance(response.data["data"]["racks"], list)
646
- names = [item["name"] for item in response.data["data"]["racks"]]
647
- self.assertEqual(names, ["Rack 1-1", "Rack 1-2", "Rack 2-1", "Rack 2-2"])
635
+ self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
648
636
 
649
637
  def test_graphql_api_wrong_token(self):
650
638
  """Validate a wrong token return 403."""