se agrega compilacion de frontend y manejo de jwt
parent
a9579af488
commit
d860dad7ea
|
@ -0,0 +1,9 @@
|
|||
from rest_framework.exceptions import APIException
|
||||
|
||||
class NotAuthorized(APIException):
|
||||
status_code = 401
|
||||
default_detail = 'Acceso negado'
|
||||
|
||||
class JWTExpired(APIException):
|
||||
status_code = 400
|
||||
default_detail = 'Acceso expiro'
|
|
@ -5,6 +5,7 @@ from .models import Project, Agency, Route
|
|||
# serializers
|
||||
from .serializers import ProjectSerializer, AgencySerializer, RouteSerializer
|
||||
from .serializers import UserSerializer, AuthSerializer
|
||||
from .exceptions import NotAuthorized, JWTExpired
|
||||
# others
|
||||
import jwt
|
||||
import datetime
|
||||
|
@ -12,9 +13,9 @@ from decouple import config
|
|||
from rest_framework.response import Response
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.decorators import action
|
||||
from django.core.exceptions import PermissionDenied
|
||||
|
||||
# Create your views here.
|
||||
|
||||
class ProjectViewSet(viewsets.ModelViewSet):
|
||||
queryset = Project.objects.all()
|
||||
serializer_class = ProjectSerializer
|
||||
|
@ -36,6 +37,7 @@ class UserViewSet(viewsets.ModelViewSet):
|
|||
"""
|
||||
private_key = config('SECRET_JWT','palabrasecreta')
|
||||
|
||||
# @csrf_exempt
|
||||
class AuthViewSet(viewsets.ViewSet):
|
||||
serializer_class = AuthSerializer
|
||||
|
||||
|
@ -47,30 +49,35 @@ class AuthViewSet(viewsets.ViewSet):
|
|||
password = request.data.get('password')
|
||||
|
||||
user = User.objects.filter(username = username).first()
|
||||
if not user:
|
||||
raise NotAuthorized
|
||||
is_correct = user.check_password(password)
|
||||
if not is_correct:
|
||||
raise PermissionDenied
|
||||
raise NotAuthorized
|
||||
|
||||
now = datetime.datetime.utcnow()
|
||||
payload = {
|
||||
'exp': now + datetime.timedelta(hours=1),
|
||||
'exp': now + datetime.timedelta(minutes=1),
|
||||
'user_id': user.id
|
||||
}
|
||||
token = jwt.encode(payload, private_key, algorithm="HS256")
|
||||
response = Response({ 'token': token })
|
||||
response.set_cookie('token', token)
|
||||
# response.set_cookie('token', token)
|
||||
return response
|
||||
|
||||
@action(detail=False, methods=['get'])
|
||||
def info(self, request, pk=None):
|
||||
token = request.COOKIES.get('token')
|
||||
if not token:
|
||||
raise PermissionDenied
|
||||
return Response(data = None, content_type = 'application/json')
|
||||
try:
|
||||
decode = jwt.decode(token, private_key, algorithms= ["HS256"])
|
||||
except jwt.ExpiredSignature:
|
||||
raise JWTExpired
|
||||
|
||||
user = User.objects.filter(id = decode.get('user_id')).values().first()
|
||||
if (user == None):
|
||||
raise PermissionDenied
|
||||
if (not user):
|
||||
raise NotAuthorized
|
||||
|
||||
return Response({
|
||||
'id': user.get('id'),
|
||||
|
@ -87,8 +94,8 @@ class AuthViewSet(viewsets.ViewSet):
|
|||
decode = jwt.decode(token, private_key, algorithms= ["HS256"])
|
||||
|
||||
user = User.objects.filter(id = decode.get('user_id')).values().first()
|
||||
if (user == None):
|
||||
raise PermissionDenied
|
||||
if (not user):
|
||||
raise NotAuthorized
|
||||
|
||||
return Response({
|
||||
'id': user.get('id'),
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
.navbar ul{list-style-type:none;margin:0;padding:0;overflow:hidden;background-color:#333}.navbar li{float:left}.navbar li a{display:block;color:#fff;text-align:center;padding:14px 16px;text-decoration:none}.navbar li a:hover{background-color:#111}
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Capacitacion de svelte</title>
|
||||
<script type="module" crossorigin src="/assets/index-0c98eb67.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-782abf0e.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -40,12 +40,14 @@ INSTALLED_APPS = [
|
|||
'django.contrib.staticfiles',
|
||||
'rest_framework',
|
||||
'coreapi',
|
||||
'corsheaders',
|
||||
'api'
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
|
@ -58,7 +60,7 @@ ROOT_URLCONF = 'project.urls'
|
|||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'DIRS': [ BASE_DIR / 'dist/' ],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
|
@ -126,7 +128,11 @@ USE_TZ = True
|
|||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/4.2/howto/static-files/
|
||||
|
||||
STATIC_URL = 'static/'
|
||||
STATIC_URL = 'assets/'
|
||||
|
||||
STATICFILES_DIRS = [
|
||||
BASE_DIR / 'dist/assets',
|
||||
]
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||
|
@ -137,3 +143,8 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|||
REST_FRAMEWORK = {
|
||||
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
|
||||
}
|
||||
|
||||
CORS_ALLOW_CREDENTIALS = True
|
||||
CORS_ALLOWED_ORIGINS = [
|
||||
"http://localhost:3000",
|
||||
]
|
|
@ -14,12 +14,26 @@ Including another URLconf
|
|||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.http import HttpResponse
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from rest_framework.documentation import include_docs_urls
|
||||
|
||||
from django.template.loader import get_template
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
|
||||
|
||||
def frontend(request):
|
||||
plantilla = get_template('index.html')
|
||||
documento = plantilla.render()
|
||||
return HttpResponse(documento)
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('', frontend),
|
||||
path('admin/', admin.site.urls),
|
||||
path('api/', include('api.urls')),
|
||||
path('docs/', include_docs_urls(title = 'API Documentation'))
|
||||
]
|
||||
] + static(settings.STATIC_URL, document_root=settings.STATICFILES_DIRS[0])
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* **Django**: framework django
|
||||
* **psycopg2-binary**: permite uso de base datos postgres
|
||||
* **djangorestframework**: permite crear rest api json
|
||||
* **django-cors-headers**: requerido para desarrollo de frontend, permite acceso desde una dominio distinto al backend
|
||||
* **coreapi**: genera documentación de rest api
|
||||
* **python-decouple**: lee archivo .env para variables de ambiente
|
||||
* **PyJWT**: permite generar json-web-token
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
Django
|
||||
psycopg2-binary
|
||||
djangorestframework
|
||||
django-cors-headers
|
||||
coreapi
|
||||
python-decouple
|
||||
PyJWT
|
Loading…
Reference in New Issue