1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Full URL for API, more consistent naming, only enabled for staff and better configuration validation

This commit is contained in:
Sander Steffann
2020-01-26 16:50:15 +01:00
parent 9d66ac4a6a
commit 008fc5623e
8 changed files with 70 additions and 55 deletions

View File

@ -157,19 +157,19 @@ Enforcement of unique IP space can be toggled on a per-VRF basis. To enforce uni
---
## GITHUB_REPOSITORY
## GITHUB_REPOSITORY_API
Default: 'netbox-community/netbox'
Default: 'https://api.github.com/repos/netbox-community/netbox'
The tags of this repository are checked to detect new releases, which are shown in the footer of the web interface. You can change this to your own fork of the NetBox repository, or set it to `None` to disable the check.
The releases of this repository are checked to detect new releases, which are shown on the home page of the web interface. You can change this to your own fork of the NetBox repository, or set it to `None` to disable the check.
---
## GITHUB_VERSION_TIMEOUT
## GITHUB_CACHE_TIMEOUT
Default: 8 * 3600
Default: 24 * 3600
The number of seconds to retain the latest version that is fetched from the GitHub API before automatically invalidating it and fetching it from the API again. Set to 0 to disable the version check.
The number of seconds to retain the latest version that is fetched from the GitHub API before automatically invalidating it and fetching it from the API again. This must be set to at least one hour (3600 seconds).
---

View File

@ -126,11 +126,10 @@ EXEMPT_VIEW_PERMISSIONS = [
# This repository is used to check whether there is a new release of NetBox available. Set to None to disable the
# version check.
GITHUB_REPOSITORY = 'netbox-community/netbox'
GITHUB_REPOSITORY_API = 'https://api.github.com/repos/netbox-community/netbox'
# This determines how often the GitHub API is called to check the latest release of NetBox. Set to 0 to disable the
# version check.
GITHUB_VERSION_TIMEOUT = 8 * 3600
# This determines how often the GitHub API is called to check the latest release of NetBox. Must be at least 1 hour.
GITHUB_CACHE_TIMEOUT = 24 * 3600
# Enable custom logging. Please see the Django documentation for detailed guidance on configuring custom logs:
# https://docs.djangoproject.com/en/stable/topics/logging/

View File

@ -4,6 +4,7 @@ import platform
import re
import socket
import warnings
from urllib.parse import urlsplit
from django.contrib.messages import constants as messages
from django.core.exceptions import ImproperlyConfigured
@ -79,8 +80,9 @@ DEVELOPER = getattr(configuration, 'DEVELOPER', False)
EMAIL = getattr(configuration, 'EMAIL', {})
ENFORCE_GLOBAL_UNIQUE = getattr(configuration, 'ENFORCE_GLOBAL_UNIQUE', False)
EXEMPT_VIEW_PERMISSIONS = getattr(configuration, 'EXEMPT_VIEW_PERMISSIONS', [])
GITHUB_REPOSITORY = getattr(configuration, 'GITHUB_REPOSITORY', 'netbox-community/netbox')
GITHUB_VERSION_TIMEOUT = getattr(configuration, 'GITHUB_VERSION_TIMEOUT', 8 * 3600)
GITHUB_REPOSITORY_API = getattr(configuration, 'GITHUB_REPOSITORY_API',
'https://api.github.com/repos/netbox-community/netbox')
GITHUB_CACHE_TIMEOUT = getattr(configuration, 'GITHUB_CACHE_TIMEOUT', 24 * 3600)
LOGGING = getattr(configuration, 'LOGGING', {})
LOGIN_REQUIRED = getattr(configuration, 'LOGIN_REQUIRED', False)
LOGIN_TIMEOUT = getattr(configuration, 'LOGIN_TIMEOUT', None)
@ -295,7 +297,6 @@ TEMPLATES = [
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'utilities.context_processors.settings',
'utilities.context_processors.latest_version',
],
},
},
@ -307,10 +308,28 @@ AUTHENTICATION_BACKENDS = [
]
# GitHub repository for version check
if GITHUB_REPOSITORY and not re.fullmatch(r'[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+', GITHUB_REPOSITORY):
raise ImproperlyConfigured(
"GITHUB_REPOSITORY must contain the name of a GitHub repository in the form '<owner>/<repository>'"
)
if GITHUB_REPOSITORY_API:
GITHUB_REPOSITORY_API = GITHUB_REPOSITORY_API.rstrip('/')
try:
scheme, netloc, path, query, fragment = urlsplit(GITHUB_REPOSITORY_API)
except ValueError:
raise ImproperlyConfigured("GITHUB_REPOSITORY_API must be a valid URL")
if scheme not in ('http', 'https'):
raise ImproperlyConfigured("GITHUB_REPOSITORY_API must be a valid http:// or https:// URL")
if not re.fullmatch(r'/repos/[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+', path):
raise ImproperlyConfigured(
"GITHUB_REPOSITORY must contain the base URL of the GitHub API in a form like "
"'https://api.github.com/repos/<owner>/<repository>'"
)
if query or fragment:
raise ImproperlyConfigured("GITHUB_REPOSITORY_API may not contain a query or fragment")
# Enforce a cache timeout of at least an hour to protect GitHub
if GITHUB_CACHE_TIMEOUT < 3600:
raise ImproperlyConfigured("GITHUB_CACHE_TIMEOUT has to be at least 3600 seconds (1 hour)")
# Internationalization
LANGUAGE_CODE = 'en-us'

View File

@ -1,8 +1,10 @@
from collections import OrderedDict
from django.db.models import Count, F
from django.conf import settings
from django.db.models import Count, F, OuterRef, Subquery
from django.shortcuts import render
from django.views.generic import View
from packaging import version
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework.views import APIView
@ -31,6 +33,7 @@ from secrets.tables import SecretTable
from tenancy.filters import TenantFilterSet
from tenancy.models import Tenant
from tenancy.tables import TenantTable
from utilities.releases import get_latest_release
from virtualization.filters import ClusterFilterSet, VirtualMachineFilterSet
from virtualization.models import Cluster, VirtualMachine
from virtualization.tables import ClusterTable, VirtualMachineDetailTable
@ -240,11 +243,25 @@ class HomeView(View):
}
new_release = None
new_release_url = None
if request.user.is_staff:
# Only check for new releases if the current user might be able to do anything about it
latest_release, github_url = get_latest_release()
if isinstance(latest_release, version.Version):
current_version = version.parse(settings.VERSION)
if latest_release > current_version:
new_release = str(latest_release)
new_release_url = github_url
return render(request, self.template_name, {
'search_form': SearchForm(),
'stats': stats,
'report_results': ReportResult.objects.order_by('-created')[:10],
'changelog': ObjectChange.objects.prefetch_related('user', 'changed_object_type')[:15]
'changelog': ObjectChange.objects.prefetch_related('user', 'changed_object_type')[:15],
'new_release': new_release,
'new_release_url': new_release_url,
})

View File

@ -50,16 +50,7 @@
<div class="container">
<div class="row">
<div class="col-xs-4">
<p class="text-muted">
{{ settings.HOSTNAME }} (v{{ settings.VERSION }})
{% if latest_version %}
{% if latest_version_url %}<a target="_blank" href="{{ latest_version_url }}">{% endif %}
<span class="label label-default" style="color: #ffffff; background-color: #ff9800">
New version: {{ latest_version }}
</span>
{% if latest_version_url %}</a>{% endif %}
{% endif %}
</p>
<p class="text-muted">{{ settings.HOSTNAME }} (v{{ settings.VERSION }})</p>
</div>
<div class="col-xs-4 text-center">
<p class="text-muted">{% now 'Y-m-d H:i:s T' %}</p>

View File

@ -1,6 +1,18 @@
{% extends '_base.html' %}
{% load helpers %}
{% block header %}
{% if new_release %}
<div class="alert alert-info" role="alert">
A new release is available:
{% if new_release_url %}<a target="_blank" href="{{ new_release_url }}">{% endif %}
NetBox v{{ new_release }}
{% if latest_version_url %}</a>{% endif %}
</div>
{% endif %}
{% endblock %}
{% block content %}
{% include 'search_form.html' %}
<div class="row">

View File

@ -1,7 +1,4 @@
from django.conf import settings as django_settings
from packaging import version
from utilities.versions import get_latest_release
def settings(request):
@ -11,23 +8,3 @@ def settings(request):
return {
'settings': django_settings,
}
def latest_version(request):
"""
Get the latest version from the GitHub repository
"""
latest_release, github_url = get_latest_release()
latest_version_str = None
latest_version_url = None
if isinstance(latest_release, version.Version):
current_version = version.parse(django_settings.VERSION)
if latest_release > current_version:
latest_version_str = str(latest_release)
latest_version_url = github_url
return {
'latest_version': latest_version_str,
'latest_version_url': latest_version_url
}

View File

@ -4,9 +4,9 @@ from django.conf import settings
from packaging import version
@cached(timeout=settings.GITHUB_VERSION_TIMEOUT if settings.GITHUB_VERSION_TIMEOUT > 0 else 1)
@cached(timeout=settings.GITHUB_CACHE_TIMEOUT, extra=settings.GITHUB_REPOSITORY_API)
def get_releases(pre_releases=False):
url = 'https://api.github.com/repos/{}/releases'.format(settings.GITHUB_REPOSITORY)
url = '{}/releases'.format(settings.GITHUB_REPOSITORY_API)
headers = {
'Accept': 'application/vnd.github.v3+json',
}
@ -27,7 +27,7 @@ def get_releases(pre_releases=False):
def get_latest_release(pre_releases=False):
if settings.GITHUB_VERSION_TIMEOUT > 0 and settings.GITHUB_REPOSITORY:
if settings.GITHUB_REPOSITORY_API:
releases = get_releases(pre_releases)
if releases:
return max(releases)