From b6df0209ba6006ce648b8cda0fa60bcbb07223fc Mon Sep 17 00:00:00 2001 From: huzichunjohn Date: Mon, 11 Sep 2017 22:55:04 +0800 Subject: [PATCH 1/7] Fixes #1472: Secret truncated when using '<' character (#1477) --- netbox/project-static/js/secrets.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/project-static/js/secrets.js b/netbox/project-static/js/secrets.js index 638638623..d1ec3d883 100644 --- a/netbox/project-static/js/secrets.js +++ b/netbox/project-static/js/secrets.js @@ -43,7 +43,7 @@ $(document).ready(function() { success: function (response, status) { if (response.plaintext) { console.log("Secret retrieved successfully"); - $('#secret_' + secret_id).html(response.plaintext); + $('#secret_' + secret_id).text(response.plaintext); $('button.unlock-secret[secret-id=' + secret_id + ']').hide(); $('button.lock-secret[secret-id=' + secret_id + ']').show(); } else { From 17c1a1e4657be60dd1d222a390c3f1fbb664f1ce Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 14 Sep 2017 14:45:45 -0400 Subject: [PATCH 2/7] Use add_blank_choice() to prepend a null choice to field options --- netbox/dcim/forms.py | 10 ++-------- netbox/ipam/forms.py | 7 ++----- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index a0fa14764..3df486a1b 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -12,7 +12,7 @@ from ipam.models import IPAddress from tenancy.forms import TenancyForm from tenancy.models import Tenant from utilities.forms import ( - APISelect, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, + APISelect, ArrayFieldSelectMultiple, add_blank_choice, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ChainedFieldsMixin, ChainedModelChoiceField, CommentField, ConfirmationForm, CSVChoiceField, ExpandableNameField, FilterChoiceField, FlexibleModelChoiceField, Livesearch, SelectWithDisabled, SmallTextarea, SlugField, FilterTreeNodeMultipleChoiceField, @@ -28,12 +28,6 @@ from .models import ( ) -FORM_STATUS_CHOICES = [ - ['', '---------'], -] - -FORM_STATUS_CHOICES += STATUS_CHOICES - DEVICE_BY_PK_RE = '{\d+\}' @@ -863,7 +857,7 @@ class DeviceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm): device_role = forms.ModelChoiceField(queryset=DeviceRole.objects.all(), required=False, label='Role') tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False) platform = forms.ModelChoiceField(queryset=Platform.objects.all(), required=False) - status = forms.ChoiceField(choices=FORM_STATUS_CHOICES, required=False, initial='', label='Status') + status = forms.ChoiceField(choices=add_blank_choice(STATUS_CHOICES), required=False, initial='') serial = forms.CharField(max_length=50, required=False, label='Serial Number') class Meta: diff --git a/netbox/ipam/forms.py b/netbox/ipam/forms.py index e19376e8e..4152b44c1 100644 --- a/netbox/ipam/forms.py +++ b/netbox/ipam/forms.py @@ -25,11 +25,8 @@ IP_FAMILY_CHOICES = [ (6, 'IPv6'), ] -PREFIX_MASK_LENGTH_CHOICES = [ - ('', '---------'), -] + [(i, i) for i in range(1, 128)] - -IPADDRESS_MASK_LENGTH_CHOICES = PREFIX_MASK_LENGTH_CHOICES + [(128, 128)] +PREFIX_MASK_LENGTH_CHOICES = add_blank_choice([(i, i) for i in range(1, 128)]) +IPADDRESS_MASK_LENGTH_CHOICES = add_blank_choice([(i, i) for i in range(1, 129)]) # From b84b526a434590797b9fadb3ceb7b9aafffeaa40 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 15 Sep 2017 15:14:35 -0400 Subject: [PATCH 3/7] Closes #1484: Added individual "add VLAN" buttons on the VLAN groups list --- netbox/ipam/models.py | 10 ++++++++++ netbox/ipam/tables.py | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index bbd5e1827..214293b7d 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -512,6 +512,16 @@ class VLANGroup(models.Model): def get_absolute_url(self): return "{}?group_id={}".format(reverse('ipam:vlan_list'), self.pk) + def get_next_available_vid(self): + """ + Return the first available VLAN ID (1-4094) in the group. + """ + vids = [vlan['vid'] for vlan in self.vlans.order_by('vid').values('vid')] + for i in range(1, 4095): + if i not in vids: + return i + return None + @python_2_unicode_compatible class VLAN(CreatedUpdatedModel, CustomFieldModel): diff --git a/netbox/ipam/tables.py b/netbox/ipam/tables.py index 96127aec5..512b75649 100644 --- a/netbox/ipam/tables.py +++ b/netbox/ipam/tables.py @@ -120,6 +120,13 @@ VLAN_ROLE_LINK = """ """ VLANGROUP_ACTIONS = """ +{% with next_vid=record.get_next_available_vid %} + {% if next_vid and perms.ipam.add_vlan %} + + + + {% endif %} +{% endwith %} {% if perms.ipam.change_vlangroup %} {% endif %} From 81df837a3381ebc9f89ea0bbfb15f191042d8bd8 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 15 Sep 2017 15:28:09 -0400 Subject: [PATCH 4/7] Closes #1485: Added LOGIN_BANNER configuration setting to display a banner on the login page --- docs/configuration/optional-settings.md | 8 +++++++- netbox/netbox/configuration.example.py | 7 +++++-- netbox/netbox/settings.py | 5 +++-- netbox/templates/login.html | 7 ++++++- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/docs/configuration/optional-settings.md b/docs/configuration/optional-settings.md index 22916d54c..9cc4e75fd 100644 --- a/docs/configuration/optional-settings.md +++ b/docs/configuration/optional-settings.md @@ -17,7 +17,7 @@ ADMINS = [ ## BANNER_BOTTOM -Setting these variables will display content in a banner at the top and/or bottom of the page, respectively. To replicate the content of the top banner in the bottom banner, set: +Setting these variables will display content in a banner at the top and/or bottom of the page, respectively. HTML is allowed. To replicate the content of the top banner in the bottom banner, set: ``` BANNER_TOP = 'Your banner text' @@ -26,6 +26,12 @@ BANNER_BOTTOM = BANNER_TOP --- +## BANNER_LOGIN + +The value of this variable will be displayed on the login page above the login form. HTML is allowed. + +--- + ## BASE_PATH Default: None diff --git a/netbox/netbox/configuration.example.py b/netbox/netbox/configuration.example.py index 192653dc4..ce7a62464 100644 --- a/netbox/netbox/configuration.example.py +++ b/netbox/netbox/configuration.example.py @@ -38,11 +38,14 @@ ADMINS = [ # ['John Doe', 'jdoe@example.com'], ] -# Optionally display a persistent banner at the top and/or bottom of every page. To display the same content in both -# banners, define BANNER_TOP and set BANNER_BOTTOM = BANNER_TOP. +# Optionally display a persistent banner at the top and/or bottom of every page. HTML is allowed. To display the same +# content in both banners, define BANNER_TOP and set BANNER_BOTTOM = BANNER_TOP. BANNER_TOP = '' BANNER_BOTTOM = '' +# Text to include on the login page above the login form. HTML is allowed. +BANNER_LOGIN = '' + # Base URL path if accessing NetBox within a directory. For example, if installed at http://example.com/netbox/, set: # BASE_PATH = 'netbox/' BASE_PATH = '' diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 02cb5953d..e9d8c04f5 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -29,8 +29,9 @@ for setting in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY']: # Import optional configuration parameters ADMINS = getattr(configuration, 'ADMINS', []) -BANNER_BOTTOM = getattr(configuration, 'BANNER_BOTTOM', False) -BANNER_TOP = getattr(configuration, 'BANNER_TOP', False) +BANNER_BOTTOM = getattr(configuration, 'BANNER_BOTTOM', '') +BANNER_LOGIN = getattr(configuration, 'BANNER_LOGIN', '') +BANNER_TOP = getattr(configuration, 'BANNER_TOP', '') BASE_PATH = getattr(configuration, 'BASE_PATH', '') if BASE_PATH: BASE_PATH = BASE_PATH.strip('/') + '/' # Enforce trailing slash only diff --git a/netbox/templates/login.html b/netbox/templates/login.html index 07b10bfcc..a34b934cc 100644 --- a/netbox/templates/login.html +++ b/netbox/templates/login.html @@ -2,8 +2,13 @@ {% load form_helpers %} {% block content %} -
+
+ {% if settings.BANNER_LOGIN %} +
+ {{ settings.BANNER_LOGIN|safe }} +
+ {% endif %} {% if form.non_field_errors %}
Errors
From ae1662e43318dabc5f6d086a748fa4d941e5b2c9 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 18 Sep 2017 16:34:28 -0400 Subject: [PATCH 5/7] Fixes #1507: Fixed error when creating the next available IP from a prefix within a VRF --- netbox/ipam/api/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index 9cf93cb4b..abff09c15 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -98,7 +98,7 @@ class PrefixViewSet(WritableSerializerMixin, CustomFieldModelViewSet): # Create the new IP address data = request.data.copy() data['address'] = '{}/{}'.format(ipaddress, prefix.prefix.prefixlen) - data['vrf'] = prefix.vrf + data['vrf'] = prefix.vrf.pk if prefix.vrf else None serializer = serializers.WritableIPAddressSerializer(data=data) if serializer.is_valid(): serializer.save() From eba30c4d792eacc427816391a1086be251df1526 Mon Sep 17 00:00:00 2001 From: Chris Howells Date: Mon, 18 Sep 2017 21:37:09 +0100 Subject: [PATCH 6/7] Document the PATCH method. Closes #1481. (#1482) --- docs/api/examples.md | 12 ++++++++++-- docs/api/overview.md | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/api/examples.md b/docs/api/examples.md index 5082534bc..4ec2f0f33 100644 --- a/docs/api/examples.md +++ b/docs/api/examples.md @@ -4,7 +4,8 @@ Supported HTTP methods: * `GET`: Retrieve an object or list of objects * `POST`: Create a new object -* `PUT`: Update an existing object +* `PUT`: Update an existing object, all mandatory fields must be specified +* `PATCH`: Updates an existing object, only specifiying the field to be changed * `DELETE`: Delete an existing object To authenticate a request, attach your token in an `Authorization` header: @@ -104,12 +105,19 @@ $ curl -X POST -H "Authorization: Token d2f763479f703d80de0ec15254237bc651f9cdc0 ### Modify an existing site -Make an authenticated `PUT` request to the site detail endpoint. As with a create (POST) request, all mandatory fields must be included. +Make an authenticated `PUT` request to the site detail endpoint. As with a create (`POST`) request, all mandatory fields must be included. ``` $ curl -X PUT -H "Authorization: Token d2f763479f703d80de0ec15254237bc651f9cdc0" -H "Content-Type: application/json" -H "Accept: application/json; indent=4" http://localhost:8000/api/dcim/sites/16/ --data '{"name": "Renamed Site", "slug": "renamed-site"}' ``` +### Modify an object by changing a field + +Make an authenticated `PATCH` request to the device endpoint. With `PATCH`, unlike `POST` and `PUT`, we only specify the field that is being changed. In this example, we add a serial number to a device. +``` +$ curl -X PATCH -H "Authorization: Token d2f763479f703d80de0ec15254237bc651f9cdc0" -H "Content-Type: application/json" -H "Accept: application/json; indent=4" http://localhost:8000/api/dcim/devices/2549/ --data '{"serial": "FTX1123A090"}' +``` + ### Delete an existing site Send an authenticated `DELETE` request to the site detail endpoint. diff --git a/docs/api/overview.md b/docs/api/overview.md index bdf0a2f4c..39a4109f9 100644 --- a/docs/api/overview.md +++ b/docs/api/overview.md @@ -6,7 +6,7 @@ REST stands for [representational state transfer](https://en.wikipedia.org/wiki/ * `GET`: Retrieve an object or list of objects * `POST`: Create an object -* `PUT` / `PATCH`: Modify an existing object +* `PUT` / `PATCH`: Modify an existing object. `PUT` requires all mandatory fields to be specified, while `PATCH` only expects the field that is being modified to be specified. * `DELETE`: Delete an existing object The NetBox API represents all objects in [JavaScript Object Notation (JSON)](http://www.json.org/). This makes it very easy to interact with NetBox data on the command line with common tools. For example, we can request an IP address from NetBox and output the JSON using `curl` and `jq`. (Piping the output through `jq` isn't strictly required but makes it much easier to read.) From b252f52f8e845f2fdf9c25917eb679566f7c1868 Mon Sep 17 00:00:00 2001 From: Ryan Breaker Date: Mon, 18 Sep 2017 15:37:51 -0500 Subject: [PATCH 7/7] Added missing package for CentOS and Fedora (#1470) Without the added package, installation fails during `pip install -r requirements.txt` on the pycrypto package for me in CentOS 6 and 7 and Fedora. --- docs/installation/netbox.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation/netbox.md b/docs/installation/netbox.md index b0928c1b5..d1aa5d001 100644 --- a/docs/installation/netbox.md +++ b/docs/installation/netbox.md @@ -20,7 +20,7 @@ Python 3: ```no-highlight # yum install -y epel-release -# yum install -y gcc python34 python34-devel python34-setuptools libxml2-devel libxslt-devel libffi-devel graphviz openssl-devel +# yum install -y gcc python34 python34-devel python34-setuptools libxml2-devel libxslt-devel libffi-devel graphviz openssl-devel redhat-rpm-config # easy_install-3.4 pip # ln -s -f python3.4 /usr/bin/python ``` @@ -29,7 +29,7 @@ Python 2: ```no-highlight # yum install -y epel-release -# yum install -y gcc python2 python-devel python-pip libxml2-devel libxslt-devel libffi-devel graphviz openssl-devel +# yum install -y gcc python2 python-devel python-pip libxml2-devel libxslt-devel libffi-devel graphviz openssl-devel redhat-rpm-config ``` You may opt to install NetBox either from a numbered release or by cloning the master branch of its repository on GitHub.