mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat(ai): update AI settings to use organization-based access control
- Refactor AI-related schemas and services to use organizationId instead of adminId - Update AI router to check organization-level permissions - Modify AI settings creation and retrieval to work with organization context - Adjust server-side props and access checks for AI settings
This commit is contained in:
12
apps/dokploy/drizzle/0068_complex_rhino.sql
Normal file
12
apps/dokploy/drizzle/0068_complex_rhino.sql
Normal file
@@ -0,0 +1,12 @@
|
||||
CREATE TABLE "ai" (
|
||||
"aiId" text PRIMARY KEY NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"apiUrl" text NOT NULL,
|
||||
"apiKey" text NOT NULL,
|
||||
"model" text NOT NULL,
|
||||
"isEnabled" boolean DEFAULT true NOT NULL,
|
||||
"organizationId" text NOT NULL,
|
||||
"createdAt" text NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "ai" ADD CONSTRAINT "ai_organizationId_organization_id_fk" FOREIGN KEY ("organizationId") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
|
||||
5118
apps/dokploy/drizzle/meta/0068_snapshot.json
Normal file
5118
apps/dokploy/drizzle/meta/0068_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -477,6 +477,13 @@
|
||||
"when": 1740892043121,
|
||||
"tag": "0067_condemned_sugar_man",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 68,
|
||||
"version": "7",
|
||||
"when": 1740897756774,
|
||||
"tag": "0068_complex_rhino",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -143,7 +143,8 @@
|
||||
"xterm-addon-fit": "^0.8.0",
|
||||
"zod": "^3.23.4",
|
||||
"zod-form-data": "^2.0.2",
|
||||
"@faker-js/faker": "^8.4.1"
|
||||
"@faker-js/faker": "^8.4.1",
|
||||
"@tailwindcss/typography": "0.5.16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/qrcode": "^1.5.5",
|
||||
|
||||
@@ -25,7 +25,7 @@ export async function getServerSideProps(
|
||||
ctx: GetServerSidePropsContext<{ serviceId: string }>,
|
||||
) {
|
||||
const { req, res } = ctx;
|
||||
const { user, session } = await validateRequest(req, res);
|
||||
const { user, session } = await validateRequest(req);
|
||||
const locale = getLocale(req.cookies);
|
||||
|
||||
const helpers = createServerSideHelpers({
|
||||
@@ -34,22 +34,17 @@ export async function getServerSideProps(
|
||||
req: req as any,
|
||||
res: res as any,
|
||||
db: null as any,
|
||||
session: session,
|
||||
user: user,
|
||||
session: session as any,
|
||||
user: user as any,
|
||||
},
|
||||
transformer: superjson,
|
||||
});
|
||||
|
||||
await helpers.settings.isCloud.prefetch();
|
||||
|
||||
await helpers.auth.get.prefetch();
|
||||
if (user?.rol === "user") {
|
||||
await helpers.user.byAuthId.prefetch({
|
||||
authId: user.authId,
|
||||
});
|
||||
}
|
||||
await helpers.user.get.prefetch();
|
||||
|
||||
if (!user) {
|
||||
if (!user || user.role === "member") {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
|
||||
@@ -15,7 +15,7 @@ import { createDomain } from "@dokploy/server/index";
|
||||
import {
|
||||
deleteAiSettings,
|
||||
getAiSettingById,
|
||||
getAiSettingsByAdminId,
|
||||
getAiSettingsByOrganizationId,
|
||||
saveAiSettings,
|
||||
suggestVariants,
|
||||
} from "@dokploy/server/services/ai";
|
||||
@@ -33,7 +33,7 @@ export const aiRouter = createTRPCRouter({
|
||||
.input(z.object({ aiId: z.string() }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const aiSetting = await getAiSettingById(input.aiId);
|
||||
if (aiSetting.adminId !== ctx.user.adminId) {
|
||||
if (aiSetting.organizationId !== ctx.session.activeOrganizationId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You don't have access to this AI configuration",
|
||||
@@ -42,24 +42,26 @@ export const aiRouter = createTRPCRouter({
|
||||
return aiSetting;
|
||||
}),
|
||||
create: adminProcedure.input(apiCreateAi).mutation(async ({ ctx, input }) => {
|
||||
return await saveAiSettings(ctx.user.adminId, input);
|
||||
return await saveAiSettings(ctx.session.activeOrganizationId, input);
|
||||
}),
|
||||
|
||||
update: protectedProcedure
|
||||
.input(apiUpdateAi)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
return await saveAiSettings(ctx.user.adminId, input);
|
||||
return await saveAiSettings(ctx.session.activeOrganizationId, input);
|
||||
}),
|
||||
|
||||
getAll: adminProcedure.query(async ({ ctx }) => {
|
||||
return await getAiSettingsByAdminId(ctx.user.adminId);
|
||||
return await getAiSettingsByOrganizationId(
|
||||
ctx.session.activeOrganizationId,
|
||||
);
|
||||
}),
|
||||
|
||||
get: protectedProcedure
|
||||
.input(z.object({ aiId: z.string() }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const aiSetting = await getAiSettingById(input.aiId);
|
||||
if (aiSetting.adminId !== ctx.user.authId) {
|
||||
if (aiSetting.organizationId !== ctx.session.activeOrganizationId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You don't have access to this AI configuration",
|
||||
@@ -72,7 +74,7 @@ export const aiRouter = createTRPCRouter({
|
||||
.input(z.object({ aiId: z.string() }))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const aiSetting = await getAiSettingById(input.aiId);
|
||||
if (aiSetting.adminId !== ctx.user.adminId) {
|
||||
if (aiSetting.organizationId !== ctx.session.activeOrganizationId) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You don't have access to this AI configuration",
|
||||
@@ -93,7 +95,7 @@ export const aiRouter = createTRPCRouter({
|
||||
try {
|
||||
return await suggestVariants({
|
||||
...input,
|
||||
adminId: ctx.user.adminId,
|
||||
organizationId: ctx.session.activeOrganizationId,
|
||||
});
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
@@ -105,8 +107,12 @@ export const aiRouter = createTRPCRouter({
|
||||
deploy: protectedProcedure
|
||||
.input(deploySuggestionSchema)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
if (ctx.user.rol === "user") {
|
||||
await checkServiceAccess(ctx.user.adminId, input.projectId, "create");
|
||||
if (ctx.user.rol === "member") {
|
||||
await checkServiceAccess(
|
||||
ctx.session.activeOrganizationId,
|
||||
input.projectId,
|
||||
"create",
|
||||
);
|
||||
}
|
||||
|
||||
if (IS_CLOUD && !input.serverId) {
|
||||
@@ -143,8 +149,12 @@ export const aiRouter = createTRPCRouter({
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.user.rol === "user") {
|
||||
await addNewService(ctx.user.authId, compose.composeId);
|
||||
if (ctx.user.rol === "member") {
|
||||
await addNewService(
|
||||
ctx.session.activeOrganizationId,
|
||||
ctx.user.ownerId,
|
||||
compose.composeId,
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user