add account deletion and password changing
This commit is contained in:
parent
902e561a09
commit
22c337f8aa
8 changed files with 179 additions and 36 deletions
|
@ -5,4 +5,4 @@ it's like pronouns.page but i made it
|
|||
|
||||
### todo
|
||||
* social links
|
||||
* sexuality/gender flags
|
||||
* templating and embeds on /u/... pages
|
||||
|
|
71
_server.py
71
_server.py
|
@ -135,39 +135,39 @@ def api_account_login():
|
|||
|
||||
for i in username:
|
||||
if i not in "abcdefghijklmnopqrstuvwxyz0123456789_-":
|
||||
return return_dynamic_content_type(json.dumps({
|
||||
return {
|
||||
"valid": False,
|
||||
"reason": "User doesn't exist."
|
||||
}), "application/json")
|
||||
}
|
||||
|
||||
try:
|
||||
open(f"{SAVING_DIRECTORY}{username}.json", "r")
|
||||
except FileNotFoundError:
|
||||
return return_dynamic_content_type(json.dumps({
|
||||
return {
|
||||
"valid": False,
|
||||
"reason": "User doesn't exist."
|
||||
}), "application/json")
|
||||
}
|
||||
|
||||
token = generate_token(username, passhash)
|
||||
|
||||
try:
|
||||
enforced_username = open(f"{SAVING_DIRECTORY}tokens/{token}.txt", "r").read()
|
||||
except FileNotFoundError:
|
||||
return return_dynamic_content_type(json.dumps({
|
||||
return {
|
||||
"valid": False,
|
||||
"reason": "Invalid password"
|
||||
}), "application/json")
|
||||
}
|
||||
|
||||
if enforced_username != username:
|
||||
return return_dynamic_content_type(json.dumps({
|
||||
return {
|
||||
"valid": False,
|
||||
"reason": "Invalid password"
|
||||
}), "application/json")
|
||||
}
|
||||
|
||||
return return_dynamic_content_type(json.dumps({
|
||||
return {
|
||||
"valid": True,
|
||||
"token": token
|
||||
}), "application/json")
|
||||
}
|
||||
|
||||
def api_account_signup():
|
||||
try:
|
||||
|
@ -191,17 +191,17 @@ def api_account_signup():
|
|||
|
||||
for i in username:
|
||||
if i not in "abcdefghijklmnopqrstuvwxyz0123456789_-":
|
||||
return return_dynamic_content_type(json.dumps({
|
||||
return {
|
||||
"valid": False,
|
||||
"reason": "Username can only contain a-z, 0-9, underscores, and hyphens."
|
||||
}), "application/json")
|
||||
}
|
||||
|
||||
try:
|
||||
open(f"{SAVING_DIRECTORY}{username}.json", "r")
|
||||
return return_dynamic_content_type(json.dumps({
|
||||
return {
|
||||
"valid": False,
|
||||
"reason": "Username taken."
|
||||
}), "application/json")
|
||||
}
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
|
@ -280,6 +280,40 @@ def api_account_self():
|
|||
except FileNotFoundError:
|
||||
flask.abort(404)
|
||||
|
||||
def api_account_change():
|
||||
username = open(f'{SAVING_DIRECTORY}tokens/{request.cookies["token"]}.txt', 'r').read()
|
||||
x = json.loads(request.data)
|
||||
|
||||
if generate_token(username, x["current"]) != request.cookies["token"]:
|
||||
flask.abort(401)
|
||||
|
||||
new = generate_token(username, x["new"])
|
||||
os.rename(f'{SAVING_DIRECTORY}tokens/{request.cookies["token"]}.txt', f'{SAVING_DIRECTORY}tokens/{new}.txt')
|
||||
|
||||
return {
|
||||
"token": new
|
||||
}
|
||||
|
||||
def api_account_delete():
|
||||
username = open(f'{SAVING_DIRECTORY}tokens/{request.cookies["token"]}.txt', 'r').read()
|
||||
x = json.loads(request.data)
|
||||
|
||||
token = generate_token(username, x["passhash"])
|
||||
if generate_token(username, x["passhash"]) != request.cookies["token"]:
|
||||
flask.abort(401)
|
||||
|
||||
os.remove(f"{SAVING_DIRECTORY}tokens/{token}.txt")
|
||||
os.remove(f"{SAVING_DIRECTORY}{username}.json")
|
||||
|
||||
f = json.loads(open(f"{SAVING_DIRECTORY}public/list.json", "r").read())
|
||||
if username in f:
|
||||
f.remove(username)
|
||||
g = open(f"{SAVING_DIRECTORY}public/list.json", "w")
|
||||
g.write(json.dumps(f))
|
||||
g.close()
|
||||
|
||||
return "200 OK"
|
||||
|
||||
def api_save():
|
||||
username = open(f'{SAVING_DIRECTORY}tokens/{request.cookies["token"]}.txt', 'r').read()
|
||||
x = json.loads(request.data)
|
||||
|
@ -357,9 +391,9 @@ def api_save():
|
|||
return "200 OK"
|
||||
|
||||
def api_browse():
|
||||
return return_dynamic_content_type(
|
||||
json.dumps(list_public(request.args.get("sort"), int(request.args.get("page")) if "page" in request.args else 0)),
|
||||
"application/json"
|
||||
return list_public(
|
||||
request.args.get("sort"), # type: ignore
|
||||
int(request.args.get("page")) if "page" in request.args else 0 # type: ignore
|
||||
)
|
||||
|
||||
def home():
|
||||
|
@ -399,6 +433,7 @@ app.route("/login")(create_file_serve("login.html"))
|
|||
app.route("/signup")(create_file_serve("signup.html"))
|
||||
app.route("/logout")(create_file_serve("logout.html"))
|
||||
app.route("/browse")(create_file_serve("browse.html"))
|
||||
app.route("/settings")(create_file_serve("settings.html"))
|
||||
|
||||
app.route("/editor")(create_file_serve("editor.html"))
|
||||
app.route("/u/<path:property>")(create_file_serve("user.html"))
|
||||
|
@ -411,6 +446,8 @@ app.route("/api/account/login", methods=["POST"])(api_account_login)
|
|||
app.route("/api/account/signup", methods=["POST"])(api_account_signup)
|
||||
app.route("/api/account/info/<path:user>", methods=["GET"])(api_account_info_)
|
||||
app.route("/api/account/self", methods=["GET"])(api_account_self)
|
||||
app.route("/api/account/change", methods=["POST"])(api_account_change)
|
||||
app.route("/api/account/delete", methods=["DELETE"])(api_account_delete)
|
||||
app.route("/api/save", methods=["PATCH"])(api_save)
|
||||
app.route("/api/browse", methods=["GET"])(api_browse)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.home-container {
|
||||
width: 20em;
|
||||
padding: 10px 0;
|
||||
margin: 0 auto;
|
||||
margin: 10px auto;
|
||||
border: 2px var(--secondary) solid;
|
||||
padding: 6px;
|
||||
border-radius: 4px;
|
||||
|
|
|
@ -14,6 +14,5 @@
|
|||
|
||||
<body>
|
||||
<script async src="/js/editor.js"></script>
|
||||
<a href="/logout">Log Out</a>
|
||||
</body>
|
||||
</html>
|
|
@ -42,6 +42,14 @@
|
|||
Shortened url:<br>
|
||||
https://infopg.web.app/u/{{USERNAME}}
|
||||
</div>
|
||||
<div tabindex="5" onclick="window.location.href = '/logout'" class="home-container">
|
||||
<p>Log out</p>
|
||||
You can always log back in
|
||||
</div>
|
||||
<div tabindex="6" onclick="window.location.href = '/settings'" class="home-container">
|
||||
<p>User Settings</p>
|
||||
Change password, delete acc, etc.
|
||||
</div>
|
||||
|
||||
<script>
|
||||
[...document.querySelectorAll("[onclick][tabindex]")].forEach(function(val, index) {
|
||||
|
|
68
public/js/settings.js
Normal file
68
public/js/settings.js
Normal file
|
@ -0,0 +1,68 @@
|
|||
|
||||
let c = 0;
|
||||
|
||||
function log(str) {
|
||||
c++;
|
||||
document.getElementById("log").innerText = str;
|
||||
setTimeout(
|
||||
function() {
|
||||
--c;
|
||||
if (!c) {
|
||||
document.getElementById("log").innerText = " ";
|
||||
}
|
||||
}, 3000
|
||||
);
|
||||
}
|
||||
|
||||
dom("submit").addEventListener("click", function() {
|
||||
let current = sha256(dom("current").value);
|
||||
let newPass = sha256(dom("new").value);
|
||||
let verify = sha256(dom("verify").value);
|
||||
|
||||
if (newPass == verify && newPass && dom("new").value) {
|
||||
fetch("/api/account/change", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
current: current,
|
||||
new: newPass
|
||||
})
|
||||
}).then(response => {
|
||||
if (response.status == 200) {
|
||||
log("Success! Password has been changed! You will need to log in on any other devices again.");
|
||||
response.json().then(json => {
|
||||
localStorage.setItem("token", json.token);
|
||||
setCookie("token", json.token);
|
||||
});
|
||||
dom("current").value = "";
|
||||
} else if (response.status == 401) {
|
||||
log("Your current password is incorrect!");
|
||||
} else {
|
||||
log("Something went wrong! Try again later.");
|
||||
}
|
||||
})
|
||||
} else {
|
||||
log("Your passwords don't match!");
|
||||
}
|
||||
});
|
||||
|
||||
dom("delete").addEventListener("click", function() {
|
||||
if (confirm("Are you 100% SURE you want to PERMANENTLY DELETE your account?")) {
|
||||
let x = prompt("By typing in your password below to confirm your identity, you acknowledge that this action is 100% IRREVERSIBLE.");
|
||||
if (x) {
|
||||
fetch("/api/account/delete", {
|
||||
method: "DELETE",
|
||||
body: JSON.stringify({
|
||||
passhash: sha256(x)
|
||||
})
|
||||
}).then(response => {
|
||||
if (response.status == 200) {
|
||||
window.location.href = "/logout";
|
||||
} else if (response.status == 401) {
|
||||
log("Wrong password!");
|
||||
} else {
|
||||
log("Something went wrong! Try again later.")
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
|
@ -29,11 +29,6 @@ dom("submit").addEventListener("click", function() {
|
|||
})
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status == 429) {
|
||||
dom("post").removeAttribute("disabled");
|
||||
dom("post-text").removeAttribute("disabled");
|
||||
showlog("You are being ratelimited! Try again in a few moments...");
|
||||
} else {
|
||||
response.json().then((json) => {
|
||||
if (json.valid) {
|
||||
setCookie("token", json.token);
|
||||
|
@ -44,7 +39,6 @@ dom("submit").addEventListener("click", function() {
|
|||
showlog(`Unable to create account! Reason: ${json.reason}`);
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
dom("submit").removeAttribute("disabled");
|
||||
|
|
37
public/settings.html
Normal file
37
public/settings.html
Normal file
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Home - InfoPage</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<link rel="stylesheet" href="/css/base.css">
|
||||
<script src="/js/base.js"></script>
|
||||
|
||||
<script>
|
||||
if (localStorage.getItem("token")) {
|
||||
setCookie("token", localStorage.getItem("token"));
|
||||
} else {
|
||||
window.location.href = "/logout";
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Settings</h1>
|
||||
<h2>Password change</h2>
|
||||
<input id="current" type="password" placeholder="Current password..."><br>
|
||||
<input id="new" type="password" placeholder="New password..."><br>
|
||||
<input id="verify" type="password" placeholder="Verify password..."><br>
|
||||
<button id="submit">Submit</button>
|
||||
|
||||
<p id="log"></p>
|
||||
|
||||
<h2>Delete account</h2>
|
||||
<button id="delete">Delete account</button><br><br>
|
||||
|
||||
<a href="/home">Return home</a>
|
||||
|
||||
<script src="/js/settings.js"></script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue