Arreglado VotePoints, y Implementado el Cambio de Correo

This commit is contained in:
adevopg
2024-11-18 09:07:52 +01:00
parent 8ec3ed14cd
commit c3c424277b
20 changed files with 525 additions and 202 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+10 -2
View File
@@ -3,7 +3,7 @@ from django.contrib import admin
from django import forms from django import forms
from .models import ( from .models import (
Noticia, ClienteCategoria, SistemaOperativo, ServerSelection, Noticia, ClienteCategoria, SistemaOperativo, ServerSelection,
RecruitAFriend, DownloadClientPage, ContentCreator, RecruitReward, GuildRenameSettings RecruitAFriend, DownloadClientPage, ContentCreator, RecruitReward, GuildRenameSettings, VoteSite
) )
from django.db import connections from django.db import connections
import logging import logging
@@ -139,7 +139,15 @@ class GuildRenameSettingsAdmin(admin.ModelAdmin):
(None, { (None, {
'fields': ('cost',) 'fields': ('cost',)
}), }),
) )
@admin.register(VoteSite)
class VoteSiteAdmin(admin.ModelAdmin):
list_display = ('name', 'points', 'url', 'image_url')
search_fields = ('name',)
list_editable = ('points',)
list_display_links = ('name',)
# Registro de modelos en el admin # Registro de modelos en el admin
+40 -3
View File
@@ -106,11 +106,13 @@ class ClaimedReward(models.Model):
class AccountActivation(models.Model): class AccountActivation(models.Model):
username = models.CharField(max_length=17) username = models.CharField(max_length=17)
email = models.EmailField() email = models.EmailField()
old_email = models.EmailField(null=True, blank=True)
password = models.CharField(max_length=64) # Hash de la contraseña password = models.CharField(max_length=64) # Hash de la contraseña
salt = models.BinaryField(max_length=32) salt = models.BinaryField(max_length=32)
verifier = models.BinaryField(max_length=32) verifier = models.BinaryField(max_length=32)
recruiter_id = models.IntegerField(null=True, blank=True) recruiter_id = models.IntegerField(null=True, blank=True)
hash = models.CharField(max_length=32, unique=True) hash = models.CharField(max_length=32, unique=True)
old_email_hash = models.CharField(max_length=32, null=True, blank=True)
created_at = models.DateTimeField(default=timezone.now) created_at = models.DateTimeField(default=timezone.now)
def is_expired(self): def is_expired(self):
@@ -118,14 +120,14 @@ class AccountActivation(models.Model):
class SecurityToken(models.Model): class SecurityToken(models.Model):
user_id = models.IntegerField() # Referencia al ID del usuario en `acore_auth` user = models.ForeignKey(User, on_delete=models.CASCADE)
token = models.CharField(max_length=6) token = models.CharField(max_length=6)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
expires_at = models.DateTimeField() expires_at = models.DateTimeField()
ip_address = models.GenericIPAddressField() ip_address = models.GenericIPAddressField()
def __str__(self): def __str__(self):
return f"Token for user_id {self.user_id}" return f"Token for {self.user.username}"
class GuildRenameSettings(models.Model): class GuildRenameSettings(models.Model):
@@ -136,5 +138,40 @@ class GuildRenameSettings(models.Model):
class Meta: class Meta:
verbose_name = "Configuración de Renombrar Hermandad" verbose_name = "Configuración de Renombrar Hermandad"
verbose_name_plural = "Configuraciones de Renombrar Hermandad" verbose_name_plural = "Configuraciones de Renombrar Hermandad"
class VoteSite(models.Model):
name = models.CharField(max_length=100, unique=True)
url = models.URLField(max_length=200, help_text="URL del sitio de votación")
image_url = models.URLField(max_length=300, help_text="URL completa de la imagen")
points = models.IntegerField(default=1, help_text="Puntos otorgados por votar")
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class VoteLog(models.Model):
account_id = models.IntegerField()
vote_site = models.ForeignKey('VoteSite', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
last_vote_time = models.DateTimeField(null=True, blank=True)
processed = models.BooleanField(default=False)
processed_at = models.DateTimeField(null=True, blank=True)
def __str__(self):
return f"Voto para {self.vote_site.name} por cuenta {self.account_id}"
class HomeApiPoints(models.Model):
accountID = models.IntegerField(unique=True)
vp = models.IntegerField(default=0)
dp = models.IntegerField(default=0)
class Meta:
db_table = 'home_api_points'
def __str__(self):
return f"Cuenta {self.accountID} - PV: {self.vp}, DP: {self.dp}"
@@ -1,70 +1,42 @@
if (window.history.replaceState) { $(document).ready(function() {
window.history.replaceState(null, null, window.location.href); $('#nw-change-email-form').on('submit', function(e) {
}; e.preventDefault(); // Evitar el envío por defecto del formulario
$(function(){
$(".toggle-password").click(function() {
$(this).toggleClass("fa-eye fa-eye-slash");
var type = $(this).hasClass("fa-eye-slash") ? "text" : "password";
$("#password").attr("type", type);
});
});
$(function(){
$(".toggle-token").click(function() {
$(this).toggleClass("fa-eye fa-eye-slash");
var type = $(this).hasClass("fa-eye-slash") ? "text" : "password";
$("#security-token").attr("type", type);
});
});
$(function(){
$('#conf-new-email').on("cut copy paste",function(e) {
e.preventDefault();
});
});
$(function(){
$('.change-email-button').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
$("#change-email-response").empty(); $("#change-email-response").empty();
var button = $(this); var form = $(this);
var buttonoriginal = button.html(); var button = $('.change-email-button');
var bValue = button.data('id'); var originalText = button.html();
var data = {changeemail: bValue};
data = $("#uw-change-email-form").serialize() + '&' + $.param(data);
changeButton(button, 'Cambiando correo'); button.html("Cambiando correo...");
button.prop("disabled", true);
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: '', url: form.attr('action'),
data: data, data: form.serialize(), // Serializar los datos correctamente
dataType: 'json', dataType: 'json',
success: function(data) { success: function(response) {
$("#change-email-response").append(data.message).hide().slideDown(); $("#change-email-response").html(response.message).hide().slideDown();
if (data.success === true) { if (response.success) {
button.html("Correo cambiado"); button.html("Correo cambiado");
button.css("color","#d79602"); } else {
}
else {
setTimeout(function() { setTimeout(function() {
$("#change-email-response").slideUp( function() { $("#change-email-response").slideUp(function() {
$("#change-email-response").empty(); $("#change-email-response").empty();
restoreButton(button, buttonoriginal); button.html(originalText);
button.prop("disabled", false);
}); });
}, 5000); }, 5000);
} }
}, },
error: function() { error: function(xhr, status, error) {
setTimeout(function() { console.error("Error:", error);
alert("Algo ha salido mal. Por favor intente más tarde"); console.error("Detalles:", xhr.responseText);
window.location.reload(); $("#change-email-response").html('<span class="red-form-response">Algo ha salido mal. Inténtelo de nuevo.</span>');
}, 2000); button.html(originalText);
button.prop("disabled", false);
} }
}); });
}); });
}); });
@@ -0,0 +1,75 @@
$(document).ready(function() {
$('.vote-button').each(function() {
var button = $(this);
var remainingTime = button.data('remaining-time');
if (remainingTime) {
startCooldownTimer(button, remainingTime);
}
});
$('.vote-button').on('click', function(e) {
e.preventDefault();
$("#voteResponse").empty();
var button = $(this);
var voteUrl = button.data('url').trim();
var data = { vote: voteUrl };
button.html("Votando...");
button.prop("disabled", true);
var otherWindow = window.open(voteUrl, "_blank");
otherWindow.opener = null;
$.ajax({
type: 'POST',
url: '',
data: data,
dataType: 'json',
success: function(response) {
$("#voteResponse").html(response.message).hide().slideDown();
if (response.success) {
button.html("Votado");
button.prop("disabled", true);
} else {
button.html("Votar");
button.prop("disabled", false);
}
// Ocultar el mensaje después de 5 segundos
setTimeout(function() {
$("#voteResponse").slideUp(function() {
$("#voteResponse").empty();
});
}, 5000);
},
error: function() {
$("#voteResponse").html('<span class="red-form-response">Algo ha salido mal. Por favor, inténtalo más tarde.</span>');
// Ocultar el mensaje después de 5 segundos en caso de error
setTimeout(function() {
$("#voteResponse").slideUp(function() {
$("#voteResponse").empty();
});
}, 5000);
}
});
});
});
function startCooldownTimer(button, remainingTime) {
var interval = setInterval(function() {
if (remainingTime <= 0) {
clearInterval(interval);
button.html("Votar");
button.prop("disabled", false);
} else {
var hours = Math.floor(remainingTime / 3600);
var minutes = Math.floor((remainingTime % 3600) / 60);
button.html(`Espera ${hours}h ${minutes}m`);
remainingTime--;
}
}, 1000);
}
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Activación del Nuevo Correo</title>
</head>
<body>
<table style="width: 100%; max-width: 600px; margin: 0 auto; border: 1px solid #dddddd; padding: 20px;">
<tr>
<td style="text-align: center;">
<h2>Activación de Nuevo Correo</h2>
</td>
</tr>
<tr>
<td>
<p>Hola {{ username }},</p>
<p>Tu solicitud para cambiar el correo electrónico en <strong>{{ NOMBRE_SERVIDOR }}</strong> ha sido recibida.</p>
<p>Por favor, haz clic en el siguiente enlace para confirmar tu nuevo correo:</p>
<p style="text-align: center;">
<a href="{{ activation_link }}" style="display: inline-block; padding: 10px 20px; background-color: #28a745; color: white; text-decoration: none; border-radius: 5px;">Activar nuevo correo</a>
</p>
<p>Si no realizaste esta solicitud, por favor contacta con soporte.</p>
<p>Atentamente,<br>El equipo de {{ NOMBRE_SERVIDOR }}</p>
</td>
</tr>
</table>
</body>
</html>
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Confirmación de Cambio de Correo</title>
</head>
<body>
<table style="width: 100%; max-width: 600px; margin: 0 auto; border: 1px solid #dddddd; padding: 20px;">
<tr>
<td style="text-align: center;">
<h2>Confirmación de Cambio de Correo</h2>
</td>
</tr>
<tr>
<td>
<p>Hola {{ username }},</p>
<p>Has solicitado cambiar tu correo electrónico registrado en <strong>{{ NOMBRE_SERVIDOR }}</strong>.</p>
<p>Para confirmar este cambio, haz clic en el siguiente enlace:</p>
<p style="text-align: center;">
<a href="{{ confirm_link }}" style="display: inline-block; padding: 10px 20px; background-color: #007bff; color: white; text-decoration: none; border-radius: 5px;">Confirmar cambio</a>
</p>
<p>Si no solicitaste este cambio, por favor ignora este correo.</p>
<p>Atentamente,<br>El equipo de {{ NOMBRE_SERVIDOR }}</p>
</td>
</tr>
</table>
</body>
</html>
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Notificación de Cambio de Correo</title>
</head>
<body>
<table style="width: 100%; max-width: 600px; margin: 0 auto; border: 1px solid #dddddd; padding: 20px;">
<tr>
<td style="text-align: center;">
<h2>Cambio de Correo Exitoso</h2>
</td>
</tr>
<tr>
<td>
<p>Hola {{ username }},</p>
<p>Te notificamos que tu correo electrónico en <strong>{{ NOMBRE_SERVIDOR }}</strong> ha sido cambiado exitosamente al siguiente correo:</p>
<p style="text-align: center;">
<strong>{{ new_email }}</strong>
</p>
<p>Si no realizaste este cambio, por favor contacta inmediatamente con soporte.</p>
<p>Atentamente,<br>El equipo de {{ NOMBRE_SERVIDOR }}</p>
</td>
</tr>
</table>
</body>
</html>
+36 -4
View File
@@ -14,10 +14,42 @@
<div class="centered"> <div class="centered">
<br> <br>
<br> <br>
<span class="red-form-response">El cambio de correo ya no es una herramienta disponible por autogestión.</span> <form id="nw-change-email-form" method="POST" accept-charset="utf-8">
<hr> {% csrf_token %}
<div class="alert-message" id="change-email-response"></div> <table class="middle-center-table">
<br> <tr>
<td><input type="password" maxlength="16" name="cur-password" id="cur-password" placeholder="Contraseña actual" required></td>
</tr>
<tr>
<td><input type="email" name="cur-email" id="cur-email" placeholder="Correo actual" required></td>
</tr>
<tr>
<td><input type="email" name="new-email" id="new-email" placeholder="Nuevo correo" required></td>
</tr>
<tr>
<td><input type="email" name="conf-new-email" id="conf-new-email" placeholder="Confirmar nuevo correo" required></td>
</tr>
<tr>
<td>
<input type="text" maxlength="6" name="security-token" id="security-token" placeholder="Token de seguridad" required>
<span class="far fa-eye toggle-token"></span>
</td>
</tr>
<tr>
<td>
<button type="submit" class="change-email-button">Cambiar Correo</button>
</td>
</tr>
</table>
<hr>
<div class="alert-message" id="change-email-response"></div>
</form>
</hr>
<br>
</div> </div>
</div> </div>
</div> </div>
+1
View File
@@ -51,6 +51,7 @@
<script src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-js-handlers/security_token_response.js"></script> <script src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-js-handlers/security_token_response.js"></script>
<script src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-js-handlers/change_password_response.js"></script> <script src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-js-handlers/change_password_response.js"></script>
<script src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-js-handlers/rename_guild_response.js"></script> <script src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-js-handlers/rename_guild_response.js"></script>
<script src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-js-handlers/vote_points_response.js"></script>
<script>var aowow_tooltips = { "colorlinks": true, "iconizelinks": true, "renamelinks": true }</script> <script>var aowow_tooltips = { "colorlinks": true, "iconizelinks": true, "renamelinks": true }</script>
<script src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-js/nw-scripts.js"></script> <script src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-js/nw-scripts.js"></script>
+11 -3
View File
@@ -20,9 +20,17 @@
<legend>Estado de la cuenta</legend> <legend>Estado de la cuenta</legend>
<div class="separate"> <div class="separate">
<img src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-images/nw-ranks/1_Newbie.svg" class="nw-rank" alt="Nivel 1" title="Nivel 1"> <img src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-images/nw-ranks/1_Newbie.svg" class="nw-rank" alt="Nivel 1" title="Nivel 1">
<p>PD: <span>0</span></p> <p>PD: <span>{{ dp }}</span></p>
<p>PV: <span>0</span></p> <p>PV: <span>{{ vp }}</span></p>
<p>Token de Seguridad: <span>Sin solicitar</span></p> <p>Token de Seguridad:
<span>
{% if token_status == "Solicitado" %}
{{ token_status }} - {{ token_date }}
{% else %}
{{ token_status }}
{% endif %}
</span>
</p>
{% if account_status.is_banned %} {% if account_status.is_banned %}
<p>Cuenta baneada: <span></span></p> <p>Cuenta baneada: <span></span></p>
+26 -116
View File
@@ -52,122 +52,32 @@
<button class="refresh-button" onclick="doRefresh();"><img class="refresh-icon" src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-images/nw-icons/refresh.webp" title="Refrescar" alt="Refrescar"></button> <button class="refresh-button" onclick="doRefresh();"><img class="refresh-icon" src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-images/nw-icons/refresh.webp" title="Refrescar" alt="Refrescar"></button>
<p><span>Nota:</span> Gtop100 puede demorar unos minutos en acreditar el voto.</p> <p><span>Nota:</span> Gtop100 puede demorar unos minutos en acreditar el voto.</p>
<br> <br>
<div class="inline-div"> <div id="vote-panel">
<table> <div id="vote-panel">
<tbody><tr> {% for site in vote_sites %}
<td><img class="img-med-icon" src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-images/nw-vote-sites/gtop100.jpg" title="Gtop100" alt="Gtop100"></td> <div class="inline-div">
</tr> <table>
<tr> <tr>
<td>Gtop100</td> <td><img class="img-med-icon" src="{{ site.image_url }}" title="{{ site.name }}" alt="{{ site.name }}"></td>
</tr> </tr>
<tr> <tr>
<td><hr></td> <td>{{ site.name }}</td>
</tr> </tr>
<tr> <tr>
<td class="lefted">PV: <span>1</span></td> <td>PV: <span>{{ site.points }}</span></td>
</tr> </tr>
<tr> <tr>
<td class="lefted"></td> <td>
</tr> <form method="POST" class="nw-vote-form" accept-charset="utf-8">
<tr> {% csrf_token %}
<td><hr></td> <button type="button" class="vote-button" data-url="{{ site.url }}" data-remaining-time="{{ site.remaining_time }}">Votar</button>
</tr> </form>
<tr> </td>
<td> </tr>
<form action="" method="POST" id="uw-vote-form" accept-charset="utf-8"> </table>
<button type="submit" name="vote" class="vote-button" value="https://gtop100.com/topsites/World-of-Warcraft/sitedetails/{{ NOMBRE_SERVIDOR }}-94649?vote=1&amp;pingUsername=91402">Votar</button> </div>
</form> {% endfor %}
</td>
</tr><tr>
</tr></tbody></table>
</div>
<div class="inline-div">
<table>
<tbody><tr>
<td><img class="img-med-icon" src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-images/nw-vote-sites/topg.webp" title="TopG" alt="TopG"></td>
</tr>
<tr>
<td>TopG</td>
</tr>
<tr>
<td><hr></td>
</tr>
<tr>
<td class="lefted">PV: <span>1</span></td>
</tr>
<tr>
<td class="lefted"></td>
</tr>
<tr>
<td><hr></td>
</tr>
<tr>
<td>
<form action="" method="POST" id="uw-vote-form" accept-charset="utf-8">
<button type="submit" name="vote" class="vote-button" value="https://topg.org/wow-private-servers/in-496618-91402">Votar</button>
</form>
</td>
</tr><tr>
</tr></tbody></table>
</div>
<div class="inline-div">
<table>
<tbody><tr>
<td><img class="img-med-icon" src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-images/nw-vote-sites/top100arena.jpg" title="Top100arena" alt="Top100arena"></td>
</tr>
<tr>
<td>Top100arena</td>
</tr>
<tr>
<td><hr></td>
</tr>
<tr>
<td class="lefted">PV: <span>1</span></td>
</tr>
<tr>
<td class="lefted"></td>
</tr>
<tr>
<td><hr></td>
</tr>
<tr>
<td>
<form action="" method="POST" id="uw-vote-form" accept-charset="utf-8">
<button type="submit" name="vote" class="vote-button" value="http://www.top100arena.com/in.asp?id=94147&amp;incentive=91402">Votar</button>
</form>
</td>
</tr><tr>
</tr></tbody></table>
</div>
<div class="inline-div">
<table>
<tbody><tr>
<td><img class="img-med-icon" src="{{ URL_PRINCIPAL }}/static/nw-themes/nw-ryu/nw-images/nw-vote-sites/arenatop100.webp" title="Arena-Top100" alt="Arena-Top100"></td>
</tr>
<tr>
<td>Arena-Top100</td>
</tr>
<tr>
<td><hr></td>
</tr>
<tr>
<td class="lefted">PV: <span>1</span></td>
</tr>
<tr>
<td class="lefted"></td>
</tr>
<tr>
<td><hr></td>
</tr>
<tr>
<td>
<form action="" method="POST" id="uw-vote-form" accept-charset="utf-8">
<button type="submit" name="vote" class="vote-button" value="https://www.arena-top100.com/index.php?a=in&amp;u={{ NOMBRE_SERVIDOR }}&amp;id=91402">Votar</button>
</form>
</td>
</tr><tr>
</tr></tbody></table>
</div>
<hr> <hr>
<div class="alert-message" id="voteResponse"></div> <div class="alert-message" id="voteResponse"></div>
<br> <br>
+3 -1
View File
@@ -23,7 +23,9 @@ urlpatterns = [
path('not-found/', views.not_found, name='not-found'), path('not-found/', views.not_found, name='not-found'),
path('change-password/', views.change_password_view, name='change_password'), path('change-password/', views.change_password_view, name='change_password'),
path('security-token/', views.security_token_view, name='security_token'), path('security-token/', views.security_token_view, name='security_token'),
path('change-email/', views.change_email_view, name='change_email'), path('change-email/', views.change_email_view, name='change-email'),
path('confirm-old-email/', views.confirm_old_email_view, name='confirm-old-email'),
path('confirm-new-email/', views.confirm_new_email_view, name='confirm-new-email'),
path('promo-code/', views.promo_code_view, name='promo_code'), path('promo-code/', views.promo_code_view, name='promo_code'),
path('transfer-d-points/', views.transfer_d_points_view, name='transfer_d_points'), path('transfer-d-points/', views.transfer_d_points_view, name='transfer_d_points'),
path('rename-guild/', views.rename_guild_view, name='rename-guild'), path('rename-guild/', views.rename_guild_view, name='rename-guild'),
+214 -19
View File
@@ -5,12 +5,12 @@ import binascii
import os import os
import re import re
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.http import JsonResponse from django.http import HttpResponse, JsonResponse
from django.db import connections from django.db import connections
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import logout from django.contrib.auth import logout
from django import forms from django import forms
from .models import Noticia, ClienteCategoria, ServerSelection, RecruitAFriend, DownloadClientPage, ContentCreator, RecruitReward, ClaimedReward, AccountActivation, SecurityToken, GuildRenameSettings from .models import Noticia, ClienteCategoria, ServerSelection, RecruitAFriend, DownloadClientPage, ContentCreator, RecruitReward, ClaimedReward, AccountActivation, SecurityToken, GuildRenameSettings, VoteSite, VoteLog, HomeApiPoints
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
import logging import logging
from datetime import datetime, timedelta from datetime import datetime, timedelta
@@ -22,7 +22,6 @@ from django.utils.crypto import get_random_string
from django.conf import settings from django.conf import settings
import secrets import secrets
# Configuración del logger # Configuración del logger
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -340,7 +339,7 @@ def register_view(request):
) )
# Enviar correo de activación # Enviar correo de activación
activation_link = f"http://localhost:8009/es/activate-account?act={activation_hash}" activation_link = f"{settings.URL_PRINCIPAL}/es/activate-account?act={activation_hash}"
context = { context = {
'username': username, 'username': username,
'password': password, 'password': password,
@@ -610,6 +609,21 @@ def my_account(request):
# Obtener el estado de la cuenta # Obtener el estado de la cuenta
account_status = get_account_status(account_id) account_status = get_account_status(account_id)
# Obtener los puntos (DP y VP) del usuario desde la tabla `home_api_points`
user_points = HomeApiPoints.objects.filter(accountID=account_id).first()
dp = user_points.dp if user_points else 0
vp = user_points.vp if user_points else 0
# Obtener el estado del token de seguridad
security_token = SecurityToken.objects.filter(user_id=account_id).first()
if security_token:
token_status = "Solicitado"
token_date = security_token.created_at.strftime('%H:%M:%S %d-%m-%Y')
else:
token_status = "Sin solicitar"
token_date = None
return render(request, 'my-account/my-account.html', { return render(request, 'my-account/my-account.html', {
'is_logged_in': is_logged_in, 'is_logged_in': is_logged_in,
@@ -620,10 +634,15 @@ def my_account(request):
'last_ip': account_data[4], 'last_ip': account_data[4],
'last_attempt_ip': account_data[5], 'last_attempt_ip': account_data[5],
'joindate': formatear_fecha(account_data[6]), 'joindate': formatear_fecha(account_data[6]),
}, },
'account_status': account_status, 'account_status': account_status,
'characters': characters, 'characters': characters,
'has_characters': has_characters, 'has_characters': has_characters,
'dp': dp,
'vp': vp,
'token_status': token_status,
'token_date': token_date
}) })
@@ -951,15 +970,146 @@ def send_security_token_email(email, username, token, ip_address):
context=context context=context
) )
def change_email_view(request): def change_email_view(request):
""" username = request.session.get('username')
Vista para la página de 'Cambiar Correo'. if not username:
Simplemente renderiza un template con información relevante. return redirect('login')
"""
# Obtener el usuario desde la base de datos de `acore_auth`
with connections['acore_auth'].cursor() as cursor:
cursor.execute("""
SELECT id, email, reg_mail
FROM account
WHERE username = %s
""", [username])
account_data = cursor.fetchone()
if not account_data:
return redirect('login')
user_id, current_email, reg_email = account_data
security_token = SecurityToken.objects.filter(user_id=user_id).first()
if request.method == 'POST':
print("Datos recibidos:", request.POST)
current_password = request.POST.get('cur-password', '').strip()
current_email_input = request.POST.get('cur-email', '').strip()
new_email = request.POST.get('new-email', '').strip()
conf_new_email = request.POST.get('conf-new-email', '').strip()
token = request.POST.get('security-token', '').strip()
# Validar los campos
if not all([current_password, current_email_input, new_email, conf_new_email, token]):
return JsonResponse({'success': False, 'message': 'Por favor, complete todos los campos.'})
if current_email_input != current_email:
return JsonResponse({'success': False, 'message': 'El correo actual no es correcto.'})
if new_email != conf_new_email:
return JsonResponse({'success': False, 'message': 'Los correos no coinciden.'})
if not re.match(r'^[a-zA-Z0-9._%+-]+@gmail\.com$', new_email):
return JsonResponse({'success': False, 'message': 'El nuevo correo no es válido.'})
if not security_token or security_token.token != token:
return JsonResponse({'success': False, 'message': 'Token de seguridad incorrecto.'})
if not authenticate(username, current_password):
return JsonResponse({'success': False, 'message': 'Contraseña incorrecta.'})
# Generar hashes
old_email_hash = secrets.token_urlsafe(16)
new_email_hash = secrets.token_urlsafe(16)
# Guardar en `AccountActivation`
AccountActivation.objects.create(
username=username,
email=new_email,
old_email=current_email,
password='',
salt=b'',
verifier=b'',
recruiter_id=user_id,
hash=new_email_hash,
old_email_hash=old_email_hash
)
# Enviar confirmación al correo actual
confirm_old_email_link = f"{settings.URL_PRINCIPAL}/es/confirm-old-email?hash={old_email_hash}"
context_old_email = {
'username': username,
'confirm_link': confirm_old_email_link,
'NOMBRE_SERVIDOR': settings.NOMBRE_SERVIDOR
}
enviar_correo(
subject=f'Confirme el cambio de correo para {username}',
to_email=current_email,
template='emails/confirm_old_email.html',
context=context_old_email
)
return JsonResponse({'success': True, 'message': 'Se ha enviado un correo de confirmación al correo actual.'})
return render(request, 'account/change_email.html') return render(request, 'account/change_email.html')
def confirm_old_email_view(request):
hash = request.GET.get('hash')
activation = AccountActivation.objects.filter(old_email_hash=hash).first()
if not activation:
return HttpResponse('Enlace no válido o expirado.', status=400)
# Enviar correo al nuevo correo para confirmar el cambio
activation_link = f"{settings.URL_PRINCIPAL}/es/confirm-new-email?hash={activation.hash}"
context_new_email = {
'username': activation.username,
'activation_link': activation_link,
'NOMBRE_SERVIDOR': settings.NOMBRE_SERVIDOR
}
enviar_correo(
subject=f'Confirme su nuevo correo para {activation.username}',
to_email=activation.email,
template='emails/confirm_new_email.html',
context=context_new_email
)
return HttpResponse('Correo confirmado. Se ha enviado un enlace al nuevo correo.')
def confirm_new_email_view(request):
hash = request.GET.get('hash')
activation = AccountActivation.objects.filter(hash=hash).first()
if not activation:
return HttpResponse('Enlace no válido o expirado.', status=400)
# Actualizar el correo en la base de datos
with connections['acore_auth'].cursor() as cursor:
cursor.execute("""
UPDATE account
SET email = %s, reg_mail = %s
WHERE username = %s
""", [activation.email, activation.email, activation.username])
# Enviar notificación al correo anterior
context_old_email = {
'username': activation.username,
'new_email': activation.email,
'NOMBRE_SERVIDOR': settings.NOMBRE_SERVIDOR
}
enviar_correo(
subject=f'Su correo ha sido cambiado en {settings.NOMBRE_SERVIDOR}',
to_email=activation.old_email,
template='emails/old_email_notification.html',
context=context_old_email
)
return HttpResponse('El cambio de correo ha sido confirmado y completado con éxito.')
def promo_code_view(request): def promo_code_view(request):
return render(request, 'account/promo_code.html') return render(request, 'account/promo_code.html')
@@ -967,9 +1117,6 @@ def transfer_d_points_view(request):
# Renderizar la plantilla para la transferencia de puntos # Renderizar la plantilla para la transferencia de puntos
return render(request, 'account/transfer_d_points.html') return render(request, 'account/transfer_d_points.html')
from .models import GuildRenameSettings
def rename_guild_view(request): def rename_guild_view(request):
# Verificar si el usuario está autenticado mediante la sesión # Verificar si el usuario está autenticado mediante la sesión
username = request.session.get('username') username = request.session.get('username')
@@ -1037,12 +1184,60 @@ def rename_guild_view(request):
'rename_cost': rename_cost 'rename_cost': rename_cost
}) })
def vote_points_view(request): def vote_points_view(request):
""" # Verificar si el usuario tiene un `username` en la sesión
Vista para la página de puntos de votación. username = request.session.get('username')
""" if not username:
return render(request, 'account/vote_points.html') return redirect('login')
# Obtener el `account_id` basado en el `username`
with connections['acore_auth'].cursor() as cursor:
cursor.execute("SELECT id FROM account WHERE username = %s", [username])
account_data = cursor.fetchone()
if not account_data:
return JsonResponse({'success': False, 'message': 'Cuenta no encontrada.'})
account_id = account_data[0]
if request.method == 'POST':
vote_url = request.POST.get('vote').strip()
site = VoteSite.objects.filter(url=vote_url).first()
if not site:
return JsonResponse({'success': False, 'message': 'Sitio de votación no encontrado.'})
# Verificar si ya ha votado en las últimas 12 horas y 30 minutos
last_vote = VoteLog.objects.filter(account_id=account_id, vote_site=site).order_by('-created_at').first()
now = timezone.now()
if last_vote:
time_diff = now - last_vote.created_at
cooldown_period = timedelta(hours=12, minutes=30)
if time_diff < cooldown_period:
remaining_time = cooldown_period - time_diff
hours, remainder = divmod(remaining_time.seconds, 3600)
minutes, _ = divmod(remainder, 60)
return JsonResponse({
'success': False,
'message': f'<span class="red-form-response">Tienes que esperar {hours} horas y {minutes} minutos antes de volver a votar.</span>'
})
# Acreditar puntos al usuario y registrar el voto
user_points = HomeApiPoints.objects.filter(accountID=account_id).first()
if user_points:
user_points.vp += site.points
user_points.save()
else:
HomeApiPoints.objects.create(accountID=account_id, vp=site.points, dp=0)
# Registrar el voto
VoteLog.objects.create(account_id=account_id, vote_site=site, last_vote_time=now)
return JsonResponse({'success': True, 'message': f'Has votado en {site.name}. Se han acreditado {site.points} PV.'})
vote_sites = VoteSite.objects.all()
return render(request, 'account/vote_points.html', {'vote_sites': vote_sites})
def d_points_view(request): def d_points_view(request):
""" """
Binary file not shown.
+1 -1
View File
@@ -43,7 +43,7 @@ INSTALLED_APPS = [
# Configuración para AC SOAP # Configuración para AC SOAP
AC_SOAP_URL = "http://127.0.0.1:2079" AC_SOAP_URL = "http://127.0.0.1:2079"
AC_SOAP_USER = "AC_SOAP" AC_SOAP_USER = " "
AC_SOAP_PASSWORD = "Ladyamy89" AC_SOAP_PASSWORD = "Ladyamy89"
AC_SOAP_URN = "urn:AC" AC_SOAP_URN = "urn:AC"