mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 09:51:22 -06:00
Merge branch 'develop' into feature
This commit is contained in:
commit
803f9b6913
@ -160,17 +160,20 @@ accumulating a large backlog of work.
|
|||||||
The core maintainers group has chosen to make use of GitHub's [Stale bot](https://github.com/apps/stale)
|
The core maintainers group has chosen to make use of GitHub's [Stale bot](https://github.com/apps/stale)
|
||||||
to aid in issue management.
|
to aid in issue management.
|
||||||
|
|
||||||
* Issues will be marked as stale after 45 days of no activity.
|
* Issues will be marked as stale after 60 days of no activity.
|
||||||
* Then after 15 more days of inactivity, the issue will be closed.
|
* If the stable label is not removed in the following 30 days, the issue will
|
||||||
|
be closed automatically.
|
||||||
* Any issue bearing one of the following labels will be exempt from all Stale
|
* Any issue bearing one of the following labels will be exempt from all Stale
|
||||||
bot actions:
|
bot actions:
|
||||||
* `status: accepted`
|
* `status: accepted`
|
||||||
* `status: blocked`
|
* `status: blocked`
|
||||||
* `status: needs milestone`
|
* `status: needs milestone`
|
||||||
|
|
||||||
It is natural that some new issues get more attention than others. Stale bot
|
It is natural that some new issues get more attention than others. The stale
|
||||||
helps bring renewed attention to potentially valuable issues that may have been
|
bot helps bring renewed attention to potentially valuable issues that may have
|
||||||
overlooked.
|
been overlooked. **Do not** comment on an issue that has been marked stale in
|
||||||
|
an effort to circumvent the bot: Doing so will not remove the stale label.
|
||||||
|
(Stale labels can be removed only by maintainers.)
|
||||||
|
|
||||||
## Maintainer Guidance
|
## Maintainer Guidance
|
||||||
|
|
||||||
|
@ -73,6 +73,11 @@ Next, clone the **master** branch of the NetBox GitHub repository into the curre
|
|||||||
|
|
||||||
```no-highlight
|
```no-highlight
|
||||||
$ sudo git clone -b master https://github.com/netbox-community/netbox.git .
|
$ sudo git clone -b master https://github.com/netbox-community/netbox.git .
|
||||||
|
```
|
||||||
|
|
||||||
|
The screen below should be the result:
|
||||||
|
|
||||||
|
```
|
||||||
Cloning into '.'...
|
Cloning into '.'...
|
||||||
remote: Counting objects: 1994, done.
|
remote: Counting objects: 1994, done.
|
||||||
remote: Compressing objects: 100% (150/150), done.
|
remote: Compressing objects: 100% (150/150), done.
|
||||||
|
@ -89,3 +89,58 @@ Restart the WSGI service to load the new plugin:
|
|||||||
```no-highlight
|
```no-highlight
|
||||||
# sudo systemctl restart netbox
|
# sudo systemctl restart netbox
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Removing Plugins
|
||||||
|
|
||||||
|
Follow these steps to completely remove a plugin.
|
||||||
|
|
||||||
|
### Update Configuration
|
||||||
|
|
||||||
|
Remove the plugin from the `PLUGINS` list in `configuration.py`. Also remove any relevant configuration parameters from `PLUGINS_CONFIG`.
|
||||||
|
|
||||||
|
### Remove the Python Package
|
||||||
|
|
||||||
|
Use `pip` to remove the installed plugin:
|
||||||
|
|
||||||
|
```no-highlight
|
||||||
|
$ source /opt/netbox/venv/bin/activate
|
||||||
|
(venv) $ pip uninstall <package>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restart WSGI Service
|
||||||
|
|
||||||
|
Restart the WSGI service:
|
||||||
|
|
||||||
|
```no-highlight
|
||||||
|
# sudo systemctl restart netbox
|
||||||
|
```
|
||||||
|
|
||||||
|
### Drop Database Tables
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
This step is necessary only for plugin which have created one or more database tables (generally through the introduction of new models). Check your plugin's documentation if unsure.
|
||||||
|
|
||||||
|
Enter the PostgreSQL database shell to determine if the plugin has created any SQL tables. Substitute `pluginname` in the example below for the name of the plugin being removed. (You can also run the `\dt` command without a pattern to list _all_ tables.)
|
||||||
|
|
||||||
|
```no-highlight
|
||||||
|
netbox=> \dt pluginname_*
|
||||||
|
List of relations
|
||||||
|
List of relations
|
||||||
|
Schema | Name | Type | Owner
|
||||||
|
--------+----------------+-------+--------
|
||||||
|
public | pluginname_foo | table | netbox
|
||||||
|
public | pluginname_bar | table | netbox
|
||||||
|
(2 rows)
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
Exercise extreme caution when removing tables. Users are strongly encouraged to perform a backup of their database immediately before taking these actions.
|
||||||
|
|
||||||
|
Drop each of the listed tables to remove it from the database:
|
||||||
|
|
||||||
|
```no-highlight
|
||||||
|
netbox=> DROP TABLE pluginname_foo;
|
||||||
|
DROP TABLE
|
||||||
|
netbox=> DROP TABLE pluginname_bar;
|
||||||
|
DROP TABLE
|
||||||
|
```
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
# NetBox v2.11
|
# NetBox v2.11
|
||||||
|
|
||||||
|
## v2.11.10 (FUTURE)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* [#5442](https://github.com/netbox-community/netbox/issues/5442) - Fix assignment of permissions based on LDAP groups
|
||||||
|
* [#6773](https://github.com/netbox-community/netbox/issues/6773) - Add missing `display` field to rack unit serializer
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## v2.11.9 (2021-07-08)
|
## v2.11.9 (2021-07-08)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
@ -209,6 +209,10 @@ class RackUnitSerializer(serializers.Serializer):
|
|||||||
face = ChoiceField(choices=DeviceFaceChoices, read_only=True)
|
face = ChoiceField(choices=DeviceFaceChoices, read_only=True)
|
||||||
device = NestedDeviceSerializer(read_only=True)
|
device = NestedDeviceSerializer(read_only=True)
|
||||||
occupied = serializers.BooleanField(read_only=True)
|
occupied = serializers.BooleanField(read_only=True)
|
||||||
|
display = serializers.SerializerMethodField(read_only=True)
|
||||||
|
|
||||||
|
def get_display(self, obj):
|
||||||
|
return obj['name']
|
||||||
|
|
||||||
|
|
||||||
class RackReservationSerializer(PrimaryModelSerializer):
|
class RackReservationSerializer(PrimaryModelSerializer):
|
||||||
|
@ -25,6 +25,15 @@ class TokenAuthentication(authentication.TokenAuthentication):
|
|||||||
if not token.user.is_active:
|
if not token.user.is_active:
|
||||||
raise exceptions.AuthenticationFailed("User inactive")
|
raise exceptions.AuthenticationFailed("User inactive")
|
||||||
|
|
||||||
|
# When LDAP authentication is active try to load user data from LDAP directory
|
||||||
|
if settings.REMOTE_AUTH_BACKEND == 'netbox.authentication.LDAPBackend':
|
||||||
|
from netbox.authentication import LDAPBackend
|
||||||
|
ldap_backend = LDAPBackend()
|
||||||
|
user = ldap_backend.populate_user(token.user.username)
|
||||||
|
# If the user is found in the LDAP directory use it, if not fallback to the local user
|
||||||
|
if user:
|
||||||
|
return user, token
|
||||||
|
|
||||||
return token.user, token
|
return token.user, token
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ from users.models import ObjectPermission
|
|||||||
from utilities.permissions import permission_is_exempt, resolve_permission, resolve_permission_ct
|
from utilities.permissions import permission_is_exempt, resolve_permission, resolve_permission_ct
|
||||||
|
|
||||||
|
|
||||||
class ObjectPermissionBackend(ModelBackend):
|
class ObjectPermissionMixin():
|
||||||
|
|
||||||
def get_all_permissions(self, user_obj, obj=None):
|
def get_all_permissions(self, user_obj, obj=None):
|
||||||
if not user_obj.is_active or user_obj.is_anonymous:
|
if not user_obj.is_active or user_obj.is_anonymous:
|
||||||
@ -20,13 +20,16 @@ class ObjectPermissionBackend(ModelBackend):
|
|||||||
user_obj._object_perm_cache = self.get_object_permissions(user_obj)
|
user_obj._object_perm_cache = self.get_object_permissions(user_obj)
|
||||||
return user_obj._object_perm_cache
|
return user_obj._object_perm_cache
|
||||||
|
|
||||||
|
def get_permission_filter(self, user_obj):
|
||||||
|
return Q(users=user_obj) | Q(groups__user=user_obj)
|
||||||
|
|
||||||
def get_object_permissions(self, user_obj):
|
def get_object_permissions(self, user_obj):
|
||||||
"""
|
"""
|
||||||
Return all permissions granted to the user by an ObjectPermission.
|
Return all permissions granted to the user by an ObjectPermission.
|
||||||
"""
|
"""
|
||||||
# Retrieve all assigned and enabled ObjectPermissions
|
# Retrieve all assigned and enabled ObjectPermissions
|
||||||
object_permissions = ObjectPermission.objects.filter(
|
object_permissions = ObjectPermission.objects.filter(
|
||||||
Q(users=user_obj) | Q(groups__user=user_obj),
|
self.get_permission_filter(user_obj),
|
||||||
enabled=True
|
enabled=True
|
||||||
).prefetch_related('object_types')
|
).prefetch_related('object_types')
|
||||||
|
|
||||||
@ -86,6 +89,10 @@ class ObjectPermissionBackend(ModelBackend):
|
|||||||
return model.objects.filter(constraints, pk=obj.pk).exists()
|
return model.objects.filter(constraints, pk=obj.pk).exists()
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectPermissionBackend(ObjectPermissionMixin, ModelBackend):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class RemoteUserBackend(_RemoteUserBackend):
|
class RemoteUserBackend(_RemoteUserBackend):
|
||||||
"""
|
"""
|
||||||
Custom implementation of Django's RemoteUserBackend which provides configuration hooks for basic customization.
|
Custom implementation of Django's RemoteUserBackend which provides configuration hooks for basic customization.
|
||||||
@ -133,11 +140,27 @@ class RemoteUserBackend(_RemoteUserBackend):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
# Create a new instance of django-auth-ldap's LDAPBackend with our own ObjectPermissions
|
||||||
|
try:
|
||||||
|
from django_auth_ldap.backend import LDAPBackend as LDAPBackend_
|
||||||
|
|
||||||
|
class NBLDAPBackend(ObjectPermissionMixin, LDAPBackend_):
|
||||||
|
def get_permission_filter(self, user_obj):
|
||||||
|
permission_filter = super().get_permission_filter(user_obj)
|
||||||
|
if (self.settings.FIND_GROUP_PERMS and
|
||||||
|
hasattr(user_obj, "ldap_user") and
|
||||||
|
hasattr(user_obj.ldap_user, "group_names")):
|
||||||
|
permission_filter = permission_filter | Q(groups__name__in=user_obj.ldap_user.group_names)
|
||||||
|
return permission_filter
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class LDAPBackend:
|
class LDAPBackend:
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
from django_auth_ldap.backend import LDAPBackend as LDAPBackend_, LDAPSettings
|
from django_auth_ldap.backend import LDAPSettings
|
||||||
import ldap
|
import ldap
|
||||||
except ModuleNotFoundError as e:
|
except ModuleNotFoundError as e:
|
||||||
if getattr(e, 'name') == 'django_auth_ldap':
|
if getattr(e, 'name') == 'django_auth_ldap':
|
||||||
@ -163,8 +186,7 @@ class LDAPBackend:
|
|||||||
"Required parameter AUTH_LDAP_SERVER_URI is missing from ldap_config.py."
|
"Required parameter AUTH_LDAP_SERVER_URI is missing from ldap_config.py."
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create a new instance of django-auth-ldap's LDAPBackend
|
obj = NBLDAPBackend()
|
||||||
obj = LDAPBackend_()
|
|
||||||
|
|
||||||
# Read LDAP configuration parameters from ldap_config.py instead of settings.py
|
# Read LDAP configuration parameters from ldap_config.py instead of settings.py
|
||||||
settings = LDAPSettings()
|
settings = LDAPSettings()
|
||||||
|
Loading…
Reference in New Issue
Block a user