Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ NEON_ORG_ID=your_neon_org_id_here
NEON_PROJECT_ID=your_neon_project_id_here
NEON_BRANCH_ID=your_neon_branch_id_here

# Clerk Authentication
CLERK_SECRET_KEY=your_clerk_secret_key_here
CLERK_WEBHOOK_SECRET=your_clerk_webhook_secret_here
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key_here
# Auth0 Authentication
# Generate AUTH0_SECRET with: openssl rand -hex 32
AUTH0_SECRET=your_auth0_secret_here
AUTH0_BASE_URL=http://localhost:3000
AUTH0_ISSUER_BASE_URL=https://YOUR_TENANT.auth0.com
AUTH0_CLIENT_ID=your_auth0_client_id_here
AUTH0_CLIENT_SECRET=your_auth0_client_secret_here

# App URLs
NEXT_PUBLIC_WEB_URL=http://localhost:3000
NEXT_PUBLIC_API_URL=http://localhost:3001
NEXT_PUBLIC_ADMIN_URL=http://localhost:3002
NEXT_PUBLIC_MARKETING_URL=http://localhost:3003
NEXT_PUBLIC_DOCS_URL=http://localhost:3004
NEXT_PUBLIC_COOKIE_DOMAIN=localhost

# Vercel Blob Storage
BLOB_READ_WRITE_TOKEN=your_blob_token_here
Expand Down
27 changes: 16 additions & 11 deletions .github/workflows/deploy-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,10 @@ jobs:
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }}
NEXT_PUBLIC_WEB_URL: https://${{ env.WEB_ALIAS }}
NEXT_PUBLIC_ADMIN_URL: https://${{ env.ADMIN_ALIAS }}
CLERK_SECRET_KEY: ${{ secrets.CLERK_SECRET_KEY }}
CLERK_WEBHOOK_SECRET: ${{ secrets.CLERK_WEBHOOK_SECRET }}
AUTH0_SECRET: ${{ secrets.AUTH0_SECRET }}
AUTH0_ISSUER_BASE_URL: ${{ secrets.AUTH0_ISSUER_BASE_URL }}
AUTH0_CLIENT_ID: ${{ secrets.AUTH0_CLIENT_ID }}
AUTH0_CLIENT_SECRET: ${{ secrets.AUTH0_CLIENT_SECRET }}
run: |
vercel pull --yes --environment=preview --token=$VERCEL_TOKEN
vercel build --token=$VERCEL_TOKEN
Expand Down Expand Up @@ -193,9 +195,10 @@ jobs:
NEXT_PUBLIC_API_URL: https://${{ env.API_ALIAS }}
NEXT_PUBLIC_MARKETING_URL: https://${{ env.MARKETING_ALIAS }}
NEXT_PUBLIC_DOCS_URL: https://${{ env.DOCS_ALIAS }}
CLERK_SECRET_KEY: ${{ secrets.CLERK_SECRET_KEY }}
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY }}
NEXT_PUBLIC_COOKIE_DOMAIN: ${{ secrets.NEXT_PUBLIC_COOKIE_DOMAIN }}
AUTH0_SECRET: ${{ secrets.AUTH0_SECRET }}
AUTH0_ISSUER_BASE_URL: ${{ secrets.AUTH0_ISSUER_BASE_URL }}
AUTH0_CLIENT_ID: ${{ secrets.AUTH0_CLIENT_ID }}
AUTH0_CLIENT_SECRET: ${{ secrets.AUTH0_CLIENT_SECRET }}
run: |
vercel pull --yes --environment=preview --token=$VERCEL_TOKEN
vercel build --token=$VERCEL_TOKEN
Expand Down Expand Up @@ -251,9 +254,10 @@ jobs:
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_MARKETING_PROJECT_ID }}
NEXT_PUBLIC_API_URL: https://${{ env.API_ALIAS }}
NEXT_PUBLIC_WEB_URL: https://${{ env.WEB_ALIAS }}
CLERK_SECRET_KEY: ${{ secrets.CLERK_SECRET_KEY }}
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY }}
NEXT_PUBLIC_COOKIE_DOMAIN: ${{ secrets.NEXT_PUBLIC_COOKIE_DOMAIN }}
AUTH0_SECRET: ${{ secrets.AUTH0_SECRET }}
AUTH0_ISSUER_BASE_URL: ${{ secrets.AUTH0_ISSUER_BASE_URL }}
AUTH0_CLIENT_ID: ${{ secrets.AUTH0_CLIENT_ID }}
AUTH0_CLIENT_SECRET: ${{ secrets.AUTH0_CLIENT_SECRET }}
run: |
vercel pull --yes --environment=preview --token=$VERCEL_TOKEN
vercel build --token=$VERCEL_TOKEN
Expand Down Expand Up @@ -322,9 +326,10 @@ jobs:
DATABASE_URL_UNPOOLED: ${{ env.DATABASE_URL_UNPOOLED }}
NEXT_PUBLIC_API_URL: https://${{ env.API_ALIAS }}
NEXT_PUBLIC_WEB_URL: https://${{ env.WEB_ALIAS }}
CLERK_SECRET_KEY: ${{ secrets.CLERK_SECRET_KEY }}
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY }}
NEXT_PUBLIC_COOKIE_DOMAIN: ${{ secrets.NEXT_PUBLIC_COOKIE_DOMAIN }}
AUTH0_SECRET: ${{ secrets.AUTH0_SECRET }}
AUTH0_ISSUER_BASE_URL: ${{ secrets.AUTH0_ISSUER_BASE_URL }}
AUTH0_CLIENT_ID: ${{ secrets.AUTH0_CLIENT_ID }}
AUTH0_CLIENT_SECRET: ${{ secrets.AUTH0_CLIENT_SECRET }}
run: |
vercel pull --yes --environment=preview --token=$VERCEL_TOKEN
vercel build --token=$VERCEL_TOKEN
Expand Down
27 changes: 16 additions & 11 deletions .github/workflows/deploy-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@ jobs:
DATABASE_URL_UNPOOLED: ${{ secrets.DATABASE_URL_UNPOOLED }}
NEXT_PUBLIC_WEB_URL: ${{ secrets.NEXT_PUBLIC_WEB_URL }}
NEXT_PUBLIC_ADMIN_URL: ${{ secrets.NEXT_PUBLIC_ADMIN_URL }}
CLERK_SECRET_KEY: ${{ secrets.CLERK_SECRET_KEY }}
CLERK_WEBHOOK_SECRET: ${{ secrets.CLERK_WEBHOOK_SECRET }}
AUTH0_SECRET: ${{ secrets.AUTH0_SECRET }}
AUTH0_ISSUER_BASE_URL: ${{ secrets.AUTH0_ISSUER_BASE_URL }}
AUTH0_CLIENT_ID: ${{ secrets.AUTH0_CLIENT_ID }}
AUTH0_CLIENT_SECRET: ${{ secrets.AUTH0_CLIENT_SECRET }}
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }}
run: |
vercel pull --yes --environment=production --token=$VERCEL_TOKEN
Expand Down Expand Up @@ -117,9 +119,10 @@ jobs:
NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}
NEXT_PUBLIC_MARKETING_URL: ${{ secrets.NEXT_PUBLIC_MARKETING_URL }}
NEXT_PUBLIC_DOCS_URL: ${{ secrets.NEXT_PUBLIC_DOCS_URL }}
CLERK_SECRET_KEY: ${{ secrets.CLERK_SECRET_KEY }}
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY }}
NEXT_PUBLIC_COOKIE_DOMAIN: ${{ secrets.NEXT_PUBLIC_COOKIE_DOMAIN }}
AUTH0_SECRET: ${{ secrets.AUTH0_SECRET }}
AUTH0_ISSUER_BASE_URL: ${{ secrets.AUTH0_ISSUER_BASE_URL }}
AUTH0_CLIENT_ID: ${{ secrets.AUTH0_CLIENT_ID }}
AUTH0_CLIENT_SECRET: ${{ secrets.AUTH0_CLIENT_SECRET }}
run: |
vercel pull --yes --environment=production --token=$VERCEL_TOKEN
vercel build --prod --token=$VERCEL_TOKEN
Expand Down Expand Up @@ -159,9 +162,10 @@ jobs:
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_MARKETING_PROJECT_ID }}
NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}
NEXT_PUBLIC_WEB_URL: ${{ secrets.NEXT_PUBLIC_WEB_URL }}
CLERK_SECRET_KEY: ${{ secrets.CLERK_SECRET_KEY }}
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY }}
NEXT_PUBLIC_COOKIE_DOMAIN: ${{ secrets.NEXT_PUBLIC_COOKIE_DOMAIN }}
AUTH0_SECRET: ${{ secrets.AUTH0_SECRET }}
AUTH0_ISSUER_BASE_URL: ${{ secrets.AUTH0_ISSUER_BASE_URL }}
AUTH0_CLIENT_ID: ${{ secrets.AUTH0_CLIENT_ID }}
AUTH0_CLIENT_SECRET: ${{ secrets.AUTH0_CLIENT_SECRET }}
run: |
vercel pull --yes --environment=production --token=$VERCEL_TOKEN
vercel build --prod --token=$VERCEL_TOKEN
Expand Down Expand Up @@ -203,9 +207,10 @@ jobs:
DATABASE_URL_UNPOOLED: ${{ secrets.DATABASE_URL_UNPOOLED }}
NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}
NEXT_PUBLIC_WEB_URL: ${{ secrets.NEXT_PUBLIC_WEB_URL }}
CLERK_SECRET_KEY: ${{ secrets.CLERK_SECRET_KEY }}
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY }}
NEXT_PUBLIC_COOKIE_DOMAIN: ${{ secrets.NEXT_PUBLIC_COOKIE_DOMAIN }}
AUTH0_SECRET: ${{ secrets.AUTH0_SECRET }}
AUTH0_ISSUER_BASE_URL: ${{ secrets.AUTH0_ISSUER_BASE_URL }}
AUTH0_CLIENT_ID: ${{ secrets.AUTH0_CLIENT_ID }}
AUTH0_CLIENT_SECRET: ${{ secrets.AUTH0_CLIENT_SECRET }}
run: |
vercel pull --yes --environment=production --token=$VERCEL_TOKEN
vercel build --prod --token=$VERCEL_TOKEN
Expand Down
2 changes: 1 addition & 1 deletion apps/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@clerk/nextjs": "^6.36.2",
"@superset/auth0": "workspace:*",
"@superset/db": "workspace:*",
"@superset/queries": "workspace:*",
"@superset/shared": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"use client";

import { useClerk } from "@clerk/nextjs";
import type { RouterOutputs } from "@superset/trpc";
import { Avatar, AvatarFallback, AvatarImage } from "@superset/ui/avatar";
import {
Expand All @@ -26,15 +25,12 @@ import {
LuSettings,
} from "react-icons/lu";

import { env } from "@/env";

export interface NavUserProps {
user: NonNullable<RouterOutputs["user"]["me"]>;
}

export function NavUser({ user }: NavUserProps) {
const { isMobile } = useSidebar();
const { signOut } = useClerk();

const userInitials = user.name
.split(" ")
Expand Down Expand Up @@ -105,11 +101,11 @@ export function NavUser({ user }: NavUserProps) {
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem
onClick={() => signOut({ redirectUrl: env.NEXT_PUBLIC_WEB_URL })}
>
<LuLogOut />
Log out
<DropdownMenuItem asChild>
<a href="/api/auth/logout">
<LuLogOut />
Log out
</a>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ export function DeletedUsersTable() {
<ul className="list-disc space-y-1 pl-6">
<li>All user data</li>
<li>All associated records</li>
<li>Their Clerk account</li>
<li>Their Auth0 account</li>
</ul>
<p className="text-destructive font-medium">
This action cannot be undone.
Expand Down
8 changes: 3 additions & 5 deletions apps/admin/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { ClerkProvider } from "@clerk/nextjs";
import { Auth0Provider } from "@superset/auth0/client";
import { Toaster } from "@superset/ui/sonner";
import { cn } from "@superset/ui/utils";
import type { Metadata, Viewport } from "next";
import { IBM_Plex_Mono, Inter } from "next/font/google";

import { env } from "@/env";

import "./globals.css";

import { Providers } from "./providers";
Expand Down Expand Up @@ -40,7 +38,7 @@ export default function RootLayout({
children: React.ReactNode;
}) {
return (
<ClerkProvider domain={env.NEXT_PUBLIC_COOKIE_DOMAIN} isSatellite={false}>
<Auth0Provider>
<html lang="en" suppressHydrationWarning>
<body
className={cn(
Expand All @@ -55,6 +53,6 @@ export default function RootLayout({
</Providers>
</body>
</html>
</ClerkProvider>
</Auth0Provider>
);
}
10 changes: 4 additions & 6 deletions apps/admin/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,21 @@ export const env = createEnv({
server: {
DATABASE_URL: z.string().url(),
DATABASE_URL_UNPOOLED: z.string().url(),
CLERK_SECRET_KEY: z.string(),
AUTH0_SECRET: z.string(),
AUTH0_ISSUER_BASE_URL: z.string().url(),
AUTH0_CLIENT_ID: z.string(),
AUTH0_CLIENT_SECRET: z.string(),
},

client: {
NEXT_PUBLIC_API_URL: z.string().url(),
NEXT_PUBLIC_WEB_URL: z.string().url(),
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string(),
NEXT_PUBLIC_COOKIE_DOMAIN: z.string(),
},

experimental__runtimeEnv: {
NODE_ENV: process.env.NODE_ENV,
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
NEXT_PUBLIC_WEB_URL: process.env.NEXT_PUBLIC_WEB_URL,
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY:
process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
NEXT_PUBLIC_COOKIE_DOMAIN: process.env.NEXT_PUBLIC_COOKIE_DOMAIN,
},

skipValidation: !!process.env.SKIP_ENV_VALIDATION,
Expand Down
25 changes: 18 additions & 7 deletions apps/admin/src/proxy.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,53 @@
import { clerkMiddleware } from "@clerk/nextjs/server";
import { auth0 } from "@superset/auth0/server";
import { db, eq } from "@superset/db";
import { users } from "@superset/db/schema";
import { COMPANY } from "@superset/shared/constants";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";

import { env } from "./env";

const PUBLIC_ROUTES = ["/ingest", "/monitoring"];
const PUBLIC_ROUTES = ["/api/auth", "/ingest", "/monitoring"];

function isPublicRoute(pathname: string): boolean {
return PUBLIC_ROUTES.some(
(route) => pathname === route || pathname.startsWith(`${route}/`),
);
}

export default clerkMiddleware(async (auth, req) => {
export default async function middleware(req: NextRequest) {
const { pathname } = req.nextUrl;

// Run Auth0 middleware first (handles /api/auth/* routes)
const authResponse = await auth0.middleware(req);

// If Auth0 handled the request, return its response
if (pathname.startsWith("/api/auth")) {
return authResponse;
}

if (isPublicRoute(pathname)) {
return NextResponse.next();
}

const { userId: clerkId } = await auth();
// Get session to check authentication
const session = await auth0.getSession();

if (!clerkId) {
if (!session?.user) {
return NextResponse.redirect(new URL(env.NEXT_PUBLIC_WEB_URL));
}

const auth0Id = session.user.sub;
const user = await db.query.users.findFirst({
where: eq(users.clerkId, clerkId),
where: eq(users.auth0Id, auth0Id),
});

if (!user?.email.endsWith(COMPANY.EMAIL_DOMAIN)) {
return NextResponse.redirect(new URL(env.NEXT_PUBLIC_WEB_URL));
}

return NextResponse.next();
});
}

export const config = {
matcher: [
Expand Down
3 changes: 1 addition & 2 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@clerk/backend": "^2.27.0",
"@clerk/nextjs": "^6.36.2",
"@superset/auth0": "workspace:*",
"@superset/db": "workspace:*",
"@superset/shared": "workspace:*",
"@superset/trpc": "workspace:*",
Expand Down
Loading