from django.views.decorators.csrf import csrf_exempt from django.contrib.auth.hashers import check_password, make_password from django.http import HttpResponse, JsonResponse from rest_framework.decorators import action, api_view, schema from project.settings import SECRET_KEY, EMAIL_HOST from api import models, schemas from datetime import datetime, timedelta from decouple import config import json import jwt import logging import random from django.conf import settings from django.core.mail import EmailMultiAlternatives from django.template.loader import get_template # Views jwt @csrf_exempt @action(detail=False, methods=['post','get']) @api_view(['GET','POST']) @schema(schemas.AuthSchema()) def jwt_login(request): if request.method == 'POST': # validar rut y password input = json.loads(request.body) rut = input['rut'].replace('.','').replace('-','') if rut != '0': dv = rut[-1].upper() rut = rut[:-1] usuario = None if rut == '0' and password == '0': usuario = { 'login': '0', 'clave': '0' } # solo se permite usuario 0 si no existen usuarios vigentes count = models.Usuario.objects.filter(vigente = True).count() if count > 0: return HttpResponse('Acceso no valido 1', status=400) else: usuario = models.Usuario.objects.filter(vigente=1, rut__rut=rut, rut__dv=dv).values().first() if not check_password(input['password'], usuario['clave']): return HttpResponse('Acceso no valido 2', status=400) ahora = datetime.utcnow() manana = ahora + timedelta(days=1) manana = manana.replace(hour=0, minute=0, second=0, microsecond=0) payload = { 'iat': ahora, 'exp': manana, # ahora + timedelta(minutes=60), 'login': usuario['login'] } token = jwt.encode(payload, SECRET_KEY, algorithm="HS256") return JsonResponse({ 'token': token }) elif request.method == 'GET': return JsonResponse(request.jwt_info) @csrf_exempt @action(detail=False, methods=['post']) @api_view(['POST']) def recuperar(request): input = json.loads(request.body) rut = input['rut'].replace('.','').replace('-','') dv = rut[-1].upper() rut = rut[:-1] persona = models.Persona.objects.filter(rut=rut, dv=dv).first() usuario = models.Usuario.objects.filter(rut=rut, vigente=True).first() if usuario == None or persona == None: return HttpResponse('Acceso no valido 3', status=400) if persona.email != input['email'].lower(): return HttpResponse('Acceso no valido 4', status=400) codigo_aleatorio = random.randint(100000, 999999) ahora = datetime.utcnow() expira = ahora + timedelta(minutes=5) payload = { 'iat': ahora, 'exp': expira, 'rut': f'{persona.rut}', 'codigo': codigo_aleatorio } token = jwt.encode(payload, SECRET_KEY, algorithm="HS256") vinculo = f"{http_referer(request)}/?s={token}#/new-password" exito = enviar_correo(persona.email, 'Recuperar acceso', { 'nombre': f'{persona.nombres} {persona.apellido_a} {persona.apellido_b}', 'codigo': codigo_aleatorio, 'vinculo': vinculo }) return JsonResponse({ 'ok': exito, 'HTTP_REFERER': request.META['HTTP_REFERER'] }) @csrf_exempt @action(detail=False, methods=['post']) @api_view(['POST']) def info_token(request): input = json.loads(request.body) token = input['token'] try: decoded = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]) persona = models.Persona.objects.filter(rut=decoded['rut']).first() return JsonResponse({ 'nombres': persona.nombres, 'apellido_a': persona.apellido_a, 'apellido_b': persona.apellido_b }) except jwt.ExpiredSignatureError: return HttpResponse('token ya no es valido', status = 400) except jwt.InvalidTokenError: return HttpResponse('token es invalido', status = 400) @csrf_exempt @action(detail=False, methods=['post']) @api_view(['POST']) def nueva_contrasena(request): input = json.loads(request.body) token = input['token'] try: decoded = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]) if f"{decoded['codigo']}" != input['codigo']: return HttpResponse('código es invalido', status = 400) usuario = models.Usuario.objects.filter(rut = decoded['rut']).first() if usuario == None: return HttpResponse('Usuario no encontrado', status = 400) usuario.clave = make_password(input['password']) usuario.save() return JsonResponse({ 'ok': True }) except jwt.ExpiredSignatureError: return HttpResponse('token ya no es valido', status = 400) except jwt.InvalidTokenError: return HttpResponse('token es invalido', status = 400) except Exception as e: logging.error(e) return HttpResponse('error al cambiar contraseña', status = 500) def enviar_correo(destinatario, asunto, contenido): try: template = get_template('correo_recuperar.html') # Ruta al template del correo contenido_renderizado = template.render(contenido) mensaje = EmailMultiAlternatives(asunto, '', settings.EMAIL_SENDER, [destinatario]) mensaje.attach_alternative(contenido_renderizado, 'text/html') mensaje.send() return True except Exception as e: print(f'EMAIL_HOST: {settings.EMAIL_HOST}', flush=True) print(f'ERROR: {e}', flush=True) return False def http_referer(request): if 'HTTP_REFERER' in request.META: referer = request.META['HTTP_REFERER'] else: protocol = request.scheme host = request.META['HTTP_HOST'] port = request.META['SERVER_PORT'] referer = f'{protocol}://{host}' return referer