This commit is contained in:
Milo Schwartz 2024-10-14 18:26:15 -04:00
commit b67e03677c
No known key found for this signature in database
19 changed files with 49 additions and 49 deletions

View file

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

View file

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

View file

@ -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 // Create the Default role if it doesn't exist
const [insertedRole] = await db const [insertedRole] = await db
.insert(roles) .insert(roles)

View file

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

View file

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

View file

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

View file

@ -10,7 +10,7 @@ import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
import logger from '@server/logger'; import logger from '@server/logger';
const deleteOrgSchema = z.object({ 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> { export async function deleteOrg(req: Request, res: Response, next: NextFunction): Promise<any> {

View file

@ -10,7 +10,7 @@ import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
import logger from '@server/logger'; import logger from '@server/logger';
const getOrgSchema = z.object({ 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> { export async function getOrg(req: Request, res: Response, next: NextFunction): Promise<any> {

View file

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

View file

@ -11,7 +11,7 @@ import { eq, and } from 'drizzle-orm';
const createResourceParamsSchema = z.object({ const createResourceParamsSchema = z.object({
siteId: z.number().int().positive(), 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 // Define Zod schema for request body validation

View file

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

View file

@ -12,7 +12,7 @@ import { eq } from 'drizzle-orm';
const addUserActionSchema = z.object({ const addUserActionSchema = z.object({
userId: z.string(), userId: z.string(),
actionId: 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> { export async function addUserAction(req: Request, res: Response, next: NextFunction): Promise<any> {

View file

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

View file

@ -15,7 +15,7 @@ const removeUserActionParamsSchema = z.object({
const removeUserActionSchema = z.object({ const removeUserActionSchema = z.object({
actionId: z.string(), 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> { export async function removeUserAction(req: Request, res: Response, next: NextFunction): Promise<any> {

View file

@ -11,7 +11,7 @@ import logger from '@server/logger';
const removeUserSchema = z.object({ const removeUserSchema = z.object({
userId: z.string().uuid(), 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> { export async function removeUserOrg(req: Request, res: Response, next: NextFunction): Promise<any> {

View file

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

10
src/api/cookies.ts Normal file
View file

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

View file

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

View file

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