GNXSOFT.COM
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
import django
|
||||
|
||||
if django.VERSION < (3, 2):
|
||||
default_app_config = 'rest_framework.authtoken.apps.AuthTokenConfig'
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,51 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib.admin.utils import quote
|
||||
from django.contrib.admin.views.main import ChangeList
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.urls import reverse
|
||||
|
||||
from rest_framework.authtoken.models import Token, TokenProxy
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class TokenChangeList(ChangeList):
|
||||
"""Map to matching User id"""
|
||||
def url_for_result(self, result):
|
||||
pk = result.user.pk
|
||||
return reverse('admin:%s_%s_change' % (self.opts.app_label,
|
||||
self.opts.model_name),
|
||||
args=(quote(pk),),
|
||||
current_app=self.model_admin.admin_site.name)
|
||||
|
||||
|
||||
class TokenAdmin(admin.ModelAdmin):
|
||||
list_display = ('key', 'user', 'created')
|
||||
fields = ('user',)
|
||||
ordering = ('-created',)
|
||||
actions = None # Actions not compatible with mapped IDs.
|
||||
|
||||
def get_changelist(self, request, **kwargs):
|
||||
return TokenChangeList
|
||||
|
||||
def get_object(self, request, object_id, from_field=None):
|
||||
"""
|
||||
Map from User ID to matching Token.
|
||||
"""
|
||||
queryset = self.get_queryset(request)
|
||||
field = User._meta.pk
|
||||
try:
|
||||
object_id = field.to_python(object_id)
|
||||
user = User.objects.get(**{field.name: object_id})
|
||||
return queryset.get(user=user)
|
||||
except (queryset.model.DoesNotExist, User.DoesNotExist, ValidationError, ValueError):
|
||||
return None
|
||||
|
||||
def delete_model(self, request, obj):
|
||||
# Map back to actual Token, since delete() uses pk.
|
||||
token = Token.objects.get(key=obj.key)
|
||||
return super().delete_model(request, token)
|
||||
|
||||
|
||||
admin.site.register(TokenProxy, TokenAdmin)
|
||||
@@ -0,0 +1,7 @@
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class AuthTokenConfig(AppConfig):
|
||||
name = 'rest_framework.authtoken'
|
||||
verbose_name = _("Auth Token")
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,45 @@
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from rest_framework.authtoken.models import Token
|
||||
|
||||
UserModel = get_user_model()
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Create DRF Token for a given user'
|
||||
|
||||
def create_user_token(self, username, reset_token):
|
||||
user = UserModel._default_manager.get_by_natural_key(username)
|
||||
|
||||
if reset_token:
|
||||
Token.objects.filter(user=user).delete()
|
||||
|
||||
token = Token.objects.get_or_create(user=user)
|
||||
return token[0]
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('username', type=str)
|
||||
|
||||
parser.add_argument(
|
||||
'-r',
|
||||
'--reset',
|
||||
action='store_true',
|
||||
dest='reset_token',
|
||||
default=False,
|
||||
help='Reset existing User token and create a new one',
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
username = options['username']
|
||||
reset_token = options['reset_token']
|
||||
|
||||
try:
|
||||
token = self.create_user_token(username, reset_token)
|
||||
except UserModel.DoesNotExist:
|
||||
raise CommandError(
|
||||
'Cannot create the Token: user {} does not exist'.format(
|
||||
username)
|
||||
)
|
||||
self.stdout.write(
|
||||
'Generated token {} for user {}'.format(token.key, username))
|
||||
@@ -0,0 +1,23 @@
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Token',
|
||||
fields=[
|
||||
('key', models.CharField(primary_key=True, serialize=False, max_length=40)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, related_name='auth_token', on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,31 @@
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authtoken', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='token',
|
||||
options={'verbose_name_plural': 'Tokens', 'verbose_name': 'Token'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='token',
|
||||
name='created',
|
||||
field=models.DateTimeField(verbose_name='Created', auto_now_add=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='token',
|
||||
name='key',
|
||||
field=models.CharField(verbose_name='Key', max_length=40, primary_key=True, serialize=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='token',
|
||||
name='user',
|
||||
field=models.OneToOneField(to=settings.AUTH_USER_MODEL, verbose_name='User', related_name='auth_token', on_delete=models.CASCADE),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 3.1.1 on 2020-09-28 09:34
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authtoken', '0002_auto_20160226_1747'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='TokenProxy',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'token',
|
||||
'proxy': True,
|
||||
'indexes': [],
|
||||
'constraints': [],
|
||||
},
|
||||
bases=('authtoken.token',),
|
||||
),
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,54 @@
|
||||
import binascii
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class Token(models.Model):
|
||||
"""
|
||||
The default authorization token model.
|
||||
"""
|
||||
key = models.CharField(_("Key"), max_length=40, primary_key=True)
|
||||
user = models.OneToOneField(
|
||||
settings.AUTH_USER_MODEL, related_name='auth_token',
|
||||
on_delete=models.CASCADE, verbose_name=_("User")
|
||||
)
|
||||
created = models.DateTimeField(_("Created"), auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
# Work around for a bug in Django:
|
||||
# https://code.djangoproject.com/ticket/19422
|
||||
#
|
||||
# Also see corresponding ticket:
|
||||
# https://github.com/encode/django-rest-framework/issues/705
|
||||
abstract = 'rest_framework.authtoken' not in settings.INSTALLED_APPS
|
||||
verbose_name = _("Token")
|
||||
verbose_name_plural = _("Tokens")
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.key:
|
||||
self.key = self.generate_key()
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def generate_key(cls):
|
||||
return binascii.hexlify(os.urandom(20)).decode()
|
||||
|
||||
def __str__(self):
|
||||
return self.key
|
||||
|
||||
|
||||
class TokenProxy(Token):
|
||||
"""
|
||||
Proxy mapping pk to user pk for use in admin.
|
||||
"""
|
||||
@property
|
||||
def pk(self):
|
||||
return self.user_id
|
||||
|
||||
class Meta:
|
||||
proxy = 'rest_framework.authtoken' in settings.INSTALLED_APPS
|
||||
abstract = 'rest_framework.authtoken' not in settings.INSTALLED_APPS
|
||||
verbose_name = "token"
|
||||
@@ -0,0 +1,42 @@
|
||||
from django.contrib.auth import authenticate
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
class AuthTokenSerializer(serializers.Serializer):
|
||||
username = serializers.CharField(
|
||||
label=_("Username"),
|
||||
write_only=True
|
||||
)
|
||||
password = serializers.CharField(
|
||||
label=_("Password"),
|
||||
style={'input_type': 'password'},
|
||||
trim_whitespace=False,
|
||||
write_only=True
|
||||
)
|
||||
token = serializers.CharField(
|
||||
label=_("Token"),
|
||||
read_only=True
|
||||
)
|
||||
|
||||
def validate(self, attrs):
|
||||
username = attrs.get('username')
|
||||
password = attrs.get('password')
|
||||
|
||||
if username and password:
|
||||
user = authenticate(request=self.context.get('request'),
|
||||
username=username, password=password)
|
||||
|
||||
# The authenticate call simply returns None for is_active=False
|
||||
# users. (Assuming the default ModelBackend authentication
|
||||
# backend.)
|
||||
if not user:
|
||||
msg = _('Unable to log in with provided credentials.')
|
||||
raise serializers.ValidationError(msg, code='authorization')
|
||||
else:
|
||||
msg = _('Must include "username" and "password".')
|
||||
raise serializers.ValidationError(msg, code='authorization')
|
||||
|
||||
attrs['user'] = user
|
||||
return attrs
|
||||
@@ -0,0 +1,62 @@
|
||||
from rest_framework import parsers, renderers
|
||||
from rest_framework.authtoken.models import Token
|
||||
from rest_framework.authtoken.serializers import AuthTokenSerializer
|
||||
from rest_framework.compat import coreapi, coreschema
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.schemas import ManualSchema
|
||||
from rest_framework.schemas import coreapi as coreapi_schema
|
||||
from rest_framework.views import APIView
|
||||
|
||||
|
||||
class ObtainAuthToken(APIView):
|
||||
throttle_classes = ()
|
||||
permission_classes = ()
|
||||
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
|
||||
renderer_classes = (renderers.JSONRenderer,)
|
||||
serializer_class = AuthTokenSerializer
|
||||
|
||||
if coreapi_schema.is_enabled():
|
||||
schema = ManualSchema(
|
||||
fields=[
|
||||
coreapi.Field(
|
||||
name="username",
|
||||
required=True,
|
||||
location='form',
|
||||
schema=coreschema.String(
|
||||
title="Username",
|
||||
description="Valid username for authentication",
|
||||
),
|
||||
),
|
||||
coreapi.Field(
|
||||
name="password",
|
||||
required=True,
|
||||
location='form',
|
||||
schema=coreschema.String(
|
||||
title="Password",
|
||||
description="Valid password for authentication",
|
||||
),
|
||||
),
|
||||
],
|
||||
encoding="application/json",
|
||||
)
|
||||
|
||||
def get_serializer_context(self):
|
||||
return {
|
||||
'request': self.request,
|
||||
'format': self.format_kwarg,
|
||||
'view': self
|
||||
}
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
kwargs['context'] = self.get_serializer_context()
|
||||
return self.serializer_class(*args, **kwargs)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
user = serializer.validated_data['user']
|
||||
token, created = Token.objects.get_or_create(user=user)
|
||||
return Response({'token': token.key})
|
||||
|
||||
|
||||
obtain_auth_token = ObtainAuthToken.as_view()
|
||||
Reference in New Issue
Block a user