import hashlib import random import string from django.conf import settings from django.db import models from django.forms import ValidationError from rest_framework.reverse import reverse from access.fields import ( AutoCreatedField, AutoLastModifiedField ) from core.lib.feature_not_used import FeatureNotUsed class AuthToken(models.Model): class Meta: ordering = [ 'expires' ] verbose_name = 'Auth Token' verbose_name_plural = 'Auth Tokens' def validate_note_no_token(self, note, token, raise_exception = True) -> bool: """ Ensure plaintext token cant be saved to notes field. called from centurion.settings.views.user_settings.TokenAdd.form_valid() Args: note (Field): _Note field_ token (Field): _Token field_ Raises: ValidationError: _Validation failed_ """ validation: bool = True if str(note) == str(token): validation = False if str(token)[:9] in str(note): # Allow user to use up to 8 chars so they can reference it. validation = False if not validation and raise_exception: raise ValidationError('Token can not be placed in the notes field.') return validation id = models.AutoField( blank=False, help_text = 'ID of this token', primary_key=True, unique=True, verbose_name = 'ID' ) note = models.CharField( blank = True, default = None, help_text = 'A note about this token', max_length = 50, null= True, verbose_name = 'Note' ) token = models.CharField( blank = False, db_index=True, help_text = 'The authorization token', max_length = 64, null = False, unique = True, verbose_name = 'Auth Token', ) user = models.ForeignKey( settings.AUTH_USER_MODEL, help_text = 'User this token belongs to', on_delete=models.CASCADE, verbose_name = 'Owner' ) expires = models.DateTimeField( blank = False, help_text = 'When this token expires', null = False, verbose_name = 'Expiry Date', ) created = AutoCreatedField() modified = AutoLastModifiedField() history_app_label: str = None history_model_name: str = None kb_model_name: str = None note_basename: str = None @property def generate(self) -> str: return str(hashlib.sha256(str(self.randomword()).encode('utf-8')).hexdigest()) def token_hash(self, token:str) -> str: salt = settings.SECRET_KEY return str(hashlib.sha256(str(token + salt).encode('utf-8')).hexdigest()) def randomword(self) -> str: return ''.join(random.choice(string.ascii_letters) for i in range(120)) def __str__(self): return self.token table_fields: list = [ 'note', 'created', 'expires', '-action_delete-', ] def get_url( self, request = None ) -> str: if request: return reverse(f"v2:_api_v2_user_settings_token-detail", request=request, kwargs = self.get_url_kwargs() ) return reverse(f"v2:_api_v2_user_settings_token-detail", kwargs = self.get_url_kwargs() ) def get_url_kwargs(self) -> dict: """Fetch the URL kwargs Returns: dict: kwargs required for generating the URL with `reverse` """ return { 'model_id': self.user.id, 'pk': self.id } def get_url_kwargs_notes(self): return FeatureNotUsed