ilab_gestion_backend/project/api/views/auth.py

186 lines
5.9 KiB
Python
Raw Normal View History

2023-12-05 10:34:47 -03:00
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.hashers import check_password, make_password
from django.http import HttpResponse, JsonResponse
2023-12-05 10:34:47 -03:00
from rest_framework.decorators import action, api_view, schema
from project.settings import SECRET_KEY, EMAIL_HOST
2023-12-05 10:34:47 -03:00
from api import models, schemas
from datetime import datetime, timedelta
2023-12-05 10:34:47 -03:00
from decouple import config
import json
import jwt
import logging
import random
2023-12-05 10:34:47 -03:00
from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.template.loader import get_template
2023-12-05 10:34:47 -03:00
# 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
2023-12-05 10:34:47 -03:00
input = json.loads(request.body)
rut = input['rut'].replace('.','').replace('-','')
if rut != '0':
dv = rut[-1].upper()
rut = rut[:-1]
2024-07-30 13:14:45 -04:00
2023-12-05 10:34:47 -03:00
usuario = None
if rut == '0' and password == '0':
2023-12-05 10:34:47 -03:00
usuario = { 'login': '0', 'clave': '0' }
2024-07-30 13:14:45 -04:00
# solo se permite usuario 0 si no existen usuarios vigentes
count = models.Usuario.objects.filter(vigente = True).count()
if count > 0:
2024-07-30 13:31:59 -04:00
return HttpResponse('Acceso no valido 1', status=400)
else:
usuario = models.Usuario.objects.filter(vigente=1, rut__rut=rut, rut__dv=dv).values().first()
2023-12-05 10:34:47 -03:00
if not check_password(input['password'], usuario['clave']):
2024-07-30 13:31:59 -04:00
return HttpResponse('Acceso no valido 2', status=400)
2023-12-05 10:34:47 -03:00
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")
2023-12-05 10:34:47 -03:00
return JsonResponse({ 'token': token })
2023-12-05 10:34:47 -03:00
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:
2024-07-30 13:43:31 -04:00
return HttpResponse('El usuario no existe', status=400)
if persona.email != input['email'].lower():
2024-07-30 13:43:31 -04:00
return HttpResponse('El correo electrónico no es el registrado para el usuario', 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']
2024-07-30 15:48:14 -04:00
logging.warning(input)
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:
2024-07-30 15:10:00 -04:00
return HttpResponse('token es invalido A', 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:
2024-07-30 15:10:00 -04:00
return HttpResponse('token es invalido B', 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)
2024-07-30 13:31:59 -04:00
mensaje = EmailMultiAlternatives(asunto, '', settings.EMAIL_SENDER, [destinatario])
mensaje.attach_alternative(contenido_renderizado, 'text/html')
mensaje.send()
return True
except Exception as e:
2024-07-30 13:14:45 -04:00
print(f'EMAIL_HOST: {settings.EMAIL_HOST}', flush=True)
print(f'ERROR: {e}', flush=True)
return False
2024-07-30 15:59:10 -04:00
def http_referer(request, clean=False):
if 'HTTP_REFERER' in request.META and clean==False:
referer = request.META['HTTP_REFERER']
else:
protocol = request.scheme
host = request.META['HTTP_HOST']
port = request.META['SERVER_PORT']
referer = f'{protocol}://{host}'
2024-07-30 13:14:45 -04:00
return referer