Browse Source

fix rendering issues on resource unauthorized

Milo Schwartz 8 months ago
parent
commit
500a81aa42

+ 1 - 1
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",

+ 2 - 2
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);
 

+ 10 - 5
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<boolean> {
+    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),
             ),
         )

+ 10 - 1
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 (
         <Card className="w-full max-w-md">
             <CardHeader>
@@ -17,6 +21,11 @@ export default async function ResourceAccessDenied() {
             <CardContent>
                 You're not alowed to access this resource. If this is a mistake,
                 please contact the administrator.
+                <div className="text-center mt-4">
+                    <Button>
+                        <Link href="/">Go Home</Link>
+                    </Button>
+                </div>
             </CardContent>
         </Card>
     );

+ 16 - 6
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) {
         <div>
             {!accessDenied ? (
                 <div>
+                    <div className="text-center mb-2">
+                        <span className="text-sm text-muted-foreground">
+                            Powered by Fossorial
+                        </span>
+                    </div>
                     <Card>
                         <CardHeader>
                             <CardTitle>Authentication Required</CardTitle>
@@ -365,7 +371,11 @@ export default function ResourceAuthPortal(props: ResourceAuthPortalProps) {
                                         className={`${numMethods <= 1 ? "mt-0" : ""}`}
                                     >
                                         <LoginForm
-                                            redirect={window.location.href}
+                                            redirect={
+                                                typeof window !== "undefined"
+                                                    ? window.location.href
+                                                    : ""
+                                            }
                                             onLogin={async () =>
                                                 await handleSSOAuth()
                                             }

+ 8 - 1
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() {
                 </CardTitle>
             </CardHeader>
             <CardContent>
-                The resource you're trying to access does not exist
+                The resource you're trying to access does not exist.
+                <div className="text-center mt-4">
+                    <Button>
+                        <Link href="/">Go Home</Link>
+                    </Button>
+                </div>
             </CardContent>
         </Card>
     );

+ 11 - 1
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}`;

+ 0 - 3
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");