diff --git a/JugarAlPadel/K8S/Makefile b/JugarAlPadel/K8S/Makefile index 79588d0..6af33c6 100644 --- a/JugarAlPadel/K8S/Makefile +++ b/JugarAlPadel/K8S/Makefile @@ -1,7 +1,7 @@ export ARQUITECTURA := $(shell lscpu |grep itectur | tr -d ' '| cut -f2 -d':') export REGISTRY=registry.reymota.es -export IMG_VERSION = 0.70.22 +export IMG_VERSION = 0.70.42 export IMG_NGINX_VERSION = 2.3 # limpia todo diff --git a/JugarAlPadel/README.md b/JugarAlPadel/README.md index b6237ba..49c6d68 100644 --- a/JugarAlPadel/README.md +++ b/JugarAlPadel/README.md @@ -65,3 +65,65 @@ Contiene una mejora en la lista de eventos, que ya no es lista sino cajas con fo ![0.27](https://gogs.reymota.es/attachments/2ea8f931-8623-441f-81d7-bca5657dd98b) + +## Generación de la tabla + +Con la modificación para generar una tabla con el perfil de usuario, hay que ejecutar migraciones lo primero + +Desde dentro del contenedor: + + ./manage.py makemigrations + ./manage.py migrate + +A partir de ahora, cada vez que se cree un usuario nuevo, se genera una entrada en la tabla de PerfilUsuario. + +Para crear las entradas en dicha tabla para los usuarios ya activos, hay que entrar en la shell de python y ejecutar unos comandos: + + python manage.py shell + + from reymota.models import UsuarioPersonalizado, PerfilUsuario + + usuarios_sin_perfil = UsuarioPersonalizado.objects.filter(perfilusuario__isnull=True) + + for usuario in usuarios_sin_perfil: + PerfilUsuario.objects.create(usuario=usuario) + print(f"Perfil creado para {usuario.nombre}") + + +## Política de privacidad + +Pasos para solicitar la aceptación de la política de privacidad. + +1. Desactivar usuarios (menos los que son administradores -staff-) +2. Enviar correo con enlace para aceptar la política + +### Desactivar usuarios + +Entrar en el contenedor + + kubectl -n jugaralpadel exec -it deployment.apps/jugaralpadel -- bash + +y desde la shell: + + ./manage.py desactiva_usuarios + +Una vez hecho esto, hay que generar el correo, pero antes hay que asegurarse que DEBUG=False, para que la SITE_URL apunte correctamente + + # Configuración de correo con Gmail + if DEBUG is True: + EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' + SITE_URL = "http://jugaralpadel.rancher.reymota.lab" + else: + EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' + SITE_URL = "http://jugaralpadel.es" + +y luego: + + ./manage.py enviar_correos_reactivacion + +### Reactivar usuarios + +Si queremos reactivar todos los usuarios: + + + ./manage.py reactiva_usuarios diff --git a/JugarAlPadel/gestion_reservas/gestion_reservas/context_processors.py b/JugarAlPadel/gestion_reservas/gestion_reservas/context_processors.py index eece58c..cbc8c74 100644 --- a/JugarAlPadel/gestion_reservas/gestion_reservas/context_processors.py +++ b/JugarAlPadel/gestion_reservas/gestion_reservas/context_processors.py @@ -1,7 +1,12 @@ from django.conf import settings +from datetime import date def app_version(request): return { 'APP_VERSION': settings.APP_VERSION } + + +def base_context(request): + return {'year': date.today().year} diff --git a/JugarAlPadel/gestion_reservas/gestion_reservas/settings.py b/JugarAlPadel/gestion_reservas/gestion_reservas/settings.py index 16ccfa4..ebda0df 100644 --- a/JugarAlPadel/gestion_reservas/gestion_reservas/settings.py +++ b/JugarAlPadel/gestion_reservas/gestion_reservas/settings.py @@ -14,6 +14,7 @@ from pathlib import Path import os import logging + APP_VERSION = "11.0.2" # Build paths inside the project like this: BASE_DIR / 'subdir'. @@ -73,6 +74,7 @@ TEMPLATES = [ 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', 'gestion_reservas.context_processors.app_version', + 'gestion_reservas.context_processors.base_context', ], 'libraries': { 'filtros_de_entorno': 'gestion_reservas.templatetags.filtros_de_entorno', @@ -156,16 +158,23 @@ MEDIA_URL = '/media/' # Configuración de correo con Gmail if DEBUG is True: EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' + SITE_URL = "http://jugaralpadel.rancher.reymota.lab" else: EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' + SITE_URL = "http://jugaralpadel.es" + +# EMAIL_HOST = 'smtp.gmail.com' +# EMAIL_HOST_USER = 'jugaralpadelentreamigos@gmail.com' +# EMAIL_HOST_PASSWORD = 'btjnlcliimxcnmhi' # Es mejor usar una contraseña de aplicación de Google +# DEFAULT_FROM_EMAIL = 'jugaralpadelentreamigos@gmail.com' -EMAIL_HOST = 'smtp.gmail.com' +EMAIL_HOST = 'smtp.ionos.es' EMAIL_PORT = 587 EMAIL_USE_TLS = True -EMAIL_HOST_USER = 'jugaralpadelentreamigos@gmail.com' -EMAIL_HOST_PASSWORD = 'btjnlcliimxcnmhi' # Es mejor usar una contraseña de aplicación de Google -DEFAULT_FROM_EMAIL = 'jugaralpadelentreamigos@gmail.com' +EMAIL_HOST_USER = 'admin@jugaralpadel.es' +EMAIL_HOST_PASSWORD = 'qunkik-mefGen-9wawku' # Es mejor usar una contraseña de aplicación de Google +DEFAULT_FROM_EMAIL = 'admin@jugaralpadel.es' # Dirección del administrador # ADMIN_EMAIL = 'king.bernard.b@gmail.com' diff --git a/JugarAlPadel/gestion_reservas/gestion_reservas/urls.py b/JugarAlPadel/gestion_reservas/gestion_reservas/urls.py index bbd163d..7442c38 100644 --- a/JugarAlPadel/gestion_reservas/gestion_reservas/urls.py +++ b/JugarAlPadel/gestion_reservas/gestion_reservas/urls.py @@ -21,7 +21,7 @@ from django.conf import settings from django.views.generic.base import TemplateView # new from . import views -from .views import api_lista_ayuda +from .views import api_lista_ayuda, politica_privacidad urlpatterns = [ @@ -37,6 +37,8 @@ urlpatterns = [ path('entorno/', views.ver_variables_entorno, name='ver_variables_entorno'), path('ayuda/', views.ayuda, name='ayuda'), + path('politica-privacidad/', views.politica_privacidad, name='politica_privacidad'), + path('api/ayuda/', api_lista_ayuda, name='api_lista_ayuda'), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/JugarAlPadel/gestion_reservas/gestion_reservas/views.py b/JugarAlPadel/gestion_reservas/gestion_reservas/views.py index 78b657b..df37b61 100644 --- a/JugarAlPadel/gestion_reservas/gestion_reservas/views.py +++ b/JugarAlPadel/gestion_reservas/gestion_reservas/views.py @@ -6,6 +6,7 @@ import os from django.conf import settings from django.contrib.auth.decorators import user_passes_test from django.shortcuts import render, get_object_or_404 +from datetime import date from django.http import HttpResponseForbidden from rest_framework.decorators import api_view @@ -64,6 +65,10 @@ def ayuda(request): return render(request, 'ayuda.html', {'elementos': elementos_ayuda, 'apartados': apartados}) +def politica_privacidad(request): + return render(request, 'politica_privacidad.html', {'fecha_actual': date.today()}) + + # # API # diff --git a/JugarAlPadel/gestion_reservas/reymotausers/admin.py b/JugarAlPadel/gestion_reservas/reymotausers/admin.py index 98081f8..496ca7a 100644 --- a/JugarAlPadel/gestion_reservas/reymotausers/admin.py +++ b/JugarAlPadel/gestion_reservas/reymotausers/admin.py @@ -1,6 +1,7 @@ from django.contrib import admin from django.core.mail import send_mail from django.contrib import messages +from django.conf import settings from django.contrib.auth.admin import UserAdmin @@ -16,7 +17,7 @@ def enviar_email_prueba(modeladmin, request, queryset): send_mail( 'Correo de Prueba', 'Este es un correo de prueba desde el panel de administración.', - 'jugaralpadelentreamigos@gmail.com', # Remitente + settings.DEFAULT_FROM_EMAIL, [user.email], # Destinatario fail_silently=False, ) diff --git a/JugarAlPadel/gestion_reservas/reymotausers/apps.py b/JugarAlPadel/gestion_reservas/reymotausers/apps.py index 0b7158b..9fd6106 100644 --- a/JugarAlPadel/gestion_reservas/reymotausers/apps.py +++ b/JugarAlPadel/gestion_reservas/reymotausers/apps.py @@ -4,3 +4,6 @@ from django.apps import AppConfig class ReymotausersConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'reymotausers' + + def ready(self): + import reymotausers.signals diff --git a/JugarAlPadel/gestion_reservas/reymotausers/forms.py b/JugarAlPadel/gestion_reservas/reymotausers/forms.py index 5e8af6c..89e1be2 100644 --- a/JugarAlPadel/gestion_reservas/reymotausers/forms.py +++ b/JugarAlPadel/gestion_reservas/reymotausers/forms.py @@ -5,7 +5,6 @@ from .models import ReyMotaUser class ReyMotaUserCreationForm(UserCreationForm): - class Meta: model = ReyMotaUser fields = ("email", "nombre", "foto") diff --git a/JugarAlPadel/gestion_reservas/reymotausers/management/commands/desactiva_usuarios.py b/JugarAlPadel/gestion_reservas/reymotausers/management/commands/desactiva_usuarios.py new file mode 100644 index 0000000..83ef20e --- /dev/null +++ b/JugarAlPadel/gestion_reservas/reymotausers/management/commands/desactiva_usuarios.py @@ -0,0 +1,11 @@ +from django.core.management.base import BaseCommand +from reymotausers.models import ReyMotaUser + + +class Command(BaseCommand): + help = "Desactivar usuarios antiguos antes de la política de privacidad" + + def handle(self, *args, **kwargs): + usuarios_actualizados = ReyMotaUser.objects.filter(is_active=True, is_staff=False).update(is_active=False) + self.stdout.write(self.style.SUCCESS(f"Usuarios desactivados: {usuarios_actualizados}")) + diff --git a/JugarAlPadel/gestion_reservas/reymotausers/management/commands/enviar_correos_reactivacion.py b/JugarAlPadel/gestion_reservas/reymotausers/management/commands/enviar_correos_reactivacion.py new file mode 100644 index 0000000..d996753 --- /dev/null +++ b/JugarAlPadel/gestion_reservas/reymotausers/management/commands/enviar_correos_reactivacion.py @@ -0,0 +1,14 @@ +from django.core.management.base import BaseCommand +from reymotausers.models import ReyMotaUser +from reymotausers.utils import enviar_correo_reactivacion + + +class Command(BaseCommand): + help = "Enviar correos a usuarios desactivados para aceptar la política de privacidad" + + def handle(self, *args, **kwargs): + usuarios = ReyMotaUser.objects.filter(is_active=False) + for usuario in usuarios: + enviar_correo_reactivacion(usuario) + self.stdout.write(self.style.SUCCESS(f"Correos enviados a {usuarios.count()} usuarios.")) + diff --git a/JugarAlPadel/gestion_reservas/reymotausers/management/commands/reactiva_usuarios.py b/JugarAlPadel/gestion_reservas/reymotausers/management/commands/reactiva_usuarios.py new file mode 100644 index 0000000..7a4066a --- /dev/null +++ b/JugarAlPadel/gestion_reservas/reymotausers/management/commands/reactiva_usuarios.py @@ -0,0 +1,11 @@ +from django.core.management.base import BaseCommand +from reymotausers.models import ReyMotaUser + + +class Command(BaseCommand): + help = "Reactivar usuarios" + + def handle(self, *args, **kwargs): + usuarios_actualizados = ReyMotaUser.objects.filter(is_active=False, is_staff=False).update(is_active=True) + self.stdout.write(self.style.SUCCESS(f"Usuarios reactivados: {usuarios_actualizados}")) + diff --git a/JugarAlPadel/gestion_reservas/reymotausers/models.py b/JugarAlPadel/gestion_reservas/reymotausers/models.py index 63b7226..fdbb715 100644 --- a/JugarAlPadel/gestion_reservas/reymotausers/models.py +++ b/JugarAlPadel/gestion_reservas/reymotausers/models.py @@ -1,9 +1,11 @@ from django.db import models -# Create your models here. from django.utils.translation import gettext_lazy as _ from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin from .managers import ReyMotaUserManager +from django.conf import settings + +import uuid # Create your models here. @@ -22,3 +24,16 @@ class ReyMotaUser(AbstractBaseUser, PermissionsMixin): def __str__(self): return self.email + + +class PerfilUsuario(models.Model): + usuario = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="perfilusuario") + acepto_politica = models.BooleanField(default=True) + token_activacion = models.UUIDField(default=uuid.uuid4, unique=True, null=True, blank=True) + + def generar_nuevo_token(self): + self.token_activacion = uuid.uuid4() + self.save() + + def __str__(self): + return f"Perfil de {self.usuario}" diff --git a/JugarAlPadel/gestion_reservas/reymotausers/signals.py b/JugarAlPadel/gestion_reservas/reymotausers/signals.py new file mode 100644 index 0000000..eec0bf5 --- /dev/null +++ b/JugarAlPadel/gestion_reservas/reymotausers/signals.py @@ -0,0 +1,11 @@ +from django.db.models.signals import post_save +from django.dispatch import receiver +from django.conf import settings +from .models import PerfilUsuario, ReyMotaUser + + +@receiver(post_save, sender=settings.AUTH_USER_MODEL) +def crear_perfil(sender, instance, created, **kwargs): + if created: + PerfilUsuario.objects.create(usuario=instance) + diff --git a/JugarAlPadel/gestion_reservas/reymotausers/urls.py b/JugarAlPadel/gestion_reservas/reymotausers/urls.py index 3207722..07787a2 100644 --- a/JugarAlPadel/gestion_reservas/reymotausers/urls.py +++ b/JugarAlPadel/gestion_reservas/reymotausers/urls.py @@ -1,9 +1,10 @@ from django.urls import path from . import views -from .views import api_lista_usuarios, api_detalle_usuario +from .views import api_lista_usuarios, api_detalle_usuario, reactivar_cuenta urlpatterns = [ path('api/usuarios/', api_lista_usuarios, name='api_lista_usuarios'), path('api/usuarios//', api_detalle_usuario, name='api_detalle_usuario'), + path("reactivar//", reactivar_cuenta, name="reactivar_cuenta"), ] diff --git a/JugarAlPadel/gestion_reservas/reymotausers/utils.py b/JugarAlPadel/gestion_reservas/reymotausers/utils.py new file mode 100644 index 0000000..d1d063a --- /dev/null +++ b/JugarAlPadel/gestion_reservas/reymotausers/utils.py @@ -0,0 +1,31 @@ +from django.core.mail import send_mail +from django.conf import settings +from django.urls import reverse + + +def enviar_correo_reactivacion(usuario): + perfil = usuario.perfilusuario + perfil.generar_nuevo_token() # Generar un nuevo token + + enlace = f"{settings.SITE_URL}{reverse('reactivar_cuenta', args=[perfil.token_activacion])}" + + asunto = "Reactivación de tu cuenta - Política de Privacidad" + mensaje = f""" + Hola {usuario.nombre}, + + Para cumplir con la nueva normativa de privacidad, hemos desactivado temporalmente tu cuenta. + Por favor, acepta la política de privacidad en el siguiente enlace para volver a activarla: + + {enlace} + + Saludos, + El equipo de soporte + """ + + send_mail( + asunto, + mensaje, + settings.DEFAULT_FROM_EMAIL, + [usuario.email] + ) + diff --git a/JugarAlPadel/gestion_reservas/reymotausers/views.py b/JugarAlPadel/gestion_reservas/reymotausers/views.py index 0f86359..21a1338 100644 --- a/JugarAlPadel/gestion_reservas/reymotausers/views.py +++ b/JugarAlPadel/gestion_reservas/reymotausers/views.py @@ -1,15 +1,47 @@ -from django.shortcuts import render +from django.shortcuts import render, redirect, get_object_or_404 from rest_framework.response import Response from rest_framework.decorators import api_view from .serializers import ReyMotaUserSerializer -from .models import ReyMotaUser +from .models import ReyMotaUser, PerfilUsuario + +from django.contrib import messages # Create your views here. +def reactivar_cuenta(request, token): + # Buscar el perfil sin generar error 404 + perfil = PerfilUsuario.objects.filter(token_activacion=token).first() + + if not perfil: + messages.error(request, "❌ Este enlace ya ha sido utilizado o es invalido.") + return redirect("login") + + usuario = perfil.usuario + + if request.method == "POST": + if perfil.acepto_politica: + messages.error(request, "❌ Este enlace ya ha sido utilizado.") + return redirect("login") + + # Marcar que el usuario ha aceptado la política + perfil.acepto_politica = True + perfil.token_activacion = None # Eliminar el token para que no se pueda reutilizar + perfil.save() + + usuario.is_active = True + usuario.save() + + messages.success(request, "Tu cuenta ha sido reactivada correctamente.") + + return redirect("login") + + return render(request, "registration/reactivar_cuenta.html", {"usuario": usuario}) + + @api_view(['GET']) def api_lista_usuarios(request): """Devuelve la lista de todos los usuarios.""" diff --git a/JugarAlPadel/gestion_reservas/templates/_footer.html b/JugarAlPadel/gestion_reservas/templates/_footer.html index 6560faa..5239d04 100644 --- a/JugarAlPadel/gestion_reservas/templates/_footer.html +++ b/JugarAlPadel/gestion_reservas/templates/_footer.html @@ -7,4 +7,7 @@ - \ No newline at end of file + + diff --git a/JugarAlPadel/gestion_reservas/templates/politica_privacidad.html b/JugarAlPadel/gestion_reservas/templates/politica_privacidad.html new file mode 100644 index 0000000..fea235a --- /dev/null +++ b/JugarAlPadel/gestion_reservas/templates/politica_privacidad.html @@ -0,0 +1,57 @@ +{% extends "base.html" %} + +{% block content %} +
+

Política de Privacidad

+

Última actualización: {{ fecha_actual }}

+ +

1. Responsable del tratamiento

+

El responsable del tratamiento de los datos personales es [Nombre de la Organización], con dirección en [Dirección] y correo electrónico [Email de contacto].

+ +

2. Datos que recopilamos

+

Recopilamos los siguientes datos personales cuando te registras en nuestra plataforma y reservas eventos:

+
    +
  • Nombre y apellidos
  • +
  • Correo electrónico
  • +
  • Información sobre las reservas realizadas
  • +
+ +

3. Finalidad del tratamiento

+

Utilizamos tus datos personales para:

+
    +
  • Gestionar las reservas en eventos
  • +
  • Enviarte confirmaciones y actualizaciones sobre los eventos
  • +
  • Enviar información relevante sobre la plataforma (solo si has dado tu consentimiento)
  • +
+ +

4. Base legal del tratamiento

+

El tratamiento de tus datos se basa en:

+
    +
  • Tu consentimiento, que puedes retirar en cualquier momento
  • +
  • La necesidad de procesar datos para la ejecución de un contrato (gestión de eventos y reservas)
  • +
  • Obligaciones legales aplicables
  • +
+ +

5. ¿Cuánto tiempo guardamos los datos?

+

Conservamos tus datos mientras tengas una cuenta en nuestra plataforma o hasta que solicites su eliminación.

+ +

6. Derechos del usuario

+

De acuerdo con el RGPD, tienes derecho a:

+
    +
  • Acceder a tus datos personales
  • +
  • Rectificar datos inexactos
  • +
  • Solicitar la eliminación de tus datos
  • +
  • Oponerte al tratamiento de datos para ciertos fines
  • +
  • Solicitar la portabilidad de tus datos
  • +
+ +

Para ejercer estos derechos, contacta con nosotros en [Email de contacto].

+ +

7. Seguridad de los datos

+

Aplicamos medidas de seguridad para proteger los datos contra accesos no autorizados, pérdidas o alteraciones.

+ +

8. Contacto

+

Si tienes preguntas sobre esta política, puedes contactarnos en [Email de contacto].

+
+{% endblock %} + diff --git a/JugarAlPadel/gestion_reservas/templates/registration/reactivar_cuenta.html b/JugarAlPadel/gestion_reservas/templates/registration/reactivar_cuenta.html new file mode 100644 index 0000000..0129806 --- /dev/null +++ b/JugarAlPadel/gestion_reservas/templates/registration/reactivar_cuenta.html @@ -0,0 +1,19 @@ +{% extends "base.html" %} + +{% block content %} +
+

Reactivar cuenta

+

Hola, {{ usuario.nombre }}. Para continuar usando nuestra plataforma, debes aceptar la política de privacidad.

+ +
+ {% csrf_token %} + +

+ +
+
+{% endblock %} + diff --git a/JugarAlPadel/gestion_reservas/templates/registration/signup.html b/JugarAlPadel/gestion_reservas/templates/registration/signup.html index 10edb44..78fd585 100644 --- a/JugarAlPadel/gestion_reservas/templates/registration/signup.html +++ b/JugarAlPadel/gestion_reservas/templates/registration/signup.html @@ -26,6 +26,14 @@

{% endfor %}
+ +
+ {{ form.aceptar_politica }} + +
+