agregar página de cambio de clave. corrección de links

master
ifiguero 2023-02-27 17:27:56 -03:00
parent a1b84a93d6
commit 19c0887bc5
4 changed files with 126 additions and 46 deletions

View File

@ -1,9 +1,9 @@
# coding: utf-8 # coding: utf-8
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField from wtforms import StringField, PasswordField, SubmitField, BooleanField, HiddenField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
from flask_login import current_user from flask_login import current_user
from webinterface.models.system import Persona from webinterface.models.system import Persona, Correo
import pwnedpasswords import pwnedpasswords
class LoginForm(FlaskForm): class LoginForm(FlaskForm):
@ -53,3 +53,32 @@ class RegistrationForm(FlaskForm):
def validate_password(self, clave): def validate_password(self, clave):
if pwnedpasswords.check(clave.data): if pwnedpasswords.check(clave.data):
raise ValidationError(u'La clave ingresada es insegura. Verifíquelo en <a href="https://haveibeenpwned.com/Passwords">\';--have i been pwned?</a>') raise ValidationError(u'La clave ingresada es insegura. Verifíquelo en <a href="https://haveibeenpwned.com/Passwords">\';--have i been pwned?</a>')
class mMiCuenta(FlaskForm):
id = HiddenField()
login = StringField('Usuario', render_kw={'readonly': True})
nombrecompleto = StringField('Nombre', render_kw={'readonly': True})
correo = StringField('Correo Principal', validators=[DataRequired(), Email()])
clave = PasswordField('Clave')
fono = StringField('Telefono', render_kw={"placeholder": "+569 8765 4321"})
submit = SubmitField('Modificar')
def validate_fono(self, field):
parsed = field.data.replace(" ", "")
if not parsed:
raise ValidationError(u'Debe ingresar un número de teléfono.')
if not parsed.startswith('+'):
raise ValidationError(u'Ingrese el número completo "+569XYZWABCD".')
if len(parsed) < 11:
raise ValidationError(u'Ingrese el número completo "+569XYZWABCD".')
if not parsed[1:].isdigit():
raise ValidationError(u'El número ingresado no es válido, contiene caracteres no-numéricos.')
def validate_clave(self, field):
if field.data and pwnedpasswords.check(field.data):
raise ValidationError(u'La clave ingresada es insegura. Verifíque la seguridad de su clave en <a href="https://haveibeenpwned.com/Passwords" target="_blank">\';--have i been pwned?</a>')

View File

@ -8,7 +8,7 @@ from webinterface import db, bcrypt
from sqlalchemy import func from sqlalchemy import func
from datetime import datetime, date from datetime import datetime, date
from webinterface.models.system import Persona, Ipaddr, Dispositivo, Identidad, Sesion, Registro, Conexion, Ruta, Sitio, Correo from webinterface.models.system import Persona, Ipaddr, Dispositivo, Identidad, Sesion, Registro, Conexion, Ruta, Sitio, Correo
from webinterface.content.forms import RegistrationForm, LoginForm, RequestResetForm, ResetPasswordForm from webinterface.content.forms import mMiCuenta, LoginForm, RequestResetForm, ResetPasswordForm
from webinterface.content.utils import clean_str, es_local from webinterface.content.utils import clean_str, es_local
main = Blueprint('main', __name__) main = Blueprint('main', __name__)
@ -23,7 +23,7 @@ else:
def login(): def login():
if current_user.is_authenticated: if current_user.is_authenticated:
return redirect(url_for('main.dashboard')) return redirect(systemuri)
form = LoginForm() form = LoginForm()
if form.validate_on_submit(): if form.validate_on_submit():
@ -52,12 +52,41 @@ def logout():
return redirect('https://tpmc.ilab.cl/') return redirect('https://tpmc.ilab.cl/')
@main.route("/me") @main.route("/system/me", methods=['GET', 'POST'])
@login_required @login_required
def me(): def micuenta():
image_file = url_for('static', filename='profile_pics/' + current_user.foto) form = mMiCuenta()
return render_template('system/me.html', title=u'¿Quién soy?',
image_file=image_file) if form.validate_on_submit():
if form.clave.data:
hashed_password = bcrypt.generate_password_hash(form.clave.data).decode('utf-8')
current_user.clave = hashed_password
trimmed = form.correo.data.strip().lower()
correo = Correo.query.filter_by(correo=trimmed).first()
if correo is None:
correo = Correo(correo=trimmed, cuenta=current_user)
current_user.correodefecto=correo
current_user.telefono = form.fono.data.replace(" ", "")
db.session.commit()
flash(u'Los datos de tu cuenta han sido actualizados.', 'success')
return redirect(url_for('main.micuenta'))
elif request.method == 'GET':
if current_user.correodefecto is not None:
form.correo.data = current_user.correodefecto.correo
form.id.data = current_user.id
form.login.data = current_user.rut
form.nombrecompleto.data = current_user.nombrecompleto
form.fono.data = current_user.telefono
return render_template('system/me.html', title='Mi Cuenta', form=form)
@main.before_app_request @main.before_app_request
def registra_sesion(): def registra_sesion():

View File

@ -1,43 +1,65 @@
{% extends "layout.html" %} {% extends "layout.html" %}
{% block content %} {% block content %}
<div class="card-header bg-primary"><h4 class="text-white"><i class="fas fa-user-circle mr-2"></i>{{ title }}</h4></div>
<div class="content-section"> <div class="content-section">
<div class="media">
<img class="rounded-circle account-img" src="{{ image_file }}">
<div class="media-body">
{% if not current_user.alias %}
<h2 class="account-heading">{{ current_user.nombrecompleto }}</h2>
{% else %}
<h2 class="account-heading">{{ current_user.alias }}</h2>
{% endif %}
<p class="text-secondary">{{ current_user.correodefecto.correo }}</p>
</div>
</div>
<fieldset class="form-group">
<legend class="border-bottom mb-4">Información de la Cuenta</legend>
<div class="form-group">
Nombre:
{{ current_user.nombrecompleto }}
</div>
<div class="form-group">
Login:
{{ current_user.login }}
</div>
<div class="form-group">
Correo:
{{ current_user.correodefecto.correo }}
</div>
<legend class="border-bottom mb-4">Personalización</legend>
<div class="form-group">
Alias:
{{ current_user.alias }}
</div>
<div class="form-group">
<form method="POST" action="" enctype="multipart/form-data">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Datos del usuario</legend>
<div class="form-group">
{{ form.nombrecompleto.label() }}
{{ form.nombrecompleto(class="form-control form-control-lg") }}
</div>
<div class="form-group">
{{ form.login.label(class="form-control-label") }}
{{ form.login(class="form-control form-control-lg") }}
</div>
<legend class="border-bottom mb-4">Actualizar Información</legend>
<div class="form-group">
{{ form.correo.label(class="form-control-label") }} <span class='text-danger'>(obligatorio)</span>
{% if form.correo.errors %}
{{ form.correo(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.correo.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.correo(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.fono.label(class="form-control-label") }} <span class='text-danger'>(obligatorio)</span>
{% if form.fono.errors %}
{{ form.fono(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.fono.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.fono(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.clave.label(class="form-control-label") }}
{% if form.clave.errors %}
{{ form.clave(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.clave.errors %}
<span>{{ error|safe }}</span>
{% endfor %}
</div>
{% else %}
{{ form.clave(class="form-control form-control-lg") }}
{% endif %}
</div> </div>
</fieldset> </fieldset>
<div class="form-group justify-content-end d-flex">
{{ form.submit(class="btn btn-lg btn-primary") }}
<a href="https://app.tpmc.ilab.cl/" class="btn btn-lg btn-secondary">Volver</a>
</div>
</form> </form>
</div> </div>
<a href="{{ url_for('main.dashboard') }}" class="btn btn-info btn-lg btn-block mt-2"><i class="fas fa-undo-alt mr-2"></i>Volver</a>
{% endblock content %} {% endblock content %}

View File

@ -10,9 +10,9 @@
<meta name="author" content=""> <meta name="author" content="">
{% if title %} {% if title %}
<title>iLab Gestión Académica - {{ title }}</title> <title>Gestión del Transporte Público del Gran Concepción - {{title}}</title>
{% else %} {% else %}
<title>iLab Gestión Académica</title> <title>Gestión del Transporte Público del Gran Concepción</title>
{% endif %} {% endif %}
<link rel="icon" href="/static/favicon.svg" sizes="any" type="image/svg+xml"> <link rel="icon" href="/static/favicon.svg" sizes="any" type="image/svg+xml">
<link href="/static/googlefonts.css" rel="stylesheet"> <link href="/static/googlefonts.css" rel="stylesheet">
@ -34,7 +34,7 @@
<div class="sidebar-brand-icon"> <div class="sidebar-brand-icon">
<i class="fas fa-bus"></i> <i class="fas fa-bus"></i>
</div> </div>
<div class="sidebar-brand-text mx-1">Gestión del Transporte Público del Gran Concepción</div> <div class="sidebar-brand-text mx-1">TPMC</div>
</a> </a>
<!-- Divider --> <!-- Divider -->
@ -111,7 +111,7 @@
</a> </a>
<!-- Dropdown - User Information --> <!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="userDropdown"> <div class="dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="userDropdown">
<a class="dropdown-item" href="/system/me"> <a class="dropdown-item" href="https://tpmc.ilab.cl/system/me">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i> <i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Mis Datos Mis Datos
</a> </a>