mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat: add permission to access to git providers
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { GitBranch, LockIcon } from "lucide-react";
|
import { CodeIcon, GitBranch, LockIcon } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { ComposeFileEditor } from "../compose-file-editor";
|
import { ComposeFileEditor } from "../compose-file-editor";
|
||||||
@@ -87,8 +87,9 @@ export const ShowProviderFormCompose = ({ composeId }: Props) => {
|
|||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="raw"
|
value="raw"
|
||||||
className="rounded-none border-b-2 border-b-transparent data-[state=active]:border-b-2 data-[state=active]:border-b-border"
|
className="rounded-none border-b-2 gap-2 border-b-transparent data-[state=active]:border-b-2 data-[state=active]:border-b-border"
|
||||||
>
|
>
|
||||||
|
<CodeIcon className="size-4 " />
|
||||||
Raw
|
Raw
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { AddGithubProvider } from "./add-github-provider";
|
|||||||
import { AddBitbucketProvider } from "./add-bitbucket-provider";
|
import { AddBitbucketProvider } from "./add-bitbucket-provider";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { RemoveGitProvider } from "../github/remove-github-app";
|
import { RemoveGitProvider } from "./remove-git-provider";
|
||||||
import { useUrl } from "@/utils/hooks/use-url";
|
import { useUrl } from "@/utils/hooks/use-url";
|
||||||
|
|
||||||
export const ShowGitProviders = () => {
|
export const ShowGitProviders = () => {
|
||||||
@@ -32,7 +32,7 @@ export const ShowGitProviders = () => {
|
|||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<h1 className="text-2xl font-bold">Git Providers</h1>
|
<h1 className="text-2xl font-bold">Git Providers</h1>
|
||||||
<p className="text-muted-foreground">
|
<p className="text-muted-foreground">
|
||||||
Connect your Git Providers to use it for login.
|
Connect your Git provider for authentication.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Card className=" bg-transparent">
|
<Card className=" bg-transparent">
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import { Button, buttonVariants } from "@/components/ui/button";
|
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "@/components/ui/card";
|
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { BadgeCheck, ExternalLink } from "lucide-react";
|
|
||||||
import Link from "next/link";
|
|
||||||
import { api } from "@/utils/api";
|
|
||||||
|
|
||||||
export const GitlabSetup = () => {
|
|
||||||
const [applicationId, setApplicationId] = useState("");
|
|
||||||
const [applicationSecret, setApplicationSecret] = useState("");
|
|
||||||
const haveGitlabConfigured = false;
|
|
||||||
const [url, setUrl] = useState("");
|
|
||||||
// const { data: haveGitlabConfigured } =
|
|
||||||
// api.admin.haveGitlabConfigured.useQuery();
|
|
||||||
const { data: adminData } = api.admin.one.useQuery();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const protocolAndHost = `${window.location.protocol}//${window.location.host}`;
|
|
||||||
|
|
||||||
setUrl(`${protocolAndHost}`);
|
|
||||||
}, [adminData]);
|
|
||||||
|
|
||||||
// const createGitlabApp = api.admin.createGitlabApp.useMutation();
|
|
||||||
|
|
||||||
const handleCreateApp = async () => {
|
|
||||||
// try {
|
|
||||||
// // await createGitlabApp.mutateAsync({
|
|
||||||
// // applicationId,
|
|
||||||
// // applicationSecret,
|
|
||||||
// // callbackUrl: `${window.location.origin}/api/gitlab/callback`,
|
|
||||||
// // });
|
|
||||||
// // Refetch the configuration status
|
|
||||||
// // await haveGitlabConfigured.refetch();
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error("Failed to create GitLab app", error);
|
|
||||||
// }
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card className="bg-transparent">
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle className="text-xl">Configure GitLab</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Setup your GitLab account to access your repositories.
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="h-full space-y-2">
|
|
||||||
{haveGitlabConfigured ? (
|
|
||||||
<div className="flex flex-col gap-2">
|
|
||||||
<div className="flex items-center gap-4">
|
|
||||||
<span className="text-muted-foreground text-sm">
|
|
||||||
GitLab account configured successfully.
|
|
||||||
</span>
|
|
||||||
<BadgeCheck className="size-4 text-green-700" />
|
|
||||||
</div>
|
|
||||||
<div className="flex items-end gap-4 flex-wrap">
|
|
||||||
<Button
|
|
||||||
variant="destructive"
|
|
||||||
onClick={() => {
|
|
||||||
/* Implement remove GitLab app logic */
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Remove GitLab App
|
|
||||||
</Button>
|
|
||||||
<Link
|
|
||||||
href="https://gitlab.com/-/profile/applications"
|
|
||||||
target="_blank"
|
|
||||||
className={buttonVariants({
|
|
||||||
className: "w-fit",
|
|
||||||
variant: "secondary",
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<span className="text-sm">Manage GitLab App</span>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="flex flex-col gap-4">
|
|
||||||
<p className="text-muted-foreground text-sm">
|
|
||||||
To integrate your GitLab account, you need to create a new
|
|
||||||
application in your GitLab settings. Follow these steps:
|
|
||||||
</p>
|
|
||||||
<ol className="list-decimal list-inside text-sm text-muted-foreground">
|
|
||||||
<li className="flex flex-row gap-2">
|
|
||||||
Go to your GitLab profile settings{" "}
|
|
||||||
<Link
|
|
||||||
href="https://gitlab.com/-/profile/applications"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<ExternalLink className="w-fit text-primary size-4" />
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
<li>Navigate to Applications</li>
|
|
||||||
<li>
|
|
||||||
Create a new application with the following details:
|
|
||||||
<ul className="list-disc list-inside ml-4">
|
|
||||||
<li>Name: Dokploy</li>
|
|
||||||
<li>Redirect URI: {`${url}/api/gitlab/callback`}</li>
|
|
||||||
<li>Scopes: api, read_user, read_repository</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
After creating, you'll receive an Application ID and Secret
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
<Input
|
|
||||||
placeholder="Application ID"
|
|
||||||
value={applicationId}
|
|
||||||
onChange={(e) => setApplicationId(e.target.value)}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
type="password"
|
|
||||||
placeholder="Application Secret"
|
|
||||||
value={applicationSecret}
|
|
||||||
onChange={(e) => setApplicationSecret(e.target.value)}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
onClick={handleCreateApp}
|
|
||||||
disabled={!applicationId || !applicationSecret}
|
|
||||||
>
|
|
||||||
Configure GitLab App
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -40,6 +40,7 @@ const addPermissions = z.object({
|
|||||||
canAccessToDocker: z.boolean().optional().default(false),
|
canAccessToDocker: z.boolean().optional().default(false),
|
||||||
canAccessToAPI: z.boolean().optional().default(false),
|
canAccessToAPI: z.boolean().optional().default(false),
|
||||||
canAccessToSSHKeys: z.boolean().optional().default(false),
|
canAccessToSSHKeys: z.boolean().optional().default(false),
|
||||||
|
canAccessToGitProviders: z.boolean().optional().default(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
type AddPermissions = z.infer<typeof addPermissions>;
|
type AddPermissions = z.infer<typeof addPermissions>;
|
||||||
@@ -84,6 +85,7 @@ export const AddUserPermissions = ({ userId }: Props) => {
|
|||||||
canAccessToDocker: data.canAccessToDocker,
|
canAccessToDocker: data.canAccessToDocker,
|
||||||
canAccessToAPI: data.canAccessToAPI,
|
canAccessToAPI: data.canAccessToAPI,
|
||||||
canAccessToSSHKeys: data.canAccessToSSHKeys,
|
canAccessToSSHKeys: data.canAccessToSSHKeys,
|
||||||
|
canAccessToGitProviders: data.canAccessToGitProviders,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [form, form.formState.isSubmitSuccessful, form.reset, data]);
|
}, [form, form.formState.isSubmitSuccessful, form.reset, data]);
|
||||||
@@ -101,6 +103,7 @@ export const AddUserPermissions = ({ userId }: Props) => {
|
|||||||
canAccessToDocker: data.canAccessToDocker,
|
canAccessToDocker: data.canAccessToDocker,
|
||||||
canAccessToAPI: data.canAccessToAPI,
|
canAccessToAPI: data.canAccessToAPI,
|
||||||
canAccessToSSHKeys: data.canAccessToSSHKeys,
|
canAccessToSSHKeys: data.canAccessToSSHKeys,
|
||||||
|
canAccessToGitProviders: data.canAccessToGitProviders,
|
||||||
})
|
})
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
toast.success("Permissions updated");
|
toast.success("Permissions updated");
|
||||||
@@ -293,6 +296,26 @@ export const AddUserPermissions = ({ userId }: Props) => {
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="canAccessToGitProviders"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-3 shadow-sm">
|
||||||
|
<div className="space-y-0.5">
|
||||||
|
<FormLabel>Access to Git Providers</FormLabel>
|
||||||
|
<FormDescription>
|
||||||
|
Allow to users to access to the Git Providers section
|
||||||
|
</FormDescription>
|
||||||
|
</div>
|
||||||
|
<FormControl>
|
||||||
|
<Switch
|
||||||
|
checked={field.value}
|
||||||
|
onCheckedChange={field.onChange}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="accesedProjects"
|
name="accesedProjects"
|
||||||
|
|||||||
1
apps/dokploy/drizzle/0054_short_hellfire_club.sql
Normal file
1
apps/dokploy/drizzle/0054_short_hellfire_club.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "user" ADD COLUMN "canAccessToGitProviders" boolean DEFAULT false NOT NULL;
|
||||||
3539
apps/dokploy/drizzle/meta/0054_snapshot.json
Normal file
3539
apps/dokploy/drizzle/meta/0054_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -379,6 +379,13 @@
|
|||||||
"when": 1725232936525,
|
"when": 1725232936525,
|
||||||
"tag": "0053_fearless_electro",
|
"tag": "0053_fearless_electro",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 54,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1725238308102,
|
||||||
|
"tag": "0054_short_hellfire_club",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
import { ShowGitProviders } from "@/components/dashboard/settings/git/show-git-providers";
|
import { ShowGitProviders } from "@/components/dashboard/settings/git/show-git-providers";
|
||||||
import { GitlabSetup } from "@/components/dashboard/settings/github/gitlab-setup";
|
|
||||||
import { ShowDestinations } from "@/components/dashboard/settings/ssh-keys/show-ssh-keys";
|
|
||||||
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
||||||
import { SettingsLayout } from "@/components/layouts/settings-layout";
|
import { SettingsLayout } from "@/components/layouts/settings-layout";
|
||||||
import { appRouter } from "@/server/api/root";
|
import { appRouter } from "@/server/api/root";
|
||||||
@@ -14,8 +12,6 @@ const Page = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-4 w-full">
|
<div className="flex flex-col gap-4 w-full">
|
||||||
<ShowGitProviders />
|
<ShowGitProviders />
|
||||||
{/* <ShowDestinations /> */}
|
|
||||||
{/* <GitlabSetup /> */}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -41,7 +37,7 @@ export async function getServerSideProps(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const { req, res, resolvedUrl } = ctx;
|
const { req, res } = ctx;
|
||||||
const helpers = createServerSideHelpers({
|
const helpers = createServerSideHelpers({
|
||||||
router: appRouter,
|
router: appRouter,
|
||||||
ctx: {
|
ctx: {
|
||||||
@@ -63,7 +59,7 @@ export async function getServerSideProps(
|
|||||||
authId: auth.id,
|
authId: auth.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!user.canAccessToSSHKeys) {
|
if (!user.canAccessToGitProviders) {
|
||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
|
|||||||
@@ -146,7 +146,6 @@ export const deployApplication = async ({
|
|||||||
}) => {
|
}) => {
|
||||||
const application = await findApplicationById(applicationId);
|
const application = await findApplicationById(applicationId);
|
||||||
const buildLink = `${await getDokployUrl()}/dashboard/project/${application.projectId}/services/application/${application.applicationId}?tab=deployments`;
|
const buildLink = `${await getDokployUrl()}/dashboard/project/${application.projectId}/services/application/${application.applicationId}?tab=deployments`;
|
||||||
const admin = await findAdmin();
|
|
||||||
const deployment = await createDeployment({
|
const deployment = await createDeployment({
|
||||||
applicationId: applicationId,
|
applicationId: applicationId,
|
||||||
title: titleLog,
|
title: titleLog,
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ export const users = pgTable("user", {
|
|||||||
canDeleteServices: boolean("canDeleteServices").notNull().default(false),
|
canDeleteServices: boolean("canDeleteServices").notNull().default(false),
|
||||||
canAccessToDocker: boolean("canAccessToDocker").notNull().default(false),
|
canAccessToDocker: boolean("canAccessToDocker").notNull().default(false),
|
||||||
canAccessToAPI: boolean("canAccessToAPI").notNull().default(false),
|
canAccessToAPI: boolean("canAccessToAPI").notNull().default(false),
|
||||||
|
canAccessToGitProviders: boolean("canAccessToGitProviders")
|
||||||
|
.notNull()
|
||||||
|
.default(false),
|
||||||
canAccessToTraefikFiles: boolean("canAccessToTraefikFiles")
|
canAccessToTraefikFiles: boolean("canAccessToTraefikFiles")
|
||||||
.notNull()
|
.notNull()
|
||||||
.default(false),
|
.default(false),
|
||||||
@@ -109,6 +112,7 @@ export const apiAssignPermissions = createSchema
|
|||||||
canAccessToDocker: true,
|
canAccessToDocker: true,
|
||||||
canAccessToAPI: true,
|
canAccessToAPI: true,
|
||||||
canAccessToSSHKeys: true,
|
canAccessToSSHKeys: true,
|
||||||
|
canAccessToGitProviders: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user