Separated Account Login and Profile Display
This commit is contained in:
parent
aa4ad62493
commit
755af71912
4 changed files with 151 additions and 125 deletions
|
|
@ -29,24 +29,6 @@
|
|||
<h2 class="center">Loading...</h2>
|
||||
</div>
|
||||
|
||||
<div id="login-error" class="error-container" style="display: none;">
|
||||
<h2 id="error-text">ERROR</h2>
|
||||
</div>
|
||||
|
||||
<form id="login" style="display: none;">
|
||||
<h3 class="center">Please log in before viewing account information</h3>
|
||||
<div class="form-group">
|
||||
<label for="username">SFID / Username:</label>
|
||||
<input class="login-input" type="text" id="username" name="username" required />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password:</label>
|
||||
<input class="login-input" type="password" id="password" name="password" required />
|
||||
</div>
|
||||
<button class="form-button" type="submit">Login</button>
|
||||
<p class="form-note">Please ask an SPFN Developer in the <a href="https://discord.gg/grMSxZf">discord server</a> for assistance with password resets</p>
|
||||
</form>
|
||||
|
||||
<div id="user-info" class="info" style="display: none;">
|
||||
<div id="user-display" class="info-container" style="width: 180px; align-items: center;">
|
||||
<img src="/res/img/mii-placeholder.png" id="mii-img" style="width: 100%">
|
||||
|
|
|
|||
52
account/login/index.html
Normal file
52
account/login/index.html
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Log In | SPFN</title>
|
||||
<link rel="icon" type="image/png" href="/res/img/spfn.png">
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div style="display: flex;">
|
||||
<img style="width: 96px; padding: 0px; margin: 0 auto" src="/res/img/spfn.png">
|
||||
<h2 style="font-size: 32px; margin: auto; padding: 12px">Account</h2>
|
||||
</div>
|
||||
<nav>
|
||||
<ul class="nav-links">
|
||||
<a href="/"><button class="header-button">Home</button></a>
|
||||
<a href="/guides"><button class="header-button">Guides</button></a>
|
||||
<a href="/account"><button class="header-button active">Account</button></a>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div id="login-error" class="error-container" style="display: none;">
|
||||
<h2 id="error-text">ERROR</h2>
|
||||
</div>
|
||||
|
||||
<form id="login">
|
||||
<h3 class="center">Please log in to access your account.</h3>
|
||||
<div class="form-group">
|
||||
<label for="username">SFID / Username:</label>
|
||||
<input class="login-input" type="text" id="username" name="username" required />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password:</label>
|
||||
<input class="login-input" type="password" id="password" name="password" required />
|
||||
</div>
|
||||
<button class="form-button" type="submit">Login</button>
|
||||
<p class="form-note">Please ask an SPFN Developer in the <a href="https://discord.gg/grMSxZf">discord server</a> for assistance with password resets</p>
|
||||
</form>
|
||||
|
||||
<script type="text/javascript" src="/js/login.js"></script>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p class="center">Need assistance? <a href="https://discord.gg/grMSxZf" target="_blank">Join the Discord</a></p>
|
||||
</footer>
|
||||
</body>
|
||||
110
js/accounts.js
110
js/accounts.js
|
|
@ -8,72 +8,6 @@ let userAccessLevels = { // Name | Text Colour | Background Colour | Border Colo
|
|||
"3": ["Admin", "#fff", "#920606", "#c80404"],
|
||||
}
|
||||
|
||||
function loginError(message, code = null) {
|
||||
let errorStr;
|
||||
if (code) {
|
||||
errorStr = `Status code ${code}: ${message}`;
|
||||
} else {
|
||||
errorStr = message;
|
||||
}
|
||||
|
||||
document.getElementById("error-text").textContent = errorStr;
|
||||
|
||||
document.getElementById("login-error").style.display = "block";
|
||||
}
|
||||
|
||||
async function generateToken(username, password) {
|
||||
const credentials = btoa(`${username} ${password}`);
|
||||
|
||||
let response;
|
||||
try {
|
||||
response = await fetch("https://account.spfn.net/api/v2/oauth2/generate_token", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Authorization": `Basic ${credentials}`,
|
||||
}
|
||||
})
|
||||
} catch (err) {
|
||||
loginError(`Internal Server Error: ${err.message}`)
|
||||
throw new Error(err);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status == 400) { // Invalid Login
|
||||
loginError("Invalid SFID or Password");
|
||||
} else {
|
||||
loginError(await response.text(), response.status);
|
||||
}
|
||||
|
||||
throw new Error("Network Response was not okay when Generating Token");
|
||||
};
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
sessionStorage.setItem("authToken", data["token"])
|
||||
|
||||
const expiry = data["expiry"].slice(0, 19) + "Z"
|
||||
sessionStorage.setItem("authExpires", expiry)
|
||||
return data["token"];
|
||||
}
|
||||
|
||||
async function getToken(username, password) {
|
||||
let token = sessionStorage.getItem("authToken");
|
||||
|
||||
let expiryStr = sessionStorage.getItem("authExpires");
|
||||
if (expiryStr) { // Expiry exists so token should exist
|
||||
let expiry = new Date(expiryStr);
|
||||
if (expiry < new Date()) { // Expired token
|
||||
token = await generateToken(username, password);
|
||||
} else if (!token) { // Expiry Saved but No Token (shouldn't be possible but it'll be caught if it happens)
|
||||
token = await generateToken(username, password);
|
||||
}
|
||||
} else { // Token Never Saved in Session
|
||||
token = await generateToken(username, password);
|
||||
}
|
||||
|
||||
return token
|
||||
}
|
||||
|
||||
function updateUserDataDisplay(data) {
|
||||
document.getElementById("display-name").textContent = data["mii"]["name"];
|
||||
document.getElementById("sfid").textContent = `SFID: ${data["user_id"]}`;
|
||||
|
|
@ -87,7 +21,6 @@ function updateUserDataDisplay(data) {
|
|||
document.getElementById("tz").innerHTML = `<strong>Timezone: </strong>${data["tz_name"]}`;
|
||||
document.getElementById("region").innerHTML = `<strong>Country/Region: </strong>${data["country"]}`;
|
||||
|
||||
document.getElementById("login").style.display = "none";
|
||||
document.getElementById("user-info").style.display = "flex";
|
||||
|
||||
let miiLink = `https://mii.spfn.net/${data["pid"]}/main.png`
|
||||
|
|
@ -101,43 +34,10 @@ function updateUserDataDisplay(data) {
|
|||
}
|
||||
|
||||
function logOut() {
|
||||
document.getElementById("login-error").style.display = "none";
|
||||
|
||||
sessionStorage.clear();
|
||||
document.getElementById("user-info").style.display = "none";
|
||||
document.getElementById("login").style.display = "flex";
|
||||
window.location.href = "/account/login?redirect=/account"
|
||||
}
|
||||
|
||||
document.getElementById("login").addEventListener("submit", async function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
document.getElementById("login-error").style.display = "none";
|
||||
|
||||
const username = await document.getElementById("username").value;
|
||||
const password = await document.getElementById("password").value;
|
||||
|
||||
let token = await getToken(username, password);
|
||||
if (!token) return;
|
||||
|
||||
document.getElementById("password").value = "";
|
||||
|
||||
const response = await fetch("https://account.spfn.net/api/v2/users/@me/profile", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Authorization": `Bearer ${token}`
|
||||
}
|
||||
})
|
||||
if (!response.ok) {
|
||||
loginError(await response.text(), response.status);
|
||||
throw new Error("Network Response was not okay when requesting Profile");
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Success - Display user data
|
||||
updateUserDataDisplay(data);
|
||||
})
|
||||
|
||||
|
||||
|
||||
// Check if there is an active login
|
||||
|
|
@ -163,14 +63,10 @@ window.onload = async function() {
|
|||
document.getElementById("loading-screen").style.display = "none";
|
||||
|
||||
} else { // Has expired - Prompt user to log back in
|
||||
document.getElementById("loading-screen").style.display = "none";
|
||||
document.getElementById("login").style.display = "block";
|
||||
|
||||
loginError("Login expired - Please log in again")
|
||||
window.location.href = "/account/login?redirect=/account"
|
||||
}
|
||||
} else { // User has never logged in for this session
|
||||
document.getElementById("loading-screen").style.display = "none";
|
||||
document.getElementById("login").style.display = "block";
|
||||
window.location.href = "/account/login?redirect=/account"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
96
js/login.js
Normal file
96
js/login.js
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
function loginError(message, code = null) {
|
||||
let errorStr;
|
||||
if (code) {
|
||||
errorStr = `Status code ${code}: ${message}`;
|
||||
} else {
|
||||
errorStr = message;
|
||||
}
|
||||
|
||||
document.getElementById("error-text").textContent = errorStr;
|
||||
|
||||
document.getElementById("login-error").style.display = "block";
|
||||
}
|
||||
|
||||
async function generateToken(username, password) {
|
||||
const credentials = btoa(`${username} ${password}`);
|
||||
|
||||
let response;
|
||||
try {
|
||||
response = await fetch("https://account.spfn.net/api/v2/oauth2/generate_token", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Authorization": `Basic ${credentials}`,
|
||||
}
|
||||
})
|
||||
} catch (err) {
|
||||
loginError(`Internal Server Error: ${err.message}`)
|
||||
throw new Error(err);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status == 400) { // Invalid Login
|
||||
loginError("Invalid SFID or Password");
|
||||
} else {
|
||||
loginError(await response.text(), response.status);
|
||||
}
|
||||
|
||||
throw new Error("Network Response was not okay when Generating Token");
|
||||
};
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
sessionStorage.setItem("authToken", data["token"])
|
||||
|
||||
const expiry = data["expiry"].slice(0, 19) + "Z"
|
||||
sessionStorage.setItem("authExpires", expiry)
|
||||
return data["token"];
|
||||
}
|
||||
|
||||
async function getToken(username, password) {
|
||||
let token = sessionStorage.getItem("authToken");
|
||||
|
||||
let expiryStr = sessionStorage.getItem("authExpires");
|
||||
if (expiryStr) { // Expiry exists so token should exist
|
||||
let expiry = new Date(expiryStr);
|
||||
if (expiry < new Date()) { // Expired token
|
||||
token = await generateToken(username, password);
|
||||
} else if (!token) { // Expiry Saved but No Token (shouldn't be possible but it'll be caught if it happens)
|
||||
token = await generateToken(username, password);
|
||||
}
|
||||
} else { // Token Never Saved in Session
|
||||
token = await generateToken(username, password);
|
||||
}
|
||||
|
||||
return token
|
||||
}
|
||||
|
||||
document.getElementById("login").addEventListener("submit", async function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
document.getElementById("login-error").style.display = "none";
|
||||
|
||||
const username = await document.getElementById("username").value;
|
||||
const password = await document.getElementById("password").value;
|
||||
|
||||
let token = await getToken(username, password);
|
||||
if (!token) return;
|
||||
|
||||
document.getElementById("password").value = "";
|
||||
|
||||
// Go Back to Origin Page
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const redirectURL = params.get("redirect")
|
||||
|
||||
window.location.href = redirectURL;
|
||||
})
|
||||
|
||||
window.onload = async function () { // Check if the token expired
|
||||
let expiryStr = sessionStorage.getItem("authExpires");
|
||||
if (expiryStr) {
|
||||
let expiry = new Date(expiryStr);
|
||||
|
||||
if (expiry < new Date()) { // Expired - Tell the user it expired
|
||||
loginError("Login Expired - Please Log In Again")
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue