Skip to content

Commit 66bc2eb

Browse files
Merge pull request #1 from anish5256/master
2 parents 34ac637 + 0e2a9f5 commit 66bc2eb

File tree

16 files changed

+398
-1
lines changed

16 files changed

+398
-1
lines changed

drfpasswordless/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
VERSION = (1, 5, 8)
1+
VERSION = (1, 5, 9)
22

33
__version__ = '.'.join(map(str, VERSION))

drfpasswordless/auth.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from rest_framework.authentication import TokenAuthentication
2+
from drfpasswordless.authtoken.models import Token
3+
4+
5+
class TokenAuthentication(TokenAuthentication):
6+
model = Token
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import django
2+
3+
if django.VERSION < (3, 2):
4+
default_app_config = 'drfpasswordless.authtoken.apps.AuthTokenConfig'

drfpasswordless/authtoken/admin.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from django.contrib import admin
2+
from django.contrib.admin.utils import quote
3+
from django.contrib.admin.views.main import ChangeList
4+
from django.contrib.auth import get_user_model
5+
from django.core.exceptions import ValidationError
6+
from django.urls import reverse
7+
8+
from drfpasswordless.authtoken.models import Token, TokenProxy
9+
10+
User = get_user_model()
11+
12+
13+
class TokenChangeList(ChangeList):
14+
"""Map to matching User id"""
15+
def url_for_result(self, result):
16+
pk = result.user.pk
17+
return reverse('admin:%s_%s_change' % (self.opts.app_label,
18+
self.opts.model_name),
19+
args=(quote(pk),),
20+
current_app=self.model_admin.admin_site.name)
21+
22+
23+
class TokenAdmin(admin.ModelAdmin):
24+
list_display = ('key', 'user', 'device_type', 'created')
25+
fields = ('user', 'device_id', 'device_type')
26+
ordering = ('-created',)
27+
actions = None # Actions not compatible with mapped IDs.
28+
29+
def get_changelist(self, request, **kwargs):
30+
return TokenChangeList
31+
32+
def get_object(self, request, object_id, from_field=None):
33+
"""
34+
Map from User ID to matching Token.
35+
"""
36+
queryset = self.get_queryset(request)
37+
field = User._meta.pk
38+
try:
39+
object_id = field.to_python(object_id)
40+
user = User.objects.filter(**{field.name: object_id}).first()
41+
return queryset.filter(user=user).first()
42+
except (queryset.model.DoesNotExist, User.DoesNotExist, ValidationError, ValueError):
43+
return None
44+
45+
def delete_model(self, request, obj):
46+
# Map back to actual Token, since delete() uses pk.
47+
token = Token.objects.get(key=obj.key)
48+
return super().delete_model(request, token)
49+
50+
51+
admin.site.register(TokenProxy, TokenAdmin)

drfpasswordless/authtoken/apps.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from django.apps import AppConfig
2+
from django.utils.translation import gettext_lazy as _
3+
4+
5+
class AuthTokenConfig(AppConfig):
6+
name = 'drfpasswordless.authtoken'
7+
verbose_name = _("Auth Token")

drfpasswordless/authtoken/management/__init__.py

Whitespace-only changes.

drfpasswordless/authtoken/management/commands/__init__.py

Whitespace-only changes.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from django.contrib.auth import get_user_model
2+
from django.core.management.base import BaseCommand, CommandError
3+
4+
from rest_framework.authtoken.models import Token
5+
6+
UserModel = get_user_model()
7+
8+
9+
class Command(BaseCommand):
10+
help = 'Create DRF Token for a given user'
11+
12+
def create_user_token(self, username, reset_token):
13+
user = UserModel._default_manager.get_by_natural_key(username)
14+
15+
if reset_token:
16+
Token.objects.filter(user=user).delete()
17+
18+
token = Token.objects.get_or_create(user=user)
19+
return token[0]
20+
21+
def add_arguments(self, parser):
22+
parser.add_argument('username', type=str)
23+
24+
parser.add_argument(
25+
'-r',
26+
'--reset',
27+
action='store_true',
28+
dest='reset_token',
29+
default=False,
30+
help='Reset existing User token and create a new one',
31+
)
32+
33+
def handle(self, *args, **options):
34+
username = options['username']
35+
reset_token = options['reset_token']
36+
37+
try:
38+
token = self.create_user_token(username, reset_token)
39+
except UserModel.DoesNotExist:
40+
raise CommandError(
41+
'Cannot create the Token: user {} does not exist'.format(
42+
username)
43+
)
44+
self.stdout.write(
45+
'Generated token {} for user {}'.format(token.key, username))
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from django.conf import settings
2+
from django.db import migrations, models
3+
4+
5+
class Migration(migrations.Migration):
6+
7+
dependencies = [
8+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
9+
]
10+
11+
operations = [
12+
migrations.CreateModel(
13+
name='Token',
14+
fields=[
15+
('key', models.CharField(primary_key=True, serialize=False, max_length=40)),
16+
('created', models.DateTimeField(auto_now_add=True)),
17+
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, related_name='auth_token', on_delete=models.CASCADE)),
18+
],
19+
options={
20+
},
21+
bases=(models.Model,),
22+
),
23+
]
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from django.conf import settings
2+
from django.db import migrations, models
3+
4+
5+
class Migration(migrations.Migration):
6+
7+
dependencies = [
8+
('authtoken', '0001_initial'),
9+
]
10+
11+
operations = [
12+
migrations.AlterModelOptions(
13+
name='token',
14+
options={'verbose_name_plural': 'Tokens', 'verbose_name': 'Token'},
15+
),
16+
migrations.AlterField(
17+
model_name='token',
18+
name='created',
19+
field=models.DateTimeField(verbose_name='Created', auto_now_add=True),
20+
),
21+
migrations.AlterField(
22+
model_name='token',
23+
name='key',
24+
field=models.CharField(verbose_name='Key', max_length=40, primary_key=True, serialize=False),
25+
),
26+
migrations.AlterField(
27+
model_name='token',
28+
name='user',
29+
field=models.OneToOneField(to=settings.AUTH_USER_MODEL, verbose_name='User', related_name='auth_token', on_delete=models.CASCADE),
30+
),
31+
]

0 commit comments

Comments
 (0)