Compare commits

...

7 Commits

26 changed files with 558 additions and 392 deletions

3
.gitignore vendored
View File

@@ -2,7 +2,8 @@ dist
frontend/dist
server/dist
dist
apiDocs/
apiDocsLSTV2
# ---> Node
bun.lock
.nx

View File

@@ -1,18 +0,0 @@
meta {
name: Login
type: http
seq: 2
}
post {
url: http://localhost:4400/api/auth/login
body: json
auth: none
}
body:json {
{
"username": "matthes01",
"password": "99Monsters200Scary!"
}
}

View File

@@ -1,19 +0,0 @@
meta {
name: Register
type: http
seq: 4
}
post {
url: http://localhost:4400/api/auth/register
body: json
auth: none
}
body:json {
{
"username": "matthes01",
"email":"blake.matthes@alpla.com",
"password": "password"
}
}

View File

@@ -1,15 +0,0 @@
meta {
name: Test Protected
type: http
seq: 1
}
get {
url: http://localhost:4000/api/protected
body: none
auth: bearer
}
auth:bearer {
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsImlhdCI6MTczOTgyNjEwNiwiZXhwIjoxNzM5ODI2MTY2fQ.y8wm4PuduJdXp_fPnRohQ8VOlNRMeYszzcPdOLRwzic
}

View File

@@ -1,15 +0,0 @@
meta {
name: getUserroles
type: http
seq: 5
}
get {
url: http://localhost:4400/api/auth/getuseraccess
body: json
auth: bearer
}
auth:bearer {
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7InVzZXJfaWQiOiIyYzYzODQ3Zi1mMWVjLTRkNTAtOGFkMi05ODBkMWYzZTgwZWIiLCJ1c2VybmFtZSI6Im1hdHRoZXMwMSIsImVtYWlsIjoiYmxha2UubWF0dGhlc0BhbHBsYS5jb20iLCJyb2xlcyI6W10sInJvbGUiOiJ1c2VyIn0sImlhdCI6MTc0MDg2ODMzNCwiZXhwIjoxNzQwODcxOTM0fQ.HpPh56_8API25IeO5FSfYSvAqf97_tKUT_GEBqbggO0
}

View File

@@ -1,15 +0,0 @@
meta {
name: session
type: http
seq: 3
}
get {
url: http://localhost:3000/api/auth/session
body: json
auth: bearer
}
auth:bearer {
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7InVzZXJfaWQiOiIwNDMxNmM4Ni1mMDg2LTRjYzYtYjNkNC1jY2ExNjRhMjZmM2YiLCJ1c2VybmFtZSI6Im1hdHRoZXMwMSIsImVtYWlsIjoiIiwicGFzc3dvcmQiOiIiLCJwYXNzd29yZFRva2VuIjpudWxsLCJwYXNzd29yZFRva2VuRXhwaXJlcyI6bnVsbCwiYWNpdHZlIjp0cnVlLCJwaW5Db2RlIjpudWxsLCJsYXN0TG9naW4iOiIyMDI1LTAyLTIxVDEyOjA4OjMxLjk4NVoiLCJhZGRfVXNlciI6IkxTVF9TeXN0ZW0iLCJhZGRfRGF0ZSI6IjIwMjUtMDItMjFUMTI6MDg6MzEuOTg1WiIsInVwZF91c2VyIjoiTFNUX1N5c3RlbSIsInVwZF9kYXRlIjoiMjAyNS0wMi0yMVQxMjowODozMS45ODVaIn0sImlhdCI6MTc0MDE3NjE2MSwiZXhwIjoxNzQwMTc2NDYxfQ.voo8qqgEbapEFnreop_XhIird_1Ea-OGLaD5J1VEdmc
}

View File

@@ -1,18 +0,0 @@
meta {
name: Api Hit
type: http
seq: 1
}
post {
url: http://localhost:3000/api/hits
body: json
auth: none
}
body:json {
{
"name": "something",
"arrayData": "{someghjdsfsd}"
}
}

View File

@@ -1,18 +0,0 @@
meta {
name: get modules
type: http
seq: 2
}
get {
url: http://localhost:4000/api/server/modules
body: none
auth: none
}
body:json {
{
"name": "something",
"arrayData": "{someghjdsfsd}"
}
}

View File

@@ -1,9 +0,0 @@
{
"version": "1",
"name": "lstV2",
"type": "collection",
"ignore": [
"node_modules",
".git"
]
}

View File

@@ -1,76 +1,129 @@
import {useState} from "react";
import {useSessionStore} from "../../lib/store/sessionStore";
import {useQueryClient} from "@tanstack/react-query";
import {LstCard} from "../extendedUI/LstCard";
import {CardHeader} from "../ui/card";
import {toast} from "sonner";
import {z} from "zod";
import {useRouter} from "@tanstack/react-router";
import {Controller, useForm} from "react-hook-form";
import {zodResolver} from "@hookform/resolvers/zod";
import {Label} from "../ui/label";
import {Input} from "../ui/input";
import {Checkbox} from "../ui/checkbox";
import {Button} from "../ui/button";
const FormSchema = z.object({
username: z.string().min(1, "You must enter a valid username"),
password: z.string().min(4, "You must enter a valid password"),
rememberMe: z.boolean(),
});
const LoginForm = () => {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const {setSession} = useSessionStore();
const queryClient = useQueryClient();
const rememeberMe = localStorage.getItem("rememberMe") === "true";
const username = localStorage.getItem("username") || "";
const router = useRouter();
const {
register,
handleSubmit,
control,
formState: {errors},
} = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
username: username || "",
password: "",
rememberMe: rememeberMe,
},
});
const onSubmitLogin = async (value: z.infer<typeof FormSchema>) => {
// Do something with form data
// first update the rememberMe incase it was selected
if (value.rememberMe) {
localStorage.setItem("rememberMe", value.rememberMe.toString());
localStorage.setItem("username", value.username);
} else {
localStorage.removeItem("rememberMe");
localStorage.removeItem("username");
}
const handleLogin = async (e: React.FormEvent) => {
e.preventDefault();
// console.log("Form data", {username, password});
try {
const response = await fetch("/api/auth/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({username, password}),
body: JSON.stringify({username: value.username, password: value.password}),
});
// if (!response.ok) {
// throw new Error("Invalid credentials");
// }
const data = await response.json();
// console.log("Response", data.data);
// Store token in localStorage
localStorage.setItem("auth_token", data.data.token);
// localStorage.setItem("auth_token", data.data.token);
// Optionally store user info
// localStorage.setItem("user", JSON.stringify(user));
setSession(data.data.user, data.data.token);
// Refetch the session data to reflect the logged-in state
queryClient.invalidateQueries();
setUsername("");
setPassword("");
setSession(data.user, data.token);
toast.success(`You are logged in as ${data.user.username}`);
router.navigate({to: "/"});
} catch (err) {
console.error(err);
setError("Invalid credentials");
toast.error("Invalid credentials");
}
};
return (
<form onSubmit={handleLogin}>
<div>
<label htmlFor="username">Username</label>
<input
id="username"
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
required
/>
</div>
<div>
<label htmlFor="password">Password</label>
<input
id="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
{error && <p>{error}</p>}
<button type="submit">Login</button>
</form>
<div className="ml-[25%]">
<LstCard className="p-3 w-96">
<CardHeader>
<div>
<p className="text-2xl">Login to LST</p>
</div>
</CardHeader>
<hr className="rounded"></hr>
<form onSubmit={handleSubmit(onSubmitLogin)}>
<div>
<Label>Username</Label>
<Input
placeholder="smith001"
{...register("username")}
className={errors.username ? "border-red-500" : ""}
aria-invalid={!!errors.username}
/>
{errors.username && <p className="text-red-500 text-sm mt-1">{errors.username.message}</p>}
</div>
<div>
<>
<Label htmlFor={"password"}>Password</Label>
<Input
type="password"
{...register("password")}
className={errors.password ? "border-red-500" : ""}
aria-invalid={!!errors.password}
/>
{errors.password && <p className="text-red-500 text-sm mt-1">{errors.password.message}</p>}
</>
</div>
<div className="flex justify-between pt-2">
<div className="flex">
<Controller
render={({field}) => (
<Checkbox id="remember" checked={field.value} onCheckedChange={field.onChange} />
)}
control={control}
name="rememberMe"
defaultValue={rememeberMe}
/>
<Label htmlFor="remember" className="pl-2">
remember me
</Label>
</div>
<div className="flex justify-end">
<Button type="submit">Submit</Button>
</div>
</div>
</form>
</LstCard>
</div>
);
};

View File

@@ -1,15 +1,6 @@
import {createFileRoute, redirect, useRouter} from "@tanstack/react-router";
import {useForm, Controller} from "react-hook-form";
import {zodResolver} from "@hookform/resolvers/zod";
import {LstCard} from "../components/extendedUI/LstCard";
import {Button} from "../components/ui/button";
import {Input} from "../components/ui/input";
import {CardHeader} from "../components/ui/card";
import {Label} from "../components/ui/label";
import {toast} from "sonner";
import {useSessionStore} from "../lib/store/sessionStore";
import {Checkbox} from "../components/ui/checkbox";
import {z} from "zod";
import {createFileRoute, redirect} from "@tanstack/react-router";
import LoginForm from "@/components/auth/LoginForm";
export const Route = createFileRoute("/login")({
component: RouteComponent,
@@ -23,117 +14,10 @@ export const Route = createFileRoute("/login")({
},
});
const FormSchema = z.object({
username: z.string().min(1, "You must enter a valid username"),
password: z.string().min(4, "You must enter a valid password"),
rememberMe: z.boolean(),
});
function RouteComponent() {
const {setSession} = useSessionStore();
const rememeberMe = localStorage.getItem("rememberMe") === "true";
const username = localStorage.getItem("username") || "";
const router = useRouter();
const {
register,
handleSubmit,
control,
formState: {errors},
} = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
username: username || "",
password: "",
rememberMe: rememeberMe,
},
});
const onSubmitLogin = async (value: z.infer<typeof FormSchema>) => {
// Do something with form data
console.log(value);
// first update the rememberMe incase it was selected
if (value.rememberMe) {
localStorage.setItem("rememberMe", value.rememberMe.toString());
localStorage.setItem("username", value.username);
} else {
localStorage.removeItem("rememberMe");
localStorage.removeItem("username");
}
try {
const response = await fetch("/api/auth/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({username: value.username, password: value.password}),
});
const data = await response.json();
// Store token in localStorage
// localStorage.setItem("auth_token", data.data.token);
setSession(data.user, data.token);
toast.success(`You are logged in as ${data.user.username}`);
router.navigate({to: "/"});
} catch (err) {
toast.error("Invalid credentials");
}
};
return (
<div className="ml-[25%]">
<LstCard className="p-3 w-96">
<CardHeader>
<div>
<p className="text-2xl">Login to LST</p>
</div>
</CardHeader>
<hr className="rounded"></hr>
<form onSubmit={handleSubmit(onSubmitLogin)}>
<div>
<Label>Username</Label>
<Input
placeholder="smith001"
{...register("username")}
className={errors.username ? "border-red-500" : ""}
aria-invalid={!!errors.username}
/>
{errors.username && <p className="text-red-500 text-sm mt-1">{errors.username.message}</p>}
</div>
<div>
<>
<Label htmlFor={"password"}>Password</Label>
<Input
type="password"
{...register("password")}
className={errors.password ? "border-red-500" : ""}
aria-invalid={!!errors.password}
/>
{errors.password && <p className="text-red-500 text-sm mt-1">{errors.password.message}</p>}
</>
</div>
<div className="flex justify-between pt-2">
<div className="flex">
<Controller
render={({field}) => (
<Checkbox id="remember" checked={field.value} onCheckedChange={field.onChange} />
)}
control={control}
name="rememberMe"
defaultValue={rememeberMe}
/>
<Label htmlFor="remember" className="pl-2">
remember me
</Label>
</div>
<div className="flex justify-end">
<Button type="submit">Submit</Button>
</div>
</div>
</form>
</LstCard>
<LoginForm />
</div>
);
}

View File

@@ -18,6 +18,6 @@ import {useModuleStore} from "../lib/store/useModuleStore";
export function moduleActive(moduleName: string): boolean {
const {modules} = useModuleStore();
const module = modules.find((m: any) => m.name === moduleName);
const module = modules?.find((m: any) => m.name === moduleName);
return module ? true : false;
}

279
package-lock.json generated
View File

@@ -19,10 +19,13 @@
"cookie": "^1.0.2",
"date-fns": "^4.1.0",
"dotenv": "^16.4.7",
"drizzle-kit": "^0.30.4",
"drizzle-orm": "^0.39.3",
"drizzle-zod": "^0.7.0",
"jsonwebtoken": "^9.0.2",
"pg": "^8.13.3",
"pino": "^9.6.0",
"pino-pretty": "^13.0.0",
"postgres": "^3.4.5",
"zod": "^3.24.2"
},
@@ -34,7 +37,6 @@
"concurrently": "^8.2.0",
"cz-conventional-changelog": "^3.3.0",
"dotenv": "^16.3.1",
"drizzle-kit": "^0.30.4",
"rimraf": "^6.0.1",
"standard-version": "^9.5.0",
"tsx": "^4.7.1",
@@ -430,7 +432,6 @@
"version": "0.10.2",
"resolved": "https://registry.npmjs.org/@drizzle-team/brocli/-/brocli-0.10.2.tgz",
"integrity": "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==",
"dev": true,
"license": "Apache-2.0"
},
"node_modules/@ecies/ciphers": {
@@ -452,7 +453,6 @@
"resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.3.2.tgz",
"integrity": "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==",
"deprecated": "Merged into tsx: https://tsx.is",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "~0.18.20",
@@ -466,7 +466,6 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -483,7 +482,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -500,7 +498,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -517,7 +514,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -534,7 +530,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -551,7 +546,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -568,7 +562,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -585,7 +578,6 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -602,7 +594,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -619,7 +610,6 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -636,7 +626,6 @@
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -653,7 +642,6 @@
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -670,7 +658,6 @@
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -687,7 +674,6 @@
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -704,7 +690,6 @@
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -721,7 +706,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -738,7 +722,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -755,7 +738,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -772,7 +754,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -789,7 +770,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -806,7 +786,6 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -823,7 +802,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -837,7 +815,6 @@
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
"integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
@@ -876,7 +853,6 @@
"resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.6.5.tgz",
"integrity": "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==",
"deprecated": "Merged into tsx: https://tsx.is",
"dev": true,
"license": "MIT",
"dependencies": {
"@esbuild-kit/core-utils": "^3.3.2",
@@ -890,7 +866,6 @@
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -907,7 +882,6 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -924,7 +898,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -941,7 +914,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -958,7 +930,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -975,7 +946,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -992,7 +962,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1009,7 +978,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1026,7 +994,6 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1043,7 +1010,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1060,7 +1026,6 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1077,7 +1042,6 @@
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1094,7 +1058,6 @@
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1111,7 +1074,6 @@
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1128,7 +1090,6 @@
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1145,7 +1106,6 @@
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1162,7 +1122,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1196,7 +1155,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1230,7 +1188,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1247,7 +1204,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1264,7 +1220,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1281,7 +1236,6 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1298,7 +1252,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1824,7 +1777,6 @@
"version": "3.9.1",
"resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.1.tgz",
"integrity": "sha512-j+ejhYwY6PeB+v1kn7lZFACUIG97u90WxMuGosILFsl9d4Ovi0sjk0GlPfoEcx+FzvXZDAfioD+NGnnPamXgMA==",
"dev": true,
"license": "MIT"
},
"node_modules/@popperjs/core": {
@@ -2998,6 +2950,15 @@
"node": ">= 4.0.0"
}
},
"node_modules/atomic-sleep": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
"integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==",
"license": "MIT",
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/axios": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.1.tgz",
@@ -3130,7 +3091,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true,
"license": "MIT"
},
"node_modules/bytes": {
@@ -3404,6 +3364,12 @@
"color-support": "bin.js"
}
},
"node_modules/colorette": {
"version": "2.0.20",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
"license": "MIT"
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -4438,7 +4404,6 @@
"version": "0.30.5",
"resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.30.5.tgz",
"integrity": "sha512-l6dMSE100u7sDaTbLczibrQZjA35jLsHNqIV+jmhNVO3O8jzM6kywMOmV9uOz9ZVSCMPQhAZEFjL/qDPVrqpUA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@drizzle-team/brocli": "^0.10.2",
@@ -4631,6 +4596,15 @@
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"license": "MIT"
},
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"license": "MIT",
"dependencies": {
"once": "^1.4.0"
}
},
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
@@ -4647,7 +4621,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz",
"integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
@@ -4715,7 +4688,6 @@
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz",
"integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
@@ -4754,7 +4726,6 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz",
"integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==",
"dev": true,
"license": "MIT",
"dependencies": {
"debug": "^4.3.4"
@@ -4846,12 +4817,33 @@
"node": ">=4"
}
},
"node_modules/fast-copy": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz",
"integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==",
"license": "MIT"
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"license": "MIT"
},
"node_modules/fast-redact": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz",
"integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/fast-safe-stringify": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
"integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
"license": "MIT"
},
"node_modules/fast-uri": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
@@ -5146,7 +5138,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/gel/-/gel-2.0.0.tgz",
"integrity": "sha512-Oq3Fjay71s00xzDc0BF/mpcLmnA+uRqMEJK8p5K4PaZjUEsxaeo+kR9OHBVAf289/qPd+0OcLOLUN0UhqiUCog==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@petamoriken/float16": "^3.8.7",
@@ -5342,7 +5333,6 @@
"version": "4.10.0",
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz",
"integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==",
"dev": true,
"license": "MIT",
"dependencies": {
"resolve-pkg-maps": "^1.0.0"
@@ -5943,6 +5933,12 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/help-me": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz",
"integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==",
"license": "MIT"
},
"node_modules/highlight.js": {
"version": "11.11.1",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
@@ -6414,6 +6410,15 @@
"jiti": "lib/jiti-cli.mjs"
}
},
"node_modules/joycon": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz",
"integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -7982,7 +7987,6 @@
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
"integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -8214,6 +8218,15 @@
"devOptional": true,
"license": "MIT"
},
"node_modules/on-exit-leak-free": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
"integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/on-headers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
@@ -8627,6 +8640,76 @@
"node": ">=0.10.0"
}
},
"node_modules/pino": {
"version": "9.6.0",
"resolved": "https://registry.npmjs.org/pino/-/pino-9.6.0.tgz",
"integrity": "sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==",
"license": "MIT",
"dependencies": {
"atomic-sleep": "^1.0.0",
"fast-redact": "^3.1.1",
"on-exit-leak-free": "^2.1.0",
"pino-abstract-transport": "^2.0.0",
"pino-std-serializers": "^7.0.0",
"process-warning": "^4.0.0",
"quick-format-unescaped": "^4.0.3",
"real-require": "^0.2.0",
"safe-stable-stringify": "^2.3.1",
"sonic-boom": "^4.0.1",
"thread-stream": "^3.0.0"
},
"bin": {
"pino": "bin.js"
}
},
"node_modules/pino-abstract-transport": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz",
"integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==",
"license": "MIT",
"dependencies": {
"split2": "^4.0.0"
}
},
"node_modules/pino-pretty": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.0.0.tgz",
"integrity": "sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==",
"license": "MIT",
"dependencies": {
"colorette": "^2.0.7",
"dateformat": "^4.6.3",
"fast-copy": "^3.0.2",
"fast-safe-stringify": "^2.1.1",
"help-me": "^5.0.0",
"joycon": "^3.1.1",
"minimist": "^1.2.6",
"on-exit-leak-free": "^2.1.0",
"pino-abstract-transport": "^2.0.0",
"pump": "^3.0.0",
"secure-json-parse": "^2.4.0",
"sonic-boom": "^4.0.1",
"strip-json-comments": "^3.1.1"
},
"bin": {
"pino-pretty": "bin.js"
}
},
"node_modules/pino-pretty/node_modules/dateformat": {
"version": "4.6.3",
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz",
"integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==",
"license": "MIT",
"engines": {
"node": "*"
}
},
"node_modules/pino-std-serializers": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz",
"integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==",
"license": "MIT"
},
"node_modules/postcss": {
"version": "8.5.3",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
@@ -8766,6 +8849,22 @@
"dev": true,
"license": "MIT"
},
"node_modules/process-warning": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz",
"integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "MIT"
},
"node_modules/property-information": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/property-information/-/property-information-7.0.0.tgz",
@@ -8782,6 +8881,16 @@
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/pump": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
"integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
"license": "MIT",
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"node_modules/q": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
@@ -8794,6 +8903,12 @@
"teleport": ">=0.2.0"
}
},
"node_modules/quick-format-unescaped": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
"integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==",
"license": "MIT"
},
"node_modules/quick-lru": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
@@ -8972,6 +9087,15 @@
"node": ">= 6"
}
},
"node_modules/real-require": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
"integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==",
"license": "MIT",
"engines": {
"node": ">= 12.13.0"
}
},
"node_modules/redent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
@@ -9219,7 +9343,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
@@ -9349,6 +9472,15 @@
],
"license": "MIT"
},
"node_modules/safe-stable-stringify": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
"integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
@@ -9356,6 +9488,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/secure-json-parse": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz",
"integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==",
"license": "BSD-3-Clause"
},
"node_modules/semver": {
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
@@ -9413,11 +9551,19 @@
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"license": "ISC"
},
"node_modules/sonic-boom": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz",
"integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==",
"license": "MIT",
"dependencies": {
"atomic-sleep": "^1.0.0"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
@@ -9436,7 +9582,6 @@
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
"license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
@@ -9807,7 +9952,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -9910,6 +10054,15 @@
"node": ">=0.10"
}
},
"node_modules/thread-stream": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz",
"integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==",
"license": "MIT",
"dependencies": {
"real-require": "^0.2.0"
}
},
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",

View File

@@ -29,25 +29,27 @@
"cookie": "^1.0.2",
"date-fns": "^4.1.0",
"dotenv": "^16.4.7",
"drizzle-kit": "^0.30.4",
"drizzle-orm": "^0.39.3",
"drizzle-zod": "^0.7.0",
"jsonwebtoken": "^9.0.2",
"pg": "^8.13.3",
"pino": "^9.6.0",
"pino-pretty": "^13.0.0",
"postgres": "^3.4.5",
"zod": "^3.24.2",
"drizzle-kit": "^0.30.4"
"zod": "^3.24.2"
},
"devDependencies": {
"@types/node": "^22.13.5",
"concurrently": "^8.2.0",
"dotenv": "^16.3.1",
"tsx": "^4.7.1",
"@types/bcrypt": "^5.0.2",
"@types/js-cookie": "^3.0.6",
"@types/node": "^22.13.5",
"@types/pg": "^8.11.11",
"concurrently": "^8.2.0",
"cz-conventional-changelog": "^3.3.0",
"dotenv": "^16.3.1",
"rimraf": "^6.0.1",
"standard-version": "^9.5.0",
"tsx": "^4.7.1",
"typescript": "~5.7.3"
},
"config": {

View File

@@ -3,6 +3,7 @@ import {OpenAPIHono} from "@hono/zod-openapi";
import {serveStatic} from "@hono/node-server/serve-static";
import {logger} from "hono/logger";
import {cors} from "hono/cors";
import {log} from "./services/logger/logger.js";
// custom routes
import scalar from "./services/general/route/scalar.js";
@@ -63,7 +64,7 @@ serve(
port: Number(process.env.VITE_SERVER_PORT),
},
(info) => {
console.log(`Server is running on http://localhost:${info.port}`);
log.info({username: "LST-SYSTEM"}, `Server is running on http://localhost:${info.port}`);
}
);

View File

@@ -1,22 +1,24 @@
import {OpenAPIHono} from "@hono/zod-openapi";
import {authMiddleware} from "./middleware/authMiddleware.js";
import login from "./routes/login.js";
import register from "./routes/register.js";
import session from "./routes/session.js";
import getAccess from "./routes/userRoles/getUserRoles.js";
import setAccess from "./routes/userRoles/setUserRoles.js";
import profile from "./routes/user/profileUpdate.js";
const app = new OpenAPIHono();
app.route("auth/login", login);
app.route("auth/register", register);
app.route("auth/session", session);
// required to login
app.use("auth/getuseraccess", authMiddleware);
/* User area just needs to be logged in to enter here */
app.route("/auth/profileUpdate", profile);
/* will need to increase to make sure the person coming here has the correct permissions */
app.route("/auth/getuseraccess", getAccess);
app.use("auth/setuseraccess", authMiddleware);
app.route("/auth/setuseraccess", setAccess);
export default app;

View File

@@ -4,6 +4,7 @@ import {users} from "../../../../database/schema/users.js";
import {eq, sql} from "drizzle-orm";
import {checkPassword} from "../utils/checkPassword.js";
import {roleCheck} from "./userRoles/getUserAccess.js";
import {log} from "../../logger/logger.js";
/**
* Authenticate a user and return a JWT.
@@ -42,14 +43,18 @@ export async function login(
};
// update the user last login
// try {
// db.update(users)
// .set({lastLogin: sql`NOW()`})
// .where(eq(users.user_id, user[0].user_id));
// } catch (e) {
// console.log(e);
// }
const token = sign({user: userData}, secret, {expiresIn: expiresIn * 60});
try {
const lastLog = await db
.update(users)
.set({lastLogin: sql`NOW()`})
.where(eq(users.user_id, user[0].user_id))
.returning({lastLogin: users.lastLogin});
log.info(`Its been 5days since ${user[0].username} has logged in`);
//]);
} catch (error) {
log.error(error, "There was an error updating the user last login");
}
const token = sign({user: userData}, secret, {expiresIn: expiresIn * 60});
return {token, user: userData};
}

View File

@@ -0,0 +1,38 @@
import {eq, sql} from "drizzle-orm";
import {db} from "../../../../../database/dbclient.js";
import {users} from "../../../../../database/schema/users.js";
import {log} from "../../../logger/logger.js";
import {createPassword} from "../../utils/createPassword.js";
const blacklistedTokens = new Set();
function blacklistToken(token: string) {
blacklistedTokens.add(token);
setTimeout(() => blacklistedTokens.delete(token), 3600 * 1000); // Remove after 1 hour
}
function isTokenBlacklisted(token: string) {
return blacklistedTokens.has(token);
}
export const updateProfile = async (user: any, data: any, token: string) => {
if (isTokenBlacklisted(token)) {
log.warn(`${user.username} is trying to use a black listed token`);
throw Error("This token was already used");
}
log.info(`${user.user_id}`);
//re salt and encrypt the password
try {
const saltPass = await createPassword(data.password);
// update the password
const profileUpdate = await db
.update(users)
.set({password: saltPass, upd_user: user.username, upd_date: sql`NOW()`})
.where(eq(users.user_id, user.user_id));
blacklistToken(token);
} catch (error) {
log.error(error, "There was an error updating the users profile");
}
};

View File

@@ -1,5 +1,6 @@
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
import {login} from "../controllers/login.js";
import {log} from "../../logger/logger.js";
const app = new OpenAPIHono();
@@ -77,7 +78,7 @@ app.openapi(route, async (c) => {
try {
const {token, user} = await login(username.toLowerCase(), password);
log.info({username: username}, "logged in");
// Set the JWT as an HTTP-only cookie
//c.header("Set-Cookie", `auth_token=${token}; HttpOnly; Secure; Path=/; SameSite=None; Max-Age=3600`);

View File

@@ -1,9 +1,9 @@
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
import {verify} from "hono/jwt";
import {log} from "../../logger/logger.js";
import {authMiddleware} from "../middleware/authMiddleware.js";
const session = new OpenAPIHono();
const tags = ["Auth"];
const JWT_SECRET = process.env.JWT_SECRET!;
const UserSchema = z.object({
username: z
@@ -21,11 +21,12 @@ const UserSchema = z.object({
session.openapi(
createRoute({
tags,
tags: ["Auth"],
summary: "Checks a user session based on there token",
description: "Can post there via Authentiaction header or cookies",
method: "get",
path: "/",
middleware: authMiddleware,
// request: {
// body: {
// content: {
@@ -79,8 +80,10 @@ session.openapi(
try {
const payload = await verify(token, process.env.JWT_SECRET!);
return c.json({data: {token: token, user: payload.user}}, 200);
} catch (error) {}
return c.json({data: {token: "tsfds"}}, 200);
} catch (error) {
log.error(error, "Failed session check, user must be logged out");
return c.json({message: "Unauthorized"}, 401);
}
}
);

View File

@@ -0,0 +1,95 @@
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
import {authMiddleware} from "../../middleware/authMiddleware.js";
import {updateProfile} from "../../controllers/users/updateProfile.js";
import {verify} from "hono/jwt";
import {log} from "../../../logger/logger.js";
const app = new OpenAPIHono();
const UserSchema = z.object({
password: z
.string()
.min(6, {message: "Passwords must be longer than 3 characters"})
.regex(/[A-Z]/, {message: "Password must contain at least one uppercase letter"})
.regex(/[\W_]/, {message: "Password must contain at least one special character"})
.openapi({example: "Password1!"}),
});
app.openapi(
createRoute({
tags: ["User"],
summary: "Updates a users Profile",
description: "Currently you can only update your password over the API",
method: "post",
path: "/",
middleware: authMiddleware,
request: {
body: {
content: {
"application/json": {schema: UserSchema},
},
},
},
responses: {
200: {
content: {
"application/json": {
schema: z.object({
message: z.string().optional().openapi({example: "User Profile has been updated"}),
}),
},
},
description: "Sucess return",
},
401: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
},
},
description: "Unauthorized",
},
500: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
},
},
description: "Internal Server Error",
},
},
}),
async (c) => {
// make sure we have a vaid user being accessed thats really logged in
const authHeader = c.req.header("Authorization");
if (authHeader?.includes("Basic")) {
return c.json({message: "You are a Basic user! Please login to get a token"}, 401);
}
if (!authHeader) {
return c.json({message: "Unauthorized"}, 401);
}
const token = authHeader?.split("Bearer ")[1] || "";
let user;
try {
const payload = await verify(token, process.env.JWT_SECRET!);
user = payload.user;
} catch (error) {
log.error(error, "Failed session check, user must be logged out");
return c.json({message: "Unauthorized"}, 401);
}
// now pass all the data over to update the user info
try {
const data = await c?.req.json();
await updateProfile(user, data, token);
return c.json({message: "Your profile has been updated"});
} catch (error) {
return c.json({message: "There was an error", error});
}
}
);
export default app;

View File

@@ -3,6 +3,7 @@ import {apiHit} from "../../../../globalUtils/apiHits.js";
import jwt from "jsonwebtoken";
import {roleCheck} from "../../controllers/userRoles/getUserAccess.js";
import type {CustomJwtPayload} from "../../../../types/jwtToken.js";
import {authMiddleware} from "../../middleware/authMiddleware.js";
const {verify} = jwt;
const app = new OpenAPIHono();
@@ -17,7 +18,7 @@ app.openapi(
summary: "Returns the useraccess table",
method: "get",
path: "/",
middleware: authMiddleware,
responses: {
200: {
content: {"application/json": {schema: responseSchema}},

View File

@@ -2,6 +2,7 @@ import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
import {setUserAccess} from "../../controllers/userRoles/setUserRoles.js";
import {apiHit} from "../../../../globalUtils/apiHits.js";
import {apiReturn} from "../../../../globalUtils/apiReturn.js";
import {authMiddleware} from "../../middleware/authMiddleware.js";
const app = new OpenAPIHono();
@@ -27,6 +28,7 @@ app.openapi(
summary: "Sets Users access",
method: "post",
path: "/",
middleware: authMiddleware,
description: "When logged in you will be able to grant new permissions",
request: {
body: {

View File

@@ -52,11 +52,11 @@ app.get(
baseServerURL: "https://scalar.com",
servers: [
{
url: `http://usday1vms006:${process.env.SERVER_PORT}`,
url: `http://usday1vms006:${process.env.VITE_SERVER_PORT}`,
description: "Production",
},
{
url: `http://localhost:${process.env.SERVER_PORT}`,
url: `http://localhost:${process.env.VITE_SERVER_PORT}`,
description: "dev server",
},
],

View File

@@ -0,0 +1,52 @@
import {pino, type Logger} from "pino";
export let logLevel = "info";
const transport = pino.transport({
targets: [
{
target: "pino-pretty",
options: {
colorize: true,
// customPrettifiers: {
// time: (timestamp) => `🕰 ${timestamp}`,
// },
destination: process.stdout.fd,
},
},
{
target: "pino-pretty",
options: {
colorize: false,
destination: "./logs/logs.log",
mkdir: true,
},
},
],
});
export const log = pino(
{
level: process.env.LOG_LEVEL || logLevel,
// formatters: {
// level: (label) => {
// return {level: label.toUpperCase()};
// },
// },
customLevels: {death: 70},
// removes data from the logs that we dont want to be shown :D
redact: {paths: ["email", "password"], remove: true},
},
transport
);
// setTimeout(() => {
// const fun = () => {
// throw Error("Just an error");
// };
// try {
// fun();
// } catch (error) {
// log.error(error, "Somethingbad");
// }
// });