forked from spacebar/spfn-website
Add Backend
This commit is contained in:
parent
dc101e28f8
commit
05beab587b
31 changed files with 59 additions and 6 deletions
115
static/js/accounts.js
Normal file
115
static/js/accounts.js
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
let userAccessLevels = { // Name | Text Colour | Background Colour | Border Colour
|
||||
"-3": ["Banned", "#fff", "#2e2e2e", "#727272"],
|
||||
"-2": ["Banned", "#fff", "#2e2e2e", "#727272"],
|
||||
"-1": ["Banned", "#fff", "#2e2e2e", "#727272"],
|
||||
"0": ["Member", "#fff", "#047205", "#00a003"],
|
||||
"1": ["Tester", "#fff", "#0c98a2", "#01c9d7"],
|
||||
"2": ["Moderator", "#000", "#00dc04", "#067708"],
|
||||
"3": ["Admin", "#fff", "#920606", "#c80404"],
|
||||
}
|
||||
|
||||
function updateUserDataDisplay(data) {
|
||||
document.getElementById("display-name").textContent = data["mii"]["name"];
|
||||
document.getElementById("sfid").textContent = `SFID: ${data["user_id"]}`;
|
||||
|
||||
document.getElementById("email").innerHTML = `<strong>Email: </strong>${data["email"]["address"]}`;
|
||||
document.getElementById("dob").innerHTML = `<strong>Date of Birth: </strong>${data["birth_date"]}`;
|
||||
|
||||
let createdAt = new Date(data["create_date"] + "Z");
|
||||
document.getElementById("created-at").innerHTML = `<strong>Created: </strong>${createdAt.toLocaleString()}`
|
||||
|
||||
document.getElementById("tz").innerHTML = `<strong>Timezone: </strong>${data["tz_name"]}`;
|
||||
document.getElementById("region").innerHTML = `<strong>Country/Region: </strong>${data["country"]}`;
|
||||
|
||||
document.getElementById("user-info").style.display = "flex";
|
||||
|
||||
let miiLink = `https://mii.spfn.net/${data["pid"]}/main.png`
|
||||
document.getElementById("mii-img").src = miiLink;
|
||||
|
||||
let level = userAccessLevels[data["account_level"]];
|
||||
if (!level) level = ["Unknown", "#fff", "#000000ff", "#ffffffff"]; // Refer to comment on userAccessLevels for a formatting guide
|
||||
|
||||
document.getElementById("access-level").textContent = level[0];
|
||||
document.getElementById("access-level").style = `color: ${level[1]}; background-color: ${level[2]}; border-color: ${level[3]}`;
|
||||
}
|
||||
|
||||
function logOut() {
|
||||
sessionStorage.clear();
|
||||
window.location.href = "/account/login?redirect=/account"
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Check if there is an active login
|
||||
window.onload = async function() {
|
||||
let expiryStr = sessionStorage.getItem("authExpires");
|
||||
if (expiryStr) {
|
||||
let expiry = new Date(parseInt(expiryStr));
|
||||
|
||||
if (expiry > new Date()) { // Hasn't expired - Get user data
|
||||
let token = sessionStorage.getItem("authToken");
|
||||
|
||||
const response = await fetch("https://account.spfn.net/api/v2/users/@me/profile", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Authorization": `Bearer ${token}`
|
||||
}
|
||||
})
|
||||
if (!response.ok) throw new Error("Network Response was not okay when requesting Profile")
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
updateUserDataDisplay(data);
|
||||
document.getElementById("loading-screen").style.display = "none";
|
||||
|
||||
} else { // Has expired - Prompt user to log back in
|
||||
console.log("Token Expired")
|
||||
//window.location.href = "/account/login?redirect=/account"
|
||||
}
|
||||
} else { // User has never logged in for this session
|
||||
window.location.href = "/account/login?redirect=/account"
|
||||
}
|
||||
}
|
||||
|
||||
function showDeleteWarning() {
|
||||
document.getElementById("confirm-delete").style = ""
|
||||
document.getElementById("user-info").style = "display: none;"
|
||||
}
|
||||
|
||||
function hideDeleteWarning() {
|
||||
document.getElementById("user-info").style = ""
|
||||
document.getElementById("confirm-delete").style = "display: none;"
|
||||
}
|
||||
|
||||
async function deleteAccount() {
|
||||
let token;
|
||||
|
||||
let expiryStr = sessionStorage.getItem("authExpires");
|
||||
if (expiryStr) { // Expiry exists so token should exist
|
||||
token = sessionStorage.getItem("authToken");
|
||||
|
||||
let expiry = new Date(expiryStr);
|
||||
if (expiry < new Date()) { // Expired token
|
||||
window.location.href = "/account/login?redirect=/account"
|
||||
} else if (!token) { // Expiry Saved but No Token (shouldn't be possible but it'll be caught if it happens)
|
||||
window.location.href = "/account/login?redirect=/account"
|
||||
}
|
||||
} else { // Token Never Saved in Session
|
||||
window.location.href = "/account/login?redirect=/account"
|
||||
}
|
||||
|
||||
const response = await fetch("https://account.spfn.net/api/v2/users/@me/delete", {
|
||||
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 Account Deletion");
|
||||
}
|
||||
|
||||
document.getElementById("confirm-delete").style = "display: none;"
|
||||
document.getElementById("delete-success").style = ""
|
||||
}
|
||||
26
static/js/guides.js
Normal file
26
static/js/guides.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
const guideContents = document.querySelectorAll(".guide-content");
|
||||
const guideButtons = document.querySelectorAll(".guide");
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const guideParam = params.get("guide");
|
||||
|
||||
let guide = "install-wiiu";
|
||||
let guidePath = '/md/install-wiiu.md';
|
||||
if (guideParam) {
|
||||
guide = guideParam;
|
||||
guidePath = `/md/${guide}.md`;
|
||||
}
|
||||
|
||||
fetch(guidePath)
|
||||
.then(res => {
|
||||
if (!res.ok) throw new Error(`Guide "${guide} was not found`);
|
||||
|
||||
const guideButton = document.getElementById(guide);
|
||||
if (guideButton) guideButton.classList.add("active");
|
||||
|
||||
return res.text();
|
||||
})
|
||||
.then(text => {
|
||||
const html = marked.parse(text);
|
||||
document.getElementById("guide-contents").innerHTML = html;
|
||||
})
|
||||
86
static/js/home.js
Normal file
86
static/js/home.js
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
async function requestFestInfo() {
|
||||
// DO NOT USE THIS - USE ROUTE https://boss-info.spfn.net/api/v2/fest-info
|
||||
const response = await fetch("https://account.spfn.net/api/v2/fest-info", { // ROUTE NOT IMPLEMENTED
|
||||
method: "GET"
|
||||
})
|
||||
|
||||
if (!response.ok) return;
|
||||
|
||||
/*
|
||||
{
|
||||
"active",
|
||||
"a-name",
|
||||
"a-hex",
|
||||
"b-name",
|
||||
"b-hex",
|
||||
"start",
|
||||
"end"
|
||||
}
|
||||
*/
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* Disabled until actually implemented
|
||||
window.onload = async function() {
|
||||
// Verify Fest Information
|
||||
let data = localStorage.getItem("fest-info");
|
||||
if (data) { // Fest data previously stored
|
||||
const end = new Date(data["end"] + "Z")
|
||||
const now = new Date()
|
||||
if (end < now) { // Fest is over - Remove and check for new fest
|
||||
localStorage.removeItem("fest-info");
|
||||
|
||||
data = await requestFestInfo();
|
||||
|
||||
if (data) {
|
||||
localStorage.setItem("fest-info", data);
|
||||
}
|
||||
} else { // Fest is either Upcoming or Active - Update active state
|
||||
const start = new Date(data["start"] + "Z");
|
||||
const active = start > now && end < now;
|
||||
if (data["active"] != active) {
|
||||
data["active"] = active;
|
||||
localStorage.setItem("fest-data", data);
|
||||
}
|
||||
}
|
||||
} else { // No saved data - Check for any
|
||||
data = await requestFestInfo();
|
||||
|
||||
if (data) {
|
||||
localStorage.setItem("fest-info", data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (data) { // Active or Upcoming Fest Found
|
||||
document.getElementById("splatfest-notfound").style.display = "none";
|
||||
|
||||
let festTitle = `<strong style="background-color: ${data["a-hex"]};">${data["a-name"]}</strong> vs. <strong style="background-color: ${data["b-hex"]};">${data["b-name"]}</strong>`;
|
||||
document.getElementById("splatfest-title").innerHTML = festTitle;
|
||||
|
||||
|
||||
let start = new Date(data["start"] + "Z");
|
||||
let startStr = `<strong>Starts: </strong>${start.toLocaleString()}`;
|
||||
document.getElementById("splatfest-starts").innerHTML = startStr;
|
||||
|
||||
let end = new Date(data["end"] + "Z");
|
||||
let endStr = `<strong>Ends: </strong>${end.toLocaleString()}`;
|
||||
document.getElementById("splatfest-ends").innerHTML = endStr;
|
||||
|
||||
let now = new Date();
|
||||
if (start > now && end < now) { // Fest is Active
|
||||
console.log("Active fest found!")
|
||||
|
||||
} else { // Fest is Upcoming
|
||||
console.log("Upcoming fest found!")
|
||||
}
|
||||
} else { // No fest
|
||||
document.getElementById("splatfest-info").style.display = "none";
|
||||
console.log("No fests currently planned or active")
|
||||
}
|
||||
}
|
||||
*/
|
||||
99
static/js/login.js
Normal file
99
static/js/login.js
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
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}`);
|
||||
|
||||
const body = `grant_type=password&username=${username}&password=${password}&client_id=website`
|
||||
|
||||
let response;
|
||||
try {
|
||||
response = await fetch("https://account.spfn.net/api/v2/oauth2/generate_token", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
body,
|
||||
})
|
||||
} 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["access_token"]);
|
||||
|
||||
const expiry = Date.now() + (data["expires_in"] * 1000);
|
||||
sessionStorage.setItem("authExpires", expiry)
|
||||
return data["access_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…
Reference in a new issue