feat(auth): add, update were added for adm account in backend only
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
import {OpenAPIHono} from "@hono/zod-openapi";
|
||||
import {authMiddleware} from "./middleware/authMiddleware.js";
|
||||
|
||||
import { OpenAPIHono } from "@hono/zod-openapi";
|
||||
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 getAccess from "./routes/user/getUserRoles.js";
|
||||
import setAccess from "./routes/userAdmin/setUserRoles.js";
|
||||
import profile from "./routes/user/profileUpdate.js";
|
||||
import {areRolesIn} from "./utils/roleCheck.js";
|
||||
import { areRolesIn } from "./utils/roleCheck.js";
|
||||
import createUser from "./routes/userAdmin/createUser.js";
|
||||
import allUsers from "./routes/userAdmin/getUsers.js";
|
||||
import updateUser from "./routes/userAdmin/updateUser.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
@@ -16,15 +17,21 @@ setTimeout(() => {
|
||||
areRolesIn();
|
||||
}, 5000);
|
||||
|
||||
app.route("auth/login", login);
|
||||
app.route("auth/register", register);
|
||||
app.route("auth/session", session);
|
||||
const routes = [
|
||||
login,
|
||||
register,
|
||||
session,
|
||||
profile,
|
||||
getAccess,
|
||||
setAccess,
|
||||
createUser,
|
||||
allUsers,
|
||||
updateUser,
|
||||
] as const;
|
||||
|
||||
// required to login
|
||||
/* User area just needs to be logged in to enter here */
|
||||
app.route("auth/profileupdate", profile);
|
||||
// app.route("/server", modules);
|
||||
const appRoutes = routes.forEach((route) => {
|
||||
app.route("/auth", route);
|
||||
});
|
||||
|
||||
/* will need to increase to make sure the person coming here has the correct permissions */
|
||||
app.route("auth/getuseraccess", getAccess);
|
||||
app.route("auth/setuseraccess", setAccess);
|
||||
export default app;
|
||||
|
||||
24
server/services/auth/controllers/userAdmin/getUsers.ts
Normal file
24
server/services/auth/controllers/userAdmin/getUsers.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { db } from "../../../../../database/dbclient.js";
|
||||
import { users } from "../../../../../database/schema/users.js";
|
||||
import { returnRes } from "../../../../globalUtils/routeDefs/returnRes.js";
|
||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||
import { createLog } from "../../../logger/logger.js";
|
||||
|
||||
export const getAllUsers = async () => {
|
||||
/**
|
||||
* returns all users that are in lst
|
||||
*/
|
||||
createLog("info", "apiAuthedRoute", "auth", "Get all users");
|
||||
const { data, error } = await tryCatch(db.select().from(users));
|
||||
|
||||
if (error) {
|
||||
returnRes(
|
||||
false,
|
||||
"There was an error getting users",
|
||||
new Error("No user exists.")
|
||||
);
|
||||
}
|
||||
|
||||
returnRes(true, "All users.", data);
|
||||
return { success: true, message: "All users", data };
|
||||
};
|
||||
68
server/services/auth/controllers/userAdmin/updateUserAdm.ts
Normal file
68
server/services/auth/controllers/userAdmin/updateUserAdm.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../../../../../database/dbclient.js";
|
||||
import { users } from "../../../../../database/schema/users.js";
|
||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||
import type { User } from "../../../../types/users.js";
|
||||
import { createPassword } from "../../utils/createPassword.js";
|
||||
import { createLog } from "../../../logger/logger.js";
|
||||
|
||||
export const updateUserADM = async (userData: User) => {
|
||||
/**
|
||||
* The user model will need to be passed over so we can update per the request on the user.
|
||||
* password, username, email.
|
||||
*/
|
||||
|
||||
createLog(
|
||||
"info",
|
||||
"apiAuthedRoute",
|
||||
"auth",
|
||||
`${userData.user_id} is being updated.`
|
||||
);
|
||||
// get the orignal user info
|
||||
const { data: user, error: userError } = await tryCatch(
|
||||
db.select().from(users).where(eq(users.user_id, userData.user_id!))
|
||||
);
|
||||
|
||||
if (userError) {
|
||||
return {
|
||||
success: false,
|
||||
message: "There was an error getting the user",
|
||||
userError,
|
||||
};
|
||||
}
|
||||
if (user?.length === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message:
|
||||
"The user you are looking for has either been deleted or dose not exist.",
|
||||
};
|
||||
}
|
||||
const upd_user = user as User;
|
||||
const password: string = userData.password
|
||||
? await createPassword(userData.password!)
|
||||
: upd_user.password!;
|
||||
const data = {
|
||||
username: userData.username ? userData.username : upd_user?.username,
|
||||
password: password,
|
||||
email: userData.email ? userData.email : upd_user.email,
|
||||
};
|
||||
|
||||
// term ? ilike(posts.title, term) : undefined
|
||||
const { data: updData, error: updError } = await tryCatch(
|
||||
db.update(users).set(data).where(eq(users.user_id, userData.user_id!))
|
||||
);
|
||||
|
||||
if (updError) {
|
||||
return {
|
||||
success: false,
|
||||
message: "There was an error getting the user",
|
||||
updError,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: `${userData.username} has been updated.`,
|
||||
updData,
|
||||
};
|
||||
};
|
||||
85
server/services/auth/middleware/roleCheck.ts
Normal file
85
server/services/auth/middleware/roleCheck.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { createMiddleware } from "hono/factory";
|
||||
|
||||
import type { CustomJwtPayload } from "../../../types/jwtToken.js";
|
||||
import { verify } from "hono/jwt";
|
||||
import { db } from "../../../../database/dbclient.js";
|
||||
import { modules } from "../../../../database/schema/modules.js";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { userRoles } from "../../../../database/schema/userRoles.js";
|
||||
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||
|
||||
const hasCorrectRole = (requiredRole: string[], module: string) =>
|
||||
createMiddleware(async (c, next) => {
|
||||
/**
|
||||
* We want to check to make sure you have the correct role to be here
|
||||
*/
|
||||
const authHeader = c.req.header("Authorization");
|
||||
|
||||
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
||||
return c.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const token = authHeader.split(" ")[1];
|
||||
|
||||
// deal with token data
|
||||
const { data: tokenData, error: tokenError } = await tryCatch(
|
||||
verify(token, process.env.JWT_SECRET!)
|
||||
);
|
||||
|
||||
if (tokenError) {
|
||||
return c.json({ error: "Invalid token" }, 401);
|
||||
}
|
||||
|
||||
const customToken = tokenData as CustomJwtPayload;
|
||||
|
||||
// Get the module
|
||||
const { data: mod, error: modError } = await tryCatch(
|
||||
db.select().from(modules).where(eq(modules.name, module))
|
||||
);
|
||||
if (modError) {
|
||||
console.log(modError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mod.length === 0) {
|
||||
return c.json({ error: "You have entered an invalid module name" }, 403);
|
||||
}
|
||||
|
||||
// check if the user has the role needed to get into this module
|
||||
const { data: userRole, error: userRoleError } = await tryCatch(
|
||||
db
|
||||
.select()
|
||||
.from(userRoles)
|
||||
.where(
|
||||
and(
|
||||
eq(userRoles.module_id, mod[0].module_id),
|
||||
eq(userRoles.user_id, customToken.user?.user_id!)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if (userRoleError) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!userRole) {
|
||||
return c.json(
|
||||
{
|
||||
error:
|
||||
"The module you are trying to access is not active or is invalid.",
|
||||
},
|
||||
403
|
||||
);
|
||||
}
|
||||
|
||||
if (!requiredRole.includes(userRole[0]?.role)) {
|
||||
return c.json(
|
||||
{ error: "You do not have access to this part of the app." },
|
||||
403
|
||||
);
|
||||
}
|
||||
|
||||
await next();
|
||||
});
|
||||
|
||||
export default hasCorrectRole;
|
||||
@@ -1,26 +1,26 @@
|
||||
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
|
||||
import {login} from "../controllers/login.js";
|
||||
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
||||
import { login } from "../controllers/login.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
const UserSchema = z
|
||||
.object({
|
||||
username: z.string().optional().openapi({example: "smith002"}),
|
||||
.object({
|
||||
username: z.string().optional().openapi({ example: "smith002" }),
|
||||
//email: z.string().optional().openapi({example: "s.smith@example.com"}),
|
||||
password: z.string().openapi({example: "password123"}),
|
||||
})
|
||||
.openapi("User");
|
||||
password: z.string().openapi({ example: "password123" }),
|
||||
})
|
||||
.openapi("User");
|
||||
|
||||
const route = createRoute({
|
||||
tags: ["Auth"],
|
||||
summary: "Login as user",
|
||||
description: "Login as a user to get a JWT token",
|
||||
method: "post",
|
||||
path: "/",
|
||||
path: "/login",
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
"application/json": {schema: UserSchema},
|
||||
"application/json": { schema: UserSchema },
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -29,8 +29,8 @@ const route = createRoute({
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
success: z.boolean().openapi({example: true}),
|
||||
message: z.string().openapi({example: "Logged in"}),
|
||||
success: z.boolean().openapi({ example: true }),
|
||||
message: z.string().openapi({ example: "Logged in" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -41,8 +41,10 @@ const route = createRoute({
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
success: z.boolean().openapi({example: false}),
|
||||
message: z.string().openapi({example: "Username and password required"}),
|
||||
success: z.boolean().openapi({ example: false }),
|
||||
message: z
|
||||
.string()
|
||||
.openapi({ example: "Username and password required" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -52,8 +54,10 @@ const route = createRoute({
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
success: z.boolean().openapi({example: false}),
|
||||
message: z.string().openapi({example: "Username and password required"}),
|
||||
success: z.boolean().openapi({ example: false }),
|
||||
message: z
|
||||
.string()
|
||||
.openapi({ example: "Username and password required" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -63,7 +67,7 @@ const route = createRoute({
|
||||
});
|
||||
|
||||
app.openapi(route, async (c) => {
|
||||
const {username, password, email} = await c.req.json();
|
||||
const { username, password, email } = await c.req.json();
|
||||
|
||||
if (!username || !password) {
|
||||
return c.json(
|
||||
@@ -76,14 +80,17 @@ app.openapi(route, async (c) => {
|
||||
}
|
||||
|
||||
try {
|
||||
const {token, user} = await login(username.toLowerCase(), password);
|
||||
const { token, user } = await login(username.toLowerCase(), password);
|
||||
|
||||
// Set the JWT as an HTTP-only cookie
|
||||
//c.header("Set-Cookie", `auth_token=${token}; HttpOnly; Secure; Path=/; SameSite=None; Max-Age=3600`);
|
||||
|
||||
return c.json({success: true, message: "Login successful", user, token}, 200);
|
||||
return c.json(
|
||||
{ success: true, message: "Login successful", user, token },
|
||||
200
|
||||
);
|
||||
} catch (err) {
|
||||
return c.json({success: false, message: "Incorrect Credentials"}, 401);
|
||||
return c.json({ success: false, message: "Incorrect Credentials" }, 401);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
|
||||
import {apiHit} from "../../../globalUtils/apiHits.js";
|
||||
import {registerUser} from "../controllers/register.js";
|
||||
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
||||
import { apiHit } from "../../../globalUtils/apiHits.js";
|
||||
import { registerUser } from "../controllers/register.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
@@ -8,21 +8,25 @@ const UserSchema = z.object({
|
||||
username: z
|
||||
.string()
|
||||
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
||||
.openapi({example: "smith034"}),
|
||||
email: z.string().email().openapi({example: "smith@example.com"}),
|
||||
.openapi({ example: "smith034" }),
|
||||
email: z.string().email().openapi({ example: "smith@example.com" }),
|
||||
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!"}),
|
||||
.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!" }),
|
||||
});
|
||||
|
||||
type User = z.infer<typeof UserSchema>;
|
||||
|
||||
const responseSchema = z.object({
|
||||
success: z.boolean().optional().openapi({example: true}),
|
||||
message: z.string().optional().openapi({example: "User Created"}),
|
||||
success: z.boolean().optional().openapi({ example: true }),
|
||||
message: z.string().optional().openapi({ example: "User Created" }),
|
||||
});
|
||||
|
||||
app.openapi(
|
||||
@@ -30,25 +34,27 @@ app.openapi(
|
||||
tags: ["Auth"],
|
||||
summary: "Register a new user",
|
||||
method: "post",
|
||||
path: "/",
|
||||
path: "/register",
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
"application/json": {schema: UserSchema},
|
||||
"application/json": { schema: UserSchema },
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
content: {"application/json": {schema: responseSchema}},
|
||||
content: { "application/json": { schema: responseSchema } },
|
||||
description: "Retrieve the user",
|
||||
},
|
||||
400: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
success: z.boolean().openapi({example: false}),
|
||||
message: z.string().openapi({example: "Invalid credentials passed"}),
|
||||
success: z.boolean().openapi({ example: false }),
|
||||
message: z
|
||||
.string()
|
||||
.openapi({ example: "Invalid credentials passed" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -58,11 +64,11 @@ app.openapi(
|
||||
}),
|
||||
async (c) => {
|
||||
// apit hit
|
||||
apiHit(c, {endpoint: "api/auth/register"});
|
||||
let {username, email, password} = await c.req.json();
|
||||
apiHit(c, { endpoint: "api/auth/register" });
|
||||
let { username, email, password } = await c.req.json();
|
||||
|
||||
if (!username || !email || !password) {
|
||||
return c.json({success: false, message: "Credentials missing"}, 400);
|
||||
return c.json({ success: false, message: "Credentials missing" }, 400);
|
||||
}
|
||||
|
||||
// some usernames that should be ignored
|
||||
@@ -80,7 +86,14 @@ app.openapi(
|
||||
try {
|
||||
const register = await registerUser(username, password, email);
|
||||
|
||||
return c.json({success: register.success, message: register.message, user: register?.user}, 200);
|
||||
return c.json(
|
||||
{
|
||||
success: register.success,
|
||||
message: register.message,
|
||||
user: register?.user,
|
||||
},
|
||||
200
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return c.json(
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
|
||||
import {verify} from "hono/jwt";
|
||||
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
||||
import { verify } from "hono/jwt";
|
||||
|
||||
import {authMiddleware} from "../middleware/authMiddleware.js";
|
||||
import { authMiddleware } from "../middleware/authMiddleware.js";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
const session = new OpenAPIHono();
|
||||
const expiresIn = Number(process.env.JWT_EXPIRES!) || 60;
|
||||
const secret: string = process.env.JWT_SECRET!;
|
||||
|
||||
const {sign} = jwt;
|
||||
const { sign } = jwt;
|
||||
const UserSchema = z.object({
|
||||
username: z
|
||||
.string()
|
||||
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
||||
.openapi({example: "smith034"}),
|
||||
email: z.string().email().openapi({example: "smith@example.com"}),
|
||||
.openapi({ example: "smith034" }),
|
||||
email: z.string().email().openapi({ example: "smith@example.com" }),
|
||||
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!"}),
|
||||
.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!" }),
|
||||
});
|
||||
|
||||
session.openapi(
|
||||
@@ -29,7 +33,7 @@ session.openapi(
|
||||
summary: "Checks a user session based on there token",
|
||||
description: "Can post there via Authentiaction header or cookies",
|
||||
method: "get",
|
||||
path: "/",
|
||||
path: "/session",
|
||||
middleware: authMiddleware,
|
||||
// request: {
|
||||
// body: {
|
||||
@@ -44,7 +48,11 @@ session.openapi(
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
data: z.object({
|
||||
token: z.string().openapi({example: "sdkjhgsldkvhdakl;jvhs;adkjfhvds.kvnsad;ovhads"}),
|
||||
token: z
|
||||
.string()
|
||||
.openapi({
|
||||
example: "sdkjhgsldkvhdakl;jvhs;adkjfhvds.kvnsad;ovhads",
|
||||
}),
|
||||
// user: z.object({
|
||||
// user_id: z.string().openapi({example: "04316c86-f086-4cc6-b3d4-cca164a26f3f"}),
|
||||
// username: z.string().openapi({example: "smith"}),
|
||||
@@ -60,7 +68,7 @@ session.openapi(
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
message: z.string().openapi({example: "Unathenticated"}),
|
||||
message: z.string().openapi({ example: "Unathenticated" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -72,11 +80,14 @@ session.openapi(
|
||||
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);
|
||||
return c.json(
|
||||
{ message: "You are a Basic user! Please login to get a token" },
|
||||
401
|
||||
);
|
||||
}
|
||||
|
||||
if (!authHeader) {
|
||||
return c.json({message: "Unauthorized"}, 401);
|
||||
return c.json({ message: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const token = authHeader?.split("Bearer ")[1] || "";
|
||||
@@ -85,11 +96,13 @@ session.openapi(
|
||||
const payload = await verify(token, process.env.JWT_SECRET!);
|
||||
|
||||
// If it's valid, return a new token
|
||||
const newToken = sign({user: payload.user}, secret, {expiresIn: expiresIn * 60});
|
||||
const newToken = sign({ user: payload.user }, secret, {
|
||||
expiresIn: expiresIn * 60,
|
||||
});
|
||||
|
||||
return c.json({data: {token: newToken, user: payload.user}}, 200);
|
||||
return c.json({ data: { token: newToken, user: payload.user } }, 200);
|
||||
} catch (error) {
|
||||
return c.json({message: "Unauthorized"}, 401);
|
||||
return c.json({ message: "Unauthorized" }, 401);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
62
server/services/auth/routes/user/getUserRoles.ts
Normal file
62
server/services/auth/routes/user/getUserRoles.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
||||
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
import type { CustomJwtPayload } from "../../../../types/jwtToken.js";
|
||||
import { authMiddleware } from "../../middleware/authMiddleware.js";
|
||||
import hasCorrectRole from "../../middleware/roleCheck.js";
|
||||
import { roleCheck } from "../../controllers/userRoles/getUserAccess.js";
|
||||
|
||||
const { verify } = jwt;
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
const responseSchema = z.object({
|
||||
message: z.string().optional().openapi({ example: "User Created" }),
|
||||
});
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["Auth:user"],
|
||||
summary: "returns the users access",
|
||||
method: "get",
|
||||
path: "/getAccess",
|
||||
middleware: [authMiddleware],
|
||||
responses: {
|
||||
200: {
|
||||
content: { "application/json": { schema: responseSchema } },
|
||||
description: "Retrieve the user",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (c) => {
|
||||
// apit hit
|
||||
//apiHit(c, { endpoint: "api/auth/getUserRoles" });
|
||||
const authHeader = c.req.header("Authorization");
|
||||
const token = authHeader?.split("Bearer ")[1] || "";
|
||||
try {
|
||||
const secret = process.env.JWT_SECRET!;
|
||||
if (!secret) {
|
||||
throw new Error("JWT_SECRET is not defined in environment variables");
|
||||
}
|
||||
|
||||
const payload = verify(token, secret) as CustomJwtPayload;
|
||||
|
||||
const canAccess = await roleCheck(payload.user?.user_id);
|
||||
|
||||
return c.json(
|
||||
{
|
||||
sucess: true,
|
||||
message: `User ${payload.user?.username} can access`,
|
||||
data: canAccess,
|
||||
},
|
||||
200
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
return c.json({ message: "UserRoles coming over" });
|
||||
}
|
||||
);
|
||||
|
||||
export default app;
|
||||
@@ -1,31 +1,35 @@
|
||||
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 {createLog} from "../../../logger/logger.js";
|
||||
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 { createLog } 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!"}),
|
||||
.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"],
|
||||
tags: ["auth:user"],
|
||||
summary: "Updates a users Profile",
|
||||
description: "Currently you can only update your password over the API",
|
||||
method: "post",
|
||||
path: "/",
|
||||
path: "/profile",
|
||||
middleware: authMiddleware,
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
"application/json": {schema: UserSchema},
|
||||
"application/json": { schema: UserSchema },
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -34,7 +38,10 @@ app.openapi(
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
message: z.string().optional().openapi({example: "User Profile has been updated"}),
|
||||
message: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({ example: "User Profile has been updated" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -43,7 +50,12 @@ app.openapi(
|
||||
401: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
|
||||
schema: z.object({
|
||||
message: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({ example: "Unauthenticated" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
description: "Unauthorized",
|
||||
@@ -51,7 +63,12 @@ app.openapi(
|
||||
500: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
|
||||
schema: z.object({
|
||||
message: z
|
||||
.string()
|
||||
.optional()
|
||||
.openapi({ example: "Internal Server error" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
description: "Internal Server Error",
|
||||
@@ -63,11 +80,14 @@ app.openapi(
|
||||
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);
|
||||
return c.json(
|
||||
{ message: "You are a Basic user! Please login to get a token" },
|
||||
401
|
||||
);
|
||||
}
|
||||
|
||||
if (!authHeader) {
|
||||
return c.json({message: "Unauthorized"}, 401);
|
||||
return c.json({ message: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const token = authHeader?.split("Bearer ")[1] || "";
|
||||
@@ -77,17 +97,22 @@ app.openapi(
|
||||
const payload = await verify(token, process.env.JWT_SECRET!);
|
||||
user = payload.user;
|
||||
} catch (error) {
|
||||
createLog("error", "lst", "auth", "Failed session check, user must be logged out");
|
||||
return c.json({message: "Unauthorized"}, 401);
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"auth",
|
||||
"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"});
|
||||
return c.json({ message: "Your profile has been updated" });
|
||||
} catch (error) {
|
||||
return c.json({message: "There was an error", error});
|
||||
return c.json({ message: "There was an error", error });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
115
server/services/auth/routes/userAdmin/createUser.ts
Normal file
115
server/services/auth/routes/userAdmin/createUser.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
||||
import { registerUser } from "../../controllers/register.js";
|
||||
import { authMiddleware } from "../../middleware/authMiddleware.js";
|
||||
import hasCorrectRole from "../../middleware/roleCheck.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
const UserSchema = z.object({
|
||||
username: z
|
||||
.string()
|
||||
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
||||
.openapi({ example: "smith034" }),
|
||||
email: z.string().email().openapi({ example: "smith@example.com" }),
|
||||
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!" }),
|
||||
});
|
||||
|
||||
type User = z.infer<typeof UserSchema>;
|
||||
|
||||
const responseSchema = z.object({
|
||||
success: z.boolean().optional().openapi({ example: true }),
|
||||
message: z.string().optional().openapi({ example: "User Created" }),
|
||||
});
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["Auth:admin"],
|
||||
summary: "Creates user",
|
||||
method: "post",
|
||||
path: "/",
|
||||
middleware: [
|
||||
authMiddleware,
|
||||
hasCorrectRole(["admin", "systemAdmin"], "admin"),
|
||||
],
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
"application/json": { schema: UserSchema },
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
content: { "application/json": { schema: responseSchema } },
|
||||
description: "Retrieve the user",
|
||||
},
|
||||
400: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
success: z.boolean().openapi({ example: false }),
|
||||
message: z
|
||||
.string()
|
||||
.openapi({ example: "Invalid credentials passed" }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
description: "Retrieve the user",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (c) => {
|
||||
// apit hit
|
||||
//apiHit(c, {endpoint: "api/auth/register"});
|
||||
let { username, email, password } = await c.req.json();
|
||||
|
||||
if (!username || !email || !password) {
|
||||
return c.json({ success: false, message: "Credentials missing" }, 400);
|
||||
}
|
||||
|
||||
// some usernames that should be ignored
|
||||
const badActors = ["admin", "root"];
|
||||
if (badActors.includes(username)) {
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
message: `${username} is not a valid name to be registerd please try again`,
|
||||
},
|
||||
400
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const register = await registerUser(username, password, email);
|
||||
|
||||
return c.json(
|
||||
{
|
||||
success: register.success,
|
||||
message: register.message,
|
||||
user: register?.user,
|
||||
},
|
||||
200
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
message: `${username} already exists please login or reset password, if you feel this is an error please contact your admin.`,
|
||||
},
|
||||
400
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export default app;
|
||||
35
server/services/auth/routes/userAdmin/getUsers.ts
Normal file
35
server/services/auth/routes/userAdmin/getUsers.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
||||
|
||||
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
||||
|
||||
import { getAllUsers } from "../../controllers/userAdmin/getUsers.js";
|
||||
import { authMiddleware } from "../../middleware/authMiddleware.js";
|
||||
import hasCorrectRole from "../../middleware/roleCheck.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["Auth:admin"],
|
||||
summary: "Gets Users",
|
||||
method: "get",
|
||||
path: "/allusers",
|
||||
middleware: [
|
||||
authMiddleware,
|
||||
hasCorrectRole(["admin", "systemAdmin"], "admin"),
|
||||
],
|
||||
responses: responses(),
|
||||
}),
|
||||
async (c) => {
|
||||
// apit hit
|
||||
//apiHit(c, {endpoint: "api/auth/register"});
|
||||
const allUsers: any = await getAllUsers();
|
||||
return c.json({
|
||||
success: allUsers?.success,
|
||||
message: allUsers?.message,
|
||||
data: allUsers?.data,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
export default app;
|
||||
71
server/services/auth/routes/userAdmin/setUserRoles.ts
Normal file
71
server/services/auth/routes/userAdmin/setUserRoles.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
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";
|
||||
import hasCorrectRole from "../../middleware/roleCheck.js";
|
||||
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
const responseSchema = z.object({
|
||||
success: z.boolean().openapi({ example: true }),
|
||||
message: z.string().optional().openapi({ example: "user access" }),
|
||||
data: z.array(z.object({})).optional().openapi({ example: [] }),
|
||||
});
|
||||
|
||||
const UserAccess = z.object({
|
||||
username: z
|
||||
.string()
|
||||
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
||||
.openapi({ example: "smith034" }),
|
||||
module: z.string().openapi({ example: "production" }),
|
||||
role: z.string().openapi({ example: "viewer" }),
|
||||
override: z.string().optional().openapi({ example: "secretString" }),
|
||||
});
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["Auth:admin"],
|
||||
summary: "Sets Users access",
|
||||
method: "post",
|
||||
path: "/setuseraccess",
|
||||
middleware: [
|
||||
authMiddleware,
|
||||
hasCorrectRole(["admin", "systemAdmin"], "admin"),
|
||||
],
|
||||
description: "When logged in you will be able to grant new permissions",
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
"application/json": { schema: UserAccess },
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: responses(),
|
||||
}),
|
||||
async (c) => {
|
||||
//apiHit(c, { endpoint: "api/auth/setUserRoles" });
|
||||
const { username, module, role, override } = await c.req.json();
|
||||
try {
|
||||
const access = await setUserAccess(username, module, role, override);
|
||||
//return apiReturn(c, true, access?.message, access?.data, 200);
|
||||
return c.json(
|
||||
{ success: access.success, message: access.message, data: access.data },
|
||||
200
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
//return apiReturn(c, false, "Error in setting the user access", error, 400);
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
message: "Error in setting the user access",
|
||||
data: error,
|
||||
},
|
||||
400
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
export default app;
|
||||
91
server/services/auth/routes/userAdmin/updateUser.ts
Normal file
91
server/services/auth/routes/userAdmin/updateUser.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
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";
|
||||
import hasCorrectRole from "../../middleware/roleCheck.js";
|
||||
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
||||
import { updateUserADM } from "../../controllers/userAdmin/updateUserAdm.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
const responseSchema = z.object({
|
||||
success: z.boolean().openapi({ example: true }),
|
||||
message: z.string().optional().openapi({ example: "user access" }),
|
||||
data: z.array(z.object({})).optional().openapi({ example: [] }),
|
||||
});
|
||||
|
||||
const UserAccess = z.object({
|
||||
user_id: z.string().openapi({ example: "users UUID" }),
|
||||
username: z
|
||||
.string()
|
||||
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
||||
.optional()
|
||||
.openapi({ example: "smith034" }),
|
||||
email: z
|
||||
.string()
|
||||
.email()
|
||||
.optional()
|
||||
.openapi({ example: "smith@example.com" }),
|
||||
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",
|
||||
})
|
||||
.optional()
|
||||
.openapi({ example: "Password1!" }),
|
||||
});
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["Auth:admin"],
|
||||
summary: "updates a specific user",
|
||||
method: "post",
|
||||
path: "/updateuser",
|
||||
middleware: [
|
||||
authMiddleware,
|
||||
hasCorrectRole(["admin", "systemAdmin"], "admin"),
|
||||
],
|
||||
//description: "When logged in you will be able to grant new permissions",
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
"application/json": { schema: UserAccess },
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: responses(),
|
||||
}),
|
||||
async (c) => {
|
||||
//apiHit(c, { endpoint: "api/auth/setUserRoles" });
|
||||
const userData = await c.req.json();
|
||||
try {
|
||||
const userUPD: any = await updateUserADM(userData);
|
||||
//return apiReturn(c, true, access?.message, access?.data, 200);
|
||||
return c.json(
|
||||
{
|
||||
success: userUPD.success,
|
||||
message: userUPD.message,
|
||||
data: userUPD.data,
|
||||
},
|
||||
200
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
//return apiReturn(c, false, "Error in setting the user access", error, 400);
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
message: "Error in setting the user access",
|
||||
data: error,
|
||||
},
|
||||
400
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
export default app;
|
||||
@@ -1,53 +0,0 @@
|
||||
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
|
||||
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();
|
||||
|
||||
const responseSchema = z.object({
|
||||
message: z.string().optional().openapi({example: "User Created"}),
|
||||
});
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["Auth"],
|
||||
summary: "Returns the useraccess table",
|
||||
method: "get",
|
||||
path: "/",
|
||||
middleware: authMiddleware,
|
||||
responses: {
|
||||
200: {
|
||||
content: {"application/json": {schema: responseSchema}},
|
||||
description: "Retrieve the user",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (c) => {
|
||||
// apit hit
|
||||
apiHit(c, {endpoint: "api/auth/getUserRoles"});
|
||||
const authHeader = c.req.header("Authorization");
|
||||
const token = authHeader?.split("Bearer ")[1] || "";
|
||||
try {
|
||||
const secret = process.env.JWT_SECRET!;
|
||||
if (!secret) {
|
||||
throw new Error("JWT_SECRET is not defined in environment variables");
|
||||
}
|
||||
|
||||
const payload = verify(token, secret) as CustomJwtPayload;
|
||||
|
||||
const canAccess = await roleCheck(payload.user?.user_id);
|
||||
|
||||
return c.json({sucess: true, message: `User ${payload.user?.username} can access`, data: canAccess}, 200);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
return c.json({message: "UserRoles coming over"});
|
||||
}
|
||||
);
|
||||
|
||||
export default app;
|
||||
@@ -1,65 +0,0 @@
|
||||
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();
|
||||
|
||||
const responseSchema = z.object({
|
||||
success: z.boolean().openapi({example: true}),
|
||||
message: z.string().optional().openapi({example: "user access"}),
|
||||
data: z.array(z.object({})).optional().openapi({example: []}),
|
||||
});
|
||||
|
||||
const UserAccess = z.object({
|
||||
username: z
|
||||
.string()
|
||||
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
||||
.openapi({example: "smith034"}),
|
||||
module: z.string().openapi({example: "production"}),
|
||||
role: z.string().openapi({example: "viewer"}),
|
||||
override: z.string().optional().openapi({example: "secretString"}),
|
||||
});
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["Auth"],
|
||||
summary: "Sets Users access",
|
||||
method: "post",
|
||||
path: "/",
|
||||
middleware: authMiddleware,
|
||||
description: "When logged in you will be able to grant new permissions",
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
"application/json": {schema: UserAccess},
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
content: {"application/json": {schema: responseSchema}},
|
||||
description: "Retrieve the user",
|
||||
},
|
||||
400: {
|
||||
content: {"application/json": {schema: responseSchema}},
|
||||
description: "Failed to get user access",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (c) => {
|
||||
apiHit(c, {endpoint: "api/auth/setUserRoles"});
|
||||
const {username, module, role, override} = await c.req.json();
|
||||
try {
|
||||
const access = await setUserAccess(username, module, role, override);
|
||||
//return apiReturn(c, true, access?.message, access?.data, 200);
|
||||
return c.json({success: access.success, message: access.message, data: access.data}, 200);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
//return apiReturn(c, false, "Error in setting the user access", error, 400);
|
||||
return c.json({success: false, message: "Error in setting the user access", data: error}, 400);
|
||||
}
|
||||
}
|
||||
);
|
||||
export default app;
|
||||
@@ -1,4 +1,4 @@
|
||||
import type {Roles} from "./roles.js";
|
||||
import type { Roles } from "./roles.js";
|
||||
|
||||
export type User = {
|
||||
user_id?: string;
|
||||
@@ -7,4 +7,5 @@ export type User = {
|
||||
roles?: Roles[];
|
||||
role?: string;
|
||||
prod?: string;
|
||||
password?: string;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user