Update texts and Fixbugs
This commit is contained in:
parent
f056300d27
commit
e09c4abf8c
37
app.py
37
app.py
@ -4,8 +4,8 @@ from functools import wraps
|
||||
from forms import LoginForm, SignupForm, EmailResetPasswordForm, ResetPasswordForm
|
||||
from models import db, User
|
||||
from flask_mail import Mail, Message
|
||||
import uuid
|
||||
import crypt
|
||||
from uuid import uuid4
|
||||
from crypt import crypt, mksalt, METHOD_SHA512
|
||||
|
||||
# CONFIGURATIONS
|
||||
# Flask
|
||||
@ -59,9 +59,13 @@ def signup():
|
||||
'''
|
||||
form = SignupForm()
|
||||
if form.validate_on_submit():
|
||||
if User.query.filter_by(email=form.email.data).all():
|
||||
if not User.query.filter_by(email=form.email.data).all():
|
||||
my_user = User()
|
||||
form.populate_obj(my_user)
|
||||
# Encrypt password
|
||||
my_user.password = crypt(
|
||||
form.password.data, mksalt(METHOD_SHA512)
|
||||
)
|
||||
db.session.add(my_user)
|
||||
# Prepare the account activation email
|
||||
msg = Message(
|
||||
@ -69,15 +73,15 @@ def signup():
|
||||
sender='no-repy@' + getenv('DOMAIN'),
|
||||
recipients=[my_user.email]
|
||||
)
|
||||
link = 'http://' + getenv('DOMAIN') + url_for('activate_account')
|
||||
link = 'http://' + getenv('DOMAIN') + url_for('activate_account', token=my_user.token)
|
||||
msg.body = render_template(
|
||||
'emails/activate.txt', username=my_user.username,
|
||||
token=link + my_user.token
|
||||
token=link
|
||||
)
|
||||
msg.html = render_template(
|
||||
'emails/activate.html',
|
||||
username=my_user.username,
|
||||
token=link + my_user.token
|
||||
token=link
|
||||
)
|
||||
try:
|
||||
# Save new User
|
||||
@ -128,13 +132,16 @@ def forgot_password():
|
||||
my_user = User.query.filter_by(email=form.email.data).first()
|
||||
if my_user:
|
||||
# Generate new token
|
||||
token = str(uuid.uuid4()).replace('-', '')
|
||||
token = str(uuid4()).replace('-', '')
|
||||
# Update user token
|
||||
my_user.token = token
|
||||
db.session.add(my_user)
|
||||
db.session.commit()
|
||||
# Send email with token
|
||||
link = 'http://' + getenv('DOMAIN') + url_for('update_password')
|
||||
link = 'http://' + getenv('DOMAIN') + url_for(
|
||||
'update_password',
|
||||
email=my_user.email, token=token
|
||||
)
|
||||
msg = Message(
|
||||
'Recover password',
|
||||
sender='no-repy@' + getenv('DOMAIN'),
|
||||
@ -142,12 +149,12 @@ def forgot_password():
|
||||
)
|
||||
msg.body = render_template(
|
||||
'emails/forgot_password.txt', username=my_user.username,
|
||||
token=link + my_user.token
|
||||
token=link
|
||||
)
|
||||
msg.html = render_template(
|
||||
'emails/forgot_password.html',
|
||||
username=my_user.username,
|
||||
token=link + my_user.token
|
||||
token=link
|
||||
)
|
||||
mail.send(msg)
|
||||
flash('''
|
||||
@ -172,8 +179,8 @@ def update_password(email, token):
|
||||
if my_user:
|
||||
if form.validate_on_submit():
|
||||
# Encrypt password
|
||||
my_user.password = crypt.crypt(
|
||||
form.password.data, crypt.mksalt(crypt.METHOD_SHA512)
|
||||
my_user.password = crypt(
|
||||
form.password.data, mksalt(METHOD_SHA512)
|
||||
)
|
||||
# Update password
|
||||
db.session.add(my_user)
|
||||
@ -194,9 +201,9 @@ def login():
|
||||
if form.validate_on_submit():
|
||||
# Validate email and password
|
||||
email = form.email.data
|
||||
password = crypt.crypt(
|
||||
form.password.data, crypt.mksalt(crypt.METHOD_SHA512)
|
||||
)
|
||||
password = crypt(
|
||||
form.password.data, mksalt(METHOD_SHA512)
|
||||
)
|
||||
my_user = User.query.filter_by(email=email, password=password).first()
|
||||
if my_user:
|
||||
# Login de usuario
|
||||
|
BIN
database.sqlite
BIN
database.sqlite
Binary file not shown.
7
envExample
Normal file
7
envExample
Normal file
@ -0,0 +1,7 @@
|
||||
export DOMAIN='example.com'
|
||||
export SECRET_KEY='my secret'
|
||||
export DEBUG=True
|
||||
export SQLALCHEMY_DATABASE_URI='sqlite:///database.sqlite'
|
||||
export MAIL_SERVER=''
|
||||
export MAIL_USERNAME=''
|
||||
export MAIL_PASSWORD=''
|
89
forms.py
89
forms.py
@ -2,24 +2,91 @@ from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, PasswordField, BooleanField
|
||||
from wtforms.validators import DataRequired, Email, Length, EqualTo
|
||||
|
||||
|
||||
class LoginForm(FlaskForm):
|
||||
email = StringField('E-mail', validators=[DataRequired('Necesito un E-mail'), Email('Debe tener un formato válido')])
|
||||
password = PasswordField('Contraseña', validators=[DataRequired('No me has indicado una contraseña')])
|
||||
'''
|
||||
Form Login
|
||||
'''
|
||||
email = StringField(
|
||||
'Email',
|
||||
validators=[
|
||||
DataRequired(),
|
||||
Email()
|
||||
]
|
||||
)
|
||||
password = PasswordField(
|
||||
'Password',
|
||||
validators=[
|
||||
DataRequired()
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class SignupForm(FlaskForm):
|
||||
username = StringField('Nombre de usuario', validators=[DataRequired('Debes indicarnos un nombre de usuario'), Length(5, 30, 'Debe estar entre 5 y 30 carácteres')])
|
||||
email = StringField('E-mail', validators=[DataRequired('Necesito un E-mail'), Email('Debe tener un formato válido'), Length(1, 254, 'Es demasiado largo')])
|
||||
password = PasswordField('Contraseña', validators=[DataRequired('No me has indicado una contraseña'), EqualTo('password_confirm', 'No coinciden las contraseñas')])
|
||||
password_confirm = PasswordField('Repetir contraseña')
|
||||
accept_tos = BooleanField('Aceptar condiciones', validators=[DataRequired('Necesito que aceptes mis condiciones. Aqui mando yo.')])
|
||||
'''
|
||||
Form signup
|
||||
'''
|
||||
username = StringField(
|
||||
'Username',
|
||||
validators=[
|
||||
DataRequired(),
|
||||
Length(5, 30, '''
|
||||
You can not have less than 5 characters or more 30.
|
||||
''')
|
||||
]
|
||||
)
|
||||
email = StringField(
|
||||
'Email',
|
||||
validators=[
|
||||
DataRequired(),
|
||||
Email(),
|
||||
Length(1, 254, 'Too long.')
|
||||
]
|
||||
)
|
||||
password = PasswordField(
|
||||
'Password',
|
||||
validators=[
|
||||
DataRequired(),
|
||||
EqualTo(
|
||||
'password_confirm',
|
||||
'Passwords are not the same.'
|
||||
)
|
||||
]
|
||||
)
|
||||
password_confirm = PasswordField('Repeat password')
|
||||
accept_tos = BooleanField(
|
||||
'I accept the terms and conditions.',
|
||||
validators=[
|
||||
DataRequired('Please accept the terms and conditions.')
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class EmailResetPasswordForm(FlaskForm):
|
||||
email = StringField('E-mail', validators=[DataRequired('Necesito un E-mail'), Email('Debe tener un formato válido')])
|
||||
'''
|
||||
Form send email reset password
|
||||
'''
|
||||
email = StringField(
|
||||
'Email',
|
||||
validators=[
|
||||
DataRequired(),
|
||||
Email()
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class ResetPasswordForm(FlaskForm):
|
||||
password = PasswordField('Contraseña', validators=[DataRequired('No me has indicado una contraseña'), EqualTo('password_confirm', 'No coinciden las contraseñas')])
|
||||
password_confirm = PasswordField('Repetir contraseña')
|
||||
|
||||
'''
|
||||
Form update password
|
||||
'''
|
||||
password = PasswordField(
|
||||
'Password',
|
||||
validators=[
|
||||
DataRequired(),
|
||||
EqualTo(
|
||||
'password_confirm',
|
||||
'Passwords are not the same.'
|
||||
)
|
||||
]
|
||||
)
|
||||
password_confirm = PasswordField('Repeat password')
|
||||
|
15
models.py
15
models.py
@ -3,8 +3,7 @@ from flask import Flask
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_script import Manager
|
||||
from flask_migrate import Migrate, MigrateCommand
|
||||
import crypt
|
||||
import uuid
|
||||
from uuid import uuid4
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@ -18,7 +17,9 @@ manager.add_command('db', MigrateCommand)
|
||||
|
||||
|
||||
class User(db.Model):
|
||||
|
||||
'''
|
||||
Table user
|
||||
'''
|
||||
__tablename__ = 'users'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
@ -28,15 +29,13 @@ class User(db.Model):
|
||||
is_active = db.Column(db.Boolean)
|
||||
token = db.Column(db.String(32), nullable=False, unique=False)
|
||||
|
||||
def __init__(self, username, email, password):
|
||||
self.username = username
|
||||
self.email = email
|
||||
self.password = crypt.crypt(password, crypt.mksalt(crypt.METHOD_SHA512))
|
||||
def __init__(self):
|
||||
self.is_active = False
|
||||
self.token = str(uuid.uuid4()).replace('-', '')
|
||||
self.token = str(uuid4()).replace('-', '')
|
||||
|
||||
def __repr__(self):
|
||||
return '<User %r>' % self.username
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
manager.run()
|
||||
|
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Activar cuenta</title>
|
||||
<title>Activate account</title>
|
||||
<style>
|
||||
/* -------------------------------------
|
||||
GLOBAL RESETS
|
||||
@ -286,8 +286,8 @@
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<p>Hola {{ username }},</p>
|
||||
<p>Gracias por registrarte en nuestro ejemplo. Activa tu cuenta pulsando en el siguiente botón.</p>
|
||||
<p>Hi {{ username }}!,</p>
|
||||
<p>Thank you for registering you in our example. Activate your account by clicking on the button below.</p>
|
||||
<table border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
|
||||
<tbody>
|
||||
<tr>
|
||||
@ -295,7 +295,7 @@
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td> <a href="{{ token }}" target="_blank">Activar</a> </td>
|
||||
<td> <a href="{{ token }}" target="_blank">Activate</a> </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -303,7 +303,7 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>En caso que no te funcione el botón, pulsa el siguiente enlace.</p>
|
||||
<p>In the event that the button will not work, click the following link.</p>
|
||||
<p>{{ token }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -1,7 +1,6 @@
|
||||
Hola {{ username }},
|
||||
restablece tu contraseña.
|
||||
|
||||
Pulsa en el siguiente enlace
|
||||
Hi {{ username }}!,
|
||||
thank you for registering you in our example. Activate your account by clicking on the link below.
|
||||
|
||||
{{ token }}
|
||||
|
||||
Example team.
|
||||
|
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Recuperar contraseña</title>
|
||||
<title>Forgot password</title>
|
||||
<style>
|
||||
/* -------------------------------------
|
||||
GLOBAL RESETS
|
||||
@ -286,8 +286,8 @@
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<p>Hola {{ username }},</p>
|
||||
<p>Para actualizar tu contraseña pulse en el boton.</p>
|
||||
<p>Hi {{ username }}!,</p>
|
||||
<p>To update your password, click on the button.</p>
|
||||
<table border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
|
||||
<tbody>
|
||||
<tr>
|
||||
@ -295,7 +295,7 @@
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td> <a href="{{ token }}" target="_blank">Restablecer contraseña</a> </td>
|
||||
<td> <a href="{{ token }}" target="_blank">Reset password</a> </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -303,7 +303,7 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>En caso que no te funcione el botón, pulsa el siguiente enlace.</p>
|
||||
<p>In the event that the button will not work, click the following link.</p>
|
||||
<p>{{ token }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -1,6 +1,6 @@
|
||||
Activa tu cuenta {{ username }}
|
||||
|
||||
Pulsa en el siguiente enlace
|
||||
Hi {{ username }}!,
|
||||
to update your password, click on the link.
|
||||
|
||||
{{ token }}
|
||||
|
||||
Example team.
|
||||
|
19
templates/helpers/_forms.html
Normal file
19
templates/helpers/_forms.html
Normal file
@ -0,0 +1,19 @@
|
||||
{% macro generate_fields(form) -%}
|
||||
{% for field in form %}
|
||||
{% if field.type != 'CSRFTokenField' %}
|
||||
<div class="form-group{%if field.errors %} has-error{% endif %}">
|
||||
{{ field.label }}
|
||||
{% if field.type in ('StringField', 'PasswordField') %}
|
||||
{{ field(class='form-control') }}
|
||||
{% else %}
|
||||
{{ field() }}
|
||||
{% endif %}
|
||||
{% for error in field.errors %}
|
||||
<span class="help-block">{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ field() }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{%- endmacro %}
|
@ -1,9 +1,10 @@
|
||||
{% from 'helpers/_forms.html' import generate_fields with context %}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{% block title %}{% endblock %} | Login example</title>
|
||||
<title>{% block title %}{% endblock %} | Login system example</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
@ -17,7 +18,7 @@
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">Example Login</a>
|
||||
<a class="navbar-brand" href="/">Example Login</a>
|
||||
</div>
|
||||
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
|
@ -1,28 +1,12 @@
|
||||
{% extends 'layouts/master.html' %}
|
||||
{% block title %}Restablecer contraseña{% endblock %}
|
||||
{% block body %}
|
||||
<h1>Restablece tu contraseña</h1>
|
||||
<p>Te enviaremos un email para cambiar la contraseña</p>
|
||||
<h1>Forgot password</h1>
|
||||
<p>We will send you an email to change your password.</p>
|
||||
<p>
|
||||
<form action="" method="post">
|
||||
{% for campo in form %}
|
||||
{% if campo.type != 'CSRFTokenField' %}
|
||||
<div class="form-group{%if campo.errors %} has-error{% endif %}">
|
||||
{{ campo.label }}
|
||||
{% if campo.type in ('StringField', 'PasswordField') %}
|
||||
{{ campo(class='form-control') }}
|
||||
{% else %}
|
||||
{{ campo() }}
|
||||
{% endif %}
|
||||
{% for error in campo.errors %}
|
||||
<span class="help-block">{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ campo() }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<input type="submit" class="btn btn-success" value="Enviar">
|
||||
{{ generate_fields(form) }}
|
||||
<input type="submit" class="btn btn-success">
|
||||
</form>
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
@ -4,30 +4,14 @@
|
||||
<h1>Login</h1>
|
||||
<p>
|
||||
<form action="" method="post">
|
||||
{% for campo in form %}
|
||||
{% if campo.type != 'CSRFTokenField' %}
|
||||
<div class="form-group{%if campo.errors %} has-error{% endif %}">
|
||||
{{ campo.label }}
|
||||
{% if campo.type in ('StringField', 'PasswordField') %}
|
||||
{{ campo(class='form-control') }}
|
||||
{% else %}
|
||||
{{ campo() }}
|
||||
{% endif %}
|
||||
{% for error in campo.errors %}
|
||||
<span class="help-block">{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ campo() }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<input type="submit" class="btn btn-success" value="Entrar">
|
||||
{{ generate_fields(form) }}
|
||||
<input type="submit" class="btn btn-success" value="Enter">
|
||||
</form>
|
||||
</p>
|
||||
<p>
|
||||
<a href="{{ url_for('signup') }}" class="btn btn-primary">Regístrate</a>
|
||||
<a href="{{ url_for('signup') }}" class="btn btn-primary">Signup</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="{{ url_for('forgot_password') }}" class="btn btn-warning">Me he olvidado la contraseña</a>
|
||||
<a href="{{ url_for('forgot_password') }}" class="btn btn-warning">Forgot password</a>
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
@ -3,23 +3,7 @@
|
||||
{% block body %}
|
||||
<h1>Signup</h1>
|
||||
<form action="" method="post">
|
||||
{% for campo in form %}
|
||||
{% if campo.type != 'CSRFTokenField' %}
|
||||
<div class="form-group{%if campo.errors %} has-error{% endif %}">
|
||||
{{ campo.label }}
|
||||
{% if campo.type in ('StringField', 'PasswordField') %}
|
||||
{{ campo(class='form-control') }}
|
||||
{% else %}
|
||||
{{ campo() }}
|
||||
{% endif %}
|
||||
{% for error in campo.errors %}
|
||||
<span class="help-block">{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ campo() }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<input type="submit" class="btn btn-success" value="Registrarse">
|
||||
{{ generate_fields(form) }}
|
||||
<input type="submit" class="btn btn-success" value="Signup">
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
@ -1,26 +1,10 @@
|
||||
{% extends 'layouts/master.html' %}
|
||||
{% block title %}Cambiar contraseña{% endblock %}
|
||||
{% block title %}Update password{% endblock %}
|
||||
{% block body %}
|
||||
<h1>Cambia tu contraseña</h1>
|
||||
<h1>Update password</h1>
|
||||
<form action="" method="post">
|
||||
{{ generate_fields(form) }}
|
||||
<input type="hidden" name="email" value="{{ email }}">
|
||||
{% for campo in form %}
|
||||
{% if campo.type != 'CSRFTokenField' %}
|
||||
<div class="form-group{%if campo.errors %} has-error{% endif %}">
|
||||
{{ campo.label }}
|
||||
{% if campo.type in ('StringField', 'PasswordField') %}
|
||||
{{ campo(class='form-control') }}
|
||||
{% else %}
|
||||
{{ campo() }}
|
||||
{% endif %}
|
||||
{% for error in campo.errors %}
|
||||
<span class="help-block">{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ campo() }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<input type="submit" class="btn btn-success" value="Actualizar">
|
||||
<input type="submit" class="btn btn-success" value="Update">
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
Loading…
Reference in New Issue
Block a user