nautobot 2.1.7__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.
- nautobot/apps/api.py +1 -2
- nautobot/apps/utils.py +4 -0
- nautobot/apps/views.py +2 -0
- nautobot/circuits/api/urls.py +1 -2
- nautobot/circuits/api/views.py +0 -12
- nautobot/circuits/tests/integration/test_relationships.py +0 -4
- nautobot/core/api/routers.py +25 -3
- nautobot/core/api/utils.py +4 -0
- nautobot/core/api/views.py +21 -15
- nautobot/core/celery/schedulers.py +13 -0
- nautobot/core/choices.py +0 -21
- nautobot/core/models/__init__.py +1 -1
- nautobot/core/models/tree_queries.py +29 -7
- nautobot/core/releases.py +1 -1
- nautobot/core/settings.py +9 -0
- nautobot/core/settings_funcs.py +0 -18
- nautobot/core/signals.py +5 -5
- nautobot/core/tasks.py +7 -3
- nautobot/core/templates/admin/base.html +23 -94
- nautobot/core/templates/generic/object_list.html +2 -0
- nautobot/core/templates/graphene/graphiql.html +18 -47
- nautobot/core/templates/inc/footer.html +5 -5
- nautobot/core/templates/inc/nav_menu.html +0 -7
- nautobot/core/templates/nautobot_config.py.j2 +6 -0
- nautobot/core/templates/rest_framework/api.html +12 -5
- nautobot/core/testing/mixins.py +13 -5
- nautobot/core/tests/integration/test_plugin_navbar.py +7 -21
- nautobot/core/tests/integration/test_view_authentication.py +67 -0
- nautobot/core/tests/runner.py +25 -2
- nautobot/core/tests/test_graphql.py +2 -14
- nautobot/core/tests/test_models.py +3 -3
- nautobot/core/tests/test_navigations.py +67 -10
- nautobot/core/tests/test_releases.py +9 -3
- nautobot/core/tests/test_views.py +23 -16
- nautobot/core/utils/lookup.py +124 -0
- nautobot/core/views/__init__.py +3 -7
- nautobot/core/views/generic.py +9 -0
- nautobot/dcim/api/urls.py +1 -2
- nautobot/dcim/api/views.py +1 -12
- nautobot/dcim/choices.py +56 -0
- nautobot/dcim/models/racks.py +1 -3
- nautobot/dcim/navigation.py +1 -1
- nautobot/dcim/templates/dcim/device/lldp_neighbors.html +67 -43
- nautobot/dcim/tests/test_api.py +3 -0
- nautobot/dcim/tests/test_filters.py +0 -28
- nautobot/dcim/views.py +5 -2
- nautobot/extras/api/urls.py +1 -2
- nautobot/extras/api/views.py +0 -10
- nautobot/extras/choices.py +14 -0
- nautobot/extras/models/customfields.py +93 -34
- nautobot/extras/models/groups.py +1 -1
- nautobot/extras/models/relationships.py +32 -19
- nautobot/extras/navigation.py +3 -2
- nautobot/extras/plugins/__init__.py +8 -0
- nautobot/extras/plugins/views.py +6 -9
- nautobot/extras/querysets.py +1 -1
- nautobot/extras/signals.py +12 -6
- nautobot/extras/templates/extras/customfield.html +22 -14
- nautobot/extras/templatetags/job_buttons.py +7 -0
- nautobot/extras/templatetags/plugins.py +5 -1
- nautobot/extras/tests/test_customfields.py +323 -287
- nautobot/extras/tests/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/test_jobs.py +2 -2
- nautobot/extras/tests/test_plugins.py +41 -0
- nautobot/extras/tests/test_relationships.py +31 -14
- nautobot/extras/tests/test_views.py +124 -1
- nautobot/extras/utils.py +7 -3
- nautobot/extras/views.py +10 -10
- nautobot/ipam/api/urls.py +1 -2
- nautobot/ipam/api/views.py +6 -13
- nautobot/ipam/tables.py +0 -1
- nautobot/ipam/tests/test_graphql.py +2 -3
- nautobot/ipam/views.py +12 -10
- nautobot/project-static/css/base.css +1 -0
- nautobot/project-static/docs/404.html +30 -2
- nautobot/project-static/docs/apps/index.html +30 -2
- nautobot/project-static/docs/apps/nautobot-apps.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +410 -410
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +386 -358
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +45 -17
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +759 -602
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +528 -467
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +205 -109
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +30 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +1265 -785
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +1827 -1746
- nautobot/project-static/docs/development/apps/api/configuration-view.html +30 -2
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +30 -2
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +30 -2
- nautobot/project-static/docs/development/apps/api/models/global-search.html +30 -2
- nautobot/project-static/docs/development/apps/api/models/graphql.html +30 -2
- nautobot/project-static/docs/development/apps/api/models/index.html +30 -2
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +31 -3
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +30 -2
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +30 -2
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +30 -2
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +30 -2
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +30 -2
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +30 -2
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +30 -2
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +30 -2
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +30 -2
- nautobot/project-static/docs/development/apps/api/prometheus.html +30 -2
- nautobot/project-static/docs/development/apps/api/setup.html +30 -2
- nautobot/project-static/docs/development/apps/api/testing.html +33 -5
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +30 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +30 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +30 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +33 -5
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-detail-views.html +13 -5559
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +5594 -0
- nautobot/project-static/docs/development/apps/api/ui-extensions/tabs.html +3 -3
- nautobot/project-static/docs/development/apps/api/views/base-template.html +30 -2
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +44 -11
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +47 -14
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +30 -2
- nautobot/project-static/docs/development/apps/api/views/index.html +30 -2
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +30 -2
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +30 -2
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +30 -2
- nautobot/project-static/docs/development/apps/api/views/notes.html +30 -2
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +30 -2
- nautobot/project-static/docs/development/apps/api/views/urls.html +30 -2
- nautobot/project-static/docs/development/apps/index.html +30 -2
- nautobot/project-static/docs/development/apps/migration/code-updates.html +30 -2
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +30 -2
- nautobot/project-static/docs/development/apps/migration/from-v1.html +30 -2
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +30 -2
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +30 -2
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +30 -2
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +30 -2
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +30 -2
- nautobot/project-static/docs/development/core/application-registry.html +30 -2
- nautobot/project-static/docs/development/core/best-practices.html +33 -5
- nautobot/project-static/docs/development/core/bootstrap-ui.html +30 -2
- nautobot/project-static/docs/development/core/caching.html +5481 -0
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +30 -2
- nautobot/project-static/docs/development/core/extending-models.html +33 -5
- nautobot/project-static/docs/development/core/generic-views.html +30 -2
- nautobot/project-static/docs/development/core/getting-started.html +49 -12
- nautobot/project-static/docs/development/core/homepage.html +30 -2
- nautobot/project-static/docs/development/core/index.html +30 -2
- nautobot/project-static/docs/development/core/model-features.html +30 -2
- nautobot/project-static/docs/development/core/natural-keys.html +30 -2
- nautobot/project-static/docs/development/core/navigation-menu.html +30 -2
- nautobot/project-static/docs/development/core/release-checklist.html +30 -2
- nautobot/project-static/docs/development/core/role-internals.html +30 -2
- nautobot/project-static/docs/development/core/style-guide.html +30 -2
- nautobot/project-static/docs/development/core/templates.html +30 -2
- nautobot/project-static/docs/development/core/testing.html +30 -2
- nautobot/project-static/docs/development/core/user-preferences.html +30 -2
- nautobot/project-static/docs/development/index.html +30 -2
- nautobot/project-static/docs/development/jobs/index.html +30 -2
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +30 -2
- nautobot/project-static/docs/index.html +30 -2
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/release-notes/index.html +30 -2
- nautobot/project-static/docs/release-notes/version-1.0.html +30 -2
- nautobot/project-static/docs/release-notes/version-1.1.html +30 -2
- nautobot/project-static/docs/release-notes/version-1.2.html +30 -2
- nautobot/project-static/docs/release-notes/version-1.3.html +30 -2
- nautobot/project-static/docs/release-notes/version-1.4.html +31 -3
- nautobot/project-static/docs/release-notes/version-1.5.html +30 -2
- nautobot/project-static/docs/release-notes/version-1.6.html +573 -134
- nautobot/project-static/docs/release-notes/version-2.0.html +30 -2
- nautobot/project-static/docs/release-notes/version-2.1.html +539 -170
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +250 -240
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +30 -2
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +30 -2
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +30 -2
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +30 -2
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +49 -2
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +30 -2
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +30 -2
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +30 -2
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +30 -2
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +30 -2
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +30 -2
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +30 -2
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +30 -2
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +30 -2
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +30 -2
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +30 -2
- nautobot/project-static/docs/user-guide/administration/installation/docker.html +37 -5
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +30 -2
- nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +6019 -0
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +30 -2
- nautobot/project-static/docs/user-guide/administration/installation/index.html +30 -2
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +30 -2
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +30 -2
- nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +33 -5
- nautobot/project-static/docs/user-guide/administration/installation/services.html +30 -2
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +30 -2
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +30 -2
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +30 -2
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +30 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +30 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +30 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +30 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +30 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +30 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +30 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +30 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +30 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +30 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +30 -2
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +33 -5
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +30 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +30 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +30 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +30 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +30 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +30 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +30 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +30 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +30 -2
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +30 -2
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +30 -2
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +30 -2
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +30 -2
- nautobot/project-static/docs/user-guide/index.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +111 -15
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +30 -2
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +30 -2
- nautobot/tenancy/api/urls.py +1 -2
- nautobot/tenancy/api/views.py +0 -12
- nautobot/tenancy/navigation.py +1 -1
- nautobot/tenancy/tests/test_filters.py +0 -168
- nautobot/users/api/urls.py +1 -2
- nautobot/users/api/views.py +2 -65
- nautobot/users/views.py +8 -8
- nautobot/virtualization/api/urls.py +1 -2
- nautobot/virtualization/api/views.py +0 -12
- nautobot/virtualization/tests/test_filters.py +0 -28
- {nautobot-2.1.7.dist-info → nautobot-2.1.9.dist-info}/METADATA +2 -2
- {nautobot-2.1.7.dist-info → nautobot-2.1.9.dist-info}/RECORD +338 -334
- {nautobot-2.1.7.dist-info → nautobot-2.1.9.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.1.7.dist-info → nautobot-2.1.9.dist-info}/NOTICE +0 -0
- {nautobot-2.1.7.dist-info → nautobot-2.1.9.dist-info}/WHEEL +0 -0
- {nautobot-2.1.7.dist-info → nautobot-2.1.9.dist-info}/entry_points.txt +0 -0
|
@@ -52,19 +52,6 @@ class TenantGroupTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
52
52
|
TenantGroup.objects.filter(children__in=[child_groups[0], child_groups[1]]).distinct(),
|
|
53
53
|
)
|
|
54
54
|
|
|
55
|
-
def test_has_children(self):
|
|
56
|
-
"""Test the `has_children` filter."""
|
|
57
|
-
params = {"has_children": True}
|
|
58
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
59
|
-
self.filterset(params, self.queryset).qs,
|
|
60
|
-
TenantGroup.objects.filter(children__isnull=False).distinct(),
|
|
61
|
-
)
|
|
62
|
-
params = {"has_children": False}
|
|
63
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
64
|
-
self.filterset(params, self.queryset).qs,
|
|
65
|
-
TenantGroup.objects.filter(children__isnull=True).distinct(),
|
|
66
|
-
)
|
|
67
|
-
|
|
68
55
|
def test_tenants(self):
|
|
69
56
|
"""Test the `tenants` filter."""
|
|
70
57
|
tenants = Tenant.objects.filter(tenant_group__isnull=False)
|
|
@@ -74,19 +61,6 @@ class TenantGroupTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
74
61
|
TenantGroup.objects.filter(tenants__in=[tenants[0], tenants[1]]).distinct(),
|
|
75
62
|
)
|
|
76
63
|
|
|
77
|
-
def test_has_tenants(self):
|
|
78
|
-
"""Test the `has_tenants` filter."""
|
|
79
|
-
params = {"has_tenants": True}
|
|
80
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
81
|
-
self.filterset(params, self.queryset).qs,
|
|
82
|
-
TenantGroup.objects.filter(tenants__isnull=False).distinct(),
|
|
83
|
-
)
|
|
84
|
-
params = {"has_tenants": False}
|
|
85
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
86
|
-
self.filterset(params, self.queryset).qs,
|
|
87
|
-
TenantGroup.objects.filter(tenants__isnull=True).distinct(),
|
|
88
|
-
)
|
|
89
|
-
|
|
90
64
|
|
|
91
65
|
class TenantTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
92
66
|
queryset = Tenant.objects.all()
|
|
@@ -160,19 +134,6 @@ class TenantTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
160
134
|
self.queryset.filter(circuits__in=circuits).distinct(),
|
|
161
135
|
)
|
|
162
136
|
|
|
163
|
-
def test_has_circuits(self):
|
|
164
|
-
"""Test the `has_circuits` filter."""
|
|
165
|
-
params = {"has_circuits": True}
|
|
166
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
167
|
-
self.filterset(params, self.queryset).qs,
|
|
168
|
-
self.queryset.filter(circuits__isnull=False).distinct(),
|
|
169
|
-
)
|
|
170
|
-
params = {"has_circuits": False}
|
|
171
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
172
|
-
self.filterset(params, self.queryset).qs,
|
|
173
|
-
self.queryset.filter(circuits__isnull=True).distinct(),
|
|
174
|
-
)
|
|
175
|
-
|
|
176
137
|
def test_clusters(self):
|
|
177
138
|
"""Test the `clusters` filter."""
|
|
178
139
|
clusters = list(Cluster.objects.filter(tenant__isnull=False))[:2]
|
|
@@ -182,19 +143,6 @@ class TenantTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
182
143
|
self.queryset.filter(clusters__in=clusters).distinct(),
|
|
183
144
|
)
|
|
184
145
|
|
|
185
|
-
def test_has_clusters(self):
|
|
186
|
-
"""Test the `has_clusters` filter."""
|
|
187
|
-
params = {"has_clusters": True}
|
|
188
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
189
|
-
self.filterset(params, self.queryset).qs,
|
|
190
|
-
self.queryset.filter(clusters__isnull=False).distinct(),
|
|
191
|
-
)
|
|
192
|
-
params = {"has_clusters": False}
|
|
193
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
194
|
-
self.filterset(params, self.queryset).qs,
|
|
195
|
-
self.queryset.filter(clusters__isnull=True).distinct(),
|
|
196
|
-
)
|
|
197
|
-
|
|
198
146
|
def test_devices(self):
|
|
199
147
|
"""Test the `devices` filter."""
|
|
200
148
|
params = {"devices": [self.devices[0].pk, self.devices[1].name]}
|
|
@@ -203,19 +151,6 @@ class TenantTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
203
151
|
self.queryset.filter(devices__in=self.devices).distinct(),
|
|
204
152
|
)
|
|
205
153
|
|
|
206
|
-
def test_has_devices(self):
|
|
207
|
-
"""Test the `has_devices` filter."""
|
|
208
|
-
params = {"has_devices": True}
|
|
209
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
210
|
-
self.filterset(params, self.queryset).qs,
|
|
211
|
-
self.queryset.filter(devices__isnull=False).distinct(),
|
|
212
|
-
)
|
|
213
|
-
params = {"has_devices": False}
|
|
214
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
215
|
-
self.filterset(params, self.queryset).qs,
|
|
216
|
-
self.queryset.filter(devices__isnull=True).distinct(),
|
|
217
|
-
)
|
|
218
|
-
|
|
219
154
|
def test_tenant_group(self):
|
|
220
155
|
groups = list(TenantGroup.objects.filter(tenants__isnull=False))[:2]
|
|
221
156
|
groups_including_children = []
|
|
@@ -241,19 +176,6 @@ class TenantTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
241
176
|
self.queryset.filter(ip_addresses__in=ip_addresses).distinct(),
|
|
242
177
|
)
|
|
243
178
|
|
|
244
|
-
def test_has_ip_addresses(self):
|
|
245
|
-
"""Test the `has_ip_addresses` filter."""
|
|
246
|
-
params = {"has_ip_addresses": True}
|
|
247
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
248
|
-
self.filterset(params, self.queryset).qs,
|
|
249
|
-
self.queryset.filter(ip_addresses__isnull=False).distinct(),
|
|
250
|
-
)
|
|
251
|
-
params = {"has_ip_addresses": False}
|
|
252
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
253
|
-
self.filterset(params, self.queryset).qs,
|
|
254
|
-
self.queryset.filter(ip_addresses__isnull=True).distinct(),
|
|
255
|
-
)
|
|
256
|
-
|
|
257
179
|
def test_locations(self):
|
|
258
180
|
params = {"locations": [self.locations[0].pk, self.locations[1].name]}
|
|
259
181
|
self.assertQuerysetEqualAndNotEmpty(
|
|
@@ -261,18 +183,6 @@ class TenantTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
261
183
|
self.queryset.filter(locations__in=[self.locations[0], self.locations[1]]).distinct(),
|
|
262
184
|
)
|
|
263
185
|
|
|
264
|
-
def test_has_locations(self):
|
|
265
|
-
params = {"has_locations": True}
|
|
266
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
267
|
-
self.filterset(params, self.queryset).qs,
|
|
268
|
-
self.queryset.filter(locations__isnull=False).distinct(),
|
|
269
|
-
)
|
|
270
|
-
params = {"has_locations": False}
|
|
271
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
272
|
-
self.filterset(params, self.queryset).qs,
|
|
273
|
-
self.queryset.filter(locations__isnull=True).distinct(),
|
|
274
|
-
)
|
|
275
|
-
|
|
276
186
|
def test_prefixes(self):
|
|
277
187
|
"""Test the `prefixes` filter."""
|
|
278
188
|
prefixes = list(Prefix.objects.filter(tenant__isnull=False))[:2]
|
|
@@ -282,19 +192,6 @@ class TenantTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
282
192
|
self.queryset.filter(prefixes__in=prefixes).distinct(),
|
|
283
193
|
)
|
|
284
194
|
|
|
285
|
-
def test_has_prefixes(self):
|
|
286
|
-
"""Test the `has_prefixes` filter."""
|
|
287
|
-
params = {"has_prefixes": True}
|
|
288
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
289
|
-
self.filterset(params, self.queryset).qs,
|
|
290
|
-
self.queryset.filter(prefixes__isnull=False).distinct(),
|
|
291
|
-
)
|
|
292
|
-
params = {"has_prefixes": False}
|
|
293
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
294
|
-
self.filterset(params, self.queryset).qs,
|
|
295
|
-
self.queryset.filter(prefixes__isnull=True).distinct(),
|
|
296
|
-
)
|
|
297
|
-
|
|
298
195
|
def test_rack_reservations(self):
|
|
299
196
|
"""Test the `rack_reservations` filter."""
|
|
300
197
|
rack_reservations = list(RackReservation.objects.filter(tenant__isnull=False))[:2]
|
|
@@ -304,19 +201,6 @@ class TenantTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
304
201
|
self.queryset.filter(rack_reservations__in=rack_reservations).distinct(),
|
|
305
202
|
)
|
|
306
203
|
|
|
307
|
-
def test_has_rack_reservations(self):
|
|
308
|
-
"""Test the `has_rack_reservations` filter."""
|
|
309
|
-
params = {"has_rack_reservations": True}
|
|
310
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
311
|
-
self.filterset(params, self.queryset).qs,
|
|
312
|
-
self.queryset.filter(rack_reservations__isnull=False).distinct(),
|
|
313
|
-
)
|
|
314
|
-
params = {"has_rack_reservations": False}
|
|
315
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
316
|
-
self.filterset(params, self.queryset).qs,
|
|
317
|
-
self.queryset.filter(rack_reservations__isnull=True).distinct(),
|
|
318
|
-
)
|
|
319
|
-
|
|
320
204
|
def test_racks(self):
|
|
321
205
|
"""Test the `racks` filter."""
|
|
322
206
|
racks = list(Rack.objects.filter(tenant__isnull=False))[:2]
|
|
@@ -326,19 +210,6 @@ class TenantTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
326
210
|
self.queryset.filter(racks__in=racks).distinct(),
|
|
327
211
|
)
|
|
328
212
|
|
|
329
|
-
def test_has_racks(self):
|
|
330
|
-
"""Test the `has_racks` filter."""
|
|
331
|
-
params = {"has_racks": True}
|
|
332
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
333
|
-
self.filterset(params, self.queryset).qs,
|
|
334
|
-
self.queryset.filter(racks__isnull=False).distinct(),
|
|
335
|
-
)
|
|
336
|
-
params = {"has_racks": False}
|
|
337
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
338
|
-
self.filterset(params, self.queryset).qs,
|
|
339
|
-
self.queryset.filter(racks__isnull=True).distinct(),
|
|
340
|
-
)
|
|
341
|
-
|
|
342
213
|
def test_route_targets(self):
|
|
343
214
|
"""Test the `route_targets` filter."""
|
|
344
215
|
route_targets = list(RouteTarget.objects.filter(tenant__isnull=False))[:2]
|
|
@@ -348,19 +219,6 @@ class TenantTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
348
219
|
self.queryset.filter(route_targets__in=route_targets).distinct(),
|
|
349
220
|
)
|
|
350
221
|
|
|
351
|
-
def test_has_route_targets(self):
|
|
352
|
-
"""Test the `has_route_targets` filter."""
|
|
353
|
-
params = {"has_route_targets": True}
|
|
354
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
355
|
-
self.filterset(params, self.queryset).qs,
|
|
356
|
-
self.queryset.filter(route_targets__isnull=False).distinct(),
|
|
357
|
-
)
|
|
358
|
-
params = {"has_route_targets": False}
|
|
359
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
360
|
-
self.filterset(params, self.queryset).qs,
|
|
361
|
-
self.queryset.filter(route_targets__isnull=True).distinct(),
|
|
362
|
-
)
|
|
363
|
-
|
|
364
222
|
def test_virtual_machines(self):
|
|
365
223
|
"""Test the `virtual_machines` filter."""
|
|
366
224
|
virtual_machines = list(VirtualMachine.objects.filter(tenant__isnull=False))[:2]
|
|
@@ -370,19 +228,6 @@ class TenantTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
370
228
|
self.queryset.filter(virtual_machines__in=virtual_machines).distinct(),
|
|
371
229
|
)
|
|
372
230
|
|
|
373
|
-
def test_has_virtual_machines(self):
|
|
374
|
-
"""Test the `has_virtual_machines` filter."""
|
|
375
|
-
params = {"has_virtual_machines": True}
|
|
376
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
377
|
-
self.filterset(params, self.queryset).qs,
|
|
378
|
-
self.queryset.filter(virtual_machines__isnull=False).distinct(),
|
|
379
|
-
)
|
|
380
|
-
params = {"has_virtual_machines": False}
|
|
381
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
382
|
-
self.filterset(params, self.queryset).qs,
|
|
383
|
-
self.queryset.filter(virtual_machines__isnull=True).distinct(),
|
|
384
|
-
)
|
|
385
|
-
|
|
386
231
|
def test_vlans(self):
|
|
387
232
|
"""Test the `vlans` filter."""
|
|
388
233
|
vlans = list(VLAN.objects.filter(tenant__isnull=False))[:2]
|
|
@@ -392,19 +237,6 @@ class TenantTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
392
237
|
self.queryset.filter(vlans__in=vlans).distinct(),
|
|
393
238
|
)
|
|
394
239
|
|
|
395
|
-
def test_has_vlans(self):
|
|
396
|
-
"""Test the `has_vlans` filter."""
|
|
397
|
-
params = {"has_vlans": True}
|
|
398
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
399
|
-
self.filterset(params, self.queryset).qs,
|
|
400
|
-
self.queryset.filter(vlans__isnull=False).distinct(),
|
|
401
|
-
)
|
|
402
|
-
params = {"has_vlans": False}
|
|
403
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
404
|
-
self.filterset(params, self.queryset).qs,
|
|
405
|
-
self.queryset.filter(vlans__isnull=True).distinct(),
|
|
406
|
-
)
|
|
407
|
-
|
|
408
240
|
def test_vrfs(self):
|
|
409
241
|
"""Test the `vrfs` filter."""
|
|
410
242
|
vrfs = list(VRF.objects.filter(tenant__isnull=False))[:2]
|
nautobot/users/api/urls.py
CHANGED
|
@@ -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.UsersRootView
|
|
5
|
+
router = OrderedDefaultRouter(view_name="Users")
|
|
7
6
|
|
|
8
7
|
# Users and groups
|
|
9
8
|
router.register("users", views.UserViewSet)
|
nautobot/users/api/views.py
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
from django.contrib.auth import get_user_model
|
|
1
|
+
from django.contrib.auth import get_user_model
|
|
2
2
|
from django.contrib.auth.models import Group
|
|
3
3
|
from django.db.models import Count
|
|
4
|
-
from django.utils.decorators import method_decorator
|
|
5
|
-
from django.views.decorators.csrf import ensure_csrf_cookie
|
|
6
4
|
from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiTypes
|
|
7
5
|
from rest_framework.authentication import BasicAuthentication
|
|
8
|
-
from rest_framework.
|
|
9
|
-
from rest_framework.permissions import AllowAny, IsAuthenticated
|
|
6
|
+
from rest_framework.permissions import IsAuthenticated
|
|
10
7
|
from rest_framework.response import Response
|
|
11
|
-
from rest_framework.routers import APIRootView
|
|
12
8
|
from rest_framework.viewsets import ViewSet
|
|
13
9
|
|
|
14
10
|
from nautobot.core.api.serializers import BulkOperationIntegerIDSerializer
|
|
@@ -20,16 +16,6 @@ from nautobot.users.models import ObjectPermission, Token
|
|
|
20
16
|
|
|
21
17
|
from . import serializers
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
class UsersRootView(APIRootView):
|
|
25
|
-
"""
|
|
26
|
-
Users API root view
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
def get_view_name(self):
|
|
30
|
-
return "Users"
|
|
31
|
-
|
|
32
|
-
|
|
33
19
|
#
|
|
34
20
|
# Users and groups
|
|
35
21
|
#
|
|
@@ -40,40 +26,6 @@ class UserViewSet(ModelViewSet):
|
|
|
40
26
|
serializer_class = serializers.UserSerializer
|
|
41
27
|
filterset_class = filters.UserFilterSet
|
|
42
28
|
|
|
43
|
-
@action(methods=["GET"], detail=False, url_path="my-profile")
|
|
44
|
-
def my_profile(self, request):
|
|
45
|
-
serializer = self.serializer_class(instance=request.user, context={"request": request})
|
|
46
|
-
return Response(serializer.data)
|
|
47
|
-
|
|
48
|
-
@method_decorator(ensure_csrf_cookie)
|
|
49
|
-
@action(methods=["GET"], detail=False, permission_classes=[AllowAny])
|
|
50
|
-
def session(self, request):
|
|
51
|
-
from django.conf import settings as django_settings
|
|
52
|
-
from django.urls import reverse
|
|
53
|
-
from social_django.context_processors import backends
|
|
54
|
-
|
|
55
|
-
from nautobot.core.settings_funcs import sso_auth_enabled
|
|
56
|
-
|
|
57
|
-
serializer = self.serializer_class(instance=request.user, context={"request": request})
|
|
58
|
-
|
|
59
|
-
_backends = []
|
|
60
|
-
sso_enabled = sso_auth_enabled(django_settings.AUTHENTICATION_BACKENDS)
|
|
61
|
-
|
|
62
|
-
social_auth_backends = backends(request)["backends"]
|
|
63
|
-
if sso_enabled:
|
|
64
|
-
for backend in social_auth_backends["backends"]:
|
|
65
|
-
_backends.append(reverse("social:begin", kwargs={"backend": backend}))
|
|
66
|
-
|
|
67
|
-
resp = {
|
|
68
|
-
"user": serializer.data,
|
|
69
|
-
"logged_in": request.user.is_authenticated,
|
|
70
|
-
"sso_enabled": sso_enabled,
|
|
71
|
-
"sso_user": (len(social_auth_backends["associated"]) > 0),
|
|
72
|
-
"backends": _backends,
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return Response(resp)
|
|
76
|
-
|
|
77
29
|
|
|
78
30
|
@extend_schema_view(
|
|
79
31
|
bulk_destroy=extend_schema(request=BulkOperationIntegerIDSerializer(many=True)),
|
|
@@ -101,21 +53,6 @@ class TokenViewSet(ModelViewSet):
|
|
|
101
53
|
classes = super().authentication_classes
|
|
102
54
|
return [*classes, BasicAuthentication]
|
|
103
55
|
|
|
104
|
-
# TODO(timizuo): Move authenticate and logout to its own view;
|
|
105
|
-
# as it is not proper to be on this.
|
|
106
|
-
@action(methods=["POST"], detail=False, permission_classes=[AllowAny])
|
|
107
|
-
def authenticate(self, request):
|
|
108
|
-
serializer = serializers.UserLoginSerializer(data=request.data, context=self.get_serializer_context())
|
|
109
|
-
serializer.is_valid(raise_exception=True)
|
|
110
|
-
user = serializer.validated_data["user"]
|
|
111
|
-
login(request, user=user)
|
|
112
|
-
return Response(status=200)
|
|
113
|
-
|
|
114
|
-
@action(methods=["GET"], detail=False)
|
|
115
|
-
def logout(self, request):
|
|
116
|
-
logout(request)
|
|
117
|
-
return Response(status=200)
|
|
118
|
-
|
|
119
56
|
def get_queryset(self):
|
|
120
57
|
"""
|
|
121
58
|
Limit users to their own Tokens.
|
nautobot/users/views.py
CHANGED
|
@@ -7,7 +7,6 @@ from django.contrib.auth import (
|
|
|
7
7
|
logout as auth_logout,
|
|
8
8
|
update_session_auth_hash,
|
|
9
9
|
)
|
|
10
|
-
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
11
10
|
from django.http import HttpResponseForbidden, HttpResponseRedirect
|
|
12
11
|
from django.shortcuts import get_object_or_404, redirect, render
|
|
13
12
|
from django.urls import reverse
|
|
@@ -18,6 +17,7 @@ from django.views.decorators.debug import sensitive_post_parameters
|
|
|
18
17
|
from django.views.generic import View
|
|
19
18
|
|
|
20
19
|
from nautobot.core.forms import ConfirmationForm
|
|
20
|
+
from nautobot.core.views.generic import GenericView
|
|
21
21
|
|
|
22
22
|
from .forms import AdvancedProfileSettingsForm, LoginForm, PasswordChangeForm, TokenForm
|
|
23
23
|
from .models import Token
|
|
@@ -118,7 +118,7 @@ def is_django_auth_user(request):
|
|
|
118
118
|
return request.session.get(BACKEND_SESSION_KEY, None) == "nautobot.core.authentication.ObjectPermissionBackend"
|
|
119
119
|
|
|
120
120
|
|
|
121
|
-
class ProfileView(
|
|
121
|
+
class ProfileView(GenericView):
|
|
122
122
|
template_name = "users/profile.html"
|
|
123
123
|
|
|
124
124
|
def get(self, request):
|
|
@@ -132,7 +132,7 @@ class ProfileView(LoginRequiredMixin, View):
|
|
|
132
132
|
)
|
|
133
133
|
|
|
134
134
|
|
|
135
|
-
class UserConfigView(
|
|
135
|
+
class UserConfigView(GenericView):
|
|
136
136
|
template_name = "users/preferences.html"
|
|
137
137
|
|
|
138
138
|
def get(self, request):
|
|
@@ -160,7 +160,7 @@ class UserConfigView(LoginRequiredMixin, View):
|
|
|
160
160
|
return redirect("user:preferences")
|
|
161
161
|
|
|
162
162
|
|
|
163
|
-
class ChangePasswordView(
|
|
163
|
+
class ChangePasswordView(GenericView):
|
|
164
164
|
template_name = "users/change_password.html"
|
|
165
165
|
|
|
166
166
|
RESTRICTED_NOTICE = "Remotely authenticated user credentials cannot be changed within Nautobot."
|
|
@@ -218,7 +218,7 @@ class ChangePasswordView(LoginRequiredMixin, View):
|
|
|
218
218
|
#
|
|
219
219
|
|
|
220
220
|
|
|
221
|
-
class TokenListView(
|
|
221
|
+
class TokenListView(GenericView):
|
|
222
222
|
def get(self, request):
|
|
223
223
|
tokens = Token.objects.filter(user=request.user)
|
|
224
224
|
|
|
@@ -233,7 +233,7 @@ class TokenListView(LoginRequiredMixin, View):
|
|
|
233
233
|
)
|
|
234
234
|
|
|
235
235
|
|
|
236
|
-
class TokenEditView(
|
|
236
|
+
class TokenEditView(GenericView):
|
|
237
237
|
def get(self, request, pk=None):
|
|
238
238
|
if pk is not None:
|
|
239
239
|
if not request.user.has_perm("users.change_token"):
|
|
@@ -292,7 +292,7 @@ class TokenEditView(LoginRequiredMixin, View):
|
|
|
292
292
|
)
|
|
293
293
|
|
|
294
294
|
|
|
295
|
-
class TokenDeleteView(
|
|
295
|
+
class TokenDeleteView(GenericView):
|
|
296
296
|
def get(self, request, pk):
|
|
297
297
|
token = get_object_or_404(Token.objects.filter(user=request.user), pk=pk)
|
|
298
298
|
initial_data = {
|
|
@@ -336,7 +336,7 @@ class TokenDeleteView(LoginRequiredMixin, View):
|
|
|
336
336
|
#
|
|
337
337
|
|
|
338
338
|
|
|
339
|
-
class AdvancedProfileSettingsEditView(
|
|
339
|
+
class AdvancedProfileSettingsEditView(GenericView):
|
|
340
340
|
template_name = "users/advanced_settings_edit.html"
|
|
341
341
|
|
|
342
342
|
def get(self, request):
|
|
@@ -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.VirtualizationRootView
|
|
5
|
+
router = OrderedDefaultRouter(view_name="Virtualization")
|
|
7
6
|
|
|
8
7
|
# Clusters
|
|
9
8
|
router.register("cluster-types", views.ClusterTypeViewSet)
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from rest_framework.routers import APIRootView
|
|
2
|
-
|
|
3
1
|
from nautobot.core.models.querysets import count_related
|
|
4
2
|
from nautobot.dcim.models import Device
|
|
5
3
|
from nautobot.extras.api.views import (
|
|
@@ -19,16 +17,6 @@ from nautobot.virtualization.models import (
|
|
|
19
17
|
|
|
20
18
|
from . import serializers
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
class VirtualizationRootView(APIRootView):
|
|
24
|
-
"""
|
|
25
|
-
Virtualization API root view
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
def get_view_name(self):
|
|
29
|
-
return "Virtualization"
|
|
30
|
-
|
|
31
|
-
|
|
32
20
|
#
|
|
33
21
|
# Clusters
|
|
34
22
|
#
|
|
@@ -49,13 +49,6 @@ class ClusterTypeTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
49
49
|
params = {"clusters": [self.clusters[0].pk, self.clusters[1].name]}
|
|
50
50
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
|
51
51
|
|
|
52
|
-
with self.subTest("Has Clusters"):
|
|
53
|
-
params = {"has_clusters": True}
|
|
54
|
-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
|
55
|
-
|
|
56
|
-
params = {"has_clusters": False}
|
|
57
|
-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
|
|
58
|
-
|
|
59
52
|
|
|
60
53
|
class ClusterGroupTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
61
54
|
queryset = ClusterGroup.objects.all()
|
|
@@ -89,13 +82,6 @@ class ClusterGroupTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
89
82
|
params = {"clusters": [self.clusters[0].pk, self.clusters[1].name]}
|
|
90
83
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
|
91
84
|
|
|
92
|
-
with self.subTest("Has Clusters"):
|
|
93
|
-
params = {"has_clusters": True}
|
|
94
|
-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
|
95
|
-
|
|
96
|
-
params = {"has_clusters": False}
|
|
97
|
-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
|
|
98
|
-
|
|
99
85
|
|
|
100
86
|
class ClusterTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilterTestCaseMixin):
|
|
101
87
|
queryset = Cluster.objects.all()
|
|
@@ -192,25 +178,11 @@ class ClusterTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFil
|
|
|
192
178
|
params = {"devices": [self.device.pk, self.device.name]}
|
|
193
179
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
|
|
194
180
|
|
|
195
|
-
with self.subTest("Has Devices"):
|
|
196
|
-
params = {"has_devices": True}
|
|
197
|
-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
|
|
198
|
-
|
|
199
|
-
params = {"has_devices": False}
|
|
200
|
-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
|
201
|
-
|
|
202
181
|
def test_virtual_machines(self):
|
|
203
182
|
with self.subTest("Virtual Machines"):
|
|
204
183
|
params = {"virtual_machines": [self.virtualmachine.pk, self.virtualmachine.name]}
|
|
205
184
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
|
|
206
185
|
|
|
207
|
-
with self.subTest("Has Virtual Machines"):
|
|
208
|
-
params = {"has_virtual_machines": True}
|
|
209
|
-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
|
|
210
|
-
|
|
211
|
-
params = {"has_virtual_machines": False}
|
|
212
|
-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
|
213
|
-
|
|
214
186
|
def test_location(self):
|
|
215
187
|
params = {"location": [self.locations[0].pk, self.locations[1].pk]}
|
|
216
188
|
self.assertQuerysetEqual(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: nautobot
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.9
|
|
4
4
|
Summary: Source of truth and network automation platform.
|
|
5
5
|
Home-page: https://nautobot.com
|
|
6
6
|
License: Apache-2.0
|
|
@@ -22,7 +22,7 @@ Provides-Extra: mysql
|
|
|
22
22
|
Provides-Extra: napalm
|
|
23
23
|
Provides-Extra: remote-storage
|
|
24
24
|
Provides-Extra: sso
|
|
25
|
-
Requires-Dist: Django (>=3.2.
|
|
25
|
+
Requires-Dist: Django (>=3.2.25,<3.3.0)
|
|
26
26
|
Requires-Dist: GitPython (>=3.1.41,<3.2.0)
|
|
27
27
|
Requires-Dist: Jinja2 (>=3.1.3,<3.2.0)
|
|
28
28
|
Requires-Dist: Markdown (>=3.3.7,<3.4.0)
|