mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 09:51:22 -06:00
Closes #2479: Add user permissions for creating/modifying API tokens
This commit is contained in:
parent
2fee977b4c
commit
5d10d8418e
@ -2,6 +2,7 @@ v2.4.6 (FUTURE)
|
|||||||
|
|
||||||
## Enhancements
|
## Enhancements
|
||||||
|
|
||||||
|
* [#2479](https://github.com/digitalocean/netbox/issues/2479) - Add user permissions for creating/modifying API tokens
|
||||||
* [#2487](https://github.com/digitalocean/netbox/issues/2487) - Return abbreviated API output when passed `?brief=1`
|
* [#2487](https://github.com/digitalocean/netbox/issues/2487) - Return abbreviated API output when passed `?brief=1`
|
||||||
|
|
||||||
## Bug Fixes
|
## Bug Fixes
|
||||||
|
@ -4,6 +4,9 @@ The NetBox API employs token-based authentication. For convenience, cookie authe
|
|||||||
|
|
||||||
A token is a unique identifier that identifies a user to the API. Each user in NetBox may have one or more tokens which he or she can use to authenticate to the API. To create a token, navigate to the API tokens page at `/user/api-tokens/`.
|
A token is a unique identifier that identifies a user to the API. Each user in NetBox may have one or more tokens which he or she can use to authenticate to the API. To create a token, navigate to the API tokens page at `/user/api-tokens/`.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
The creation and modification of API tokens can be restricted per user by an administrator. If you don't see an option to create an API token, ask an administrator to grant you access.
|
||||||
|
|
||||||
Each token contains a 160-bit key represented as 40 hexadecimal characters. When creating a token, you'll typically leave the key field blank so that a random key will be automatically generated. However, NetBox allows you to specify a key in case you need to restore a previously deleted token to operation.
|
Each token contains a 160-bit key represented as 40 hexadecimal characters. When creating a token, you'll typically leave the key field blank so that a random key will be automatically generated. However, NetBox allows you to specify a key in case you need to restore a previously deleted token to operation.
|
||||||
|
|
||||||
By default, a token can be used for all operations available via the API. Deselecting the "write enabled" option will restrict API requests made with the token to read operations (e.g. GET) only.
|
By default, a token can be used for all operations available via the API. Deselecting the "write enabled" option will restrict API requests made with the token to read operations (e.g. GET) only.
|
||||||
|
@ -10,8 +10,12 @@
|
|||||||
<div class="panel panel-{% if token.is_expired %}danger{% else %}default{% endif %}">
|
<div class="panel panel-{% if token.is_expired %}danger{% else %}default{% endif %}">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<a href="{% url 'user:token_edit' pk=token.pk %}" class="btn btn-xs btn-warning">Edit</a>
|
{% if perms.users.change_token %}
|
||||||
<a href="{% url 'user:token_delete' pk=token.pk %}" class="btn btn-xs btn-danger">Delete</a>
|
<a href="{% url 'user:token_edit' pk=token.pk %}" class="btn btn-xs btn-warning">Edit</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if perms.users.delete_token %}
|
||||||
|
<a href="{% url 'user:token_delete' pk=token.pk %}" class="btn btn-xs btn-danger">Delete</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<i class="fa fa-key"></i> {{ token.key }}
|
<i class="fa fa-key"></i> {{ token.key }}
|
||||||
{% if token.is_expired %}
|
{% if token.is_expired %}
|
||||||
@ -49,10 +53,16 @@
|
|||||||
{% empty %}
|
{% empty %}
|
||||||
<p>You do not have any API tokens.</p>
|
<p>You do not have any API tokens.</p>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<a href="{% url 'user:token_add' %}" class="btn btn-primary">
|
{% if perms.users.add_token %}
|
||||||
<span class="fa fa-plus" aria-hidden="true"></span>
|
<a href="{% url 'user:token_add' %}" class="btn btn-primary">
|
||||||
Add a token
|
<span class="fa fa-plus" aria-hidden="true"></span>
|
||||||
</a>
|
Add a token
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
<div class="alert alert-info text-center" role="alert">
|
||||||
|
You do not have permission to create new API tokens. If needed, ask an administrator to enable token creation for your account or an assigned group.
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
17
netbox/users/migrations/0003_token_permissions.py
Normal file
17
netbox/users/migrations/0003_token_permissions.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 2.0.8 on 2018-10-05 14:32
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('users', '0001_api_tokens_squashed_0002_unicode_literals'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='token',
|
||||||
|
options={},
|
||||||
|
),
|
||||||
|
]
|
@ -43,7 +43,7 @@ class Token(models.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
default_permissions = []
|
pass
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# Only display the last 24 bits of the token to avoid accidental exposure.
|
# Only display the last 24 bits of the token to avoid accidental exposure.
|
||||||
|
@ -3,8 +3,8 @@ from __future__ import unicode_literals
|
|||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth import login as auth_login, logout as auth_logout, update_session_auth_hash
|
from django.contrib.auth import login as auth_login, logout as auth_logout, update_session_auth_hash
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseForbidden, HttpResponseRedirect
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
@ -231,8 +231,12 @@ class TokenEditView(LoginRequiredMixin, View):
|
|||||||
def get(self, request, pk=None):
|
def get(self, request, pk=None):
|
||||||
|
|
||||||
if pk is not None:
|
if pk is not None:
|
||||||
|
if not request.user.has_perm('users.change_token'):
|
||||||
|
return HttpResponseForbidden()
|
||||||
token = get_object_or_404(Token.objects.filter(user=request.user), pk=pk)
|
token = get_object_or_404(Token.objects.filter(user=request.user), pk=pk)
|
||||||
else:
|
else:
|
||||||
|
if not request.user.has_perm('users.add_token'):
|
||||||
|
return HttpResponseForbidden()
|
||||||
token = Token(user=request.user)
|
token = Token(user=request.user)
|
||||||
|
|
||||||
form = TokenForm(instance=token)
|
form = TokenForm(instance=token)
|
||||||
@ -274,7 +278,8 @@ class TokenEditView(LoginRequiredMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class TokenDeleteView(LoginRequiredMixin, View):
|
class TokenDeleteView(PermissionRequiredMixin, View):
|
||||||
|
permission_required = 'users.delete_token'
|
||||||
|
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user