Initial commit

This commit is contained in:
2023-12-29 18:31:43 +00:00
commit b09f0ad7bd
24 changed files with 1530 additions and 0 deletions

7
static/src/constants.js Normal file
View File

@@ -0,0 +1,7 @@
const ACCOUNT_TYPE_CUSTOMER = 1
const ACCOUNT_TYPE_ASSISTANT = 2
const TICKET_STATUS_OPEN = 1
const TICKET_STATUS_CLOSED = 2
const SYSTEM_USER_ID = 0

125
static/src/jwt-decode.js Normal file
View File

@@ -0,0 +1,125 @@
// CODE IS FROM https://github.com/auth0/jwt-decode
(function (factory) {
typeof define === 'function' && define.amd ? define(factory) :
factory();
}((function () { 'use strict';
/**
* The code was extracted from:
* https://github.com/davidchambers/Base64.js
*/
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
function InvalidCharacterError(message) {
this.message = message;
}
InvalidCharacterError.prototype = new Error();
InvalidCharacterError.prototype.name = "InvalidCharacterError";
function polyfill(input) {
var str = String(input).replace(/=+$/, "");
if (str.length % 4 == 1) {
throw new InvalidCharacterError(
"'atob' failed: The string to be decoded is not correctly encoded."
);
}
for (
// initialize result and counters
var bc = 0, bs, buffer, idx = 0, output = "";
// get next character
(buffer = str.charAt(idx++));
// character found in table? initialize bit storage and add its ascii value;
~buffer &&
((bs = bc % 4 ? bs * 64 + buffer : buffer),
// and if not first of each 4 characters,
// convert the first 8 bits to one ascii character
bc++ % 4) ?
(output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)))) :
0
) {
// try to find character in table (0-63, not found => -1)
buffer = chars.indexOf(buffer);
}
return output;
}
var atob = (typeof window !== "undefined" &&
window.atob &&
window.atob.bind(window)) ||
polyfill;
function b64DecodeUnicode(str) {
return decodeURIComponent(
atob(str).replace(/(.)/g, function(m, p) {
var code = p.charCodeAt(0).toString(16).toUpperCase();
if (code.length < 2) {
code = "0" + code;
}
return "%" + code;
})
);
}
function base64_url_decode(str) {
var output = str.replace(/-/g, "+").replace(/_/g, "/");
switch (output.length % 4) {
case 0:
break;
case 2:
output += "==";
break;
case 3:
output += "=";
break;
default:
throw "Illegal base64url string!";
}
try {
return b64DecodeUnicode(output);
} catch (err) {
return atob(output);
}
}
function InvalidTokenError(message) {
this.message = message;
}
InvalidTokenError.prototype = new Error();
InvalidTokenError.prototype.name = "InvalidTokenError";
function jwtDecode(token, options) {
if (typeof token !== "string") {
throw new InvalidTokenError("Invalid token specified");
}
options = options || {};
var pos = options.header === true ? 0 : 1;
try {
return JSON.parse(base64_url_decode(token.split(".")[pos]));
} catch (e) {
throw new InvalidTokenError("Invalid token specified: " + e.message);
}
}
/*
* Expose the function on the window object
*/
//use amd or just through the window object.
if (window) {
if (typeof window.define == "function" && window.define.amd) {
window.define("jwt_decode", function() {
return jwtDecode;
});
} else if (window) {
window.jwt_decode = jwtDecode;
}
}
})));
//# sourceMappingURL=jwt-decode.js.map

143
static/src/ticketTools.js Normal file
View File

@@ -0,0 +1,143 @@
async function openTicket() {
let ticket_title_input = document.getElementById("ticket_title_input");
let message_input = document.getElementById("message_input");
const res = await (await fetch('/ticket/new', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem("access_token")
},
redirect: 'manual',
body: JSON.stringify({
ticket_title: ticket_title_input.value,
message: message_input.value
})
})).json();
if (res["error"] != undefined) {
alert(res["error"]);
} else {
window.location.href = "/ticket/" + res["ticket_id"];
};
}
async function getTicket(ticket_id) {
const res = await (await fetch('/get-ticket/' + ticket_id, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem("access_token")
}
})).json();
if (res["error"] != undefined) {
alert(res["error"]);
return false;
} else {
return res;
};
}
async function getOpenTicketsByUserID(user_id) {
const res = await (await fetch('/get-open-tickets/' + user_id, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem("access_token")
}
})).json();
if (res["error"] != undefined) {
alert(res["error"]);
return [];
} else {
return res["tickets"];
};
}
async function getClosedTicketsByUserID(user_id) {
const res = await (await fetch('/get-closed-tickets/' + user_id, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem("access_token")
}
})).json();
if (res["error"] != undefined) {
alert(res["error"]);
return [];
} else {
return res["tickets"];
};
}
async function getUnclaimedTickets() {
const res = await (await fetch('/get-unclaimed-tickets', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem("access_token")
}
})).json();
if (res["error"] != undefined) {
alert(res["error"]);
return [];
} else {
return res["tickets"];
};
}
async function sendMessage(message_input=document.getElementById("message_input").value) {
const res = await (await fetch('/ticket/' + ticketID, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem("access_token")
},
body: JSON.stringify({
message: message_input
})
})).json();
if (res["error"] != undefined) {
alert(res["error"]);
return [];
} else {
window.location.reload();
return res;
}
}
async function getMessages(ticket_id) {
const res = await (await fetch('/get-messages/' + ticket_id, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem("access_token")
}
})).json();
if (res["error"] != undefined) {
alert(res["error"]);
return [];
} else {
return res["message_list"];
};
}

130
static/src/userTools.js Normal file
View File

@@ -0,0 +1,130 @@
const getDecodedAccessToken = () => {
return localStorage.getItem("access_token") != null ? jwt_decode(localStorage.getItem("access_token")) : null;
}
function getLoggedInUser() {
let d_at = getDecodedAccessToken();
if (d_at == null) return null;
if (d_at["exp"] < (Date.now() / 1000)) {
localStorage.removeItem("access_token");
return null
};
return d_at;
}
async function register() {
let username_input = document.getElementById("username_input");
let email_input = document.getElementById("email_input");
let password_input = document.getElementById("password_input");
let passwordc_input = document.getElementById("passwordc_input");
if (password_input.value != passwordc_input.value) return alert("Passwords do not match.")
const res = await (await fetch('/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
redirect: 'manual',
body: JSON.stringify({
username: username_input.value,
email: email_input.value,
password: password_input.value
})
})).json();
if (res["error"] != undefined) {
alert(res["error"]);
} else {
localStorage.setItem("access_token", res["access_token"]);
window.location.href = "/home";
};
}
async function login() {
let username_input = document.getElementById("username_input");
let password_input = document.getElementById("password_input");
const res = await (await fetch('/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
redirect: 'manual',
body: JSON.stringify({
username: username_input.value,
password: password_input.value
})
})).json();
if (res["error"] != undefined) {
alert(res["error"]);
} else {
localStorage.setItem("access_token", res["access_token"]);
window.location.href = "/home";
};
}
async function logout() {
localStorage.removeItem("access_token");
alert("Successfully logged out.");
window.location.href = "/login";
}
async function getProfile(user_id) {
const res = await (await fetch('/get-profile/' + user_id, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem("access_token")
}
})).json();
if (res["error"] != undefined) {
alert(res["error"]);
return false;
} else {
return res["user"];
};
}
async function updateProfile() {
let new_password_input = document.getElementById("new_password_input");
let new_passwordc_input = document.getElementById("new_passwordc_input");
let old_password_input = document.getElementById("old_password_input");
let profile_icon_select = document.getElementById("profile_icon_select");
if (new_password_input.value != new_passwordc_input.value) return alert("Passwords do not match.");
if (old_password_input.value == "") return alert("Old password is needed to confirm changes.");
const res = await (await fetch('/profile', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem("access_token")
},
redirect: 'manual',
body: JSON.stringify({
new_password: new_password_input.value,
old_password: old_password_input.value,
profile_icon: profile_icon_select.value
})
})).json();
if (res["error"] != undefined) {
alert(res["error"]);
} else {
alert("Profile updated.");
window.location.reload();
};
}