admin_transporte_backend/project/api/views/auth.py

188 lines
5.9 KiB
Python
Executable File

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', 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', 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', status=400)
if persona.email != input['email'].lower():
return HttpResponse('Acceso no valido', 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_HOST_USER, [destinatario])
mensaje.attach_alternative(contenido_renderizado, 'text/html')
mensaje.send()
return True
except Exception as e:
print(f'EMAIL_HOST: {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