diff --git a/app.py b/app.py index 267510c..3e2286a 100644 --- a/app.py +++ b/app.py @@ -97,12 +97,12 @@ def update_last_login(user_id): def welcome(): return render_template('welcome.html') -@app.errorhandler(Exception) -def handle_exception(e): - code = 404 - if isinstance(e, HTTPException): - code = e.code - return render_template('404.html'), code +#@app.errorhandler(Exception) +#def handle_exception(e): +# code = 404 +# if isinstance(e, HTTPException): +# code = e.code +# return render_template('404.html'), code @app.route('/faq') def faq(): @@ -1812,6 +1812,12 @@ def accessing(): # Actualizar el último inicio de sesión del usuario update_last_login(user_id) + last_login = get_last_login(user_id) + + # Enviar correo electrónico de notificación + requester_ip = get_requester_ip() + sender = app.config['MAIL_USERNAME'] + send_login_notification(sender, email, email, last_login, requester_ip) conn.close() return redirect(url_for('index')) @@ -1858,42 +1864,69 @@ def recovery(): def register(): if request.method == 'POST': email = request.form['email'] + conn = sqlite3.connect(DATABASE) + conn.row_factory = sqlite3.Row + cursor = conn.cursor() + cursor.execute("SELECT * FROM emptor WHERE correo = ?", (email,)) + user = cursor.fetchone() + + if user: + flash('El usuario ya existe. Por favor, selecciona la opción de reenviar token.') + return redirect(url_for('resend_token', email=email)) + else: + token = secrets.token_urlsafe(16) + token_expiration = datetime.datetime.now() + timedelta(hours=1) + confirm_url = url_for('confirm_email', token=token, _external=True) + requester_ip = get_requester_ip() + sender = app.config['MAIL_USERNAME'] + send_email(sender, email, confirm_url, requester_ip) + + cursor.execute("INSERT INTO emptor (correo, token, token_expiration, database) VALUES (?, ?, ?, ?)", (email, token, token_expiration, f'{email.split("@")[0]}.db')) + conn.commit() + conn.close() + + try: + shutil.copy("kha.db", f"{email.split('@')[0]}.db") + except FileNotFoundError: + flash('Error: la base de datos "kha.db" no se encontró.') + return redirect(url_for('register')) + except Exception as e: + flash(f'Error al copiar la base de datos: {str(e)}') + return redirect(url_for('register')) + + user_db_name = f"{email.split('@')[0]}.db" + if not os.path.exists(user_db_name): + user_conn = sqlite3.connect(user_db_name) + user_cursor = user_conn.cursor() + user_cursor.execute("CREATE TABLE IF NOT EXISTS user_data (id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT)") + user_conn.commit() + user_conn.close() + + flash('Se ha enviado un enlace de confirmación a tu correo.') + return redirect(url_for('register')) + return render_template('signup.html') + +@app.route('/resend_token/', methods=['GET', 'POST']) +def resend_token(email): + if request.method == 'POST' or request.method == 'GET': token = secrets.token_urlsafe(16) + token_expiration = datetime.datetime.now() + timedelta(hours=24) confirm_url = url_for('confirm_email', token=token, _external=True) requester_ip = get_requester_ip() sender = app.config['MAIL_USERNAME'] send_email(sender, email, confirm_url, requester_ip) - # Crear una conexión directa a cavea.db conn = sqlite3.connect(DATABASE) conn.row_factory = sqlite3.Row cursor = conn.cursor() - cursor.execute("INSERT INTO emptor (correo, token, database) VALUES (?, ?, ?)", (email, token, f'{email.split("@")[0]}.db')) + cursor.execute("UPDATE emptor SET token = ?, token_expiration = ? WHERE correo = ?", (token, token_expiration, email)) conn.commit() conn.close() - # Copiar la base de datos kha.db y renombrarla con el nombre de usuario - try: - shutil.copy("kha.db", f"{email.split('@')[0]}.db") - except FileNotFoundError: - flash('Error: la base de datos "kha.db" no se encontró.') - return redirect(url_for('register')) - except Exception as e: - flash(f'Error al copiar la base de datos: {str(e)}') - return redirect(url_for('register')) - - # Crear la base de datos para el usuario - user_db_name = f"{email.split('@')[0]}.db" - if not os.path.exists(user_db_name): - user_conn = sqlite3.connect(user_db_name) - user_cursor = user_conn.cursor() - user_cursor.execute("CREATE TABLE IF NOT EXISTS user_data (id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT)") - user_conn.commit() - user_conn.close() - - flash('Se ha enviado un enlace de confirmación a tu correo.') + flash('Se ha reenviado un nuevo enlace de confirmación a tu correo.') return redirect(url_for('register')) - return render_template('signup.html') + return render_template('signup.html', email=email) + def get_requester_ip(): if request.headers.get('X-Forwarded-For'): @@ -1903,28 +1936,752 @@ def get_requester_ip(): ip = request.remote_addr return ip +def send_login_notification(sender, recipient, email, last_login, requester_ip): + msg = Message('Nuevo inicio de sesión en Kingdom Hall Attendant', sender=sender, recipients=[recipient]) + # Cuerpo del mensaje en HTML + msg.html = f""" + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+
+ + + + +
+ + + + + + +
+ kingdom hall attendant logo +
+
+
+
+
+ +
+ + + + + + +
+
+ + + + +
+
Nuevo inicio de sesión en Kingdom Hall Attendant
+
+
+
+
+ +
+ + + + + + +
+
+ + + + +
+ + + + + + +
kingdom hall attendant subscribe loader
+
+
+
+
+ +
+ + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +
+
Notamos que iniciaste sesión. Si fuiste tú, puedes ignorar este correo.
+
+
Ubicación: {requester_ip}
Hora: {last_login}
+
+
¿No fuiste tú? Tómate unos minutos para proteger tu cuenta.
+
+
 
+
+ + + + +
+ Proteger cuenta +
+
+
© 2024 Kingdom Hall Attendant. Todos los derechos reservados.
+
+
+
+
+
+ + + + """ + mail.send(msg) + def send_email(sender, recipient, confirm_url, requester_ip): msg = Message('Kingdom Hall Attendant: Completa tu registro', sender=sender, recipients=[recipient]) - msg.body = ( - f"🗝\n\n" - f"Hola, soy Livrädo Sandoval de Kingdom Hall Attendant.\n\n" - f"Estás a un clic de terminar tu registro en Kingdom Hall Attendant. Por favor, confirma tu correo " - f"electrónico haciendo clic en el siguiente enlace:\n{confirm_url}\n\n" - "💡 Consejo: ¿Quieres que Kingdom Hall Attendant recuerde tu contraseña la próxima vez?\n" - "Acepta el recordatorio de contraseñas de tu navegador.\n\n" - f"Este correo electrónico fue solicitado por {requester_ip}. Si no ha solicitado este correo electrónico, infórmele a jwpubcatalog@gmail.com." - ) + # Cuerpo del mensaje en HTML + msg.html = f""" + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+
+ + + + +
+ + + + + + +
+ kingdom hall attendant logo +
+
+
+
+
+ +
+ + + + + + +
+
+ + + + +
+
Hola. Gracias por registrarte 👏
+
+
+
+
+ +
+ + + + + + +
+
+ + + + +
+ + + + + + +
kingdom hall attendant subscribe loader
+
+
+
+
+ +
+ + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
Ya casi terminas. Confirma tu correo electrónico y presiona el botón a continuación. No hacemos spam ✌️
+
+
You're almost done. Confirm your email and press the button below. We don't spam ✌️
+
+
Hai quasi finito. Conferma la tua email e premi il pulsante qui sotto. Non inviamo spam ✌️
+
+
Vous avez presque fini. Confirmez votre email et appuyez sur le bouton ci-dessous. Nous ne spammons pas ✌️
+
+
Você está quase pronto. Confirme seu e-mail e pressione o botão abaixo. Não enviamos spam ✌️
+
+
 
+
+ + + + +
+ Confirmar correo +
+
+
Este enlace expirará en 1 hora. Nos vemos pronto. Este correo electrónico fue solicitado por {requester_ip}. Si no ha solicitado este correo electrónico, infórmele a livrasand@outlook.com.
+
+
 
+
+
© 2024 Kingdom Hall Attendant. Todos los derechos reservados.
+
+
+
+
+
+ + + + """ mail.send(msg) def send_password_email(sender, recipient, password, requester_ip): msg = Message('Kingdom Hall Attendant: Recuperación de contraseña', sender=sender, recipients=[recipient]) - msg.body = ( - f"🔑\n\n" - f"Hola de nuevo, soy Livrädo Sandoval de Kingdom Hall Attendant. Tu contraseña para Kingdom Hall Attendant ha sido recuperada.\n\n" - f"Tu contraseña es: {password}\n\n" - "Por favor, mantén esta información en un lugar seguro y no compartas tu contraseña con nadie.\n\n" - f"Esta recuperación fue solicitada por {requester_ip}. Si no has solicitado esta recuperación de contraseña, infórmele a jwpubcatalog@gmail.com para cambiar tu contraseña.\n\n" - ) + msg.html = f""" + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+
+ + + + +
+ + + + + + +
+ kingdom hall attendant logo +
+
+
+
+
+ +
+ + + + + + +
+
+ + + + +
+
Hola. ¿Se te olvidó tu contraseña?
+
+
+
+
+ +
+ + + + + + +
+
+ + + + +
+ + + + + + +
kingdom hall attendant subscribe loader
+
+
+
+
+ +
+ + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
Tu contraseña es: {password}. Por favor, mantén esta información en un lugar seguro y no compartas tu contraseña con nadie.
+
+
Your password is: {password}. Please keep this information in a safe place and do not share your password with anyone.
+
+
La tua password è: {password}. Ti preghiamo di conservare queste informazioni in un luogo sicuro e di non condividere la tua password con nessuno.
+
+
Votre mot de passe est : {password}. Veuillez conserver ces informations dans un endroit sûr et ne partagez votre mot de passe avec personne.
+
+
Sua senha é: {password}. Por favor, guarde essas informações em um local seguro e não compartilhe sua senha com ninguém.
+
+
 
+
+ + + + +
+ Iniciar sesión +
+
+
Este correo electrónico fue solicitado por {requester_ip}. Si no ha solicitado este correo electrónico, infórmele a livrasand@outlook.com.
+
+
 
+
+
© 2024 Kingdom Hall Attendant. Todos los derechos reservados.
+
+
+
+
+
+ + + + """ mail.send(msg) @app.route('/confirm') @@ -1937,11 +2694,18 @@ def confirm_email(token): conn = sqlite3.connect(DATABASE) conn.row_factory = sqlite3.Row cursor = conn.cursor() - cursor.execute("SELECT correo FROM emptor WHERE token = ?", (token,)) + cursor.execute("SELECT correo, token_expiration FROM emptor WHERE token = ?", (token,)) result = cursor.fetchone() if result: email = result['correo'] + token_expiration = result['token_expiration'] + + # Verificar si el token ha expirado + if datetime.datetime.now() > datetime.datetime.fromisoformat(token_expiration): + flash('El enlace de confirmación ha expirado. Por favor, solicita un nuevo enlace.') + return redirect(url_for('resend_token', email=email)) + if request.method == 'POST': password = request.form['password'] @@ -1954,6 +2718,7 @@ def confirm_email(token): flash('Correo confirmado y contraseña establecida.') return redirect(url_for('login')) + conn.close() return render_template('confirm.html', token=token) else: diff --git a/cavea.db b/cavea.db index 2066366..2bcccb6 100644 Binary files a/cavea.db and b/cavea.db differ diff --git a/templates/confirm.html b/templates/confirm.html index 063f110..c13a661 100644 --- a/templates/confirm.html +++ b/templates/confirm.html @@ -17,243 +17,7 @@ - + @@ -262,15 +26,15 @@ -
- + \ No newline at end of file diff --git a/templates/vida-ministerio.html b/templates/vida-ministerio.html index 67e1b72..d9b2f73 100644 --- a/templates/vida-ministerio.html +++ b/templates/vida-ministerio.html @@ -18,10 +18,16 @@ + +
@@ -76,6 +82,13 @@

¡Aún no tienes ningún programa registrado! Para empeza

+ \ No newline at end of file