forked from TDTP/admin_transporte_backend
Merge branch 'master' of https://gitlab.com/m3f_usm/admin_transporte/backend into develop/Ronald
Obteniendo ultima versionfrancisco/photos
commit
b1041b2a2f
|
@ -0,0 +1,19 @@
|
||||||
|
# Conexion con base datos principal
|
||||||
|
DBHOST=db
|
||||||
|
DBPORT=5432
|
||||||
|
DBNAME=transporte
|
||||||
|
DBSCHEMA=public
|
||||||
|
DBUSER=postgres
|
||||||
|
DBPASS=password
|
||||||
|
|
||||||
|
# Conexion con base datos redis
|
||||||
|
DB_REDIS_HOST=dbproto
|
||||||
|
DB_REDIS_PORT=6379
|
||||||
|
|
||||||
|
# Datos de emisor de correos
|
||||||
|
SMTP_HOST=smtp-mail.outlook.com
|
||||||
|
SMTP_PORT=587
|
||||||
|
SMTP_PROTOCOL=tls
|
||||||
|
SMTP_USER=francisco.sandoval@outlook.cl
|
||||||
|
SMTP_PASS=ppcsrdsvecdewnfl
|
||||||
|
SMTP_FROM='"Sistema Transporte" <francisco.sandoval@outlook.cl>'
|
|
@ -2,11 +2,10 @@ from django.urls import resolve
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from .models import Usuario, Persona
|
from .models import Usuario, Persona
|
||||||
from decouple import config
|
from decouple import config
|
||||||
|
from project.settings import SECRET_KEY
|
||||||
import jwt
|
import jwt
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
private_key = config('SECRET_JWT')
|
|
||||||
|
|
||||||
class ApiMiddleware:
|
class ApiMiddleware:
|
||||||
def __init__(self, get_response):
|
def __init__(self, get_response):
|
||||||
self.get_response = get_response
|
self.get_response = get_response
|
||||||
|
@ -17,11 +16,6 @@ class ApiMiddleware:
|
||||||
response = self.get_response(request)
|
response = self.get_response(request)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
# se omite esta regla en login
|
|
||||||
if request.path == '/api/auth/' and request.method == 'POST':
|
|
||||||
response = self.get_response(request)
|
|
||||||
return response
|
|
||||||
|
|
||||||
match = resolve(request.path)
|
match = resolve(request.path)
|
||||||
logging.error(match)
|
logging.error(match)
|
||||||
|
|
||||||
|
@ -30,6 +24,22 @@ class ApiMiddleware:
|
||||||
response = self.get_response(request)
|
response = self.get_response(request)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
if match.url_name == 'auth_login' and request.method == 'POST':
|
||||||
|
response = self.get_response(request)
|
||||||
|
return response
|
||||||
|
|
||||||
|
if match.url_name == 'auth_recuperar':
|
||||||
|
response = self.get_response(request)
|
||||||
|
return response
|
||||||
|
|
||||||
|
if match.url_name == 'auth_info':
|
||||||
|
response = self.get_response(request)
|
||||||
|
return response
|
||||||
|
|
||||||
|
if match.url_name == 'auth_contrasena':
|
||||||
|
response = self.get_response(request)
|
||||||
|
return response
|
||||||
|
|
||||||
# se omite esta regla al mostrar informacion publica de paradero
|
# se omite esta regla al mostrar informacion publica de paradero
|
||||||
if match.url_name == 'paradero-info-public' and request.method == 'GET':
|
if match.url_name == 'paradero-info-public' and request.method == 'GET':
|
||||||
response = self.get_response(request)
|
response = self.get_response(request)
|
||||||
|
@ -42,7 +52,7 @@ class ApiMiddleware:
|
||||||
token = authorization[1]
|
token = authorization[1]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
decoded = jwt.decode(token, private_key, algorithms=["HS256"])
|
decoded = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
|
||||||
except jwt.ExpiredSignatureError:
|
except jwt.ExpiredSignatureError:
|
||||||
return HttpResponse('token ya no es valido', status = 400)
|
return HttpResponse('token ya no es valido', status = 400)
|
||||||
except jwt.InvalidTokenError:
|
except jwt.InvalidTokenError:
|
||||||
|
|
|
@ -369,24 +369,13 @@ class Usuario(models.Model):
|
||||||
vigente = models.BooleanField(blank=True, null=True)
|
vigente = models.BooleanField(blank=True, null=True)
|
||||||
superuser = models.BooleanField(blank=True, null=True)
|
superuser = models.BooleanField(blank=True, null=True)
|
||||||
id_rol = models.ForeignKey(Rol, models.DO_NOTHING, db_column='id_rol', blank=False, null=False)
|
id_rol = models.ForeignKey(Rol, models.DO_NOTHING, db_column='id_rol', blank=False, null=False)
|
||||||
|
clave = models.CharField(max_length=100, blank=True, null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
managed = False
|
managed = False
|
||||||
db_table = 'usuario'
|
db_table = 'usuario'
|
||||||
|
|
||||||
|
|
||||||
class UsuarioClave(models.Model):
|
|
||||||
login = models.OneToOneField(Usuario, models.DO_NOTHING, db_column='login', primary_key=True)
|
|
||||||
clave = models.CharField(max_length=60, blank=True, null=True)
|
|
||||||
clave_anterior = models.CharField(max_length=60, blank=True, null=True)
|
|
||||||
fecha_modificacion = models.DateField(blank=True, null=True)
|
|
||||||
codigo = models.DecimalField(max_digits=8, decimal_places=0, blank=True, null=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
managed = False
|
|
||||||
db_table = 'usuario_clave'
|
|
||||||
|
|
||||||
|
|
||||||
class Vehiculo(models.Model):
|
class Vehiculo(models.Model):
|
||||||
ppu = models.CharField(primary_key=True, max_length=10)
|
ppu = models.CharField(primary_key=True, max_length=10)
|
||||||
id_tipo_vehiculo = models.ForeignKey(TipoVehiculo, models.DO_NOTHING, db_column='id_tipo_vehiculo', blank=True, null=True)
|
id_tipo_vehiculo = models.ForeignKey(TipoVehiculo, models.DO_NOTHING, db_column='id_tipo_vehiculo', blank=True, null=True)
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<p><strong>Estimado/a {{ nombre }}</strong></p>
|
||||||
|
<p>Para crear una nueva contraseña, es necesario que ingrese el siguiente código:
|
||||||
|
<strong style="font-size: 1.5rem;">{{ codigo }}</strong>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Pinche el siguiente botón para crear una nueva contraseña.</p>
|
||||||
|
<p>
|
||||||
|
<a href="{{ vinculo }}" target="_blank" style="background: steelblue; color: #fff; padding: 1rem;">
|
||||||
|
CREAR NUEVA CONTRASEÑA
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -34,7 +34,10 @@ router.register('roles-lineas', rol_linea.RolLineaViewSet, basename='rol_linea')
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', include(router.urls)),
|
path('', include(router.urls)),
|
||||||
path('auth/', auth.jwt_login, name='auth'),
|
path('auth/', auth.jwt_login, name='auth_login'),
|
||||||
|
path('auth/recuperar/', auth.recuperar, name='auth_recuperar'),
|
||||||
|
path('auth/info/', auth.info_token, name='auth_info'),
|
||||||
|
path('auth/nueva-contrasena/', auth.nueva_contrasena, name='auth_contrasena'),
|
||||||
path('mapas/paraderos/', mapa.paraderos, name='mapa-paraderos'),
|
path('mapas/paraderos/', mapa.paraderos, name='mapa-paraderos'),
|
||||||
path('mapas/rutas/', mapa.rutas, name='mapa-rutas'),
|
path('mapas/rutas/', mapa.rutas, name='mapa-rutas'),
|
||||||
path('upload/zip/', upload.upload_zip, name='upload_zip'),
|
path('upload/zip/', upload.upload_zip, name='upload_zip'),
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
|
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.http import HttpResponse
|
from django.contrib.auth.hashers import check_password, make_password
|
||||||
from django.http import JsonResponse
|
from django.http import HttpResponse, JsonResponse
|
||||||
|
|
||||||
from rest_framework.decorators import action, api_view, schema
|
from rest_framework.decorators import action, api_view, schema
|
||||||
|
from project.settings import SECRET_KEY, EMAIL_HOST
|
||||||
|
|
||||||
from .. import models, schemas
|
from api import models, schemas
|
||||||
|
from datetime import datetime, timedelta
|
||||||
from decouple import config
|
from decouple import config
|
||||||
import json
|
import json
|
||||||
import jwt
|
import jwt
|
||||||
from datetime import datetime, timedelta
|
|
||||||
import logging
|
import logging
|
||||||
|
import random
|
||||||
|
|
||||||
private_key = config('SECRET_JWT')
|
from django.conf import settings
|
||||||
|
from django.core.mail import EmailMultiAlternatives
|
||||||
|
from django.template.loader import get_template
|
||||||
|
|
||||||
# Views jwt
|
# Views jwt
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
|
@ -21,26 +25,27 @@ private_key = config('SECRET_JWT')
|
||||||
@schema(schemas.AuthSchema())
|
@schema(schemas.AuthSchema())
|
||||||
def jwt_login(request):
|
def jwt_login(request):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
count = models.Usuario.objects.filter(vigente = True).count()
|
# validar rut y password
|
||||||
logging.error(f'count usuario vigente = {count}')
|
|
||||||
|
|
||||||
# validar username y password
|
|
||||||
input = json.loads(request.body)
|
input = json.loads(request.body)
|
||||||
username = input['username']
|
rut = input['rut'].replace('.','').replace('-','')
|
||||||
password = input['password']
|
|
||||||
|
if rut != '0':
|
||||||
|
dv = rut[-1].upper()
|
||||||
|
rut = rut[:-1]
|
||||||
|
|
||||||
usuario = None
|
usuario = None
|
||||||
|
|
||||||
if count > 0:
|
if rut == '0' and password == '0':
|
||||||
usuario = models.Usuario.objects.filter(login = username, vigente = True).values().first()
|
|
||||||
elif username == '0' and password == '0':
|
|
||||||
usuario = { 'login': '0', 'clave': '0' }
|
usuario = { 'login': '0', 'clave': '0' }
|
||||||
|
|
||||||
if not usuario:
|
# 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)
|
return HttpResponse('Acceso no valido', status=400)
|
||||||
|
else:
|
||||||
|
usuario = models.Usuario.objects.filter(vigente=1, rut__rut=rut, rut__dv=dv).values().first()
|
||||||
|
|
||||||
if username != '0':
|
if not check_password(input['password'], usuario['clave']):
|
||||||
clave = models.UsuarioClave.objects.filter(login = username).first()
|
|
||||||
if not clave or clave.clave != password:
|
|
||||||
return HttpResponse('Acceso no valido', status=400)
|
return HttpResponse('Acceso no valido', status=400)
|
||||||
|
|
||||||
ahora = datetime.utcnow()
|
ahora = datetime.utcnow()
|
||||||
|
@ -52,7 +57,132 @@ def jwt_login(request):
|
||||||
'exp': manana, # ahora + timedelta(minutes=60),
|
'exp': manana, # ahora + timedelta(minutes=60),
|
||||||
'login': usuario['login']
|
'login': usuario['login']
|
||||||
}
|
}
|
||||||
token = jwt.encode(payload, private_key, algorithm="HS256")
|
token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
|
||||||
return JsonResponse({ 'token': token })
|
return JsonResponse({ 'token': token })
|
||||||
|
|
||||||
elif request.method == 'GET':
|
elif request.method == 'GET':
|
||||||
return JsonResponse(request.jwt_info)
|
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
|
|
@ -28,7 +28,7 @@ class ParaderoViewSet(viewsets.ModelViewSet):
|
||||||
|
|
||||||
@action(detail=False, methods=['get'], url_path='info-public/(?P<pk>\S+)')
|
@action(detail=False, methods=['get'], url_path='info-public/(?P<pk>\S+)')
|
||||||
def info_public(self, request, pk=None):
|
def info_public(self, request, pk=None):
|
||||||
if hasattr(request.META,'HTTP_REFERER'):
|
if 'HTTP_REFERER' in request.META:
|
||||||
referer = request.META['HTTP_REFERER']
|
referer = request.META['HTTP_REFERER']
|
||||||
else:
|
else:
|
||||||
protocol = request.scheme
|
protocol = request.scheme
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.http import HttpResponse, JsonResponse
|
from django.http import HttpResponse, JsonResponse
|
||||||
|
from django.contrib.auth.hashers import make_password
|
||||||
from rest_framework import viewsets
|
from rest_framework import viewsets
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
|
@ -60,24 +61,10 @@ class UsuarioViewSet(viewsets.ModelViewSet):
|
||||||
)
|
)
|
||||||
usuario.save()
|
usuario.save()
|
||||||
|
|
||||||
# logging.error(f'clave = {input["clave"]}')
|
|
||||||
if input['clave']:
|
if input['clave']:
|
||||||
logging.error('Modificar clave de usuario')
|
logging.error('Modificar clave de usuario')
|
||||||
clave = models.UsuarioClave.objects.filter(login = usuario.login).first()
|
usuario.clave = make_password(input['clave'])
|
||||||
if clave:
|
usuario.save()
|
||||||
logging.error('Clave Usuario ya existe')
|
|
||||||
clave.clave_anterior = clave.clave
|
|
||||||
clave.clave = input['clave']
|
|
||||||
clave.fecha_modificacion = datetime.datetime.now()
|
|
||||||
clave.save()
|
|
||||||
else:
|
|
||||||
logging.error('Clave Usuario se creará')
|
|
||||||
clave = models.UsuarioClave(
|
|
||||||
login = usuario,
|
|
||||||
clave = input['clave'],
|
|
||||||
fecha_modificacion = datetime.datetime.now()
|
|
||||||
)
|
|
||||||
clave.save()
|
|
||||||
|
|
||||||
return Response({
|
return Response({
|
||||||
'rut': persona.rut,
|
'rut': persona.rut,
|
||||||
|
@ -101,13 +88,11 @@ class UsuarioViewSet(viewsets.ModelViewSet):
|
||||||
|
|
||||||
def update(self, request, *args, **kwargs):
|
def update(self, request, *args, **kwargs):
|
||||||
input = json.loads(request.body)
|
input = json.loads(request.body)
|
||||||
logging.error(input)
|
|
||||||
try:
|
try:
|
||||||
pk = input['rut']
|
pk = input['rut']
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
|
|
||||||
# validaciones se realiza a nivel del model
|
# validaciones se realiza a nivel del model
|
||||||
|
|
||||||
persona = models.Persona.objects.filter(rut = pk).first()
|
persona = models.Persona.objects.filter(rut = pk).first()
|
||||||
rol = models.Rol.objects.filter(id_rol = input.get('id_rol')).first()
|
rol = models.Rol.objects.filter(id_rol = input.get('id_rol')).first()
|
||||||
|
|
||||||
|
@ -119,23 +104,8 @@ class UsuarioViewSet(viewsets.ModelViewSet):
|
||||||
|
|
||||||
if 'clave' in input:
|
if 'clave' in input:
|
||||||
logging.error('Modificar clave de usuario')
|
logging.error('Modificar clave de usuario')
|
||||||
logging.error(f'clave = {input["clave"]}')
|
usuario.clave = make_password(input['clave'])
|
||||||
|
usuario.save()
|
||||||
clave = models.UsuarioClave.objects.filter(login = usuario.login).first()
|
|
||||||
if clave:
|
|
||||||
logging.error('Clave Usuario ya existe')
|
|
||||||
clave.clave_anterior = clave.clave
|
|
||||||
clave.clave = input['clave']
|
|
||||||
clave.fecha_modificacion = datetime.datetime.now()
|
|
||||||
clave.save()
|
|
||||||
else:
|
|
||||||
logging.error('Clave Usuario se creará')
|
|
||||||
clave = models.UsuarioClave(
|
|
||||||
login = usuario,
|
|
||||||
clave = input['clave'],
|
|
||||||
fecha_modificacion = datetime.datetime.now()
|
|
||||||
)
|
|
||||||
clave.save()
|
|
||||||
|
|
||||||
return Response({
|
return Response({
|
||||||
'rut': persona.rut,
|
'rut': persona.rut,
|
||||||
|
|
|
@ -9,9 +9,12 @@ https://docs.djangoproject.com/en/4.2/topics/settings/
|
||||||
For the full list of settings and their values, see
|
For the full list of settings and their values, see
|
||||||
https://docs.djangoproject.com/en/4.2/ref/settings/
|
https://docs.djangoproject.com/en/4.2/ref/settings/
|
||||||
"""
|
"""
|
||||||
|
from dotenv import load_dotenv
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from decouple import config
|
from decouple import config
|
||||||
|
import os
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
@ -62,7 +65,10 @@ ROOT_URLCONF = 'project.urls'
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
'DIRS': [ BASE_DIR / 'dist' ],
|
'DIRS': [
|
||||||
|
os.path.join(BASE_DIR, 'dist'),
|
||||||
|
os.path.join(BASE_DIR, 'api', 'templates')
|
||||||
|
],
|
||||||
'APP_DIRS': True,
|
'APP_DIRS': True,
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
'context_processors': [
|
'context_processors': [
|
||||||
|
@ -170,3 +176,10 @@ LOGGING = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
EMAIL_HOST = config('SMTP_HOST')
|
||||||
|
EMAIL_PORT = config('SMTP_PORT', 587)
|
||||||
|
EMAIL_HOST_USER = config('SMTP_USER', 'tu_correo@gmail.com') # Tu dirección de correo
|
||||||
|
EMAIL_HOST_PASSWORD = config('SMTP_PASS', 'tu_contraseña') # Tu contraseña de correo
|
||||||
|
EMAIL_USE_TLS = config('SMTP_PROTOCOL') == 'tls'
|
|
@ -4,6 +4,7 @@ djangorestframework
|
||||||
django-cors-headers
|
django-cors-headers
|
||||||
django-filter
|
django-filter
|
||||||
coreapi
|
coreapi
|
||||||
|
python-dotenv
|
||||||
python-decouple
|
python-decouple
|
||||||
PyJWT
|
PyJWT
|
||||||
pymongo
|
pymongo
|
||||||
|
|
Loading…
Reference in New Issue