diff --git a/server/routers/external.ts b/server/routers/external.ts index cb3ac680..f207b431 100644 --- a/server/routers/external.ts +++ b/server/routers/external.ts @@ -287,6 +287,8 @@ unauthenticated.post( resource.authWithPassword ); +unauthenticated.get("/resource/:resourceId/auth", resource.getResourceAuthInfo); + // authenticated.get( // "/role/:roleId/resources", // verifyRoleAccess, diff --git a/server/routers/resource/getResourceAuthInfo.ts b/server/routers/resource/getResourceAuthInfo.ts new file mode 100644 index 00000000..df08d4bd --- /dev/null +++ b/server/routers/resource/getResourceAuthInfo.ts @@ -0,0 +1,89 @@ +import { Request, Response, NextFunction } from "express"; +import { z } from "zod"; +import { db } from "@server/db"; +import { + resourcePassword, + resourcePincode, + resources, +} from "@server/db/schema"; +import { eq } from "drizzle-orm"; +import response from "@server/utils/response"; +import HttpCode from "@server/types/HttpCode"; +import createHttpError from "http-errors"; +import { fromError } from "zod-validation-error"; + +const getResourceAuthInfoSchema = z.object({ + resourceId: z.string().transform(Number).pipe(z.number().int().positive()), +}); + +export type GetResourceAuthInfoResponse = { + resourceId: number; + resourceName: string; + password: boolean; + pincode: boolean; + sso: boolean; + blockAccess: boolean; +}; + +export async function getResourceAuthInfo( + req: Request, + res: Response, + next: NextFunction +): Promise { + try { + const parsedParams = getResourceAuthInfoSchema.safeParse(req.params); + if (!parsedParams.success) { + return next( + createHttpError( + HttpCode.BAD_REQUEST, + fromError(parsedParams.error).toString() + ) + ); + } + + const { resourceId } = parsedParams.data; + + const [result] = await db + .select() + .from(resources) + .leftJoin( + resourcePincode, + eq(resourcePincode.resourceId, resources.resourceId) + ) + .leftJoin( + resourcePassword, + eq(resourcePassword.resourceId, resources.resourceId) + ) + .where(eq(resources.resourceId, resourceId)) + .limit(1); + + const resource = result?.resources; + const pincode = result?.resourcePincode; + const password = result?.resourcePassword; + + if (!resource) { + return next( + createHttpError(HttpCode.NOT_FOUND, "Resource not found") + ); + } + + return response(res, { + data: { + resourceId: resource.resourceId, + resourceName: resource.name, + password: password !== null, + pincode: pincode !== null, + sso: resource.sso, + blockAccess: resource.blockAccess, + }, + success: true, + error: false, + message: "Resource auth info retrieved successfully", + status: HttpCode.OK, + }); + } catch (error) { + return next( + createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred") + ); + } +} diff --git a/server/routers/resource/index.ts b/server/routers/resource/index.ts index 47d066b6..2595c57b 100644 --- a/server/routers/resource/index.ts +++ b/server/routers/resource/index.ts @@ -9,3 +9,4 @@ export * from "./setResourceRoles"; export * from "./listResourceUsers"; export * from "./setResourcePassword"; export * from "./authWithPassword"; +export * from "./getResourceAuthInfo"; diff --git a/server/routers/resource/setResourcePassword.ts b/server/routers/resource/setResourcePassword.ts index afd7973b..f54de902 100644 --- a/server/routers/resource/setResourcePassword.ts +++ b/server/routers/resource/setResourcePassword.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resourcePassword, resources } from "@server/db/schema"; +import { resourcePassword } from "@server/db/schema"; import { eq } from "drizzle-orm"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; @@ -15,7 +15,7 @@ const setResourceAuthMethodsParamsSchema = z.object({ const setResourceAuthMethodsBodySchema = z .object({ - password: z.string().nullable(), + password: z.string().min(4).max(255).nullable(), }) .strict(); diff --git a/src/app/[orgId]/settings/resources/[resourceId]/general/page.tsx b/src/app/[orgId]/settings/resources/[resourceId]/general/page.tsx index c17d1842..26d09e3a 100644 --- a/src/app/[orgId]/settings/resources/[resourceId]/general/page.tsx +++ b/src/app/[orgId]/settings/resources/[resourceId]/general/page.tsx @@ -36,7 +36,7 @@ import { AxiosResponse } from "axios"; import api from "@app/api"; import { useParams } from "next/navigation"; import { useForm } from "react-hook-form"; -import { GetResourceResponse } from "@server/routers/resource"; +import { GetResourceAuthInfoResponse } from "@server/routers/resource"; import { useToast } from "@app/hooks/useToast"; import SettingsSectionTitle from "@app/components/SettingsSectionTitle"; import { useOrgContext } from "@app/hooks/useOrgContext"; @@ -87,7 +87,7 @@ export default function GeneralForm() { async function onSubmit(data: GeneralFormValues) { setSaveLoading(true); - api.post>( + api.post>( `resource/${resource?.resourceId}`, { name: data.name, diff --git a/src/app/[orgId]/settings/resources/[resourceId]/layout.tsx b/src/app/[orgId]/settings/resources/[resourceId]/layout.tsx index c6eac1b4..90da54f6 100644 --- a/src/app/[orgId]/settings/resources/[resourceId]/layout.tsx +++ b/src/app/[orgId]/settings/resources/[resourceId]/layout.tsx @@ -1,6 +1,6 @@ import ResourceProvider from "@app/providers/ResourceProvider"; import { internal } from "@app/api"; -import { GetResourceResponse } from "@server/routers/resource"; +import { GetResourceAuthInfoResponse } from "@server/routers/resource"; import { AxiosResponse } from "axios"; import { redirect } from "next/navigation"; import { authCookieHeader } from "@app/api/cookies"; @@ -25,7 +25,7 @@ export default async function ResourceLayout(props: ResourceLayoutProps) { let resource = null; try { - const res = await internal.get>( + const res = await internal.get>( `/resource/${params.resourceId}`, await authCookieHeader() );