Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
acb7e00
copy changes from malsolec:32-add-email-address-to-db-and-display-in-…
bizmarcin Nov 7, 2019
a37328e
fix input data to tests
bizmarcin Nov 7, 2019
2d74b45
add password recovery form template
bizmarcin Nov 7, 2019
bdcc86e
add reference between views login and pass_rec
bizmarcin Nov 7, 2019
a2622ef
chenge butons class in pass rec
bizmarcin Nov 7, 2019
2a1056b
Merge branch '32_add_address_email_to_db_and_registration_display_val…
bizmarcin Nov 7, 2019
973a417
check login&mail, message works in wrong way
bizmarcin Nov 7, 2019
1826c5e
prepare method to check login and email, notification works in right way
bizmarcin Nov 7, 2019
ed734f5
add table pass_rec, prepare email content
bizmarcin Nov 12, 2019
3b6b554
prepare view
bizmarcin Nov 12, 2019
0f7160a
add recovery sha GET
bizmarcin Nov 20, 2019
2bc84f4
Merge branch 'master' into 33_reset_user_password
bizmarcin Nov 20, 2019
d2545ec
prepare check and redirection to change password template
bizmarcin Nov 20, 2019
2f36c5e
prepare flash messages
bizmarcin Nov 20, 2019
7f497d4
change mechanism works fine, send email - still to do
bizmarcin Nov 20, 2019
89626dc
add verification file email_test.txt
bizmarcin Nov 20, 2019
e4c3af1
test with SendGrid api
bizmarcin Nov 21, 2019
3dc1335
add send mail mechanism
bizmarcin Nov 21, 2019
5375cc6
Merge branch 'master' into 33_reset_user_password
bizmarcin Nov 21, 2019
2d2eb71
add sendgrid to requirements.txt
bizmarcin Nov 21, 2019
b98cbd3
Merge branch '33_reset_user_password' of https://github.com/tgbdc7/ze…
bizmarcin Nov 21, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ db.sqlite
node_modules/
.coverage
tests/TODO.txt
email_test.txt
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ werkzeug
Flask
pytest
lxml
sendgrid
11 changes: 10 additions & 1 deletion sql/01_db_init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ DROP TABLE IF EXISTS bans;
DROP TABLE IF EXISTS caregiver_to_child;
DROP TABLE IF EXISTS main_points;
DROP TABLE IF EXISTS users;

DROP TABLE IF EXISTS pass_rec;


create table users
Expand Down Expand Up @@ -101,6 +101,15 @@ create table points_history
FOREIGN KEY (id_changing_user) REFERENCES users (id)
);

create table pass_rec
(
id integer UNIQUE primary key autoincrement,
username text not null,
email text not null,
sha text not null,
expire text not null
);

CREATE TRIGGER points_log AFTER UPDATE ON main_points for each row when new.points <> old.points
begin
INSERT INTO points_history (child_id,points_change, id_changing_user, change_timestamp)
Expand Down
25 changes: 25 additions & 0 deletions zeton/api/send_email.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# using SendGrid's Python Library
# https://github.com/sendgrid/sendgrid-python

import os
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail

def is_pass_rec_email(mail,sha):
message = Mail(
from_email='zeton@zeton.com', #fix me in this place should be registred sender mail
to_emails=mail,
subject='Sending with Twilio SendGrid is Fun',
html_content=f'<strong>Poniżej znajdziesz link do resetu hasła:</strong><br>http://127.0.0.1:5000/pass_rec/{sha}') #fix me destination domain
try:
sg = SendGridAPIClient('SG. ...') #fix me in this place should be registred api key

response = sg.send(message)
print(response.status_code)
print(response.body)
print(response.headers)
except Exception as e:
print(str(e))
return False

return True
24 changes: 23 additions & 1 deletion zeton/api/user.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from flask import request, redirect, url_for, g, flash, abort
from flask import request, redirect, url_for, g, flash, abort, render_template
from werkzeug.security import generate_password_hash, check_password_hash

from zeton import auth
Expand Down Expand Up @@ -36,6 +36,28 @@ def set_password():

return redirect(url_for('views.password_change'))

@bp.route('/settings/set_new_password/<user_id>/<sha>', methods=['POST'])
def set_new_password(user_id, sha):
new_password = request.form['new_password']
repeat_new_password = request.form['repeat_new_password']
hashed_new_password = generate_password_hash(new_password)

if not user_id:
return abort(403)

if not (new_password == '' or repeat_new_password == ''):
if new_password == repeat_new_password:
if auth.password_validation(new_password):
users.update_password(user_id, hashed_new_password)
flash('Nowe hasło wprowadzone poprawnie')
return redirect(url_for('views.index'))
flash('Hasło musi zawierać 1 dużą literę, 1 małą literę, 1 cyfrę i musi mieć długość 8 znaków')
flash('Nowe hasło i powtórzone nowe hasło muszą się zgadzać. Spróbuj ponownie')
else:
flash('Wypełnij wszystkie pola')


return redirect(url_for('auth.new_pass', sha=sha))

@bp.route("/user", methods=['POST'])
def register():
Expand Down
53 changes: 48 additions & 5 deletions zeton/auth.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import functools

from flask import Blueprint, redirect, render_template, request, url_for, session, g, abort
from werkzeug.security import check_password_hash

import datetime
from flask import Blueprint, redirect, render_template, request, url_for, session, g, abort, get_flashed_messages
from werkzeug.security import check_password_hash, generate_password_hash
from zeton.data_access import users
from . import db
from zeton.api.send_email import is_pass_rec_email

bp = Blueprint('auth', __name__)

Expand Down Expand Up @@ -47,9 +47,39 @@ def login():
session['role'] = user_data['role']
return redirect(url_for('views.index'))

error = 'Invalid login or username'
error = 'Błędny login lub hasło'
return render_template('base/login.html', error=error)

@bp.route('/pass_rec', methods=['GET', 'POST'])
def pass_rec():
error = None
if request.method == 'POST':
username = request.form['username']
emial = request.form['email']

user_data = get_user_data(username)

if user_data:
user_data_username = user_data['username']
user_data_email = user_data['email']
if user_data_username == username and user_data_email == emial:
# fix me
# send mail
sha = generate_password_hash(str(datetime.datetime.now()), "sha256")
sha = sha.replace('sha256$', '')
expire = datetime.datetime.now() + datetime.timedelta(hours=1)
message = users.pass_rec(username, emial, sha, expire)
if not is_pass_rec_email(emial,sha):
message = "Blad wysylania email, skontaktuj sie z administratorem"

# file
f = open("email_test.txt", "a")
f.write(f"http://127.0.0.1:5000/pass_rec/{sha}\n")
return render_template('base/login.html', error=message)

error = 'Invalid login or email'
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proponuję zmienić komunikat na polski

return render_template('user/pass_rec_form.html', error=error)


@bp.route('/logout')
def logout():
Expand All @@ -66,6 +96,19 @@ def register():
prev_url = request.referrer
return render_template('user/register_form.html', prev_url=prev_url)

@bp.route('/pass_rec/<sha>', methods=['GET'])
def new_pass(sha, messages=None):
user_name = users.get_user_name_pass_recovery_sha(sha)
if user_name!=None:
user_id = users.get_user_id(user_name)
user_data = users.get_user_data(user_id)

context = {'user_data': user_data}
messages = get_flashed_messages()
return render_template('user/password_recovery.html', **context, sha=sha, messages=messages)
else:
message = "Link do odzyskania hasłą jest błędny lub przeterminowany"
return render_template('base/login.html', error=message)

@bp.route('/add-person', methods=['GET'])
def add_person():
Expand Down
53 changes: 51 additions & 2 deletions zeton/data_access/users.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import datetime
from flask import session, g

from zeton.data_access.bans import check_bans_status
from zeton.data_access.points import get_child_points

from zeton.db import get_db


Expand Down Expand Up @@ -103,6 +102,56 @@ def get_user_id(username):
return row['id']
return False

def get_user_name_pass_recovery_sha(sha):
query = f"select * from pass_rec where expire > '{datetime.datetime.now()}' and sha='{sha}'"
result = get_db().execute(query)
row = result.fetchone()
if row!=None:
return row['username']
else:
return None

def pass_rec(username, email, sha, expire):
query = f"select * from pass_rec where expire > '{datetime.datetime.now()}' and username='{username}'"
result = get_db().execute(query)
rows = result.fetchall()
rows_count = rows.__len__()
if rows_count > 0:
check_old = False
else:
check_old = True
if check_old:
query = "INSERT INTO 'pass_rec' " \
"(username, email, sha, expire) " \
f"VALUES ('{username}', '{email}', '{sha}', '{expire}') "

get_db().execute(query)
get_db().commit()
return "Sprawdz skrzynkę pocztową w celu odzyskania hasła"
else:
return "Poprzedni link jeszcze nie wygasł, sprawdź stare maile i spam"

def check_pass_rec(username, sha):
query = f"select * from pass_rec where expire > '{datetime.datetime.now()}' and username='{username}'"
result = get_db().execute(query)
rows = result.fetchone()
rows_count = rows.__len__()
if rows_count == 1:
check = True
else:
check = False
return check

def get_email_address(email):
query = """
SELECT email FROM users
WHERE email = ?
"""
result = get_db().execute(query, (email,))
row = result.fetchone()
if row:
return row['email']
return False

def get_email_address(email):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zduplikowana funkcja

query = """
Expand Down
6 changes: 5 additions & 1 deletion zeton/templates/base/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@ <h2 class="section__title">Zaloguj się</h2>
<!--#TODO add and styling button `Zarejestruj się` -->
<a href="{{ url_for('auth.register') }}" class="button-add" role="button">Zarejestruj się</a>
</div>
<center>
<a href="/pass_rec">Odzyskaj hasło</a>
</center>

{% if error %}
<h3 style="text-align: center; color: red;">Błędny login lub hasło</h3>
<h3 style="text-align: center; color: red;">{{ error }}</h3>
{% endif %}
</form>

Expand Down
30 changes: 30 additions & 0 deletions zeton/templates/user/pass_rec_form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{% extends "base/base.html" %}
{% block head %}
{{ super() }}
{% block password %}
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
{% endblock password %}
{% endblock head %}

{% block content %}
<div class="col col-sm-5">
<form action="/pass_rec" method="POST">

<h2>Odzyskiwanie hasła użytkownika</h2>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brakuje flashowania z errorem, kiedy podany email jest błędny.

{% block add_person %}{% endblock add_person %}
<div class="form-group">
<label>Nazwa użytkownika:</label>
<input class="form-control" type="text" name="username" placeholder="Nazwa użytkownika" required>
</div>
<div class="form-group">
<label>Adres email:</label>
<input class="form-control" type="email" name="email" placeholder="Adres email" required>
</div>
<div class="form-group button">
<a href="/" class="button-add">Powrót</a>
<button type="submit" class="button-switch">Odzyskaj hasło</button>
</div>
</form>
</div>
{% endblock content %}
33 changes: 33 additions & 0 deletions zeton/templates/user/password_recovery.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{% extends "base/base.html" %}
{% block content %}

<div class="col col-sm-6">

<div class="text-center">
<h2>{{ user_data.firstname }}</h2>

{% if messages %}
<div class="alert alert-dark">{{ messages[0] }}</div>
{% endif %}
<form action="/api/settings/set_new_password/{{ user_data.id }}/{{ sha }}" method="post">
<div class="form-group">
<label for="inputPassword2">Wpisz nowe hasło </label>
<br>
<input type="password" class="form-control" name="new_password" id="inputPassword2"
placeholder="Nowe hasło">
</div>
<div class="form-group">
<label for="inputPassword3">Powtórz nowe hasło </label>
<br>
<input type="password" class="form-control" name="repeat_new_password" id="inputPassword3"
placeholder="Powtórz nowe hasło">
</div>
<br>
<div class="form-group button">
<button type="submit" class="btn btn-info">Prześlij</button>
</div>
</form>
</div>
</div>

{% endblock %}
1 change: 0 additions & 1 deletion zeton/views/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ def password_change():

return render_template('user/password_change.html', **context, messages=messages)


@bp.route('/settings/firstname')
@auth.login_required
def firstname_change():
Expand Down