se agrega compilacion de frontend y manejo de jwt

francisco/prueba1
Francisco Sandoval 2023-06-12 23:09:22 -04:00
parent a9579af488
commit d860dad7ea
10 changed files with 83 additions and 15 deletions

View File

@ -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'

View File

@ -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

View File

@ -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}

15
project/dist/index.html vendored 100644
View File

@ -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>

1
project/dist/vite.svg vendored 100644
View File

@ -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

View File

@ -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",
]

View File

@ -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])

View File

@ -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

View File

@ -1,6 +1,7 @@
Django
psycopg2-binary
djangorestframework
django-cors-headers
coreapi
python-decouple
PyJWT