feat: add user property to git-providers (bitbucket, gitea)

- relate a provider to the user who created it.
- for now the provider is only visible to its user.
This commit is contained in:
ayham291
2025-05-31 01:21:46 +02:00
parent 2619cb49d1
commit 39af44daef
10 changed files with 5827 additions and 37 deletions

View File

@@ -0,0 +1,3 @@
ALTER TABLE "git_provider" ADD COLUMN "userId" text NOT NULL;--> statement-breakpoint
ALTER TABLE "git_provider" ADD CONSTRAINT "git_provider_userId_account_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."account"("user_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_unique" UNIQUE("user_id");

File diff suppressed because it is too large Load Diff

View File

@@ -652,6 +652,13 @@
"when": 1747713229160, "when": 1747713229160,
"tag": "0092_stiff_the_watchers", "tag": "0092_stiff_the_watchers",
"breakpoints": true "breakpoints": true
},
{
"idx": 93,
"version": "7",
"when": 1748644790490,
"tag": "0093_elite_warlock",
"breakpoints": true
} }
] ]
} }

View File

@@ -22,7 +22,11 @@ export const bitbucketRouter = createTRPCRouter({
.input(apiCreateBitbucket) .input(apiCreateBitbucket)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { try {
return await createBitbucket(input, ctx.session.activeOrganizationId); return await createBitbucket(
input,
ctx.session.activeOrganizationId,
ctx.session.userId,
);
} catch (error) { } catch (error) {
throw new TRPCError({ throw new TRPCError({
code: "BAD_REQUEST", code: "BAD_REQUEST",
@@ -36,8 +40,9 @@ export const bitbucketRouter = createTRPCRouter({
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
const bitbucketProvider = await findBitbucketById(input.bitbucketId); const bitbucketProvider = await findBitbucketById(input.bitbucketId);
if ( if (
bitbucketProvider.gitProvider.organizationId !== (bitbucketProvider.gitProvider.organizationId !==
ctx.session.activeOrganizationId ctx.session.activeOrganizationId &&
bitbucketProvider.gitProvider.userId !== ctx.session.userId)
) { ) {
throw new TRPCError({ throw new TRPCError({
code: "UNAUTHORIZED", code: "UNAUTHORIZED",
@@ -56,21 +61,28 @@ export const bitbucketRouter = createTRPCRouter({
}, },
}); });
result = result.filter( result = result.filter((provider) => {
(provider) => return (
provider.gitProvider.organizationId === provider.gitProvider.organizationId === ctx.session.activeOrganizationId &&
ctx.session.activeOrganizationId, provider.gitProvider.userId === ctx.session.userId
); );
});
return result; return result;
}), }),
getBitbucketRepositories: protectedProcedure getBitbucketRepositories: protectedProcedure
.input(apiFindOneBitbucket) .input(apiFindOneBitbucket)
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
console.log({
activeOrganizationId: ctx.session.activeOrganizationId,
userId: ctx.session.userId,
bitbucketId: input.bitbucketId,
});
const bitbucketProvider = await findBitbucketById(input.bitbucketId); const bitbucketProvider = await findBitbucketById(input.bitbucketId);
if ( if (
bitbucketProvider.gitProvider.organizationId !== (bitbucketProvider.gitProvider.organizationId !==
ctx.session.activeOrganizationId ctx.session.activeOrganizationId &&
bitbucketProvider.gitProvider.userId !== ctx.session.userId)
) { ) {
throw new TRPCError({ throw new TRPCError({
code: "UNAUTHORIZED", code: "UNAUTHORIZED",
@@ -82,12 +94,11 @@ export const bitbucketRouter = createTRPCRouter({
getBitbucketBranches: protectedProcedure getBitbucketBranches: protectedProcedure
.input(apiFindBitbucketBranches) .input(apiFindBitbucketBranches)
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
const bitbucketProvider = await findBitbucketById( const bitbucketProvider = await findBitbucketById(input.bitbucketId || "");
input.bitbucketId || "",
);
if ( if (
bitbucketProvider.gitProvider.organizationId !== (bitbucketProvider.gitProvider.organizationId !==
ctx.session.activeOrganizationId ctx.session.activeOrganizationId &&
bitbucketProvider.gitProvider.userId !== ctx.session.userId)
) { ) {
throw new TRPCError({ throw new TRPCError({
code: "UNAUTHORIZED", code: "UNAUTHORIZED",
@@ -102,8 +113,9 @@ export const bitbucketRouter = createTRPCRouter({
try { try {
const bitbucketProvider = await findBitbucketById(input.bitbucketId); const bitbucketProvider = await findBitbucketById(input.bitbucketId);
if ( if (
bitbucketProvider.gitProvider.organizationId !== (bitbucketProvider.gitProvider.organizationId !==
ctx.session.activeOrganizationId ctx.session.activeOrganizationId &&
bitbucketProvider.gitProvider.userId !== ctx.session.userId)
) { ) {
throw new TRPCError({ throw new TRPCError({
code: "UNAUTHORIZED", code: "UNAUTHORIZED",
@@ -125,8 +137,9 @@ export const bitbucketRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
const bitbucketProvider = await findBitbucketById(input.bitbucketId); const bitbucketProvider = await findBitbucketById(input.bitbucketId);
if ( if (
bitbucketProvider.gitProvider.organizationId !== (bitbucketProvider.gitProvider.organizationId !==
ctx.session.activeOrganizationId ctx.session.activeOrganizationId &&
bitbucketProvider.gitProvider.userId !== ctx.session.userId)
) { ) {
throw new TRPCError({ throw new TRPCError({
code: "UNAUTHORIZED", code: "UNAUTHORIZED",

View File

@@ -3,7 +3,7 @@ import { db } from "@/server/db";
import { apiRemoveGitProvider, gitProvider } from "@/server/db/schema"; import { apiRemoveGitProvider, gitProvider } from "@/server/db/schema";
import { findGitProviderById, removeGitProvider } from "@dokploy/server"; import { findGitProviderById, removeGitProvider } from "@dokploy/server";
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { desc, eq } from "drizzle-orm"; import { desc, eq, or } from "drizzle-orm";
export const gitProviderRouter = createTRPCRouter({ export const gitProviderRouter = createTRPCRouter({
getAll: protectedProcedure.query(async ({ ctx }) => { getAll: protectedProcedure.query(async ({ ctx }) => {
@@ -15,7 +15,7 @@ export const gitProviderRouter = createTRPCRouter({
gitea: true, gitea: true,
}, },
orderBy: desc(gitProvider.createdAt), orderBy: desc(gitProvider.createdAt),
where: eq(gitProvider.organizationId, ctx.session.activeOrganizationId), where: eq(gitProvider.userId, ctx.session.userId),
}); });
}), }),
remove: protectedProcedure remove: protectedProcedure

View File

@@ -26,7 +26,11 @@ export const giteaRouter = createTRPCRouter({
.input(apiCreateGitea) .input(apiCreateGitea)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { try {
return await createGitea(input, ctx.session.activeOrganizationId); return await createGitea(
input,
ctx.session.activeOrganizationId,
ctx.session.userId,
);
} catch (error) { } catch (error) {
throw new TRPCError({ throw new TRPCError({
code: "BAD_REQUEST", code: "BAD_REQUEST",
@@ -41,8 +45,9 @@ export const giteaRouter = createTRPCRouter({
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
const giteaProvider = await findGiteaById(input.giteaId); const giteaProvider = await findGiteaById(input.giteaId);
if ( if (
giteaProvider.gitProvider.organizationId !== (giteaProvider.gitProvider.organizationId !==
ctx.session.activeOrganizationId ctx.session.activeOrganizationId &&
giteaProvider.gitProvider.userId !== ctx.session.userId)
) { ) {
throw new TRPCError({ throw new TRPCError({
code: "UNAUTHORIZED", code: "UNAUTHORIZED",
@@ -61,8 +66,9 @@ export const giteaRouter = createTRPCRouter({
result = result.filter( result = result.filter(
(provider) => (provider) =>
provider.gitProvider.organizationId === (provider.gitProvider.organizationId ===
ctx.session.activeOrganizationId, ctx.session.activeOrganizationId &&
provider.gitProvider.userId === ctx.session.userId)
); );
const filtered = result const filtered = result
@@ -93,8 +99,9 @@ export const giteaRouter = createTRPCRouter({
const giteaProvider = await findGiteaById(giteaId); const giteaProvider = await findGiteaById(giteaId);
if ( if (
giteaProvider.gitProvider.organizationId !== (giteaProvider.gitProvider.organizationId !==
ctx.session.activeOrganizationId ctx.session.activeOrganizationId &&
giteaProvider.gitProvider.userId !== ctx.session.userId)
) { ) {
throw new TRPCError({ throw new TRPCError({
code: "UNAUTHORIZED", code: "UNAUTHORIZED",
@@ -129,8 +136,9 @@ export const giteaRouter = createTRPCRouter({
const giteaProvider = await findGiteaById(giteaId); const giteaProvider = await findGiteaById(giteaId);
if ( if (
giteaProvider.gitProvider.organizationId !== (giteaProvider.gitProvider.organizationId !==
ctx.session.activeOrganizationId ctx.session.activeOrganizationId &&
giteaProvider.gitProvider.userId !== ctx.session.userId)
) { ) {
throw new TRPCError({ throw new TRPCError({
code: "UNAUTHORIZED", code: "UNAUTHORIZED",
@@ -161,8 +169,9 @@ export const giteaRouter = createTRPCRouter({
try { try {
const giteaProvider = await findGiteaById(giteaId); const giteaProvider = await findGiteaById(giteaId);
if ( if (
giteaProvider.gitProvider.organizationId !== (giteaProvider.gitProvider.organizationId !==
ctx.session.activeOrganizationId ctx.session.activeOrganizationId &&
giteaProvider.gitProvider.userId !== ctx.session.userId)
) { ) {
throw new TRPCError({ throw new TRPCError({
code: "UNAUTHORIZED", code: "UNAUTHORIZED",
@@ -189,8 +198,9 @@ export const giteaRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
const giteaProvider = await findGiteaById(input.giteaId); const giteaProvider = await findGiteaById(input.giteaId);
if ( if (
giteaProvider.gitProvider.organizationId !== (giteaProvider.gitProvider.organizationId !==
ctx.session.activeOrganizationId ctx.session.activeOrganizationId &&
giteaProvider.gitProvider.userId !== ctx.session.userId)
) { ) {
throw new TRPCError({ throw new TRPCError({
code: "UNAUTHORIZED", code: "UNAUTHORIZED",
@@ -230,8 +240,9 @@ export const giteaRouter = createTRPCRouter({
const giteaProvider = await findGiteaById(giteaId); const giteaProvider = await findGiteaById(giteaId);
if ( if (
giteaProvider.gitProvider.organizationId !== (giteaProvider.gitProvider.organizationId !==
ctx.session.activeOrganizationId ctx.session.activeOrganizationId &&
giteaProvider.gitProvider.userId !== ctx.session.userId)
) { ) {
throw new TRPCError({ throw new TRPCError({
code: "UNAUTHORIZED", code: "UNAUTHORIZED",

View File

@@ -21,6 +21,7 @@ export const account = pgTable("account", {
providerId: text("provider_id").notNull(), providerId: text("provider_id").notNull(),
userId: text("user_id") userId: text("user_id")
.notNull() .notNull()
.unique()
.references(() => users_temp.id, { onDelete: "cascade" }), .references(() => users_temp.id, { onDelete: "cascade" }),
accessToken: text("access_token"), accessToken: text("access_token"),
refreshToken: text("refresh_token"), refreshToken: text("refresh_token"),

View File

@@ -3,7 +3,7 @@ import { pgEnum, pgTable, text } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod"; import { createInsertSchema } from "drizzle-zod";
import { nanoid } from "nanoid"; import { nanoid } from "nanoid";
import { z } from "zod"; import { z } from "zod";
import { organization } from "./account"; import { organization, account } from "./account";
import { bitbucket } from "./bitbucket"; import { bitbucket } from "./bitbucket";
import { gitea } from "./gitea"; import { gitea } from "./gitea";
import { github } from "./github"; import { github } from "./github";
@@ -29,6 +29,9 @@ export const gitProvider = pgTable("git_provider", {
organizationId: text("organizationId") organizationId: text("organizationId")
.notNull() .notNull()
.references(() => organization.id, { onDelete: "cascade" }), .references(() => organization.id, { onDelete: "cascade" }),
userId: text("userId")
.notNull()
.references(() => account.userId, { onDelete: "cascade" }),
}); });
export const gitProviderRelations = relations(gitProvider, ({ one }) => ({ export const gitProviderRelations = relations(gitProvider, ({ one }) => ({
@@ -52,6 +55,10 @@ export const gitProviderRelations = relations(gitProvider, ({ one }) => ({
fields: [gitProvider.organizationId], fields: [gitProvider.organizationId],
references: [organization.id], references: [organization.id],
}), }),
account: one(account, {
fields: [gitProvider.userId],
references: [account.userId],
}),
})); }));
const createSchema = createInsertSchema(gitProvider); const createSchema = createInsertSchema(gitProvider);

View File

@@ -13,6 +13,7 @@ export type Bitbucket = typeof bitbucket.$inferSelect;
export const createBitbucket = async ( export const createBitbucket = async (
input: typeof apiCreateBitbucket._type, input: typeof apiCreateBitbucket._type,
organizationId: string, organizationId: string,
userId: string,
) => { ) => {
return await db.transaction(async (tx) => { return await db.transaction(async (tx) => {
const newGitProvider = await tx const newGitProvider = await tx
@@ -21,6 +22,7 @@ export const createBitbucket = async (
providerType: "bitbucket", providerType: "bitbucket",
organizationId: organizationId, organizationId: organizationId,
name: input.name, name: input.name,
userId: userId,
}) })
.returning() .returning()
.then((response) => response[0]); .then((response) => response[0]);

View File

@@ -12,6 +12,7 @@ export type Gitea = typeof gitea.$inferSelect;
export const createGitea = async ( export const createGitea = async (
input: typeof apiCreateGitea._type, input: typeof apiCreateGitea._type,
organizationId: string, organizationId: string,
userId: string,
) => { ) => {
return await db.transaction(async (tx) => { return await db.transaction(async (tx) => {
const newGitProvider = await tx const newGitProvider = await tx
@@ -20,6 +21,7 @@ export const createGitea = async (
providerType: "gitea", providerType: "gitea",
organizationId: organizationId, organizationId: organizationId,
name: input.name, name: input.name,
userId: userId,
}) })
.returning() .returning()
.then((response) => response[0]); .then((response) => response[0]);