Merge branch 'canary' into fix/environment-access-fallback

This commit is contained in:
Mauricio Siu
2026-01-21 11:09:02 +01:00
75 changed files with 10590 additions and 1898 deletions

View File

@@ -909,7 +909,9 @@ const EnvironmentPage = (
<ProjectEnvironment projectId={projectId}>
<Button variant="outline">Project Environment</Button>
</ProjectEnvironment>
{(auth?.role === "owner" || auth?.canCreateServices) && (
{(auth?.role === "owner" ||
auth?.role === "admin" ||
auth?.canCreateServices) && (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button>
@@ -1032,6 +1034,7 @@ const EnvironmentPage = (
</Button>
</DialogAction>
{(auth?.role === "owner" ||
auth?.role === "admin" ||
auth?.canDeleteServices) && (
<>
<DialogAction

View File

@@ -108,6 +108,7 @@ const Service = (
{ name: "Projects", href: "/dashboard/projects" },
{
name: data?.environment?.project?.name || "",
href: `/dashboard/project/${projectId}/environment/${environmentId}`,
},
{
name: data?.environment?.name || "",
@@ -192,7 +193,9 @@ const Service = (
<div className="flex flex-row gap-2 justify-end">
<UpdateApplication applicationId={applicationId} />
{(auth?.role === "owner" || auth?.canDeleteServices) && (
{(auth?.role === "owner" ||
auth?.role === "admin" ||
auth?.canDeleteServices) && (
<DeleteService id={applicationId} type="application" />
)}
</div>

View File

@@ -97,6 +97,7 @@ const Service = (
{ name: "Projects", href: "/dashboard/projects" },
{
name: data?.environment?.project?.name || "",
href: `/dashboard/project/${projectId}/environment/${environmentId}`,
},
{
name: data?.environment?.name || "",
@@ -182,7 +183,9 @@ const Service = (
<div className="flex flex-row gap-2 justify-end">
<UpdateCompose composeId={composeId} />
{(auth?.role === "owner" || auth?.canDeleteServices) && (
{(auth?.role === "owner" ||
auth?.role === "admin" ||
auth?.canDeleteServices) && (
<DeleteService id={composeId} type="compose" />
)}
</div>

View File

@@ -79,6 +79,7 @@ const Mariadb = (
{ name: "Projects", href: "/dashboard/projects" },
{
name: data?.environment?.project?.name || "",
href: `/dashboard/project/${projectId}/environment/${environmentId}`,
},
{
name: data?.environment?.name || "",
@@ -156,7 +157,9 @@ const Mariadb = (
</div>
<div className="flex flex-row gap-2 justify-end">
<UpdateMariadb mariadbId={mariadbId} />
{(auth?.role === "owner" || auth?.canDeleteServices) && (
{(auth?.role === "owner" ||
auth?.role === "admin" ||
auth?.canDeleteServices) && (
<DeleteService id={mariadbId} type="mariadb" />
)}
</div>

View File

@@ -78,6 +78,7 @@ const Mongo = (
{ name: "Projects", href: "/dashboard/projects" },
{
name: data?.environment?.project?.name || "",
href: `/dashboard/project/${projectId}/environment/${environmentId}`,
},
{
name: data?.environment?.name || "",
@@ -155,7 +156,9 @@ const Mongo = (
<div className="flex flex-row gap-2 justify-end">
<UpdateMongo mongoId={mongoId} />
{(auth?.role === "owner" || auth?.canDeleteServices) && (
{(auth?.role === "owner" ||
auth?.role === "admin" ||
auth?.canDeleteServices) && (
<DeleteService id={mongoId} type="mongo" />
)}
</div>

View File

@@ -77,6 +77,7 @@ const MySql = (
{ name: "Projects", href: "/dashboard/projects" },
{
name: data?.environment?.project?.name || "",
href: `/dashboard/project/${projectId}/environment/${environmentId}`,
},
{
name: data?.environment?.name || "",
@@ -156,7 +157,9 @@ const MySql = (
<div className="flex flex-row gap-2 justify-end">
<UpdateMysql mysqlId={mysqlId} />
{(auth?.role === "owner" || auth?.canDeleteServices) && (
{(auth?.role === "owner" ||
auth?.role === "admin" ||
auth?.canDeleteServices) && (
<DeleteService id={mysqlId} type="mysql" />
)}
</div>

View File

@@ -77,6 +77,7 @@ const Postgresql = (
{ name: "Projects", href: "/dashboard/projects" },
{
name: data?.environment?.project?.name || "",
href: `/dashboard/project/${projectId}/environment/${environmentId}`,
},
{
name: data?.environment?.name || "",
@@ -154,7 +155,9 @@ const Postgresql = (
<div className="flex flex-row gap-2 justify-end">
<UpdatePostgres postgresId={postgresId} />
{(auth?.role === "owner" || auth?.canDeleteServices) && (
{(auth?.role === "owner" ||
auth?.role === "admin" ||
auth?.canDeleteServices) && (
<DeleteService id={postgresId} type="postgres" />
)}
</div>

View File

@@ -77,6 +77,7 @@ const Redis = (
{ name: "Projects", href: "/dashboard/projects" },
{
name: data?.environment?.project?.name || "",
href: `/dashboard/project/${projectId}/environment/${environmentId}`,
},
{
name: data?.environment?.name || "",
@@ -154,7 +155,9 @@ const Redis = (
<div className="flex flex-row gap-2 justify-end">
<UpdateRedis redisId={redisId} />
{(auth?.role === "owner" || auth?.canDeleteServices) && (
{(auth?.role === "owner" ||
auth?.role === "admin" ||
auth?.canDeleteServices) && (
<DeleteService id={redisId} type="redis" />
)}
</div>

View File

@@ -0,0 +1,63 @@
import { IS_CLOUD } from "@dokploy/server/constants";
import { validateRequest } from "@dokploy/server/lib/auth";
import { createServerSideHelpers } from "@trpc/react-query/server";
import type { GetServerSidePropsContext } from "next";
import type { ReactElement } from "react";
import superjson from "superjson";
import { ShowBillingInvoices } from "@/components/dashboard/settings/billing/show-billing-invoices";
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
import { appRouter } from "@/server/api/root";
const Page = () => {
return <ShowBillingInvoices />;
};
export default Page;
Page.getLayout = (page: ReactElement) => {
return <DashboardLayout metaName="Invoices">{page}</DashboardLayout>;
};
export async function getServerSideProps(
ctx: GetServerSidePropsContext<{ serviceId: string }>,
) {
if (!IS_CLOUD) {
return {
redirect: {
permanent: true,
destination: "/dashboard/projects",
},
};
}
const { req, res } = ctx;
const { user, session } = await validateRequest(req);
if (!user || user.role !== "owner") {
return {
redirect: {
permanent: true,
destination: "/",
},
};
}
const helpers = createServerSideHelpers({
router: appRouter,
ctx: {
req: req as any,
res: res as any,
db: null as any,
session: session as any,
user: user as any,
},
transformer: superjson,
});
await helpers.user.get.prefetch();
await helpers.settings.isCloud.prefetch();
return {
props: {
trpcState: helpers.dehydrate(),
},
};
}