aboutsummaryrefslogtreecommitdiff
path: root/src/web/helpers
diff options
context:
space:
mode:
authorNicolas James <Eele1Ephe7uZahRie@tutanota.com>2025-02-13 18:04:18 +1100
committerNicolas James <Eele1Ephe7uZahRie@tutanota.com>2025-02-13 18:04:18 +1100
commit93dfe2be64e8658839bcfe5356adf35f8cde7075 (patch)
treec60b1e20d569b74dbde85123e1b2bf3590c66244 /src/web/helpers
initial commit
Diffstat (limited to 'src/web/helpers')
-rw-r--r--src/web/helpers/Auth.jsx66
-rw-r--r--src/web/helpers/Input.jsx31
-rw-r--r--src/web/helpers/Location.jsx29
3 files changed, 126 insertions, 0 deletions
diff --git a/src/web/helpers/Auth.jsx b/src/web/helpers/Auth.jsx
new file mode 100644
index 0000000..bbbe577
--- /dev/null
+++ b/src/web/helpers/Auth.jsx
@@ -0,0 +1,66 @@
+import {getCookie, setCookie} from "react-use-cookie";
+import jwtDecode from "jwt-decode";
+
+export async function refreshToken({user, setUser}) {
+ const init = {
+ method: "POST",
+ referrer: "same-origin",
+ };
+ return fetch("/api/refresh", init)
+ .then((response) => {
+ if (!response.ok) {
+ throw new Error("server rejected refresh");
+ }
+ const user = maybeGetUser();
+ if (user == null) {
+ throw new Error("bad token response");
+ }
+ setUser(user);
+ })
+ .catch((error) => {
+ console.log(error);
+ setUser(null);
+ })
+}
+
+export function maybeGetUser() {
+ const token = getCookie("token");
+ if (token == null || token == "") {
+ return null;
+ }
+
+ const jwt = jwtDecode(token);
+ if (jwt.iss !== "react-go-forum") {
+ return null;
+ }
+
+ const expiry_date = (() => {
+ var time = new Date(Date.UTC, 0, 1);
+ time.setUTCSeconds(jwt.exp);
+ return time;
+ })();
+ if (expiry_date <= new Date(Date.now())) {
+ return null;
+ }
+
+ return {
+ id: jwt.sub,
+ expiry: expiry_date,
+ }
+}
+
+export function maybeAuthFromCookie(userState) {
+ const user = maybeGetUser();
+ if (user == null) {
+ return false;
+ }
+
+ const [_, setUser] = userState;
+ setUser(user);
+ return true;
+}
+
+export function logout(setUser) {
+ setCookie("token", "", {path: "/"});
+ setUser(null);
+} \ No newline at end of file
diff --git a/src/web/helpers/Input.jsx b/src/web/helpers/Input.jsx
new file mode 100644
index 0000000..55f6016
--- /dev/null
+++ b/src/web/helpers/Input.jsx
@@ -0,0 +1,31 @@
+export function getFieldError(field, minmax) {
+ if (field == null || field.length == 0) {
+ return "Required"
+ }
+ const [min, max] = minmax;
+ if (field.length < min) {
+ return "Too short";
+ }
+ if (field.length > max) {
+ return "Too long";
+ }
+ return null;
+}
+
+// Removes consecutive spaces.
+export function cleanField(field) {
+ return field.replace(/\s{2,}/g, " ").replace(/\n{2,}/g, "\n");
+}
+
+export function correctFieldAnimate(field, setField, fieldErrors) {
+ if (fieldErrors == null) {
+ return;
+ }
+ setField({...field, animating: true, erroring: true});
+}
+
+// Requires lower case extension.
+export function isSupportedExtension(ext) {
+ const extensions = ["png", "jpeg", "jpg"];
+ return extensions.some((e) => e == ext);
+} \ No newline at end of file
diff --git a/src/web/helpers/Location.jsx b/src/web/helpers/Location.jsx
new file mode 100644
index 0000000..cae0b9e
--- /dev/null
+++ b/src/web/helpers/Location.jsx
@@ -0,0 +1,29 @@
+import {faHouse,
+ faBolt,
+ faCode,
+ faCamera,
+ faCar,
+ faWrench,
+ faGamepad,
+ faQuestion} from "@fortawesome/free-solid-svg-icons";
+
+
+export function getSubreactFromLocation(location) {
+ const paths = location.pathname.split("/");
+ return paths.length >= 1 ? paths[1] : "";
+}
+
+export function getInfoFromSubreact(subreact) {
+ switch (subreact) {
+ case "": return {icon: faHouse, name: "home"}
+ case "t": return {icon: faBolt, name: "technology"}
+ case "g": return {icon: faGamepad, name: "gaming"}
+ case "k": return {icon: faCode, name: "programming"}
+ case "p": return {icon: faCamera, name: "photography"}
+ case "a": return {icon: faCar, name: "automobiles"}
+ case "pr": return {icon: faWrench, name: "projects"}
+ case "m": return {icon: faQuestion, name: "miscellaneous"}
+ default: break;
+ }
+ return {};
+} \ No newline at end of file