This commit is contained in:
Iliyan Angelov
2025-09-14 23:24:25 +03:00
commit c67067a2a4
71311 changed files with 6800714 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
import django
if django.VERSION < (3, 2):
default_app_config = 'rest_framework.authtoken.apps.AuthTokenConfig'

View File

@@ -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)

View File

@@ -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")

View File

@@ -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))

View File

@@ -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,),
),
]

View File

@@ -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),
),
]

View File

@@ -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',),
),
]

View File

@@ -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"

View File

@@ -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

View File

@@ -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()