Browse Source

Merge branch 'main' of https://github.com/fosrl/pangolin

Milo Schwartz 9 months ago
parent
commit
b67e03677c

+ 4 - 2
scripts/hydrate.ts

@@ -14,24 +14,26 @@ async function insertDummyData() {
     const org1 = db
         .insert(orgs)
         .values({
+            orgId: "default",
             name: "Default",
             domain: "fosrl.io",
         })
         .returning()
         .get();
 
-    await createSuperuserRole(org1.orgId);
+    await createSuperuserRole(org1.orgId!);
 
     const org2 = db
         .insert(orgs)
         .values({
+            orgId: "fossorial",
             name: "Fossorial",
             domain: "fossorial.io",
         })
         .returning()
         .get();
 
-    await createSuperuserRole(org2.orgId);
+    await createSuperuserRole(org2.orgId!);
 
     // Insert dummy exit nodes
     const exitNode1 = db

+ 1 - 1
server/auth/limits.ts

@@ -5,7 +5,7 @@ import createHttpError from 'http-errors';
 import HttpCode from '@server/types/HttpCode';
 
 interface CheckLimitOptions {
-    orgId: number;
+    orgId: string;
     limitName: string;
     currentValue: number;
     increment?: number;

+ 1 - 1
server/db/ensureActions.ts

@@ -39,7 +39,7 @@ export async function ensureActions() {
     }
 }
 
-export async function createSuperuserRole(orgId: number) {
+export async function createSuperuserRole(orgId: string) {
     // Create the Default role if it doesn't exist
     const [insertedRole] = await db
         .insert(roles)

+ 8 - 8
server/db/schema.ts

@@ -2,14 +2,14 @@ import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
 import { InferSelectModel } from "drizzle-orm";
 
 export const orgs = sqliteTable("orgs", {
-    orgId: integer("orgId").primaryKey({ autoIncrement: true }),
+    orgId: text("orgId").primaryKey(),
     name: text("name").notNull(),
     domain: text("domain").notNull(),
 });
 
 export const sites = sqliteTable("sites", {
     siteId: integer("siteId").primaryKey({ autoIncrement: true }),
-    orgId: integer("orgId").references(() => orgs.orgId, {
+    orgId: text("orgId").references(() => orgs.orgId, {
         onDelete: "cascade",
     }),
     exitNode: integer("exitNode").references(() => exitNodes.exitNodeId, {
@@ -28,7 +28,7 @@ export const resources = sqliteTable("resources", {
     siteId: integer("siteId").references(() => sites.siteId, {
         onDelete: "cascade",
     }),
-    orgId: integer("orgId").references(() => orgs.orgId, {
+    orgId: text("orgId").references(() => orgs.orgId, {
         onDelete: "cascade",
     }),
     name: text("name").notNull(),
@@ -97,7 +97,7 @@ export const userOrgs = sqliteTable("userOrgs", {
     userId: text("userId")
         .notNull()
         .references(() => users.userId),
-    orgId: integer("orgId")
+    orgId: text("orgId")
         .notNull()
         .references(() => orgs.orgId),
     roleId: integer("roleId")
@@ -132,7 +132,7 @@ export const actions = sqliteTable("actions", {
 
 export const roles = sqliteTable("roles", {
     roleId: integer("roleId").primaryKey({ autoIncrement: true }),
-    orgId: integer("orgId").references(() => orgs.orgId, {
+    orgId: text("orgId").references(() => orgs.orgId, {
         onDelete: "cascade",
     }),
     isSuperuserRole: integer("isSuperuserRole", { mode: "boolean" }),
@@ -147,7 +147,7 @@ export const roleActions = sqliteTable("roleActions", {
     actionId: text("actionId")
         .notNull()
         .references(() => actions.actionId, { onDelete: "cascade" }),
-    orgId: integer("orgId")
+    orgId: text("orgId")
         .notNull()
         .references(() => orgs.orgId, { onDelete: "cascade" }),
 });
@@ -159,7 +159,7 @@ export const userActions = sqliteTable("userActions", {
     actionId: text("actionId")
         .notNull()
         .references(() => actions.actionId, { onDelete: "cascade" }),
-    orgId: integer("orgId")
+    orgId: text("orgId")
         .notNull()
         .references(() => orgs.orgId, { onDelete: "cascade" }),
 });
@@ -202,7 +202,7 @@ export const userResources = sqliteTable("userResources", {
 
 export const limitsTable = sqliteTable("limits", {
     limitId: integer("limitId").primaryKey({ autoIncrement: true }),
-    orgId: integer("orgId").references(() => orgs.orgId, {
+    orgId: text("orgId").references(() => orgs.orgId, {
         onDelete: "cascade",
     }),
     name: text("name").notNull(),

+ 2 - 2
server/index.ts

@@ -91,8 +91,8 @@ declare global {
         interface Request {
             user?: User;
             userOrgRoleId?: number;
-            userOrgId?: number;
-            userOrgIds?: number[];
+            userOrgId?: string;
+            userOrgIds?: string[];
         }
     }
 }

+ 2 - 2
server/routers/auth/verifyOrgAccess.ts

@@ -8,13 +8,13 @@ import { AuthenticatedRequest } from '@server/types/Auth';
 
 export function verifyOrgAccess(req: Request, res: Response, next: NextFunction) {
     const userId = req.user!.userId; // Assuming you have user information in the request
-    const orgId = parseInt(req.params.orgId);
+    const orgId = req.params.orgId;
 
     if (!userId) {
         return next(createHttpError(HttpCode.UNAUTHORIZED, 'User not authenticated'));
     }
 
-    if (isNaN(orgId)) {
+    if (!orgId) {
         return next(createHttpError(HttpCode.BAD_REQUEST, 'Invalid organization ID'));
     }
 

+ 1 - 1
server/routers/org/deleteOrg.ts

@@ -10,7 +10,7 @@ import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
 import logger from '@server/logger';
 
 const deleteOrgSchema = z.object({
-    orgId: z.string().transform(Number).pipe(z.number().int().positive())
+    orgId: z.string()
 });
 
 export async function deleteOrg(req: Request, res: Response, next: NextFunction): Promise<any> {

+ 1 - 1
server/routers/org/getOrg.ts

@@ -10,7 +10,7 @@ import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
 import logger from '@server/logger';
 
 const getOrgSchema = z.object({
-    orgId: z.string().transform(Number).pipe(z.number().int().positive())
+    orgId: z.string()
 });
 
 export async function getOrg(req: Request, res: Response, next: NextFunction): Promise<any> {

+ 1 - 1
server/routers/org/updateOrg.ts

@@ -10,7 +10,7 @@ import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
 import logger from '@server/logger';
 
 const updateOrgParamsSchema = z.object({
-    orgId: z.string().transform(Number).pipe(z.number().int().positive())
+    orgId: z.string()
 });
 
 const updateOrgBodySchema = z.object({

+ 1 - 1
server/routers/resource/createResource.ts

@@ -11,7 +11,7 @@ import { eq, and } from 'drizzle-orm';
 
 const createResourceParamsSchema = z.object({
     siteId: z.number().int().positive(),
-    orgId: z.string().transform(Number).pipe(z.number().int().positive())
+    orgId: z.string()
 });
 
 // Define Zod schema for request body validation

+ 1 - 1
server/routers/site/createSite.ts

@@ -13,7 +13,7 @@ import { eq, and } from 'drizzle-orm';
 const API_BASE_URL = "http://localhost:3000";
 
 const createSiteParamsSchema = z.object({
-    orgId: z.string().transform(Number).pipe(z.number().int().positive())
+    orgId: z.string()
 });
 
 // Define Zod schema for request body validation

+ 1 - 1
server/routers/user/addUserAction.ts

@@ -12,7 +12,7 @@ import { eq } from 'drizzle-orm';
 const addUserActionSchema = z.object({
     userId: z.string(),
     actionId: z.string(),
-    orgId: z.string().transform(Number).pipe(z.number().int().positive()),
+    orgId: z.string(),
 });
 
 export async function addUserAction(req: Request, res: Response, next: NextFunction): Promise<any> {

+ 1 - 1
server/routers/user/addUserOrg.ts

@@ -11,7 +11,7 @@ import logger from '@server/logger';
 
 const addUserParamsSchema = z.object({
     userId: z.string().uuid(),
-    orgId: z.string().transform(Number).pipe(z.number().int().positive())
+    orgId: z.string()
 });
 
 const addUserSchema = z.object({

+ 1 - 1
server/routers/user/removeUserAction.ts

@@ -15,7 +15,7 @@ const removeUserActionParamsSchema = z.object({
 
 const removeUserActionSchema = z.object({
     actionId: z.string(),
-    orgId: z.string().transform(Number).pipe(z.number().int().positive())
+    orgId: z.string()
 });
 
 export async function removeUserAction(req: Request, res: Response, next: NextFunction): Promise<any> {

+ 1 - 1
server/routers/user/removeUserOrg.ts

@@ -11,7 +11,7 @@ import logger from '@server/logger';
 
 const removeUserSchema = z.object({
     userId: z.string().uuid(),
-    orgId: z.string().transform(Number).pipe(z.number().int().positive())
+    orgId: z.string()
 });
 
 export async function removeUserOrg(req: Request, res: Response, next: NextFunction): Promise<any> {

+ 1 - 1
server/routers/user/setUserRole.ts

@@ -12,7 +12,7 @@ import logger from '@server/logger';
 const addUserRoleSchema = z.object({
     userId: z.string(),
     roleId: z.number().int().positive(),
-    orgId: z.string().transform(Number).pipe(z.number().int().positive())
+    orgId: z.string()
 });
 
 export async function addUserRole(req: Request, res: Response, next: NextFunction): Promise<any> {

+ 10 - 0
src/api/cookies.ts

@@ -0,0 +1,10 @@
+import { cookies } from "next/headers";
+
+export function authCookieHeader() {
+    const sessionId = cookies().get("session")?.value ?? null;
+    return {
+        headers: {
+            Cookie: `session=${sessionId}`
+        }
+    }
+}

+ 9 - 15
src/app/[orgId]/sites/[siteId]/layout.tsx

@@ -5,9 +5,10 @@ import { Separator } from "@/components/ui/separator"
 import { SidebarNav } from "@/components/sidebar-nav"
 import SiteProvider from "@app/providers/SiteProvider"
 import { internal } from "@app/api"
-import { cookies } from "next/headers"
 import { GetSiteResponse } from "@server/routers/site"
 import { AxiosResponse } from "axios"
+import { redirect } from "next/navigation"
+import { authCookieHeader } from "@app/api/cookies"
 
 export const metadata: Metadata = {
     title: "Forms",
@@ -42,17 +43,10 @@ export default async function SettingsLayout({ children, params }: SettingsLayou
     let site = null;
     if (params.siteId !== "create") {
         try {
-            const sessionId = cookies().get("session")?.value ?? null;
-            const res = await internal
-            .get<AxiosResponse<GetSiteResponse>>(`/site/${params.siteId}`,          {
-                headers: {
-                    Cookie: `session=${sessionId}`,
-                },
-            });
-
+            const res = await internal.get<AxiosResponse<GetSiteResponse>>(`/site/${params.siteId}`, authCookieHeader());
             site = res.data.data;
         } catch {
-            return null;
+            redirect(`/${params.orgId}/sites`)
         }
     }
 
@@ -78,7 +72,7 @@ export default async function SettingsLayout({ children, params }: SettingsLayou
                 <div className="space-y-0.5">
                     <h2 className="text-2xl font-bold tracking-tight">Settings</h2>
                     <p className="text-muted-foreground">
-                        { params.siteId == "create" ? "Create site..." : "Manage settings on " + site?.name || ""}.
+                        {params.siteId == "create" ? "Create site..." : "Manage settings on " + site?.name || ""}.
                     </p>
                 </div>
                 <Separator className="my-6" />
@@ -87,10 +81,10 @@ export default async function SettingsLayout({ children, params }: SettingsLayou
                         <SidebarNav items={sidebarNavItems} disabled={params.siteId == "create"} />
                     </aside>
                     <div className="flex-1 lg:max-w-2xl">
-                    <SiteProvider site={site}>
-                        {children}
-                    </SiteProvider>
-                        </div>
+                        <SiteProvider site={site}>
+                            {children}
+                        </SiteProvider>
+                    </div>
                 </div>
             </div>
         </>

+ 2 - 8
src/lib/auth/verifySession.ts

@@ -1,4 +1,5 @@
 import { internal } from "@app/api";
+import { authCookieHeader } from "@app/api/cookies";
 import { GetUserResponse } from "@server/routers/user";
 import { AxiosResponse } from "axios";
 import { cookies } from "next/headers";
@@ -7,14 +8,7 @@ export async function verifySession(): Promise<GetUserResponse | null> {
     const sessionId = cookies().get("session")?.value ?? null;
 
     try {
-        const res = await internal.get<AxiosResponse<GetUserResponse>>(
-            "/user",
-            {
-                headers: {
-                    Cookie: `session=${sessionId}`,
-                },
-            },
-        );
+        const res = await internal.get<AxiosResponse<GetUserResponse>>("/user", authCookieHeader());
 
         return res.data.data;
     } catch {