summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--public/style.css9
-rw-r--r--server.js229
-rw-r--r--views/account_change_about.pug (renamed from views/change_about.pug)2
-rw-r--r--views/account_change_mail.pug (renamed from views/change_mail.pug)6
-rw-r--r--views/account_change_name.pug (renamed from views/change_name.pug)6
-rw-r--r--views/account_change_password.pug (renamed from views/change_password.pug)2
-rw-r--r--views/account_delete.pug (renamed from views/delete_account.pug)2
-rw-r--r--views/account_forgot_password.pug (renamed from views/forgot_password.pug)2
-rw-r--r--views/account_mail_verify.pug32
-rw-r--r--views/account_reset_password.pug (renamed from views/reset_password.pug)2
-rw-r--r--views/account_webhook.pug (renamed from views/webhook.pug)4
-rw-r--r--views/contacts_search.pug (renamed from views/search_user.pug)0
-rw-r--r--views/create_index.pug (renamed from views/create-index.pug)0
-rw-r--r--views/create_title.pug (renamed from views/create.pug)0
-rw-r--r--views/head.pug33
-rw-r--r--views/login.pug4
-rw-r--r--views/profile.pug65
-rw-r--r--views/signup.pug2
-rw-r--r--views/stats_title.pug (renamed from views/game_stats.pug)2
-rw-r--r--views/stats_user.pug (renamed from views/user_stats.pug)0
-rw-r--r--views/title.pug (renamed from views/info.pug)0
-rw-r--r--views/tm_seed.pug6
-rw-r--r--views/user.pug34
-rw-r--r--views/verify_mail.pug21
24 files changed, 255 insertions, 208 deletions
diff --git a/public/style.css b/public/style.css
index bbbcbbd..7c0c07b 100644
--- a/public/style.css
+++ b/public/style.css
@@ -226,6 +226,15 @@ div.logo img {
border: var(--thin-border);
}
+p.box {
+ white-space: pre-wrap;
+ font-style: italic;
+ padding: 8px 12px;
+ border: var(--thin-border);
+ box-shadow: var(--drop-shadow);
+ background-color: var(--color-text);
+}
+
/* TABLES */
table {
diff --git a/server.js b/server.js
index 7165a9b..9ba77f2 100644
--- a/server.js
+++ b/server.js
@@ -340,6 +340,12 @@ function format_minutes(mins) {
return mins + " minutes"
}
+function is_valid_password(password) {
+ if (password.length < 4 || password.length > 100)
+ return false
+ return true
+}
+
function is_valid_email(email) {
return REGEX_MAIL.test(email)
}
@@ -372,6 +378,14 @@ function hash_password(password, salt) {
return hash.digest("hex")
}
+function verify_password(user, password) {
+ var user_login = SQL_SELECT_LOGIN.get(user.user_id)
+ var hash = hash_password(password, user_login.salt)
+ if (hash !== user_login.password)
+ return false
+ return true
+}
+
/*
* ALTCHA ANTI-BOT SIGNUP
*/
@@ -462,6 +476,7 @@ const SQL_SELECT_USER_DYNAMIC = SQL("select * from user_dynamic_view where user_
const SQL_SELECT_USER_ID = SQL("SELECT user_id FROM users WHERE name=?").pluck()
const SQL_SELECT_USER_BY_SEARCH = SQL("select name, atime from users left join user_last_seen using(user_id) where name like ? order by name")
+const SQL_SELECT_USER_ABOUT = SQL("SELECT about FROM user_about WHERE user_id=?").pluck()
const SQL_SELECT_USER_NOTIFY = SQL("SELECT notify FROM users WHERE user_id=?").pluck()
const SQL_SELECT_USER_VERIFIED = SQL("SELECT is_verified FROM users WHERE user_id=?").pluck()
const SQL_UPDATE_USER_NOTIFY = SQL("UPDATE users SET notify=? WHERE user_id=?")
@@ -495,7 +510,7 @@ app.use(function (req, res, next) {
let user_id = login_sql_select.get(sid)
if (user_id) {
login_touch(res, sid)
- req.user = SQL_SELECT_USER_DYNAMIC.get(user_id)
+ req.user = res.locals.user = SQL_SELECT_USER_DYNAMIC.get(user_id)
SQL_UPDATE_USER_LAST_SEEN.run(user_id, ip)
if (req.user.is_banned)
return res.status(403).send("")
@@ -524,15 +539,15 @@ function must_be_administrator(req, res, next) {
}
app.get("/", function (req, res) {
- res.render("index.pug", { user: req.user })
+ res.render("index.pug")
})
app.get("/create", function (req, res) {
- res.render("create-index.pug", { user: req.user })
+ res.render("create_index.pug")
})
app.get("/about", function (req, res) {
- res.render("about.pug", { user: req.user })
+ res.render("about.pug")
})
app.post("/logout", function (req, res) {
@@ -599,89 +614,67 @@ app.post("/signup", must_pass_altcha, function (req, res) {
res.redirect("/profile")
})
-function create_and_mail_verification_token(user) {
- if (!SQL_FIND_TOKEN.get(user.user_id))
- mail_verification_token(user, SQL_CREATE_TOKEN.get(user.user_id))
-}
-
-app.get("/verify-mail", must_be_logged_in, function (req, res) {
+app.get("/account/mail/verify", must_be_logged_in, function (req, res) {
if (SQL_SELECT_USER_VERIFIED.get(req.user.user_id))
return res.redirect("/profile")
- create_and_mail_verification_token(req.user)
- res.render("verify_mail.pug", { user: req.user })
+ var sent_token = SQL_FIND_TOKEN.get(req.user.user_id)
+ var input_token = req.query.token
+ res.render("account_mail_verify.pug", { input_token, sent_token })
})
-app.get("/verify-mail/:token", must_be_logged_in, function (req, res) {
- if (SQL_SELECT_USER_VERIFIED.get(req.user.user_id))
- return res.redirect("/profile")
- res.render("verify_mail.pug", { user: req.user, token: req.params.token })
+app.post("/account/mail/verify-send", must_be_logged_in, function (req, res) {
+ if (!SQL_FIND_TOKEN.get(req.user.user_id))
+ mail_verification_token(req.user, SQL_CREATE_TOKEN.get(req.user.user_id))
+ res.redirect("/account/mail/verify")
})
-app.post("/verify-mail", must_be_logged_in, function (req, res) {
+app.post("/account/mail/verify", must_be_logged_in, function (req, res) {
if (SQL_VERIFY_TOKEN.get(req.user.user_id, req.body.token)) {
SQL_UPDATE_USER_VERIFIED.run(1, req.user.user_id)
res.redirect("/profile")
} else {
- create_and_mail_verification_token(req.user)
- res.render("verify_mail.pug", { user: req.user, flash: "Invalid or expired token!" })
+ var sent_token = SQL_FIND_TOKEN.get(req.user.user_id)
+ res.render("account_mail_verify.pug", { sent_token, flash: "Invalid or expired token!" })
}
})
-app.get("/forgot-password", function (req, res) {
+app.get("/account/forgot-password", function (req, res) {
if (req.user)
return res.redirect("/")
- res.render("forgot_password.pug")
+ res.render("account_forgot_password.pug")
})
-app.post("/forgot-password", must_pass_altcha, function (req, res) {
+app.post("/account/forgot-password", must_pass_altcha, function (req, res) {
let mail = req.body.mail
let user = SQL_SELECT_LOGIN_BY_MAIL.get(mail)
if (user) {
- let token = SQL_FIND_TOKEN.get(user.user_id)
- if (!token) {
- token = SQL_CREATE_TOKEN.get(user.user_id)
- mail_password_reset_token(user, token)
- }
- return res.redirect("/reset-password/" + mail)
+ var token = SQL_CREATE_TOKEN.get(user.user_id)
+ mail_password_reset_token(user, token)
+ return res.redirect("/account/reset-password?mail=" + mail)
}
- res.render("forgot_password.pug", { flash: "User not found." })
+ res.render("account_forgot_password.pug", { flash: "User not found." })
})
-app.get("/reset-password", function (req, res) {
+app.get("/account/reset-password", function (req, res) {
if (req.user)
return res.redirect("/")
- res.render("reset_password.pug", { mail: "", token: "" })
+ var mail = req.query.mail
+ var token = req.query.token
+ res.render("account_reset_password.pug", { mail, token })
})
-app.get("/reset-password/:mail", function (req, res) {
- if (req.user)
- return res.redirect("/")
- let mail = req.params.mail
- res.render("reset_password.pug", { mail: mail, token: "" })
-})
-
-app.get("/reset-password/:mail/:token", function (req, res) {
- if (req.user)
- return res.redirect("/")
- let mail = req.params.mail
- let token = req.params.token
- res.render("reset_password.pug", { mail: mail, token: token })
-})
-
-app.post("/reset-password", must_pass_altcha, function (req, res) {
+app.post("/account/reset-password", must_pass_altcha, function (req, res) {
let mail = req.body.mail
let token = req.body.token
let password = req.body.password
function err(msg) {
- res.render("reset_password.pug", { mail: mail, token: token, flash: msg })
+ res.render("account_reset_password.pug", { mail: mail, token: token, flash: msg })
}
let user = SQL_SELECT_LOGIN_BY_MAIL.get(mail)
if (!user)
return err("User not found.")
- if (password.length < 4)
- return err("Password is too short!")
- if (password.length > 100)
- return err("Password is too long!")
+ if (!is_valid_password(password))
+ return err("New password is invalid!")
if (!SQL_VERIFY_TOKEN.get(user.user_id, token))
return err("Invalid or expired token!")
let salt = crypto.randomBytes(32).toString("hex")
@@ -692,22 +685,19 @@ app.post("/reset-password", must_pass_altcha, function (req, res) {
return res.redirect("/profile")
})
-app.get("/change-password", must_be_logged_in, function (req, res) {
- res.render("change_password.pug", { user: req.user })
+app.get("/account/change-password", must_be_logged_in, function (req, res) {
+ res.render("account_change_password.pug")
})
-app.post("/change-password", must_be_logged_in, function (req, res) {
+app.post("/account/change-password", must_be_logged_in, function (req, res) {
let oldpass = req.body.password
let newpass = req.body.newpass
// Get full user record including password and salt
let user = SQL_SELECT_LOGIN.get(req.user.user_id)
- if (newpass.length < 4)
- return res.render("change_password.pug", { user: req.user, flash: "Password is too short!" })
- if (newpass.length > 100)
- return res.render("change_password.pug", { user: req.user, flash: "Password is too long!" })
- let oldhash = hash_password(oldpass, user.salt)
- if (oldhash !== user.password)
- return res.render("change_password.pug", { user: req.user, flash: "Wrong password!" })
+ if (!is_valid_password(newpass))
+ return res.render("account_change_password.pug", { flash: "New password is invalid!" })
+ if (!verify_password(req.user, oldpass))
+ return res.render("account_change_password.pug", { flash: "Wrong password!" })
let salt = crypto.randomBytes(32).toString("hex")
let hash = hash_password(newpass, salt)
SQL_UPDATE_USER_PASSWORD.run(user.user_id, hash, salt)
@@ -726,17 +716,17 @@ function may_delete_account(user_id) {
return true
}
-app.get("/delete-account", must_be_logged_in, function (req, res) {
+app.get("/account/delete", must_be_logged_in, function (req, res) {
if (!may_delete_account(req.user.user_id))
return res.status(401).send("You may not delete your account while you have unfinished games.")
- res.render("delete_account.pug", { user: req.user })
+ res.render("account_delete.pug")
})
const SQL_SELECT_GAME_ROLE_FOR_DELETED_USER = SQL(`
select game_id, role from players where user_id = ? and game_id in (select game_id from games where status <= 1)
`)
-app.post("/delete-account", must_be_logged_in, function (req, res) {
+app.post("/account/delete", must_be_logged_in, function (req, res) {
if (!may_delete_account(req.user.user_id))
res.status(401).send("You may not delete your account while you have unfinished games.")
@@ -745,7 +735,7 @@ app.post("/delete-account", must_be_logged_in, function (req, res) {
let user = SQL_SELECT_LOGIN.get(req.user.user_id)
let hash = hash_password(password, user.salt)
if (hash !== user.password)
- return res.render("delete_account.pug", { user: req.user, flash: "Wrong password!" })
+ return res.render("account_delete.pug", { flash: "Wrong password!" })
let list = SQL_SELECT_GAME_ROLE_FOR_DELETED_USER.all(req.user.user_id)
for (let item of list)
@@ -771,27 +761,27 @@ app.get("/admin/unban-user/:who", must_be_administrator, function (req, res) {
* USER PROFILE
*/
-app.get("/subscribe", must_be_logged_in, function (req, res) {
+app.get("/account/mail/subscribe", must_be_logged_in, function (req, res) {
SQL_UPDATE_USER_NOTIFY.run(1, req.user.user_id)
res.redirect("/profile")
})
-app.get("/unsubscribe", must_be_logged_in, function (req, res) {
+app.get("/account/mail/unsubscribe", must_be_logged_in, function (req, res) {
SQL_UPDATE_USER_NOTIFY.run(0, req.user.user_id)
res.redirect("/profile")
})
-app.get("/webhook", must_be_logged_in, function (req, res) {
+app.get("/account/webhook", must_be_logged_in, function (req, res) {
let webhook = SQL_SELECT_WEBHOOK.get(req.user.user_id)
- res.render("webhook.pug", { user: req.user, webhook: webhook })
+ res.render("account_webhook.pug", { webhook: webhook })
})
-app.post("/api/webhook/delete", must_be_logged_in, function (req, res) {
+app.post("/account/webhook/delete", must_be_logged_in, function (req, res) {
SQL_DELETE_WEBHOOK.run(req.user.user_id)
- res.redirect("/webhook")
+ res.redirect("/account/webhook")
})
-app.post("/api/webhook/update", must_be_logged_in, function (req, res) {
+app.post("/account/webhook/update", must_be_logged_in, function (req, res) {
let url = req.body.url
let prefix = req.body.prefix
let format = req.body.format
@@ -799,45 +789,50 @@ app.post("/api/webhook/update", must_be_logged_in, function (req, res) {
const webhook = SQL_SELECT_WEBHOOK_SEND.get(req.user.user_id)
if (webhook)
send_webhook(req.user.user_id, webhook, "Test message!", 0)
- res.setHeader("refresh", "3; url=/webhook")
+ res.setHeader("refresh", "3; url=/account/webhook")
res.send("Testing Webhook. Please wait...")
})
-app.get("/change-name", must_be_logged_in, function (req, res) {
- res.render("change_name.pug", { user: req.user })
+app.get("/account/change-name", must_be_logged_in, function (req, res) {
+ res.render("account_change_name.pug")
})
-app.post("/change-name", must_be_logged_in, function (req, res) {
+app.post("/account/change-name", must_be_logged_in, function (req, res) {
let newname = clean_user_name(req.body.newname)
if (!is_valid_user_name(newname))
- return res.render("change_name.pug", { user: req.user, flash: "Invalid user name!" })
+ return res.render("account_change_name.pug", { flash: "Invalid user name!" })
if (SQL_EXISTS_USER_NAME.get(newname))
- return res.render("change_name.pug", { user: req.user, flash: "That name is already taken!" })
+ return res.render("account_change_name.pug", { flash: "That name is already taken!" })
+ if (!verify_password(req.user, req.body.password))
+ return res.render("account_change_name.pug", { flash: "Wrong password!" })
SQL_UPDATE_USER_NAME.run(newname, req.user.user_id)
return res.redirect("/profile")
})
-app.get("/change-mail", must_be_logged_in, function (req, res) {
- res.render("change_mail.pug", { user: req.user })
+app.get("/account/change-mail", must_be_logged_in, function (req, res) {
+ res.render("account_change_mail.pug")
})
-app.post("/change-mail", must_be_logged_in, function (req, res) {
+app.post("/account/change-mail", must_be_logged_in, function (req, res) {
let newmail = req.body.newmail
if (!is_valid_email(newmail) || is_forbidden_mail(newmail))
- return res.render("change_mail.pug", { user: req.user, flash: "Invalid mail address!" })
+ return res.render("account_change_mail.pug", { flash: "Invalid mail address!" })
if (SQL_EXISTS_USER_MAIL.get(newmail))
- return res.render("change_mail.pug", { user: req.user, flash: "That mail address is already taken!" })
+ return res.render("account_change_mail.pug", { flash: "That mail address is already taken!" })
+ if (!verify_password(req.user, req.body.password))
+ return res.render("account_change_mail.pug", { flash: "Wrong password!" })
SQL_UPDATE_USER_MAIL.run(newmail, req.user.user_id)
SQL_UPDATE_USER_VERIFIED.run(0, req.user.user_id)
+ SQL_UPDATE_USER_NOTIFY.run(0, req.user.user_id)
return res.redirect("/profile")
})
-app.get("/change-about", must_be_logged_in, function (req, res) {
- let about = SQL_SELECT_USER_PROFILE.get(req.user.name).about
- res.render("change_about.pug", { user: req.user, about: about || "" })
+app.get("/account/change-about", must_be_logged_in, function (req, res) {
+ let about = SQL_SELECT_USER_ABOUT.get(req.user.user_id)
+ res.render("account_change_about.pug", { about })
})
-app.post("/change-about", must_be_logged_in, function (req, res) {
+app.post("/account/change-about", must_be_logged_in, function (req, res) {
SQL_UPDATE_USER_ABOUT.run(req.user.user_id, req.body.about)
return res.redirect("/profile")
})
@@ -916,13 +911,13 @@ app.get("/contacts/search", must_be_logged_in, function (req, res) {
if (!q.includes("%"))
q = "%" + q + "%"
let results = SQL_SELECT_USER_BY_SEARCH.all(q)
- res.render("search_user.pug", {
+ res.render("contacts_search.pug", {
user: req.user,
search: req.query.q,
results
})
} else {
- res.render("search_user.pug", {
+ res.render("contacts_search.pug", {
user: req.user,
search: null,
results: null,
@@ -1255,7 +1250,7 @@ app.get("/forum/search", must_be_logged_in, function (req, res) {
results = FORUM_SEARCH.all('"' + search.replaceAll('"', '""') + '"')
}
}
- res.render("forum_search.pug", { user: req.user, search, results })
+ res.render("forum_search.pug", { search, results })
})
/*
@@ -1694,10 +1689,14 @@ function annotate_games(list, user_id, unread, unseen) {
}
app.get("/profile", must_be_logged_in, function (req, res) {
- req.user.notify = SQL_SELECT_USER_NOTIFY.get(req.user.user_id)
- req.user.is_verified = SQL_SELECT_USER_VERIFIED.get(req.user.user_id)
- req.user.webhook = SQL_SELECT_WEBHOOK.get(req.user.user_id)
- res.render("profile.pug", { user: req.user })
+ var who = SQL_SELECT_USER_PROFILE.get(req.user.name)
+ var mail = {
+ notify: SQL_SELECT_USER_NOTIFY.get(req.user.user_id),
+ is_verified: SQL_SELECT_USER_VERIFIED.get(req.user.user_id)
+ }
+ var webhook = SQL_SELECT_WEBHOOK.get(req.user.user_id)
+ var ratings = SQL_USER_RATINGS.all(req.user.user_id)
+ res.render("profile.pug", { who, mail, webhook, ratings })
})
app.get("/games", function (_req, res) {
@@ -1725,7 +1724,7 @@ app.get("/games/active", must_be_logged_in, function (req, res) {
let active_pools = TM_POOL_LIST_USER_ACTIVE.all(user_id)
let finished_pools = TM_POOL_LIST_USER_RECENT_FINISHED.all(user_id)
- res.render("games_active.pug", { user: req.user, who: req.user, games, seeds, active_pools, finished_pools })
+ res.render("games_active.pug", { who: req.user, games, seeds, active_pools, finished_pools })
})
app.get("/tm/active", must_be_logged_in, function (req, res) {
@@ -1733,7 +1732,7 @@ app.get("/tm/active", must_be_logged_in, function (req, res) {
let seeds = TM_SEED_LIST_USER.all(user_id)
let active_pools = TM_POOL_LIST_USER_ACTIVE.all(user_id)
let finished_pools = TM_POOL_LIST_USER_RECENT_FINISHED.all(user_id)
- res.render("tm_active.pug", { user: req.user, who: req.user, seeds, active_pools, finished_pools })
+ res.render("tm_active.pug", { who: req.user, seeds, active_pools, finished_pools })
})
app.get("/games/finished", must_be_logged_in, function (req, res) {
@@ -1741,12 +1740,12 @@ app.get("/games/finished", must_be_logged_in, function (req, res) {
let unread = SQL_SELECT_UNREAD_CHAT_GAMES.all(req.user.user_id)
let unseen = SQL_SELECT_UNSEEN_GAME_LIST.all(req.user.user_id)
annotate_games(games, req.user.user_id, unread, unseen)
- res.render("games_finished.pug", { user: req.user, who: req.user, games })
+ res.render("games_finished.pug", { who: req.user, games })
})
app.get("/tm/finished", must_be_logged_in, function (req, res) {
let pools = TM_POOL_LIST_USER_ALL_FINISHED.all(req.user.user_id)
- res.render("tm_finished.pug", { user: req.user, who: req.user, pools })
+ res.render("tm_finished.pug", { who: req.user, pools })
})
app.get("/games/finished/:who_name", function (req, res) {
@@ -1754,7 +1753,7 @@ app.get("/games/finished/:who_name", function (req, res) {
if (who) {
let games = QUERY_LIST_FINISHED_GAMES_OF_USER.all({ user_id: who.user_id })
annotate_games(games, 0, null, null)
- res.render("games_finished.pug", { user: req.user, who, games })
+ res.render("games_finished.pug", { who, games })
} else {
return res.status(404).send("Invalid user name.")
}
@@ -1764,7 +1763,7 @@ app.get("/tm/finished/:who_name", function (req, res) {
let who = SQL_SELECT_USER_BY_NAME.get(req.params.who_name)
if (who) {
let pools = TM_POOL_LIST_USER_ALL_FINISHED.all(who.user_id)
- res.render("tm_finished.pug", { user: req.user, who, pools })
+ res.render("tm_finished.pug", { who, pools })
} else {
return res.status(404).send("Invalid user name.")
}
@@ -1826,7 +1825,7 @@ function get_title_page(req, res, title_id) {
let active_pools = TM_POOL_LIST_TITLE_ACTIVE.all(title_id)
let finished_pools = TM_POOL_LIST_TITLE_FINISHED.all(title_id)
- res.render("info.pug", {
+ res.render("title.pug", {
user: req.user,
title: title,
open_games,
@@ -1847,7 +1846,7 @@ app.get("/create/:title_id", function (req, res) {
let title = TITLE_TABLE[title_id]
if (!title)
return res.status(404).send("Invalid title.")
- res.render("create.pug", {
+ res.render("create_title.pug", {
user: req.user,
title: title,
limit: req.user ? check_create_game_limit(req.user) : null,
@@ -2479,7 +2478,7 @@ function mail_password_reset_token(user, token) {
let subject = "Password reset request"
let body =
"Your password reset token is: " + token + "\n\n" +
- SITE_URL + "/reset-password/" + user.mail + "/" + token + "\n"
+ SITE_URL + "/account/reset-password?mail=" + user.mail + "&token=" + token + "\n"
console.log("SENT MAIL:", mail_addr(user), subject)
mailer.sendMail({ from: MAIL_FROM, to: mail_addr(user), subject: subject, text: body }, mail_callback)
}
@@ -2490,7 +2489,7 @@ function mail_verification_token(user, token) {
let subject = "Verify mail address"
let body =
"Your mail verification token is: " + token + "\n\n" +
- SITE_URL + "/verify-mail/" + token + "\n"
+ SITE_URL + "/account/mail/verify?token=" + token + "\n"
console.log("SENT MAIL:", mail_addr(user), subject)
mailer.sendMail({ from: MAIL_FROM, to: mail_addr(user), subject: subject, text: body }, mail_callback)
}
@@ -3159,7 +3158,7 @@ const TM_SELECT_SEED_READY_MINI_CUP = SQL(`
app.get("/tm/list", function (req, res) {
let seeds = TM_SEED_LIST_ALL.all(req.user ? req.user.user_id : 0)
- res.render("tm_list.pug", { user: req.user, seeds })
+ res.render("tm_list.pug", { seeds })
})
app.get("/tm/seed/:seed_name", function (req, res) {
@@ -3188,7 +3187,7 @@ app.get("/tm/seed/:seed_name", function (req, res) {
may_register = true
}
- res.render("tm_seed.pug", { user: req.user, error, may_register, seed, queues, active_pools, finished_pools })
+ res.render("tm_seed.pug", { error, may_register, seed, queues, active_pools, finished_pools })
})
app.get("/tm/pool/:pool_name", function (req, res) {
@@ -3206,10 +3205,10 @@ app.get("/tm/pool/:pool_name", function (req, res) {
players = TM_SELECT_PLAYERS_MP.all(pool_id)
let games = TM_SELECT_GAMES.all(pool_id)
let games_by_round = object_group_by(games, "round")
- res.render("tm_pool.pug", { user: req.user, seed, pool, roles, players, games, games_by_round })
+ res.render("tm_pool.pug", { seed, pool, roles, players, games, games_by_round })
})
-app.post("/api/tm/register/:seed_id/:level", must_be_logged_in, function (req, res) {
+app.post("/tm/register/:seed_id/:level", must_be_logged_in, function (req, res) {
let seed_id = req.params.seed_id | 0
let level = req.params.level | 0
let user_id = req.user.user_id
@@ -3225,7 +3224,7 @@ app.post("/api/tm/register/:seed_id/:level", must_be_logged_in, function (req, r
return res.redirect(req.headers.referer)
})
-app.post("/api/tm/withdraw/:seed_id/:level", must_be_logged_in, function (req, res) {
+app.post("/tm/withdraw/:seed_id/:level", must_be_logged_in, function (req, res) {
let seed_id = req.params.seed_id | 0
let level = req.params.level | 0
let user_id = req.user.user_id
@@ -3233,7 +3232,7 @@ app.post("/api/tm/withdraw/:seed_id/:level", must_be_logged_in, function (req, r
return res.redirect(req.headers.referer)
})
-app.post("/api/tm/start/:seed_id/:level", must_be_administrator, function (req, res) {
+app.post("/tm/start/:seed_id/:level", must_be_administrator, function (req, res) {
let seed_id = req.params.seed_id | 0
let level = req.params.level | 0
start_tournament_seed(seed_id, level)
@@ -4240,23 +4239,23 @@ const SQL_GAME_RATINGS = SQL(`
limit 50
`)
-app.get("/user-stats/:who_name", must_be_administrator, function (req, res) {
+app.get("/stats/user/:who_name", must_be_administrator, function (req, res) {
let who = SQL_SELECT_USER_BY_NAME.get(req.params.who_name)
if (who) {
let stats = SQL_USER_STATS.all(who.user_id, who.user_id)
let ratings = SQL_USER_RATINGS.all(who.user_id)
- res.render("user_stats.pug", { user: req.user, who, stats, ratings })
+ res.render("stats_user.pug", { who, stats, ratings })
} else {
return res.status(404).send("Invalid user name.")
}
})
-app.get("/game-stats/:title_id", must_be_administrator, function (req, res) {
+app.get("/stats/title/:title_id", must_be_administrator, function (req, res) {
let title_id = req.params.title_id
if (title_id in TITLE_TABLE) {
let title_name = TITLE_NAME[title_id]
let ratings = SQL_GAME_RATINGS.all(title_id)
- res.render("game_stats.pug", { user: req.user, title_name, ratings })
+ res.render("stats_title.pug", { title_name, ratings })
} else {
return res.status(404).send("Invalid title.")
}
diff --git a/views/change_about.pug b/views/account_change_about.pug
index b5e2c84..7a0531e 100644
--- a/views/change_about.pug
+++ b/views/account_change_about.pug
@@ -10,7 +10,7 @@ html
include header
article
h1 Change profile text
- form(method="post" action="/change-about")
+ form(method="post")
p Name: #{user.name}
p Mail: #{user.mail}
p
diff --git a/views/change_mail.pug b/views/account_change_mail.pug
index d244e98..4d0605a 100644
--- a/views/change_mail.pug
+++ b/views/account_change_mail.pug
@@ -11,7 +11,7 @@ html
if flash
p.error= flash
- form(method="post" action="/change-mail")
+ form(method="post")
p Name: #{user.name}
p Mail: #{user.mail}
p
@@ -19,4 +19,8 @@ html
br
input(type="text" name="newmail" required)
p
+ label Password:
+ br
+ input(type="password" name="password" required)
+ p
button(type="submit") Change mail
diff --git a/views/change_name.pug b/views/account_change_name.pug
index 03763ac..b1845ab 100644
--- a/views/change_name.pug
+++ b/views/account_change_name.pug
@@ -11,7 +11,7 @@ html
if flash
p.error= flash
- form(method="post" action="/change-name")
+ form(method="post")
p Name: #{user.name}
p Mail: #{user.mail}
p
@@ -19,4 +19,8 @@ html
br
input(type="text" name="newname" required)
p
+ label Password:
+ br
+ input(type="password" name="password" required)
+ p
button(type="submit") Change name
diff --git a/views/change_password.pug b/views/account_change_password.pug
index 022a67c..ca8e973 100644
--- a/views/change_password.pug
+++ b/views/account_change_password.pug
@@ -11,7 +11,7 @@ html
if flash
p.error= flash
- form(method="post" action="/change-password")
+ form(method="post")
p Name: #{user.name}
p Mail: #{user.mail}
p
diff --git a/views/delete_account.pug b/views/account_delete.pug
index e16e1b6..54c3bc4 100644
--- a/views/delete_account.pug
+++ b/views/account_delete.pug
@@ -11,7 +11,7 @@ html
if flash
p.error= flash
- form(method="post" action="/delete-account")
+ form(method="post")
p Name: #{user.name}
p Mail: #{user.mail}
p
diff --git a/views/forgot_password.pug b/views/account_forgot_password.pug
index 935cae1..0913857 100644
--- a/views/forgot_password.pug
+++ b/views/account_forgot_password.pug
@@ -15,7 +15,7 @@ html
if user
p You're already logged in!
else
- form(method="post" action="/forgot-password")
+ form(method="post")
p
label Mail:
br
diff --git a/views/account_mail_verify.pug b/views/account_mail_verify.pug
new file mode 100644
index 0000000..fddf2fa
--- /dev/null
+++ b/views/account_mail_verify.pug
@@ -0,0 +1,32 @@
+//- vim:ts=4:sw=4:
+doctype html
+html
+ head
+ include head
+ title Verify mail
+ body
+ include header
+ article
+ h1 Verify mail
+ if flash
+ p.error= flash
+
+ p Your mail address is <code>#{user.mail}</code>
+
+ p If the above address is wrong, you can <a href="/account/change-mail">change it</a>!
+
+ if sent_token
+ p Your token is in the mail!
+ else
+ form(method="post" action="/account/mail/verify-send")
+ p
+ button(type="submit") Send token
+
+ form(method="post")
+ p
+ label Enter your mail verification token here:
+ br
+ input(type="text" name="token" size=32 value=token style="font-family:monospace" required)
+ p
+ button(type="submit") Verify
+
diff --git a/views/reset_password.pug b/views/account_reset_password.pug
index 2fda418..8707ebc 100644
--- a/views/reset_password.pug
+++ b/views/account_reset_password.pug
@@ -13,7 +13,7 @@ html
p You should have received a password reset token in your mail.
- form(method="post" action="/reset-password")
+ form(method="post")
p
label Mail:
br
diff --git a/views/webhook.pug b/views/account_webhook.pug
index 20d20ac..b9817ef 100644
--- a/views/webhook.pug
+++ b/views/account_webhook.pug
@@ -14,7 +14,7 @@ html(lang="en")
- var format = webhook && webhook.format || ""
- var prefix = webhook && webhook.prefix || ""
- form(action="/api/webhook/update" method="post")
+ form(action="/account/webhook/update" method="post")
if webhook && webhook.error
p.error ERROR: #{webhook.error}
p Webhook URL:
@@ -34,7 +34,7 @@ html(lang="en")
button(type="submit") Create
if webhook
- form(action="/api/webhook/delete" method="post")
+ form(action="/account/webhook/delete" method="post")
button(type="submit") Delete
h2 Discord Notifications
diff --git a/views/search_user.pug b/views/contacts_search.pug
index 308cc41..308cc41 100644
--- a/views/search_user.pug
+++ b/views/contacts_search.pug
diff --git a/views/create-index.pug b/views/create_index.pug
index c508be7..c508be7 100644
--- a/views/create-index.pug
+++ b/views/create_index.pug
diff --git a/views/create.pug b/views/create_title.pug
index c4c5c2a..c4c5c2a 100644
--- a/views/create.pug
+++ b/views/create_title.pug
diff --git a/views/head.pug b/views/head.pug
index eec1299..da73d4e 100644
--- a/views/head.pug
+++ b/views/head.pug
@@ -212,3 +212,36 @@ mixin tourlist(seeds, pools, fin)
+poollist(pools, "Active", TM_ICON_ACTIVE)
div
+poollist(fin, "Finished", TM_ICON_FINISHED)
+
+mixin userstats(who, ratings)
+ if (who.move_time_mean !== null)
+ h3 Response time
+ div Average response time: #{format_minutes(who.move_time_mean)}
+ if (who.move_time_q2 !== null)
+ div Median response time: #{format_minutes(who.move_time_q2)}
+ if (who.move_time_q1 !== null && who.move_time_q2 !== null)
+ div Middle half of response times: #{format_minutes(who.move_time_q1)} to #{format_minutes(who.move_time_q3)}
+
+ h3 Timeouts
+ div Total number of timeouts: #{who.timeout_total}
+ div Games completed since last timeout: #{who.games_since_timeout}
+
+ if ratings.length > 0
+ h3 Most played games
+ table
+ thead
+ tr
+ th Title
+ th Count
+ th Last played
+ if user && user.user_id === 1
+ th Elo
+ tbody
+ each row in ratings
+ tr
+ td
+ a.black(href="/" + row.title_id)= row.title_name
+ td.r= row.count
+ td.r= row.last
+ if user && user.user_id === 1
+ td.r= row.rating
diff --git a/views/login.pug b/views/login.pug
index 9a44b44..ec8be48 100644
--- a/views/login.pug
+++ b/views/login.pug
@@ -19,7 +19,7 @@ html
p You need to be logged in to view this page!
p Log in below, or <a href="/signup">sign up</a> for a free account.
- form(method="post" action="/login")
+ form(method="post")
input(type="hidden" name="redirect" value=redirect)
p
label Name or mail:
@@ -33,4 +33,4 @@ html
p
button(type="submit") Login
p
- a(href="/forgot-password") Forgot password
+ a(href="/account/forgot-password") Forgot password
diff --git a/views/profile.pug b/views/profile.pug
index 4ecf289..fc9a1d3 100644
--- a/views/profile.pug
+++ b/views/profile.pug
@@ -7,43 +7,60 @@ html
body
include header
article
- h1= SITE_NAME
+ h1 Profile
p Welcome, <a class="black" href="/user/#{user.name}">#{user.name}</a>!
+
+ if who.about
+ p.box= who.about
+
+ p Member since #{human_date(who.ctime)}.
+
+ +userstats(who, ratings)
+
+ h3 Notifications
+
p Your mail address is #{user.mail}
if ENABLE_MAIL
- if !user.is_verified
- p &#x26a0; <a href="/verify-mail">Verify your mail address!</a>
+ if !mail.is_verified
+ p &#x26a0; <a href="/account/mail/verify">Verify your mail address!</a>
p You must verify your mail address before you can enable notifications.
else
- if !user.notify
- p <a href="/subscribe">Enable mail notifications</a>
- if user.notify
- p <a href="/unsubscribe">Disable mail notifications</a>
+ if !mail.notify
+ p <a href="/account/mail/subscribe">Enable mail notifications</a>
+ if mail.notify
+ p <a href="/account/mail/unsubscribe">Disable mail notifications</a>
+ else
+ p.error Mail notifications are disabled on this server.
+
+ if ENABLE_WEBHOOKS
+ if !webhook
+ p <a href="/account/webhook">Configure webhook</a>
+ else if webhook.error
+ dl
+ dt <a href="/account/webhook">Configure webhook</a>
+ dd.error ERROR: #{webhook.error}
+ else
+ dl
+ dt <a href="/account/webhook">Configure webhook</a>
+ dd= new URL(webhook.url).hostname
+ else
+ p.error Webhook notifications are disabled on this server.
+
+ h3 Account
p
- | <a href="/change-password">Change password</a>
+ | <a href="/account/change-password">Change password</a>
br
- | <a href="/change-mail">Change mail address</a>
+ | <a href="/account/change-mail">Change mail address</a>
br
- | <a href="/change-name">Change user name</a>
+ | <a href="/account/change-name">Change user name</a>
br
- | <a href="/change-about">Change profile text</a>
- br
- | <a href="/delete-account">Delete account</a>
+ | <a href="/account/change-about">Change profile text</a>
- if ENABLE_WEBHOOKS
- if !user.webhook
- p <a href="/webhook">Configure webhook</a>
- else if user.webhook.error
- dl
- dt <a href="/webhook">Configure webhook</a>
- dd.error ERROR: #{user.webhook.error}
- else
- dl
- dt <a href="/webhook">Configure webhook</a>
- dd= new URL(user.webhook.url).hostname
+ p
+ | <a href="/account/delete">Delete account</a>
p
form(action="/logout" method="post")
diff --git a/views/signup.pug b/views/signup.pug
index 63b9ab3..5dec458 100644
--- a/views/signup.pug
+++ b/views/signup.pug
@@ -15,7 +15,7 @@ html
if user
p You're already logged in!
else
- form(method="post" action="/signup")
+ form(method="post")
p You need to sign up for a free account to play games on #{SITE_NAME_P}
p
label Name:
diff --git a/views/game_stats.pug b/views/stats_title.pug
index 692c30b..aed6e63 100644
--- a/views/game_stats.pug
+++ b/views/stats_title.pug
@@ -19,7 +19,7 @@ html
tbody
each row in ratings
tr
- td= row.name
+ td <a class="black" href="/stats/user/#{row.name}">#{row.name}</a>
td.r= row.rating
td.r= row.count
td.r= row.last
diff --git a/views/user_stats.pug b/views/stats_user.pug
index 3b201ef..3b201ef 100644
--- a/views/user_stats.pug
+++ b/views/stats_user.pug
diff --git a/views/info.pug b/views/title.pug
index 32837e9..32837e9 100644
--- a/views/info.pug
+++ b/views/title.pug
diff --git a/views/tm_seed.pug b/views/tm_seed.pug
index 45659c5..abf02c1 100644
--- a/views/tm_seed.pug
+++ b/views/tm_seed.pug
@@ -67,11 +67,11 @@ html
if user
if queue.find(p => p.user_id === user.user_id)
- form(method="post" action="/api/tm/withdraw/" + seed.seed_id + "/" + (ix+1))
+ form(method="post" action="/tm/withdraw/" + seed.seed_id + "/" + (ix+1))
button(disabled) Register
button(type="submit") Withdraw
else if may_register && may_join_seed_level(user.user_id, seed.seed_id, ix+1)
- form(method="post" action="/api/tm/register/" + seed.seed_id + "/" + (ix+1))
+ form(method="post" action="/tm/register/" + seed.seed_id + "/" + (ix+1))
button(type="submit") Register
button(disabled) Withdraw
else
@@ -81,7 +81,7 @@ html
if user.user_id === 1
if queue.length >= seed.pool_size
- form(method="post" action="/api/tm/start/" + seed.seed_id + "/" + (ix+1))
+ form(method="post" action="/tm/start/" + seed.seed_id + "/" + (ix+1))
button(type="submit") Start
else
p <a href="/login">Login</a> or <a href="/signup">sign up</a> to register.
diff --git a/views/user.pug b/views/user.pug
index c3e8925..b5859a2 100644
--- a/views/user.pug
+++ b/views/user.pug
@@ -24,7 +24,7 @@ html
h1= who.name
if who.about
- p.about= who.about
+ p.box= who.about
p Member since #{human_date(who.ctime)}.
p Last seen #{human_date(who.atime)}.
@@ -42,37 +42,7 @@ html
br
a(href="/contacts/add-enemy/"+who.name) Add to blacklist
- if (who.move_time_mean !== null)
- h3 Response time
- div Average response time: #{format_minutes(who.move_time_mean)}
- if (who.move_time_q2 !== null)
- div Median response time: #{format_minutes(who.move_time_q2)}
- if (who.move_time_q1 !== null && who.move_time_q2 !== null)
- div Middle half of response times: #{format_minutes(who.move_time_q1)} to #{format_minutes(who.move_time_q3)}
-
- h3 Timeouts
- div Total number of timeouts: #{who.timeout_total}
- div Games completed since last timeout: #{who.games_since_timeout}
-
- if ratings.length > 0
- h3 Most played games
- table
- thead
- tr
- th Title
- th Count
- th Last played
- if user && user.user_id === 1
- th Elo
- tbody
- each row in ratings
- tr
- td
- a.black(href="/" + row.title_id)= row.title_name
- td.r= row.count
- td.r= row.last
- if user && user.user_id === 1
- td.r= row.rating
+ +userstats(who, ratings)
+tourlist(null, active_pools, finished_pools)
diff --git a/views/verify_mail.pug b/views/verify_mail.pug
deleted file mode 100644
index 01a2e82..0000000
--- a/views/verify_mail.pug
+++ /dev/null
@@ -1,21 +0,0 @@
-//- vim:ts=4:sw=4:
-doctype html
-html
- head
- include head
- title Verify mail
- body
- include header
- article
- h1 Verify mail
- if flash
- p.error= flash
-
- form(method="post" action="/verify-mail")
- p A token has been sent to #{user.mail}.
- p
- label Enter the token here:
- br
- input(type="text" name="token" size=32 value=token style="font-family:monospace" required)
- p
- button(type="submit") Verify