addd password recovery
This commit is contained in:
parent
39574a2c06
commit
f7d2e8563b
Binary file not shown.
BIN
__pycache__/mail.cpython-310.pyc
Normal file
BIN
__pycache__/mail.cpython-310.pyc
Normal file
Binary file not shown.
@ -1 +1,14 @@
|
|||||||
{"users": {"1": {"camille@chauvet.pro": "b'$2b$12$AMuNu9CU/lUyaQjDmyWypeVg8beyRA795lrldMGAmHMXaeyfNnke.'"}}}
|
{
|
||||||
|
"users": {
|
||||||
|
"1": {
|
||||||
|
"email": "camille@chauvet.pro",
|
||||||
|
"password": "b'$2b$12$FVOKVF9p/SlSv9ANVNDW.eOmv1f3qtB0WU86g4ED4B8J2fMBPZu7.'"
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"email": "spam@camille.chauvet.pro",
|
||||||
|
"password": "b'$2b$12$D2DexgunhMTbYWkXmEQKw.Aa13W9QZE4CjsNUyaU5bSaZ8ZpdJ2hO'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resets": {},
|
||||||
|
"_default": {}
|
||||||
|
}
|
46
database.py
46
database.py
@ -1,27 +1,59 @@
|
|||||||
from tinydb import TinyDB, Query
|
from tinydb import TinyDB, where, Query
|
||||||
|
import uuid
|
||||||
import hasher
|
import hasher
|
||||||
|
|
||||||
db = TinyDB("./database.json")
|
db = TinyDB("./database.json", indent=4)
|
||||||
|
query = Query()
|
||||||
|
|
||||||
users = db.table("users");
|
users = db.table("users");
|
||||||
|
|
||||||
def get_users():
|
def get_users():
|
||||||
return (users.all())
|
return (users.all())
|
||||||
|
|
||||||
def get_user_by_email(email: str):
|
def get_user_by_email(email: str):
|
||||||
for user in get_users():
|
user_lst = users.search(query.email == email)
|
||||||
if (list(user.keys())[0] == email):
|
if (user_lst == []):
|
||||||
return (user);
|
return (None)
|
||||||
|
return (user_lst[0])
|
||||||
|
|
||||||
|
def email_exist(email: str) -> bool:
|
||||||
|
return (get_user_by_email(email) != None)
|
||||||
|
|
||||||
def user_exist(email: str):
|
def user_exist(email: str):
|
||||||
return (get_user_by_email(email) != None)
|
return (get_user_by_email(email) != None)
|
||||||
|
|
||||||
def add_user(email: str, password: str):
|
def add_user(email: str, password: str):
|
||||||
password_hashed = hasher.hash_text(password)
|
password_hashed = hasher.hash_text(password)
|
||||||
users.insert({email: str(password_hashed)});
|
users.insert({"email": email, "password": str(password_hashed)});
|
||||||
|
|
||||||
def check_password(email: str, password: str):
|
def check_password(email: str, password: str):
|
||||||
password_hashed = get_user_by_email(email).get(email)
|
password_hashed = get_user_by_email(email).get("password")
|
||||||
password_hashed = bytes(password_hashed[2:-1], "utf-8")
|
password_hashed = bytes(password_hashed[2:-1], "utf-8")
|
||||||
return (hasher.is_same(password, password_hashed))
|
return (hasher.is_same(password, password_hashed))
|
||||||
|
|
||||||
|
def change_user_password(email: str, password: str):
|
||||||
|
password_hashed = hasher.hash_text(password)
|
||||||
|
db.update({"password": password_hashed}, query.email == email)
|
||||||
|
|
||||||
resets = db.table("resets")
|
resets = db.table("resets")
|
||||||
|
|
||||||
|
def get_email_by_reset_code(code: str):
|
||||||
|
user_lst = resets.search(query.code == code)
|
||||||
|
if (user_lst == []):
|
||||||
|
return (None)
|
||||||
|
return (user_lst[0])
|
||||||
|
|
||||||
|
def reset_code_exist(code: str) -> bool:
|
||||||
|
return (get_email_by_reset_code(code) != None)
|
||||||
|
|
||||||
|
def remove_reset_code_by_email(email: str):
|
||||||
|
resets.remove(query.email == email)
|
||||||
|
|
||||||
|
def remove_reset_code_by_code(code: str):
|
||||||
|
resets.remove(query.code == code)
|
||||||
|
|
||||||
|
def create_reset_code_by_email(email: str):
|
||||||
|
code = str(uuid.uuid4());
|
||||||
|
remove_reset_code_by_email(email);
|
||||||
|
resets.insert({"email": email, "code": code})
|
||||||
|
return (code)
|
||||||
|
Binary file not shown.
Binary file not shown.
8
mail.py
8
mail.py
@ -1,6 +1,7 @@
|
|||||||
import ssl
|
import ssl
|
||||||
import smtplib
|
import smtplib
|
||||||
from email.message import EmailMessage
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
"server": "ssl0.ovh.net",
|
"server": "ssl0.ovh.net",
|
||||||
@ -11,11 +12,11 @@ config = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def send_mail(mail_add:str, subject:str, mail_content:str):
|
def send_mail(mail_add:str, subject:str, mail_content:str):
|
||||||
email = EmailMessage()
|
email = MIMEMultipart()
|
||||||
email['From'] = config["display_name"]
|
email['From'] = config["display_name"]
|
||||||
email["To"] = mail_add;
|
email["To"] = mail_add;
|
||||||
email["subject"] = subject;
|
email["subject"] = subject;
|
||||||
email.set_content(mail_content);
|
email.attach(MIMEText(mail_content, "html"))
|
||||||
|
|
||||||
context = ssl.create_default_context();
|
context = ssl.create_default_context();
|
||||||
|
|
||||||
@ -23,4 +24,3 @@ def send_mail(mail_add:str, subject:str, mail_content:str):
|
|||||||
smtp.login(config["email"], config["password"]);
|
smtp.login(config["email"], config["password"]);
|
||||||
smtp.sendmail(config["email"], mail_add, email.as_string());
|
smtp.sendmail(config["email"], mail_add, email.as_string());
|
||||||
|
|
||||||
send_mail("camille@chauvet.pro", "test", "text")
|
|
||||||
|
40
main.py
40
main.py
@ -2,6 +2,7 @@ from flask import Flask, render_template, request, redirect, session
|
|||||||
from flask_session import Session
|
from flask_session import Session
|
||||||
import utils
|
import utils
|
||||||
import database
|
import database
|
||||||
|
import mail
|
||||||
|
|
||||||
app = Flask(__name__);
|
app = Flask(__name__);
|
||||||
app.config["SESSION_PERMANENT"] = False
|
app.config["SESSION_PERMANENT"] = False
|
||||||
@ -12,7 +13,6 @@ Session(app)
|
|||||||
def home():
|
def home():
|
||||||
return (render_template("home.html"));
|
return (render_template("home.html"));
|
||||||
|
|
||||||
|
|
||||||
@app.route("/connected")
|
@app.route("/connected")
|
||||||
def connected():
|
def connected():
|
||||||
if (not session.get("email")):
|
if (not session.get("email")):
|
||||||
@ -21,12 +21,12 @@ def connected():
|
|||||||
|
|
||||||
@app.route("/login")
|
@app.route("/login")
|
||||||
def login():
|
def login():
|
||||||
|
if (session.get("email")):
|
||||||
|
return (redirect("/connected"))
|
||||||
return (render_template("login.html"));
|
return (render_template("login.html"));
|
||||||
|
|
||||||
@app.route('/login', methods=['POST'])
|
@app.route('/login', methods=['POST'])
|
||||||
def login_post():
|
def login_post():
|
||||||
if (not session.get("email")):
|
|
||||||
return (redirect("/connected"))
|
|
||||||
email = request.form.get('email')
|
email = request.form.get('email')
|
||||||
password = request.form.get('password')
|
password = request.form.get('password')
|
||||||
if (not database.user_exist(email)):
|
if (not database.user_exist(email)):
|
||||||
@ -43,12 +43,12 @@ def logout():
|
|||||||
|
|
||||||
@app.route("/signin")
|
@app.route("/signin")
|
||||||
def signin():
|
def signin():
|
||||||
|
if (session.get("email")):
|
||||||
|
return (redirect("/connected"))
|
||||||
return (render_template("signin.html"));
|
return (render_template("signin.html"));
|
||||||
|
|
||||||
@app.route('/signin', methods=['POST'])
|
@app.route('/signin', methods=['POST'])
|
||||||
def signup_post():
|
def signin_post():
|
||||||
if (not session.get("email")):
|
|
||||||
return (redirect("/connected"))
|
|
||||||
email = request.form.get('email')
|
email = request.form.get('email')
|
||||||
password = request.form.get('password')
|
password = request.form.get('password')
|
||||||
repassword = request.form.get('repassword')
|
repassword = request.form.get('repassword')
|
||||||
@ -65,9 +65,35 @@ def signup_post():
|
|||||||
def forgot():
|
def forgot():
|
||||||
return (render_template("forgot.html"));
|
return (render_template("forgot.html"));
|
||||||
|
|
||||||
|
@app.route("/forgot", methods=["POST"])
|
||||||
|
def forgot_post():
|
||||||
|
email = request.form.get('email')
|
||||||
|
if (not database.email_exist(email)):
|
||||||
|
return (render_template("forgot.html", error="Ce compte n'existe pas'"))
|
||||||
|
uuid = database.create_reset_code_by_email(email);
|
||||||
|
mail.send_mail(email, "Password recovery", render_template("mails/password_recovery.html", code=uuid))
|
||||||
|
return (redirect(f"/reset/{uuid}"))
|
||||||
|
|
||||||
@app.route("/reset/<uuid>")
|
@app.route("/reset/<uuid>")
|
||||||
def reset(uuid):
|
def reset(uuid):
|
||||||
return ("bozo")
|
if (not database.reset_code_exist(uuid)):
|
||||||
|
return (render_template("error.html", error="code inconnu"))
|
||||||
|
email = database.get_email_by_reset_code(uuid)
|
||||||
|
email = email["email"]
|
||||||
|
return (render_template("reset.html", email=email))
|
||||||
|
|
||||||
|
@app.route("/reset/<uuid>", methods=['POST'])
|
||||||
|
def reset_post(uuid):
|
||||||
|
if (not database.reset_code_exist(uuid)):
|
||||||
|
return (render_template("error.html", error="code inconnu"))
|
||||||
|
email = database.get_email_by_reset_code(uuid)
|
||||||
|
password = request.form.get('password')
|
||||||
|
repassword = request.form.get('repassword')
|
||||||
|
if (password != repassword):
|
||||||
|
return (render_template("reset.html", error="Les deux mots de passe sont differents"))
|
||||||
|
database.change_user_password(email, password);
|
||||||
|
database.remove_reset_code_by_code(uuid);
|
||||||
|
return (redirect("/login"))
|
||||||
|
|
||||||
@app.route("/join/<uuid>")
|
@app.route("/join/<uuid>")
|
||||||
def join(uuid):
|
def join(uuid):
|
||||||
|
14
templates/connected.html
Normal file
14
templates/connected.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>PyMenu</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>connected</h1>
|
||||||
|
<h2>Welcome to FlaskApp!</h2>
|
||||||
|
<a href="/logout">
|
||||||
|
<input type="button" value="logout">
|
||||||
|
</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
16
templates/error.html
Normal file
16
templates/error.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>PyMenu</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Error</h1>
|
||||||
|
{% if error %}
|
||||||
|
<h2>{{error}}</h2>
|
||||||
|
{% endif %}
|
||||||
|
<a href="/">
|
||||||
|
<input type="button" value="Revenir a l'acceuil">
|
||||||
|
</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
83
templates/forgot.html
Normal file
83
templates/forgot.html
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" href="index.css" />
|
||||||
|
<title>Beyond School</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="container">
|
||||||
|
<form method="post">
|
||||||
|
<h2>Mot de passe oublié ?</h2>
|
||||||
|
<label><b>Email :</b></label>
|
||||||
|
<input type="email" name="email" placeholder="Insérez votre email" required>
|
||||||
|
<br>
|
||||||
|
{% if error %}
|
||||||
|
<p>{{error}}</p>
|
||||||
|
{% endif %}
|
||||||
|
<input type="submit" value="Valider">
|
||||||
|
<a href="/login">
|
||||||
|
<input type="button" value="connection">
|
||||||
|
</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
body{
|
||||||
|
background: #67BE4B;
|
||||||
|
}
|
||||||
|
#container{
|
||||||
|
width:400px;
|
||||||
|
margin:0 auto;
|
||||||
|
margin-top:10%;
|
||||||
|
}
|
||||||
|
/* Bordered form */
|
||||||
|
form {
|
||||||
|
width:100%;
|
||||||
|
padding: 40px;
|
||||||
|
border: 1px solid #f1f1f1;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
|
||||||
|
}
|
||||||
|
#container h2{
|
||||||
|
width: 38%;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Full-width inputs */
|
||||||
|
input[type=email], input[type=password], input[type=number] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px 20px;
|
||||||
|
margin: 8px 0;
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set a style for all buttons */
|
||||||
|
input[type=submit], input[type=button] {
|
||||||
|
background-color: #53af57;
|
||||||
|
color: white;
|
||||||
|
padding: 14px 20px;
|
||||||
|
margin: 8px 0;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
input[type=submit]:hover {
|
||||||
|
background-color: white;
|
||||||
|
color: #53af57;
|
||||||
|
border: 1px solid #53af57;
|
||||||
|
}
|
||||||
|
h6 {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
</html>
|
76
templates/mails/password_recovery.html
Normal file
76
templates/mails/password_recovery.html
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" href="index.css" />
|
||||||
|
<title>Beyond School</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="container">
|
||||||
|
<form method="post">
|
||||||
|
<h2>Mot de passe oublié ?</h2>
|
||||||
|
<a href="http://localhost:5000/reset/{{code}}">
|
||||||
|
<input type="button" value="connection">
|
||||||
|
</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
body{
|
||||||
|
background: #67BE4B;
|
||||||
|
}
|
||||||
|
#container{
|
||||||
|
width:400px;
|
||||||
|
margin:0 auto;
|
||||||
|
margin-top:10%;
|
||||||
|
}
|
||||||
|
/* Bordered form */
|
||||||
|
form {
|
||||||
|
width:100%;
|
||||||
|
padding: 40px;
|
||||||
|
border: 1px solid #f1f1f1;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
|
||||||
|
}
|
||||||
|
#container h2{
|
||||||
|
width: 38%;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Full-width inputs */
|
||||||
|
input[type=email], input[type=password], input[type=number] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px 20px;
|
||||||
|
margin: 8px 0;
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set a style for all buttons */
|
||||||
|
input[type=submit], input[type=button] {
|
||||||
|
background-color: #53af57;
|
||||||
|
color: white;
|
||||||
|
padding: 14px 20px;
|
||||||
|
margin: 8px 0;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
input[type=submit]:hover {
|
||||||
|
background-color: white;
|
||||||
|
color: #53af57;
|
||||||
|
border: 1px solid #53af57;
|
||||||
|
}
|
||||||
|
h6 {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
</html>
|
83
templates/reset.html
Normal file
83
templates/reset.html
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" href="index.css" />
|
||||||
|
<title>Beyond School</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="container">
|
||||||
|
<form name="signin" method="post">
|
||||||
|
<h2>Connection</h2>
|
||||||
|
<label><b>Email :</b></label>
|
||||||
|
<input type="email" name="email" placeholder={{email}} disabled=true>
|
||||||
|
<br>
|
||||||
|
<label><b>Mot de passe :</b></label>
|
||||||
|
<input type="password" name="password" placeholder="Insérez votre mot de passe" required>
|
||||||
|
<br>
|
||||||
|
<label><b>Mot de passe :</b></label>
|
||||||
|
<input type="password" name="repassword" placeholder="Insérez votre mot de passe" required>
|
||||||
|
<br>
|
||||||
|
<input type="submit" value="Changer de mot de passe">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
body{
|
||||||
|
background: #67BE4B;
|
||||||
|
}
|
||||||
|
#container{
|
||||||
|
width:400px;
|
||||||
|
margin:0 auto;
|
||||||
|
margin-top:10%;
|
||||||
|
}
|
||||||
|
/* Bordered form */
|
||||||
|
form {
|
||||||
|
width:100%;
|
||||||
|
padding: 40px;
|
||||||
|
border: 1px solid #f1f1f1;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
|
||||||
|
}
|
||||||
|
#container h2{
|
||||||
|
width: 38%;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Full-width inputs */
|
||||||
|
input[type=email], input[type=password], input[type=number] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px 20px;
|
||||||
|
margin: 8px 0;
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set a style for all buttons */
|
||||||
|
input[type=submit], input[type=button] {
|
||||||
|
background-color: #53af57;
|
||||||
|
color: white;
|
||||||
|
padding: 14px 20px;
|
||||||
|
margin: 8px 0;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
input[type=submit]:hover {
|
||||||
|
background-color: white;
|
||||||
|
color: #53af57;
|
||||||
|
border: 1px solid #53af57;
|
||||||
|
}
|
||||||
|
h6 {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
color: red
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user