Skip to content

Commit

Permalink
feat(missing-env-handle): Added handle method for missing .env values…
Browse files Browse the repository at this point in the history
… when executing quickstart
  • Loading branch information
oindrila-b authored and zereraz committed Feb 11, 2025
1 parent d4b251f commit f2a1374
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 6 deletions.
Binary file modified frontend/bun.lockb
Binary file not shown.
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@radix-ui/react-dialog": "^1.1.5",
"@radix-ui/react-dropdown-menu": "^2.1.4",
"@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-label": "^2.1.1",
Expand Down
119 changes: 119 additions & 0 deletions frontend/src/components/ui/dialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import * as React from "react"
import * as DialogPrimitive from "@radix-ui/react-dialog"
import { cn } from "@/lib/utils"
import { Cross2Icon } from "@radix-ui/react-icons"

const Dialog = DialogPrimitive.Root

const DialogTrigger = DialogPrimitive.Trigger

const DialogPortal = DialogPrimitive.Portal

const DialogClose = DialogPrimitive.Close

const DialogOverlay = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Overlay
ref={ref}
className={cn(
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className
)}
{...props}
/>
))
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName

const DialogContent = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<DialogPortal>
<DialogOverlay />
<DialogPrimitive.Content
ref={ref}
className={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
className
)}
{...props}
>
{children}
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
<Cross2Icon className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</DialogPortal>
))
DialogContent.displayName = DialogPrimitive.Content.displayName

const DialogHeader = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-1.5 text-center sm:text-left",
className
)}
{...props}
/>
)
DialogHeader.displayName = "DialogHeader"

const DialogFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className
)}
{...props}
/>
)
DialogFooter.displayName = "DialogFooter"

const DialogTitle = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Title
ref={ref}
className={cn(
"text-lg font-semibold leading-none tracking-tight",
className
)}
{...props}
/>
))
DialogTitle.displayName = DialogPrimitive.Title.displayName

const DialogDescription = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
))
DialogDescription.displayName = DialogPrimitive.Description.displayName

export {
Dialog,
DialogPortal,
DialogOverlay,
DialogTrigger,
DialogClose,
DialogContent,
DialogHeader,
DialogFooter,
DialogTitle,
DialogDescription,
}
55 changes: 49 additions & 6 deletions frontend/src/routes/auth.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useState } from "react";
import { createFileRoute, redirect } from "@tanstack/react-router"

import { Button } from "@/components/ui/button"
Expand All @@ -8,6 +9,7 @@ import {
CardHeader,
CardTitle,
} from "@/components/ui/card"
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog"
import { api } from "@/api"
import { errorComponent } from "@/components/error"

Expand All @@ -19,33 +21,74 @@ export const containerClassName =

export default function LoginForm() {
const logger = console
const [showModal, setShowModal] = useState(false);
const [modalMessage, setModalMessage] = useState("");

const handleLogin = async () => {
try {
const response = await fetch(
`${import.meta.env.VITE_API_BASE_URL}/v1/credential/status`,
{ method: "GET"}
);
// Error - Modal pops up
if (response.status === 500) {
const data = await response.json();
if (data.message === "EnvError: Google OAuth credentials are not configured") {
logger.warn("Google OAuth credentials are not configured.");
setModalMessage(
"EnvError: Google OAuth credentials are not configured. Please configure the Google Credentials in your .env.temp file."
);
setShowModal(true);
return;
}
}
// No Error - Proceed with authentication
const redirectUrl = `${import.meta.env.VITE_API_BASE_URL}/v1/auth/callback`;
window.location.href = redirectUrl;
} catch (error) {
logger.error("An error occurred during login:", error);
setModalMessage(
"An unexpected error occurred. Please try again later."
);
setShowModal(true);
}
};
return (
<div className="flex w-full h-full justify-center">
<div className="max-w-sm flex items-center">
<Card className="h-auto">
<CardHeader>
<CardTitle className="text-2xl">Login</CardTitle>
<CardDescription>
Login with your workspace google account
Login with your workspace Google account
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid gap-4">
<Button
variant="outline"
className="w-full"
onClick={(e) => {
logger.info("User Clicked login with google")
const redirectUrl = `${import.meta.env.VITE_API_BASE_URL}/v1/auth/callback`
window.location.href = redirectUrl
}}
onClick={handleLogin}
>
Login with Google
</Button>
</div>
</CardContent>
</Card>
</div>

<Dialog open={showModal} onOpenChange={setShowModal}>
<DialogContent>
<DialogHeader>
<DialogTitle className="text-xl font-bold text-red-600">
Configuration Error
</DialogTitle>
<DialogDescription className="text-gray-600">
{modalMessage}
</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>
</div>
)
}
Expand Down
15 changes: 15 additions & 0 deletions server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,21 @@ const generateToken = async (
const jwtToken = await sign(payload, jwtSecret)
return jwtToken
}

// This method is just to check of the google credentials are set or not, we want to
// inform the user to set their Google credentials before they can login
app.get('/v1/credential/status', async(c: Context) => {
if(clientId && clientSecret && redirectURI) {
return c.json({
message: "EnvSuccess: Google OAuth credentials are configured",
}, 200)
}else {
return c.json({
message: "EnvError: Google OAuth credentials are not configured",
}, 500)
}
})

// we won't allow user to reach the login page if they are already logged in
// or if they have an expired token

Expand Down

0 comments on commit f2a1374

Please sign in to comment.