feat(auth): add, update were added for adm account in backend only
This commit is contained in:
@@ -1,30 +1,37 @@
|
|||||||
import {OpenAPIHono} from "@hono/zod-openapi";
|
import { OpenAPIHono } from "@hono/zod-openapi";
|
||||||
import {authMiddleware} from "./middleware/authMiddleware.js";
|
|
||||||
|
|
||||||
import login from "./routes/login.js";
|
import login from "./routes/login.js";
|
||||||
import register from "./routes/register.js";
|
import register from "./routes/register.js";
|
||||||
import session from "./routes/session.js";
|
import session from "./routes/session.js";
|
||||||
import getAccess from "./routes/userRoles/getUserRoles.js";
|
import getAccess from "./routes/user/getUserRoles.js";
|
||||||
import setAccess from "./routes/userRoles/setUserRoles.js";
|
import setAccess from "./routes/userAdmin/setUserRoles.js";
|
||||||
import profile from "./routes/user/profileUpdate.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();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
// run the role check
|
// run the role check
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
areRolesIn();
|
areRolesIn();
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
|
||||||
app.route("auth/login", login);
|
const routes = [
|
||||||
app.route("auth/register", register);
|
login,
|
||||||
app.route("auth/session", session);
|
register,
|
||||||
|
session,
|
||||||
|
profile,
|
||||||
|
getAccess,
|
||||||
|
setAccess,
|
||||||
|
createUser,
|
||||||
|
allUsers,
|
||||||
|
updateUser,
|
||||||
|
] as const;
|
||||||
|
|
||||||
// required to login
|
// app.route("/server", modules);
|
||||||
/* User area just needs to be logged in to enter here */
|
const appRoutes = routes.forEach((route) => {
|
||||||
app.route("auth/profileupdate", profile);
|
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;
|
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,90 +1,97 @@
|
|||||||
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
|
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
||||||
import {login} from "../controllers/login.js";
|
import { login } from "../controllers/login.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
const UserSchema = z
|
const UserSchema = z
|
||||||
.object({
|
.object({
|
||||||
username: z.string().optional().openapi({example: "smith002"}),
|
username: z.string().optional().openapi({ example: "smith002" }),
|
||||||
//email: z.string().optional().openapi({example: "s.smith@example.com"}),
|
//email: z.string().optional().openapi({example: "s.smith@example.com"}),
|
||||||
password: z.string().openapi({example: "password123"}),
|
password: z.string().openapi({ example: "password123" }),
|
||||||
})
|
})
|
||||||
.openapi("User");
|
.openapi("User");
|
||||||
|
|
||||||
const route = createRoute({
|
const route = createRoute({
|
||||||
tags: ["Auth"],
|
tags: ["Auth"],
|
||||||
summary: "Login as user",
|
summary: "Login as user",
|
||||||
description: "Login as a user to get a JWT token",
|
description: "Login as a user to get a JWT token",
|
||||||
method: "post",
|
method: "post",
|
||||||
path: "/",
|
path: "/login",
|
||||||
request: {
|
request: {
|
||||||
body: {
|
body: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {schema: UserSchema},
|
"application/json": { schema: UserSchema },
|
||||||
},
|
},
|
||||||
},
|
|
||||||
},
|
},
|
||||||
responses: {
|
},
|
||||||
200: {
|
responses: {
|
||||||
content: {
|
200: {
|
||||||
"application/json": {
|
content: {
|
||||||
schema: z.object({
|
"application/json": {
|
||||||
success: z.boolean().openapi({example: true}),
|
schema: z.object({
|
||||||
message: z.string().openapi({example: "Logged in"}),
|
success: z.boolean().openapi({ example: true }),
|
||||||
}),
|
message: z.string().openapi({ example: "Logged in" }),
|
||||||
},
|
}),
|
||||||
},
|
|
||||||
description: "Response message",
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
description: "Response message",
|
||||||
|
},
|
||||||
|
|
||||||
400: {
|
400: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
success: z.boolean().openapi({example: false}),
|
success: z.boolean().openapi({ example: false }),
|
||||||
message: z.string().openapi({example: "Username and password required"}),
|
message: z
|
||||||
}),
|
.string()
|
||||||
},
|
.openapi({ example: "Username and password required" }),
|
||||||
},
|
}),
|
||||||
description: "Bad request",
|
|
||||||
},
|
|
||||||
401: {
|
|
||||||
content: {
|
|
||||||
"application/json": {
|
|
||||||
schema: z.object({
|
|
||||||
success: z.boolean().openapi({example: false}),
|
|
||||||
message: z.string().openapi({example: "Username and password required"}),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
description: "Bad request",
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
description: "Bad request",
|
||||||
},
|
},
|
||||||
|
401: {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: z.object({
|
||||||
|
success: z.boolean().openapi({ example: false }),
|
||||||
|
message: z
|
||||||
|
.string()
|
||||||
|
.openapi({ example: "Username and password required" }),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: "Bad request",
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
app.openapi(route, async (c) => {
|
app.openapi(route, async (c) => {
|
||||||
const {username, password, email} = await c.req.json();
|
const { username, password, email } = await c.req.json();
|
||||||
|
|
||||||
if (!username || !password) {
|
if (!username || !password) {
|
||||||
return c.json(
|
return c.json(
|
||||||
{
|
{
|
||||||
success: false,
|
success: false,
|
||||||
message: "Username and password are required",
|
message: "Username and password are required",
|
||||||
},
|
},
|
||||||
400
|
400
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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
|
// Set the JWT as an HTTP-only cookie
|
||||||
//c.header("Set-Cookie", `auth_token=${token}; HttpOnly; Secure; Path=/; SameSite=None; Max-Age=3600`);
|
//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(
|
||||||
} catch (err) {
|
{ success: true, message: "Login successful", user, token },
|
||||||
return c.json({success: false, message: "Incorrect Credentials"}, 401);
|
200
|
||||||
}
|
);
|
||||||
|
} catch (err) {
|
||||||
|
return c.json({ success: false, message: "Incorrect Credentials" }, 401);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -1,97 +1,110 @@
|
|||||||
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
|
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
||||||
import {apiHit} from "../../../globalUtils/apiHits.js";
|
import { apiHit } from "../../../globalUtils/apiHits.js";
|
||||||
import {registerUser} from "../controllers/register.js";
|
import { registerUser } from "../controllers/register.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
const UserSchema = z.object({
|
const UserSchema = z.object({
|
||||||
username: z
|
username: z
|
||||||
.string()
|
.string()
|
||||||
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
||||||
.openapi({example: "smith034"}),
|
.openapi({ example: "smith034" }),
|
||||||
email: z.string().email().openapi({example: "smith@example.com"}),
|
email: z.string().email().openapi({ example: "smith@example.com" }),
|
||||||
password: z
|
password: z
|
||||||
.string()
|
.string()
|
||||||
.min(6, {message: "Passwords must be longer than 3 characters"})
|
.min(6, { message: "Passwords must be longer than 3 characters" })
|
||||||
.regex(/[A-Z]/, {message: "Password must contain at least one uppercase letter"})
|
.regex(/[A-Z]/, {
|
||||||
.regex(/[\W_]/, {message: "Password must contain at least one special character"})
|
message: "Password must contain at least one uppercase letter",
|
||||||
.openapi({example: "Password1!"}),
|
})
|
||||||
|
.regex(/[\W_]/, {
|
||||||
|
message: "Password must contain at least one special character",
|
||||||
|
})
|
||||||
|
.openapi({ example: "Password1!" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
type User = z.infer<typeof UserSchema>;
|
type User = z.infer<typeof UserSchema>;
|
||||||
|
|
||||||
const responseSchema = z.object({
|
const responseSchema = z.object({
|
||||||
success: z.boolean().optional().openapi({example: true}),
|
success: z.boolean().optional().openapi({ example: true }),
|
||||||
message: z.string().optional().openapi({example: "User Created"}),
|
message: z.string().optional().openapi({ example: "User Created" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["Auth"],
|
tags: ["Auth"],
|
||||||
summary: "Register a new user",
|
summary: "Register a new user",
|
||||||
method: "post",
|
method: "post",
|
||||||
path: "/",
|
path: "/register",
|
||||||
request: {
|
request: {
|
||||||
body: {
|
body: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {schema: UserSchema},
|
"application/json": { schema: UserSchema },
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
responses: {
|
},
|
||||||
200: {
|
},
|
||||||
content: {"application/json": {schema: responseSchema}},
|
responses: {
|
||||||
description: "Retrieve the user",
|
200: {
|
||||||
},
|
content: { "application/json": { schema: responseSchema } },
|
||||||
400: {
|
description: "Retrieve the user",
|
||||||
content: {
|
},
|
||||||
"application/json": {
|
400: {
|
||||||
schema: z.object({
|
content: {
|
||||||
success: z.boolean().openapi({example: false}),
|
"application/json": {
|
||||||
message: z.string().openapi({example: "Invalid credentials passed"}),
|
schema: z.object({
|
||||||
}),
|
success: z.boolean().openapi({ example: false }),
|
||||||
},
|
message: z
|
||||||
},
|
.string()
|
||||||
description: "Retrieve the user",
|
.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();
|
async (c) => {
|
||||||
|
// apit hit
|
||||||
|
apiHit(c, { endpoint: "api/auth/register" });
|
||||||
|
let { username, email, password } = await c.req.json();
|
||||||
|
|
||||||
if (!username || !email || !password) {
|
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
|
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
export default app;
|
||||||
|
|||||||
@@ -1,97 +1,110 @@
|
|||||||
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
|
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
||||||
import {verify} from "hono/jwt";
|
import { verify } from "hono/jwt";
|
||||||
|
|
||||||
import {authMiddleware} from "../middleware/authMiddleware.js";
|
import { authMiddleware } from "../middleware/authMiddleware.js";
|
||||||
import jwt from "jsonwebtoken";
|
import jwt from "jsonwebtoken";
|
||||||
|
|
||||||
const session = new OpenAPIHono();
|
const session = new OpenAPIHono();
|
||||||
const expiresIn = Number(process.env.JWT_EXPIRES!) || 60;
|
const expiresIn = Number(process.env.JWT_EXPIRES!) || 60;
|
||||||
const secret: string = process.env.JWT_SECRET!;
|
const secret: string = process.env.JWT_SECRET!;
|
||||||
|
|
||||||
const {sign} = jwt;
|
const { sign } = jwt;
|
||||||
const UserSchema = z.object({
|
const UserSchema = z.object({
|
||||||
username: z
|
username: z
|
||||||
.string()
|
.string()
|
||||||
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
||||||
.openapi({example: "smith034"}),
|
.openapi({ example: "smith034" }),
|
||||||
email: z.string().email().openapi({example: "smith@example.com"}),
|
email: z.string().email().openapi({ example: "smith@example.com" }),
|
||||||
password: z
|
password: z
|
||||||
.string()
|
.string()
|
||||||
.min(6, {message: "Passwords must be longer than 3 characters"})
|
.min(6, { message: "Passwords must be longer than 3 characters" })
|
||||||
.regex(/[A-Z]/, {message: "Password must contain at least one uppercase letter"})
|
.regex(/[A-Z]/, {
|
||||||
.regex(/[\W_]/, {message: "Password must contain at least one special character"})
|
message: "Password must contain at least one uppercase letter",
|
||||||
.openapi({example: "Password1!"}),
|
})
|
||||||
|
.regex(/[\W_]/, {
|
||||||
|
message: "Password must contain at least one special character",
|
||||||
|
})
|
||||||
|
.openapi({ example: "Password1!" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
session.openapi(
|
session.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["Auth"],
|
tags: ["Auth"],
|
||||||
summary: "Checks a user session based on there token",
|
summary: "Checks a user session based on there token",
|
||||||
description: "Can post there via Authentiaction header or cookies",
|
description: "Can post there via Authentiaction header or cookies",
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/",
|
path: "/session",
|
||||||
middleware: authMiddleware,
|
middleware: authMiddleware,
|
||||||
// request: {
|
// request: {
|
||||||
// body: {
|
// body: {
|
||||||
// content: {
|
// content: {
|
||||||
// "application/json": {schema: UserSchema},
|
// "application/json": {schema: UserSchema},
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
responses: {
|
responses: {
|
||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
data: z.object({
|
data: z.object({
|
||||||
token: z.string().openapi({example: "sdkjhgsldkvhdakl;jvhs;adkjfhvds.kvnsad;ovhads"}),
|
token: z
|
||||||
// user: z.object({
|
.string()
|
||||||
// user_id: z.string().openapi({example: "04316c86-f086-4cc6-b3d4-cca164a26f3f"}),
|
.openapi({
|
||||||
// username: z.string().openapi({example: "smith"}),
|
example: "sdkjhgsldkvhdakl;jvhs;adkjfhvds.kvnsad;ovhads",
|
||||||
// email: z.string().openapi({example: "smith@example.com"}).optional(),
|
}),
|
||||||
// }),
|
// user: z.object({
|
||||||
}),
|
// user_id: z.string().openapi({example: "04316c86-f086-4cc6-b3d4-cca164a26f3f"}),
|
||||||
}),
|
// username: z.string().openapi({example: "smith"}),
|
||||||
},
|
// email: z.string().openapi({example: "smith@example.com"}).optional(),
|
||||||
},
|
// }),
|
||||||
description: "Login successful",
|
}),
|
||||||
},
|
}),
|
||||||
401: {
|
},
|
||||||
content: {
|
|
||||||
"application/json": {
|
|
||||||
schema: z.object({
|
|
||||||
message: z.string().openapi({example: "Unathenticated"}),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
description: "Error of why you were not logged in.",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}),
|
description: "Login successful",
|
||||||
async (c) => {
|
},
|
||||||
const authHeader = c.req.header("Authorization");
|
401: {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: z.object({
|
||||||
|
message: z.string().openapi({ example: "Unathenticated" }),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: "Error of why you were not logged in.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const authHeader = c.req.header("Authorization");
|
||||||
|
|
||||||
if (authHeader?.includes("Basic")) {
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
const token = authHeader?.split("Bearer ")[1] || "";
|
|
||||||
|
|
||||||
try {
|
|
||||||
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});
|
|
||||||
|
|
||||||
return c.json({data: {token: newToken, user: payload.user}}, 200);
|
|
||||||
} catch (error) {
|
|
||||||
return c.json({message: "Unauthorized"}, 401);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!authHeader) {
|
||||||
|
return c.json({ message: "Unauthorized" }, 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = authHeader?.split("Bearer ")[1] || "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
|
||||||
|
return c.json({ data: { token: newToken, user: payload.user } }, 200);
|
||||||
|
} catch (error) {
|
||||||
|
return c.json({ message: "Unauthorized" }, 401);
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// const token = authHeader?.split("Bearer ")[1] || "";
|
// const token = authHeader?.split("Bearer ")[1] || "";
|
||||||
|
|||||||
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,95 +1,120 @@
|
|||||||
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
import {authMiddleware} from "../../middleware/authMiddleware.js";
|
import { authMiddleware } from "../../middleware/authMiddleware.js";
|
||||||
import {updateProfile} from "../../controllers/users/updateProfile.js";
|
import { updateProfile } from "../../controllers/users/updateProfile.js";
|
||||||
import {verify} from "hono/jwt";
|
import { verify } from "hono/jwt";
|
||||||
import {createLog} from "../../../logger/logger.js";
|
import { createLog } from "../../../logger/logger.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
const UserSchema = z.object({
|
const UserSchema = z.object({
|
||||||
password: z
|
password: z
|
||||||
.string()
|
.string()
|
||||||
.min(6, {message: "Passwords must be longer than 3 characters"})
|
.min(6, { message: "Passwords must be longer than 3 characters" })
|
||||||
.regex(/[A-Z]/, {message: "Password must contain at least one uppercase letter"})
|
.regex(/[A-Z]/, {
|
||||||
.regex(/[\W_]/, {message: "Password must contain at least one special character"})
|
message: "Password must contain at least one uppercase letter",
|
||||||
.openapi({example: "Password1!"}),
|
})
|
||||||
|
.regex(/[\W_]/, {
|
||||||
|
message: "Password must contain at least one special character",
|
||||||
|
})
|
||||||
|
.openapi({ example: "Password1!" }),
|
||||||
});
|
});
|
||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["User"],
|
tags: ["auth:user"],
|
||||||
summary: "Updates a users Profile",
|
summary: "Updates a users Profile",
|
||||||
description: "Currently you can only update your password over the API",
|
description: "Currently you can only update your password over the API",
|
||||||
method: "post",
|
method: "post",
|
||||||
path: "/",
|
path: "/profile",
|
||||||
middleware: authMiddleware,
|
middleware: authMiddleware,
|
||||||
request: {
|
request: {
|
||||||
body: {
|
body: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {schema: UserSchema},
|
"application/json": { schema: UserSchema },
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
responses: {
|
},
|
||||||
200: {
|
},
|
||||||
content: {
|
responses: {
|
||||||
"application/json": {
|
200: {
|
||||||
schema: z.object({
|
content: {
|
||||||
message: z.string().optional().openapi({example: "User Profile has been updated"}),
|
"application/json": {
|
||||||
}),
|
schema: z.object({
|
||||||
},
|
message: z
|
||||||
},
|
.string()
|
||||||
description: "Sucess return",
|
.optional()
|
||||||
},
|
.openapi({ example: "User Profile has been updated" }),
|
||||||
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",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}),
|
description: "Sucess return",
|
||||||
async (c) => {
|
},
|
||||||
// make sure we have a vaid user being accessed thats really logged in
|
401: {
|
||||||
const authHeader = c.req.header("Authorization");
|
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")) {
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
const token = authHeader?.split("Bearer ")[1] || "";
|
|
||||||
let user;
|
|
||||||
|
|
||||||
try {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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" });
|
||||||
|
} catch (error) {
|
||||||
|
return c.json({ message: "There was an error", error });
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
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,10 +1,11 @@
|
|||||||
import type {Roles} from "./roles.js";
|
import type { Roles } from "./roles.js";
|
||||||
|
|
||||||
export type User = {
|
export type User = {
|
||||||
user_id?: string;
|
user_id?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
username?: string;
|
username?: string;
|
||||||
roles?: Roles[];
|
roles?: Roles[];
|
||||||
role?: string;
|
role?: string;
|
||||||
prod?: string;
|
prod?: string;
|
||||||
|
password?: string;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user