Skip to content
Snippets Groups Projects
Commit e69e8a92 authored by Anton's avatar Anton
Browse files

kompletterat lab4 - added functionality for getting a new password

parent 61c74c74
Branches
No related tags found
No related merge requests found
...@@ -2,15 +2,13 @@ ...@@ -2,15 +2,13 @@
### Instructions ### Instructions
There is 1 folder for each lab. There is 1 folder for each lab.
### Lab 4 ### Lab 4
In lab 4 I did 4 extra things for a total of 10 points: In lab 4 I did 4 extra things for a total of 10 points:
* Providing Live Data Presentation [3 points] * Recover Your Password [2 points (reset by generating new pw)]
- Your messages are received using websocket - you will receive an email with your new password from the gmail klasklatt3rmus123@gmail.com. If you you have gmail you gotta check your spam folder (I tried). Got it in the inbox using other emails :-)
- Also showing number of active users (nr of users connected with web-sockets)
- Nr views on your profile by other users
* Applying Further Security Measures [3 points] * Applying Further Security Measures [3 points]
......
No preview for this file type
...@@ -10,7 +10,21 @@ import json ...@@ -10,7 +10,21 @@ import json
import uuid import uuid
import logging import logging
from flask_mail import Mail, Message
app = Flask(__name__, static_url_path="") app = Flask(__name__, static_url_path="")
app.config.update(dict(
DEBUG = True,
MAIL_SERVER = 'smtp.gmail.com',
MAIL_PORT = 587,
MAIL_USE_TLS = True,
MAIL_USE_SSL = False,
MAIL_USERNAME = 'klasklatt3rmus1234@gmail.com',
MAIL_PASSWORD = 'wallwalla1',
))
mail = Mail(app)
app.logger.setLevel(logging.DEBUG) app.logger.setLevel(logging.DEBUG)
active_sockets = dict() active_sockets = dict()
...@@ -51,6 +65,7 @@ def create_response(success, message, data=None): ...@@ -51,6 +65,7 @@ def create_response(success, message, data=None):
def generate_token(): def generate_token():
return secrets.token_urlsafe(32) return secrets.token_urlsafe(32)
def validate_ws(data): def validate_ws(data):
user_identifier = data["email"] user_identifier = data["email"]
hashed_data = data["hashed_email"] hashed_data = data["hashed_email"]
...@@ -74,6 +89,7 @@ def validate_ws(data): ...@@ -74,6 +89,7 @@ def validate_ws(data):
print("Ws auth failed") print("Ws auth failed")
return False return False
def validate_request(): def validate_request():
data = request.args.to_dict() if request.method == "GET" else request.get_json() data = request.args.to_dict() if request.method == "GET" else request.get_json()
print("DATA", data) print("DATA", data)
...@@ -122,6 +138,36 @@ def root(): ...@@ -122,6 +138,36 @@ def root():
return app.send_static_file("client.html") return app.send_static_file("client.html")
@app.route("/new-password", methods=["GET"])
def new_password():
print("NEW PASSWORD ENDPOINT")
email = request.args.get("email")
if not is_already_user(email):
return create_response(
success=True,
message="If you have an account with this email you will receive a new password on your email shortly.",
)
new_password = generate_token()
hashed_pw = hash_password(new_password)
database_helper.set_password(email, hashed_pw)
msg = Message(
"New password requested",
sender="twidder@info.se",
recipients=[email],
)
msg.body = "Your new password is: " + new_password
mail.send(msg)
return create_response(
success=True,
message="If you have an account with this email you will receive a new password on your email shortly.",
)
@app.route("/sign-in", methods=["POST"]) @app.route("/sign-in", methods=["POST"])
def sign_in(): def sign_in():
data = request.get_json() data = request.get_json()
...@@ -393,7 +439,7 @@ def web_socket(): ...@@ -393,7 +439,7 @@ def web_socket():
return "" return ""
#database_helper.init_db(app) # database_helper.init_db(app)
if __name__ == "__main__": if __name__ == "__main__":
server = pywsgi.WSGIServer(("", 5002), app, handler_class=WebSocketHandler) server = pywsgi.WSGIServer(("", 5002), app, handler_class=WebSocketHandler)
server.serve_forever() server.serve_forever()
...@@ -27,7 +27,7 @@ body { ...@@ -27,7 +27,7 @@ body {
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;
width: 100%; width: 100%;
height: 340px; height: 285px;
border-radius: 10px; border-radius: 10px;
margin-top: 20px; margin-top: 20px;
background-color: #f5f5f5; background-color: #f5f5f5;
......
...@@ -37,6 +37,9 @@ ...@@ -37,6 +37,9 @@
</div> </div>
</div> </div>
</form> </form>
<div class="form-element">
<button onclick="javascript:showForgotPassModal()" value="Forgot password">Forgot password</button>
</div>
</div> </div>
<div class="container-img"></div> <div class="container-img"></div>
</div> </div>
...@@ -96,6 +99,28 @@ ...@@ -96,6 +99,28 @@
</div> </div>
</div> </div>
<!-- Modal for forgot password -->
<div id="modal_forgot_pass" class="modal" >
<div class="modal-content">
<span class="close" id="close_forgot_pass">&times;</span>
<div class="modal-text">
<h3>Forgot password</h3>
<form id="forgot-pass-form" action="javascript:handleNewPassword()">
<div class="form-container">
<div class="form-element">
<input type="email" name="email" placeholder="Email" required>
</div>
<div class="form-element">
<button type="submit" value="New password">Get new password</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div> </div>
</script> </script>
...@@ -103,7 +128,7 @@ ...@@ -103,7 +128,7 @@
<!-- Profile view --> <!-- Profile view -->
<script id="profile-view" type="text/view"> <script id="profile-view" type="text/view">
<div class="form"> <div class="form">
<!-- Navigation tabs --> <!-- Navigation tabs -->
......
...@@ -220,6 +220,7 @@ function loadWelcomeView() { ...@@ -220,6 +220,7 @@ function loadWelcomeView() {
let welcomeView = document.getElementById("welcome-view"); let welcomeView = document.getElementById("welcome-view");
app.innerHTML = welcomeView.innerHTML; app.innerHTML = welcomeView.innerHTML;
loadModal(); loadModal();
loadForgotPassModal();
} }
function showModal(msg) { function showModal(msg) {
...@@ -229,8 +230,30 @@ function showModal(msg) { ...@@ -229,8 +230,30 @@ function showModal(msg) {
errorMessage.innerHTML = msg; errorMessage.innerHTML = msg;
} }
function showForgotPassModal() {
let modal = document.getElementById("modal_forgot_pass");
modal.style.display = "flex";
}
function loadForgotPassModal() {
let modal_forgot_pass = document.getElementById("modal_forgot_pass");
let span = document.getElementById("close_forgot_pass");
span.onclick = function () {
modal_forgot_pass.style.display = "none";
};
// When the user clicks anywhere outside of the password modal, close it
window.onclick = function (event) {
if (event.target == modal_forgot_pass) {
modal_forgot_pass.style.display = "none";
}
};
}
function loadModal() { function loadModal() {
let modal = document.getElementById("modal"); let modal = document.getElementById("modal");
let span = document.getElementsByClassName("close")[0]; let span = document.getElementsByClassName("close")[0];
span.onclick = function () { span.onclick = function () {
modal.style.display = "none"; modal.style.display = "none";
...@@ -271,6 +294,23 @@ function signIn(email, password) { ...@@ -271,6 +294,23 @@ function signIn(email, password) {
xmlRequest("/sign-in", myCallback, params, null, "POST"); xmlRequest("/sign-in", myCallback, params, null, "POST");
} }
function handleNewPassword() {
let email = document.forms["forgot-pass-form"]["email"].value;
let params = {
email: email,
};
let myCallback = function (res) {
modal_forgot_pass = document.getElementById("modal_forgot_pass");
modal_forgot_pass.style.display = "none";
showModal(res.message);
};
xmlRequest("/new-password", myCallback, params, null, "GET");
}
function validatePassword(pw, pw2) { function validatePassword(pw, pw2) {
if (pw.length < 5) { if (pw.length < 5) {
let msg = "Password must be at least 5 characters"; let msg = "Password must be at least 5 characters";
...@@ -394,7 +434,7 @@ function signOut() { ...@@ -394,7 +434,7 @@ function signOut() {
window.localStorage.removeItem("token"); window.localStorage.removeItem("token");
window.localStorage.removeItem("email"); window.localStorage.removeItem("email");
displayView(); displayView();
} }
}; };
user_identifier = localStorage.getItem("email"); user_identifier = localStorage.getItem("email");
...@@ -450,7 +490,7 @@ function xmlRequest(url, callback, params, token = null, requestType) { ...@@ -450,7 +490,7 @@ function xmlRequest(url, callback, params, token = null, requestType) {
window.localStorage.removeItem("token"); window.localStorage.removeItem("token");
window.localStorage.removeItem("email"); window.localStorage.removeItem("email");
displayView(); displayView();
showModal("Authentication failed. You must sign in again") showModal("Authentication failed. You must sign in again");
} }
} }
}; };
...@@ -485,12 +525,12 @@ function connectWebSocket() { ...@@ -485,12 +525,12 @@ function connectWebSocket() {
ws.onopen = function () { ws.onopen = function () {
let email = localStorage.getItem("email"); let email = localStorage.getItem("email");
let token = localStorage.getItem("token"); let token = localStorage.getItem("token");
hashed_email = CryptoJS.SHA512(email + token).toString(CryptoJS.enc.Hex);; hashed_email = CryptoJS.SHA512(email + token).toString(CryptoJS.enc.Hex);
let userData = { email: email, hashed_email: hashed_email}; let userData = { email: email, hashed_email: hashed_email };
ws.send(JSON.stringify(userData)); ws.send(JSON.stringify(userData));
console.log("Web socket opened"); console.log("Web socket opened");
// ping neccessary when using Heroku because of defualt timout on idle connections // ping neccessary when using Heroku because of defualt timout on idle connections
let clock = setInterval(function () { let clock = setInterval(function () {
console.log("Ping server"); console.log("Ping server");
ws.send("ping"); ws.send("ping");
...@@ -498,9 +538,8 @@ function connectWebSocket() { ...@@ -498,9 +538,8 @@ function connectWebSocket() {
ws.onclose = function () { ws.onclose = function () {
console.log("Web socket closed"); console.log("Web socket closed");
clearInterval(clock) clearInterval(clock);
}; };
}; };
ws.onmessage = function (res) { ws.onmessage = function (res) {
...@@ -534,8 +573,8 @@ function setLocation() { ...@@ -534,8 +573,8 @@ function setLocation() {
async function onSuccess(position) { async function onSuccess(position) {
const geocode = await fetch( const geocode = await fetch(
`https://geocode.xyz/${position.coords.latitude},${position.coords.longitude}?json=1?` `https://geocode.xyz/${position.coords.latitude},${position.coords.longitude}?json=1?`
); );
if (geocode.status == "200") { if (geocode.status == "200") {
console.log("Successfulyy fetched location from geocode.xyz"); console.log("Successfulyy fetched location from geocode.xyz");
const geoResponse = await geocode.json(); const geoResponse = await geocode.json();
localStorage.setItem( localStorage.setItem(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment