diff --git a/package.json b/package.json index 45a1ad21..e817ac04 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "dev": "ENVIRONMENT=dev tsx watch server/index.ts", + "dev": "NODE_ENV=development ENVIRONMENT=dev tsx watch server/index.ts", "db:generate": "drizzle-kit generate", "db:push": "npx tsx server/db/migrate.ts", "db:hydrate": "npx tsx scripts/hydrate.ts", diff --git a/server/index.ts b/server/index.ts index 909bf796..f1c5e79b 100644 --- a/server/index.ts +++ b/server/index.ts @@ -51,7 +51,7 @@ app.prepare().then(() => { externalServer.use(logIncomingMiddleware); externalServer.use(prefix, unauthenticated); externalServer.use(prefix, authenticated); - externalServer.use(`${prefix}/ws`, wsRouter); + // externalServer.use(`${prefix}/ws`, wsRouter); externalServer.use(notFoundMiddleware); @@ -68,7 +68,7 @@ app.prepare().then(() => { ); }); - handleWSUpgrade(httpServer); + // handleWSUpgrade(httpServer); externalServer.use(errorHandlerMiddleware); diff --git a/server/routers/badger/verifySession.ts b/server/routers/badger/verifySession.ts index 25b212fa..46fe6df3 100644 --- a/server/routers/badger/verifySession.ts +++ b/server/routers/badger/verifySession.ts @@ -10,6 +10,7 @@ import { resourcePassword, resourcePincode, resources, + User, userOrgs, } from "@server/db/schema"; import { and, eq } from "drizzle-orm"; @@ -106,7 +107,7 @@ export async function verifyResourceSession( const { session, user } = await validateSessionToken(sessionToken); if (session && user) { const isAllowed = await isUserAllowedToAccessResource( - user.userId, + user, resource, ); @@ -191,15 +192,19 @@ function allowed(res: Response) { } async function isUserAllowedToAccessResource( - userId: string, + user: User, resource: Resource, -) { +): Promise { + if (config.flags?.require_email_verification && !user.emailVerified) { + return false; + } + const userOrgRole = await db .select() .from(userOrgs) .where( and( - eq(userOrgs.userId, userId), + eq(userOrgs.userId, user.userId), eq(userOrgs.orgId, resource.orgId), ), ) @@ -229,7 +234,7 @@ async function isUserAllowedToAccessResource( .from(userResources) .where( and( - eq(userResources.userId, userId), + eq(userResources.userId, user.userId), eq(userResources.resourceId, resource.resourceId), ), ) diff --git a/src/app/auth/resource/[resourceId]/components/ResourceAccessDenied.tsx b/src/app/auth/resource/[resourceId]/components/ResourceAccessDenied.tsx index c352bb4d..b47b976f 100644 --- a/src/app/auth/resource/[resourceId]/components/ResourceAccessDenied.tsx +++ b/src/app/auth/resource/[resourceId]/components/ResourceAccessDenied.tsx @@ -1,3 +1,6 @@ +"use client"; + +import { Button } from "@app/components/ui/button"; import { Card, CardContent, @@ -5,8 +8,9 @@ import { CardHeader, CardTitle, } from "@app/components/ui/card"; +import Link from "next/link"; -export default async function ResourceAccessDenied() { +export default function ResourceAccessDenied() { return ( @@ -17,6 +21,11 @@ export default async function ResourceAccessDenied() { You're not alowed to access this resource. If this is a mistake, please contact the administrator. +
+ +
); diff --git a/src/app/auth/resource/[resourceId]/components/ResourceAuthPortal.tsx b/src/app/auth/resource/[resourceId]/components/ResourceAuthPortal.tsx index 4e3a612b..014c8503 100644 --- a/src/app/auth/resource/[resourceId]/components/ResourceAuthPortal.tsx +++ b/src/app/auth/resource/[resourceId]/components/ResourceAuthPortal.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import * as z from "zod"; @@ -23,7 +23,7 @@ import { FormLabel, FormMessage, } from "@/components/ui/form"; -import { LockIcon, UserIcon, Binary, Key, User } from "lucide-react"; +import { LockIcon, Binary, Key, User } from "lucide-react"; import { InputOTP, InputOTPGroup, @@ -34,11 +34,10 @@ import { useRouter } from "next/navigation"; import { Alert, AlertDescription } from "@app/components/ui/alert"; import { formatAxiosError } from "@app/lib/utils"; import { AxiosResponse } from "axios"; -import { LoginResponse } from "@server/routers/auth"; -import ResourceAccessDenied from "./ResourceAccessDenied"; import LoginForm from "@app/components/LoginForm"; import { AuthWithPasswordResponse } from "@server/routers/resource"; import { redirect } from "next/dist/server/api-utils"; +import ResourceAccessDenied from "./ResourceAccessDenied"; const pinSchema = z.object({ pin: z @@ -159,13 +158,15 @@ export default function ResourceAuthPortal(props: ResourceAuthPortalProps) { }; async function handleSSOAuth() { + let isAllowed = false; try { await api.get(`/resource/${props.resource.id}`); + isAllowed = true; } catch (e) { setAccessDenied(true); } - if (!accessDenied) { + if (isAllowed) { window.location.href = props.redirect; } } @@ -174,6 +175,11 @@ export default function ResourceAuthPortal(props: ResourceAuthPortalProps) {
{!accessDenied ? (
+
+ + Powered by Fossorial + +
Authentication Required @@ -365,7 +371,11 @@ export default function ResourceAuthPortal(props: ResourceAuthPortalProps) { className={`${numMethods <= 1 ? "mt-0" : ""}`} > await handleSSOAuth() } diff --git a/src/app/auth/resource/[resourceId]/components/ResourceNotFound.tsx b/src/app/auth/resource/[resourceId]/components/ResourceNotFound.tsx index d72f5633..5b101297 100644 --- a/src/app/auth/resource/[resourceId]/components/ResourceNotFound.tsx +++ b/src/app/auth/resource/[resourceId]/components/ResourceNotFound.tsx @@ -1,3 +1,4 @@ +import { Button } from "@app/components/ui/button"; import { Card, CardContent, @@ -5,6 +6,7 @@ import { CardHeader, CardTitle, } from "@app/components/ui/card"; +import Link from "next/link"; export default async function ResourceNotFound() { return ( @@ -15,7 +17,12 @@ export default async function ResourceNotFound() { - The resource you're trying to access does not exist + The resource you're trying to access does not exist. +
+ +
); diff --git a/src/app/auth/resource/[resourceId]/page.tsx b/src/app/auth/resource/[resourceId]/page.tsx index 1c436171..23b27c43 100644 --- a/src/app/auth/resource/[resourceId]/page.tsx +++ b/src/app/auth/resource/[resourceId]/page.tsx @@ -33,7 +33,7 @@ export default async function ResourceAuthPage(props: { } catch (e) {} const getUser = cache(verifySession); - const user = await getUser(); + const user = await getUser({ skipCheckVerifyEmail: true }); if (!authInfo) { return ( @@ -48,6 +48,16 @@ export default async function ResourceAuthPage(props: { const redirectUrl = searchParams.redirect || authInfo.url; + if ( + user && + !user.emailVerified && + process.env.FLAGS_EMAIL_VERIFICATION_REQUIRED === "true" + ) { + redirect( + `/auth/verify-email?redirect=/auth/resource/${authInfo.resourceId}`, + ); + } + const allCookies = await cookies(); const cookieName = process.env.RESOURCE_SESSION_COOKIE_NAME + `_${params.resourceId}`; diff --git a/src/components/LoginForm.tsx b/src/components/LoginForm.tsx index c57d9ab9..b7a04c2f 100644 --- a/src/components/LoginForm.tsx +++ b/src/components/LoginForm.tsx @@ -72,14 +72,11 @@ export default function LoginForm({ redirect, onLogin }: LoginFormProps) { ); }); - console.log(res); - if (res && res.status === 200) { setError(null); if (res.data?.data?.emailVerificationRequired) { if (redirect) { - console.log("here", redirect) router.push(`/auth/verify-email?redirect=${redirect}`); } else { router.push("/auth/verify-email");