mirror of
https://github.com/LukeHagar/dokploy.git
synced 2025-12-09 12:27:48 +00:00
refactor: migrate admin API calls to user router
This commit is contained in:
@@ -79,7 +79,7 @@ export const ContainerPaidMonitoring = ({ appName, baseUrl, token }: Props) => {
|
|||||||
data,
|
data,
|
||||||
isLoading,
|
isLoading,
|
||||||
error: queryError,
|
error: queryError,
|
||||||
} = api.admin.getContainerMetrics.useQuery(
|
} = api.user.getContainerMetrics.useQuery(
|
||||||
{
|
{
|
||||||
url: baseUrl,
|
url: baseUrl,
|
||||||
token,
|
token,
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export const ShowPaidMonitoring = ({
|
|||||||
data,
|
data,
|
||||||
isLoading,
|
isLoading,
|
||||||
error: queryError,
|
error: queryError,
|
||||||
} = api.admin.getServerMetrics.useQuery(
|
} = api.user.getServerMetrics.useQuery(
|
||||||
{
|
{
|
||||||
url: BASE_URL,
|
url: BASE_URL,
|
||||||
token,
|
token,
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ import { ProjectEnvironment } from "./project-environment";
|
|||||||
export const ShowProjects = () => {
|
export const ShowProjects = () => {
|
||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
const { data, isLoading } = api.project.all.useQuery();
|
const { data, isLoading } = api.project.all.useQuery();
|
||||||
const { data: auth } = api.auth.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const { mutateAsync } = api.project.remove.useMutation();
|
const { mutateAsync } = api.project.remove.useMutation();
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export const calculatePrice = (count: number, isAnnual = false) => {
|
|||||||
};
|
};
|
||||||
export const ShowBilling = () => {
|
export const ShowBilling = () => {
|
||||||
const { data: servers } = api.server.all.useQuery(undefined);
|
const { data: servers } = api.server.all.useQuery(undefined);
|
||||||
const { data: admin } = api.admin.one.useQuery();
|
const { data: admin } = api.user.get.useQuery();
|
||||||
const { data, isLoading } = api.stripe.getProducts.useQuery();
|
const { data, isLoading } = api.stripe.getProducts.useQuery();
|
||||||
const { mutateAsync: createCheckoutSession } =
|
const { mutateAsync: createCheckoutSession } =
|
||||||
api.stripe.createCheckoutSession.useMutation();
|
api.stripe.createCheckoutSession.useMutation();
|
||||||
@@ -70,7 +70,7 @@ export const ShowBilling = () => {
|
|||||||
return isAnnual ? interval === "year" : interval === "month";
|
return isAnnual ? interval === "year" : interval === "month";
|
||||||
});
|
});
|
||||||
|
|
||||||
const maxServers = admin?.serversQuantity ?? 1;
|
const maxServers = admin?.user.serversQuantity ?? 1;
|
||||||
const percentage = ((servers?.length ?? 0) / maxServers) * 100;
|
const percentage = ((servers?.length ?? 0) / maxServers) * 100;
|
||||||
const safePercentage = Math.min(percentage, 100);
|
const safePercentage = Math.min(percentage, 100);
|
||||||
|
|
||||||
@@ -98,17 +98,17 @@ export const ShowBilling = () => {
|
|||||||
<TabsTrigger value="annual">Annual</TabsTrigger>
|
<TabsTrigger value="annual">Annual</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
{admin?.stripeSubscriptionId && (
|
{admin?.user.stripeSubscriptionId && (
|
||||||
<div className="space-y-2 flex flex-col">
|
<div className="space-y-2 flex flex-col">
|
||||||
<h3 className="text-lg font-medium">Servers Plan</h3>
|
<h3 className="text-lg font-medium">Servers Plan</h3>
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
You have {servers?.length} server on your plan of{" "}
|
You have {servers?.length} server on your plan of{" "}
|
||||||
{admin?.serversQuantity} servers
|
{admin?.user.serversQuantity} servers
|
||||||
</p>
|
</p>
|
||||||
<div>
|
<div>
|
||||||
<Progress value={safePercentage} className="max-w-lg" />
|
<Progress value={safePercentage} className="max-w-lg" />
|
||||||
</div>
|
</div>
|
||||||
{admin && admin.serversQuantity! <= servers?.length! && (
|
{admin && admin.user.serversQuantity! <= servers?.length! && (
|
||||||
<div className="flex flex-row gap-4 p-2 bg-yellow-50 dark:bg-yellow-950 rounded-lg items-center">
|
<div className="flex flex-row gap-4 p-2 bg-yellow-50 dark:bg-yellow-950 rounded-lg items-center">
|
||||||
<AlertTriangle className="text-yellow-600 dark:text-yellow-400" />
|
<AlertTriangle className="text-yellow-600 dark:text-yellow-400" />
|
||||||
<span className="text-sm text-yellow-600 dark:text-yellow-400">
|
<span className="text-sm text-yellow-600 dark:text-yellow-400">
|
||||||
@@ -279,7 +279,7 @@ export const ShowBilling = () => {
|
|||||||
"flex flex-row items-center gap-2 mt-4",
|
"flex flex-row items-center gap-2 mt-4",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{admin?.stripeCustomerId && (
|
{admin?.user.stripeCustomerId && (
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
className="w-full"
|
className="w-full"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import type React from "react";
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
export const ShowWelcomeDokploy = () => {
|
export const ShowWelcomeDokploy = () => {
|
||||||
const { data } = api.auth.get.useQuery();
|
const { data } = api.user.get.useQuery();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
const { data: isCloud, isLoading } = api.settings.isCloud.useQuery();
|
const { data: isCloud, isLoading } = api.settings.isCloud.useQuery();
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export const AddBitbucketProvider = () => {
|
|||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const url = useUrl();
|
const url = useUrl();
|
||||||
const { mutateAsync, error, isError } = api.bitbucket.create.useMutation();
|
const { mutateAsync, error, isError } = api.bitbucket.create.useMutation();
|
||||||
const { data: auth } = api.auth.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const form = useForm<Schema>({
|
const form = useForm<Schema>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { useEffect, useState } from "react";
|
|||||||
export const AddGithubProvider = () => {
|
export const AddGithubProvider = () => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const { data: activeOrganization } = authClient.useActiveOrganization();
|
const { data: activeOrganization } = authClient.useActiveOrganization();
|
||||||
const { data } = api.auth.get.useQuery();
|
const { data } = api.user.get.useQuery();
|
||||||
const [manifest, setManifest] = useState("");
|
const [manifest, setManifest] = useState("");
|
||||||
const [isOrganization, setIsOrganization] = useState(false);
|
const [isOrganization, setIsOrganization] = useState(false);
|
||||||
const [organizationName, setOrganization] = useState("");
|
const [organizationName, setOrganization] = useState("");
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const AddGitlabProvider = () => {
|
|||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const url = useUrl();
|
const url = useUrl();
|
||||||
const { data: auth } = api.auth.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const { mutateAsync, error, isError } = api.gitlab.create.useMutation();
|
const { mutateAsync, error, isError } = api.gitlab.create.useMutation();
|
||||||
const webhookUrl = `${url}/api/providers/gitlab/callback`;
|
const webhookUrl = `${url}/api/providers/gitlab/callback`;
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ export const Disable2FA = () => {
|
|||||||
|
|
||||||
toast.success("2FA disabled successfully");
|
toast.success("2FA disabled successfully");
|
||||||
utils.auth.get.invalidate();
|
utils.auth.get.invalidate();
|
||||||
|
setIsOpen(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
form.setError("password", {
|
form.setError("password", {
|
||||||
message: "Connection error. Please try again.",
|
message: "Connection error. Please try again.",
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import Link from "next/link";
|
|||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
export const GenerateToken = () => {
|
export const GenerateToken = () => {
|
||||||
const { data, refetch } = api.auth.get.useQuery();
|
const { data, refetch } = api.user.get.useQuery();
|
||||||
|
|
||||||
const { mutateAsync: generateToken, isLoading: isLoadingToken } =
|
const { mutateAsync: generateToken, isLoading: isLoadingToken } =
|
||||||
api.auth.generateToken.useMutation();
|
api.auth.generateToken.useMutation();
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export const ProfileForm = () => {
|
|||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
const { mutateAsync: disable2FA, isLoading: isDisabling } =
|
const { mutateAsync: disable2FA, isLoading: isDisabling } =
|
||||||
api.auth.disable2FA.useMutation();
|
api.auth.disable2FA.useMutation();
|
||||||
const { data, refetch, isLoading } = api.auth.get.useQuery();
|
const { data, refetch, isLoading } = api.user.get.useQuery();
|
||||||
const {
|
const {
|
||||||
mutateAsync,
|
mutateAsync,
|
||||||
isLoading: isUpdating,
|
isLoading: isUpdating,
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const profileSchema = z.object({
|
|||||||
type Profile = z.infer<typeof profileSchema>;
|
type Profile = z.infer<typeof profileSchema>;
|
||||||
|
|
||||||
export const RemoveSelfAccount = () => {
|
export const RemoveSelfAccount = () => {
|
||||||
const { data } = api.auth.get.useQuery();
|
const { data } = api.user.get.useQuery();
|
||||||
const { mutateAsync, isLoading, error, isError } =
|
const { mutateAsync, isLoading, error, isError } =
|
||||||
api.auth.removeSelfAccount.useMutation();
|
api.auth.removeSelfAccount.useMutation();
|
||||||
const { t } = useTranslation("settings");
|
const { t } = useTranslation("settings");
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ interface Props {
|
|||||||
serverId?: string;
|
serverId?: string;
|
||||||
}
|
}
|
||||||
export const ToggleDockerCleanup = ({ serverId }: Props) => {
|
export const ToggleDockerCleanup = ({ serverId }: Props) => {
|
||||||
const { data, refetch } = api.admin.one.useQuery(undefined, {
|
const { data, refetch } = api.user.get.useQuery(undefined, {
|
||||||
enabled: !serverId,
|
enabled: !serverId,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ export const ToggleDockerCleanup = ({ serverId }: Props) => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const enabled = data?.enableDockerCleanup || server?.enableDockerCleanup;
|
const enabled = data?.user.enableDockerCleanup || server?.enableDockerCleanup;
|
||||||
|
|
||||||
const { mutateAsync } = api.settings.updateDockerCleanup.useMutation();
|
const { mutateAsync } = api.settings.updateDockerCleanup.useMutation();
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export const SetupMonitoring = ({ serverId }: Props) => {
|
|||||||
enabled: !!serverId,
|
enabled: !!serverId,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: api.admin.one.useQuery();
|
: api.user.get.useQuery();
|
||||||
|
|
||||||
const url = useUrl();
|
const url = useUrl();
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export const AddUserPermissions = ({ userId }: Props) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const { mutateAsync, isError, error, isLoading } =
|
const { mutateAsync, isError, error, isLoading } =
|
||||||
api.admin.assignPermissions.useMutation();
|
api.user.assignPermissions.useMutation();
|
||||||
|
|
||||||
const form = useForm<AddPermissions>({
|
const form = useForm<AddPermissions>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import {
|
|||||||
import { authClient } from "@/lib/auth-client";
|
import { authClient } from "@/lib/auth-client";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import copy from "copy-to-clipboard";
|
import copy from "copy-to-clipboard";
|
||||||
import { format } from "date-fns";
|
import { format, isPast } from "date-fns";
|
||||||
import { Mail, MoreHorizontal, Users } from "lucide-react";
|
import { Mail, MoreHorizontal, Users } from "lucide-react";
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
@@ -35,8 +35,6 @@ import { AddInvitation } from "./add-invitation";
|
|||||||
export const ShowInvitations = () => {
|
export const ShowInvitations = () => {
|
||||||
const { data, isLoading, refetch } =
|
const { data, isLoading, refetch } =
|
||||||
api.organization.allInvitations.useQuery();
|
api.organization.allInvitations.useQuery();
|
||||||
const { mutateAsync, isLoading: isRemoving } =
|
|
||||||
api.admin.removeUser.useMutation();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
@@ -84,6 +82,9 @@ export const ShowInvitations = () => {
|
|||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{data?.map((invitation) => {
|
{data?.map((invitation) => {
|
||||||
|
const isExpired = isPast(
|
||||||
|
new Date(invitation.expiresAt),
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<TableRow key={invitation.id}>
|
<TableRow key={invitation.id}>
|
||||||
<TableCell className="w-[100px]">
|
<TableCell className="w-[100px]">
|
||||||
@@ -104,17 +105,22 @@ export const ShowInvitations = () => {
|
|||||||
<Badge
|
<Badge
|
||||||
variant={
|
variant={
|
||||||
invitation.status === "pending"
|
invitation.status === "pending"
|
||||||
? "default"
|
? "secondary"
|
||||||
: invitation.status === "canceled"
|
: invitation.status === "canceled"
|
||||||
? "destructive"
|
? "destructive"
|
||||||
: "secondary"
|
: "default"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{invitation.status}
|
{invitation.status}
|
||||||
</Badge>
|
</Badge>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="text-center">
|
<TableCell className="text-center">
|
||||||
{format(new Date(invitation.expiresAt), "PPpp")}
|
{format(new Date(invitation.expiresAt), "PPpp")}{" "}
|
||||||
|
{isExpired ? (
|
||||||
|
<span className="text-muted-foreground">
|
||||||
|
(Expired)
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell className="text-right flex justify-end">
|
<TableCell className="text-right flex justify-end">
|
||||||
@@ -132,44 +138,51 @@ export const ShowInvitations = () => {
|
|||||||
<DropdownMenuLabel>
|
<DropdownMenuLabel>
|
||||||
Actions
|
Actions
|
||||||
</DropdownMenuLabel>
|
</DropdownMenuLabel>
|
||||||
|
{!isExpired && (
|
||||||
|
<>
|
||||||
|
{invitation.status === "pending" && (
|
||||||
|
<DropdownMenuItem
|
||||||
|
className="w-full cursor-pointer"
|
||||||
|
onSelect={(e) => {
|
||||||
|
copy(
|
||||||
|
`${origin}/invitation?token=${invitation.id}`,
|
||||||
|
);
|
||||||
|
toast.success(
|
||||||
|
"Invitation Copied to clipboard",
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Copy Invitation
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
|
|
||||||
{invitation.status === "pending" && (
|
{invitation.status === "pending" && (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className="w-full cursor-pointer"
|
className="w-full cursor-pointer"
|
||||||
onSelect={(e) => {
|
onSelect={async (e) => {
|
||||||
copy(
|
const result =
|
||||||
`${origin}/invitation?token=${invitation.id}`,
|
await authClient.organization.cancelInvitation(
|
||||||
);
|
{
|
||||||
toast.success(
|
invitationId: invitation.id,
|
||||||
"Invitation Copied to clipboard",
|
},
|
||||||
);
|
);
|
||||||
}}
|
|
||||||
>
|
|
||||||
Copy Invitation
|
|
||||||
</DropdownMenuItem>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{invitation.status === "pending" && (
|
if (result.error) {
|
||||||
<DropdownMenuItem
|
toast.error(
|
||||||
className="w-full cursor-pointer"
|
result.error.message,
|
||||||
onSelect={async (e) => {
|
);
|
||||||
const result =
|
} else {
|
||||||
await authClient.organization.cancelInvitation(
|
toast.success(
|
||||||
{
|
"Invitation deleted",
|
||||||
invitationId: invitation.id,
|
);
|
||||||
},
|
refetch();
|
||||||
);
|
}
|
||||||
|
}}
|
||||||
if (result.error) {
|
>
|
||||||
toast.error(result.error.message);
|
Cancel Invitation
|
||||||
} else {
|
</DropdownMenuItem>
|
||||||
toast.success("Invitation deleted");
|
)}
|
||||||
refetch();
|
</>
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cancel Invitation
|
|
||||||
</DropdownMenuItem>
|
|
||||||
)}
|
)}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
|||||||
@@ -75,9 +75,7 @@ export const ShowUsers = () => {
|
|||||||
<TableHead className="w-[100px]">Email</TableHead>
|
<TableHead className="w-[100px]">Email</TableHead>
|
||||||
<TableHead className="text-center">Role</TableHead>
|
<TableHead className="text-center">Role</TableHead>
|
||||||
<TableHead className="text-center">2FA</TableHead>
|
<TableHead className="text-center">2FA</TableHead>
|
||||||
<TableHead className="text-center">
|
|
||||||
Is Registered
|
|
||||||
</TableHead>
|
|
||||||
<TableHead className="text-center">
|
<TableHead className="text-center">
|
||||||
Created At
|
Created At
|
||||||
</TableHead>
|
</TableHead>
|
||||||
@@ -108,12 +106,6 @@ export const ShowUsers = () => {
|
|||||||
: "Disabled"}
|
: "Disabled"}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="text-center">
|
<TableCell className="text-center">
|
||||||
{member.user.isRegistered ||
|
|
||||||
member.role === "owner"
|
|
||||||
? "Registered"
|
|
||||||
: "Not Registered"}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="text-right">
|
|
||||||
<span className="text-sm text-muted-foreground">
|
<span className="text-sm text-muted-foreground">
|
||||||
{format(new Date(member.createdAt), "PPpp")}
|
{format(new Date(member.createdAt), "PPpp")}
|
||||||
</span>
|
</span>
|
||||||
@@ -134,22 +126,6 @@ export const ShowUsers = () => {
|
|||||||
<DropdownMenuLabel>
|
<DropdownMenuLabel>
|
||||||
Actions
|
Actions
|
||||||
</DropdownMenuLabel>
|
</DropdownMenuLabel>
|
||||||
{!member.user.isRegistered &&
|
|
||||||
member.role !== "owner" && (
|
|
||||||
<DropdownMenuItem
|
|
||||||
className="w-full cursor-pointer"
|
|
||||||
onSelect={(e) => {
|
|
||||||
copy(
|
|
||||||
`${origin}/invitation?token=${member.user.token}`,
|
|
||||||
);
|
|
||||||
toast.success(
|
|
||||||
"Invitation Copied to clipboard",
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Copy Invitation
|
|
||||||
</DropdownMenuItem>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{member.role !== "owner" && (
|
{member.role !== "owner" && (
|
||||||
<AddUserPermissions
|
<AddUserPermissions
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ type AddServerDomain = z.infer<typeof addServerDomain>;
|
|||||||
|
|
||||||
export const WebDomain = () => {
|
export const WebDomain = () => {
|
||||||
const { t } = useTranslation("settings");
|
const { t } = useTranslation("settings");
|
||||||
const { data, refetch } = api.auth.get.useQuery();
|
const { data, refetch } = api.user.get.useQuery();
|
||||||
const { mutateAsync, isLoading } =
|
const { mutateAsync, isLoading } =
|
||||||
api.settings.assignDomainServer.useMutation();
|
api.settings.assignDomainServer.useMutation();
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
export const WebServer = ({ className }: Props) => {
|
export const WebServer = ({ className }: Props) => {
|
||||||
const { t } = useTranslation("settings");
|
const { t } = useTranslation("settings");
|
||||||
const { data } = api.admin.one.useQuery();
|
const { data } = api.user.get.useQuery();
|
||||||
|
|
||||||
const { data: dokployVersion } = api.settings.getDokployVersion.useQuery();
|
const { data: dokployVersion } = api.settings.getDokployVersion.useQuery();
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ export const WebServer = ({ className }: Props) => {
|
|||||||
|
|
||||||
<div className="flex items-center flex-wrap justify-between gap-4">
|
<div className="flex items-center flex-wrap justify-between gap-4">
|
||||||
<span className="text-sm text-muted-foreground">
|
<span className="text-sm text-muted-foreground">
|
||||||
Server IP: {data?.serverIp}
|
Server IP: {data?.user.serverIp}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-sm text-muted-foreground">
|
<span className="text-sm text-muted-foreground">
|
||||||
Version: {dokployVersion}
|
Version: {dokployVersion}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export const UpdateServerIp = ({ children, serverId }: Props) => {
|
|||||||
|
|
||||||
const form = useForm<Schema>({
|
const form = useForm<Schema>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
serverIp: data?.serverIp || "",
|
serverIp: data?.user.serverIp || "",
|
||||||
},
|
},
|
||||||
resolver: zodResolver(schema),
|
resolver: zodResolver(schema),
|
||||||
});
|
});
|
||||||
@@ -62,7 +62,7 @@ export const UpdateServerIp = ({ children, serverId }: Props) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data) {
|
if (data) {
|
||||||
form.reset({
|
form.reset({
|
||||||
serverIp: data.serverIp || "",
|
serverIp: data.user.serverIp || "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [form, form.reset, data]);
|
}, [form, form.reset, data]);
|
||||||
|
|||||||
@@ -526,7 +526,7 @@ const data = {
|
|||||||
function SidebarLogo() {
|
function SidebarLogo() {
|
||||||
const { state } = useSidebar();
|
const { state } = useSidebar();
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
const { data: user } = api.auth.get.useQuery();
|
const { data: user } = api.user.get.useQuery();
|
||||||
const { data: dokployVersion } = api.settings.getDokployVersion.useQuery();
|
const { data: dokployVersion } = api.settings.getDokployVersion.useQuery();
|
||||||
const { data: session } = authClient.useSession();
|
const { data: session } = authClient.useSession();
|
||||||
const {
|
const {
|
||||||
@@ -714,7 +714,7 @@ export default function Page({ children }: Props) {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const currentPath = router.pathname;
|
const currentPath = router.pathname;
|
||||||
const { data: auth } = api.auth.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
|
|
||||||
const includesProjects = pathname?.includes("/dashboard/project");
|
const includesProjects = pathname?.includes("/dashboard/project");
|
||||||
const { data: isCloud, isLoading } = api.settings.isCloud.useQuery();
|
const { data: isCloud, isLoading } = api.settings.isCloud.useQuery();
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const AUTO_CHECK_UPDATES_INTERVAL_MINUTES = 7;
|
|||||||
|
|
||||||
export const UserNav = () => {
|
export const UserNav = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { data } = api.auth.get.useQuery();
|
const { data } = api.user.get.useQuery();
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
const { locale, setLocale } = useLocale();
|
const { locale, setLocale } = useLocale();
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const Dashboard = () => {
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: monitoring, isLoading } = api.admin.getMetricsToken.useQuery();
|
const { data: monitoring, isLoading } = api.user.getMetricsToken.useQuery();
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4 pb-10">
|
<div className="space-y-4 pb-10">
|
||||||
{/* <AlertBlock>
|
{/* <AlertBlock>
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ const Project = (
|
|||||||
) => {
|
) => {
|
||||||
const [isBulkActionLoading, setIsBulkActionLoading] = useState(false);
|
const [isBulkActionLoading, setIsBulkActionLoading] = useState(false);
|
||||||
const { projectId } = props;
|
const { projectId } = props;
|
||||||
const { data: auth } = api.auth.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
|
|
||||||
const { data, isLoading, refetch } = api.project.one.useQuery({ projectId });
|
const { data, isLoading, refetch } = api.project.one.useQuery({ projectId });
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
@@ -86,8 +86,8 @@ const Service = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
const { data: auth } = api.auth.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const { data: monitoring } = api.admin.getMetricsToken.useQuery();
|
const { data: monitoring } = api.user.getMetricsToken.useQuery();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="pb-10">
|
<div className="pb-10">
|
||||||
|
|||||||
@@ -79,8 +79,8 @@ const Service = (
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: auth } = api.auth.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const { data: monitoring } = api.admin.getMetricsToken.useQuery();
|
const { data: monitoring } = api.user.getMetricsToken.useQuery();
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ const Mariadb = (
|
|||||||
const { projectId } = router.query;
|
const { projectId } = router.query;
|
||||||
const [tab, setSab] = useState<TabState>(activeTab);
|
const [tab, setSab] = useState<TabState>(activeTab);
|
||||||
const { data } = api.mariadb.one.useQuery({ mariadbId });
|
const { data } = api.mariadb.one.useQuery({ mariadbId });
|
||||||
const { data: auth } = api.auth.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const { data: monitoring } = api.admin.getMetricsToken.useQuery();
|
const { data: monitoring } = api.user.getMetricsToken.useQuery();
|
||||||
|
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ const Mongo = (
|
|||||||
const [tab, setSab] = useState<TabState>(activeTab);
|
const [tab, setSab] = useState<TabState>(activeTab);
|
||||||
const { data } = api.mongo.one.useQuery({ mongoId });
|
const { data } = api.mongo.one.useQuery({ mongoId });
|
||||||
|
|
||||||
const { data: auth } = api.auth.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const { data: monitoring } = api.admin.getMetricsToken.useQuery();
|
const { data: monitoring } = api.user.getMetricsToken.useQuery();
|
||||||
|
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ const MySql = (
|
|||||||
const { projectId } = router.query;
|
const { projectId } = router.query;
|
||||||
const [tab, setSab] = useState<TabState>(activeTab);
|
const [tab, setSab] = useState<TabState>(activeTab);
|
||||||
const { data } = api.mysql.one.useQuery({ mysqlId });
|
const { data } = api.mysql.one.useQuery({ mysqlId });
|
||||||
const { data: auth } = api.auth.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const { data: monitoring } = api.admin.getMetricsToken.useQuery();
|
const { data: monitoring } = api.user.getMetricsToken.useQuery();
|
||||||
|
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
|
|||||||
@@ -60,9 +60,9 @@ const Postgresql = (
|
|||||||
const { projectId } = router.query;
|
const { projectId } = router.query;
|
||||||
const [tab, setSab] = useState<TabState>(activeTab);
|
const [tab, setSab] = useState<TabState>(activeTab);
|
||||||
const { data } = api.postgres.one.useQuery({ postgresId });
|
const { data } = api.postgres.one.useQuery({ postgresId });
|
||||||
const { data: auth } = api.auth.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
|
|
||||||
const { data: monitoring } = api.admin.getMetricsToken.useQuery();
|
const { data: monitoring } = api.user.getMetricsToken.useQuery();
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ const Redis = (
|
|||||||
const [tab, setSab] = useState<TabState>(activeTab);
|
const [tab, setSab] = useState<TabState>(activeTab);
|
||||||
const { data } = api.redis.one.useQuery({ redisId });
|
const { data } = api.redis.one.useQuery({ redisId });
|
||||||
|
|
||||||
const { data: auth } = api.auth.get.useQuery();
|
const { data: auth } = api.user.get.useQuery();
|
||||||
const { data: monitoring } = api.admin.getMetricsToken.useQuery();
|
const { data: monitoring } = api.user.getMetricsToken.useQuery();
|
||||||
|
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
|
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ const settings = z.object({
|
|||||||
type SettingsType = z.infer<typeof settings>;
|
type SettingsType = z.infer<typeof settings>;
|
||||||
|
|
||||||
const Page = () => {
|
const Page = () => {
|
||||||
const { data, refetch } = api.admin.one.useQuery();
|
const { data, refetch } = api.user.get.useQuery();
|
||||||
const { mutateAsync, isLoading, isError, error } =
|
const { mutateAsync, isLoading, isError, error } =
|
||||||
api.admin.update.useMutation();
|
api.user.update.useMutation();
|
||||||
const form = useForm<SettingsType>({
|
const form = useForm<SettingsType>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
cleanCacheOnApplications: false,
|
cleanCacheOnApplications: false,
|
||||||
@@ -55,9 +55,9 @@ const Page = () => {
|
|||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
form.reset({
|
form.reset({
|
||||||
cleanCacheOnApplications: data?.cleanupCacheApplications || false,
|
cleanCacheOnApplications: data?.user.cleanupCacheApplications || false,
|
||||||
cleanCacheOnCompose: data?.cleanupCacheOnCompose || false,
|
cleanCacheOnCompose: data?.user.cleanupCacheOnCompose || false,
|
||||||
cleanCacheOnPreviews: data?.cleanupCacheOnPreviews || false,
|
cleanCacheOnPreviews: data?.user.cleanupCacheOnPreviews || false,
|
||||||
});
|
});
|
||||||
}, [form, form.reset, form.formState.isSubmitSuccessful, data]);
|
}, [form, form.reset, form.formState.isSubmitSuccessful, data]);
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import React, { type ReactElement } from "react";
|
|||||||
import superjson from "superjson";
|
import superjson from "superjson";
|
||||||
|
|
||||||
const Page = () => {
|
const Page = () => {
|
||||||
const { data } = api.auth.get.useQuery();
|
const { data } = api.user.get.useQuery();
|
||||||
|
|
||||||
const { data: isCloud } = api.settings.isCloud.useQuery();
|
const { data: isCloud } = api.settings.isCloud.useQuery();
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -2,19 +2,7 @@ import { SetupMonitoring } from "@/components/dashboard/settings/servers/setup-m
|
|||||||
import { WebDomain } from "@/components/dashboard/settings/web-domain";
|
import { WebDomain } from "@/components/dashboard/settings/web-domain";
|
||||||
import { WebServer } from "@/components/dashboard/settings/web-server";
|
import { WebServer } from "@/components/dashboard/settings/web-server";
|
||||||
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
||||||
import { DialogAction } from "@/components/shared/dialog-action";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "@/components/ui/card";
|
|
||||||
import { Switch } from "@/components/ui/switch";
|
|
||||||
|
|
||||||
import { appRouter } from "@/server/api/root";
|
import { appRouter } from "@/server/api/root";
|
||||||
import { api } from "@/utils/api";
|
|
||||||
import { getLocale, serverSideTranslations } from "@/utils/i18n";
|
import { getLocale, serverSideTranslations } from "@/utils/i18n";
|
||||||
import { IS_CLOUD, validateRequest } from "@dokploy/server";
|
import { IS_CLOUD, validateRequest } from "@dokploy/server";
|
||||||
import { createServerSideHelpers } from "@trpc/react-query/server";
|
import { createServerSideHelpers } from "@trpc/react-query/server";
|
||||||
@@ -25,8 +13,6 @@ import { toast } from "sonner";
|
|||||||
import superjson from "superjson";
|
import superjson from "superjson";
|
||||||
|
|
||||||
const Page = () => {
|
const Page = () => {
|
||||||
const { data, refetch } = api.admin.one.useQuery();
|
|
||||||
const { mutateAsync: update } = api.admin.update.useMutation();
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="h-full rounded-xl max-w-5xl mx-auto flex flex-col gap-4">
|
<div className="h-full rounded-xl max-w-5xl mx-auto flex flex-col gap-4">
|
||||||
|
|||||||
@@ -4,6 +4,14 @@ import { AlertBlock } from "@/components/shared/alert-block";
|
|||||||
import { Logo } from "@/components/shared/logo";
|
import { Logo } from "@/components/shared/logo";
|
||||||
import { Button, buttonVariants } from "@/components/ui/button";
|
import { Button, buttonVariants } from "@/components/ui/button";
|
||||||
import { CardContent, CardDescription } from "@/components/ui/card";
|
import { CardContent, CardDescription } from "@/components/ui/card";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
@@ -20,14 +28,6 @@ import {
|
|||||||
InputOTPSlot,
|
InputOTPSlot,
|
||||||
} from "@/components/ui/input-otp";
|
} from "@/components/ui/input-otp";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import {
|
|
||||||
Dialog,
|
|
||||||
DialogContent,
|
|
||||||
DialogDescription,
|
|
||||||
DialogHeader,
|
|
||||||
DialogTitle,
|
|
||||||
DialogTrigger,
|
|
||||||
} from "@/components/ui/dialog";
|
|
||||||
import { authClient } from "@/lib/auth-client";
|
import { authClient } from "@/lib/auth-client";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ const Invitation = ({
|
|||||||
userAlreadyExists,
|
userAlreadyExists,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { data } = api.admin.getUserByToken.useQuery(
|
const { data } = api.user.getUserByToken.useQuery(
|
||||||
{
|
{
|
||||||
token,
|
token,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { db } from "@/server/db";
|
|
||||||
import {
|
import {
|
||||||
apiAssignPermissions,
|
apiAssignPermissions,
|
||||||
apiCreateUserInvitation,
|
apiCreateUserInvitation,
|
||||||
@@ -14,11 +13,9 @@ import {
|
|||||||
getUserByToken,
|
getUserByToken,
|
||||||
removeUserById,
|
removeUserById,
|
||||||
setupWebMonitoring,
|
setupWebMonitoring,
|
||||||
updateAdminById,
|
|
||||||
updateUser,
|
updateUser,
|
||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { eq } from "drizzle-orm";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import {
|
import {
|
||||||
adminProcedure,
|
adminProcedure,
|
||||||
@@ -131,7 +128,7 @@ export const adminRouter = createTRPCRouter({
|
|||||||
if (user.id !== ctx.user.ownerId) {
|
if (user.id !== ctx.user.ownerId) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "UNAUTHORIZED",
|
code: "UNAUTHORIZED",
|
||||||
message: "You are not authorized to setup this server",
|
message: "You are not authorized to setup the monitoring",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import {
|
|||||||
createComposeByTemplate,
|
createComposeByTemplate,
|
||||||
createDomain,
|
createDomain,
|
||||||
createMount,
|
createMount,
|
||||||
findAdminById,
|
|
||||||
findComposeById,
|
findComposeById,
|
||||||
findDomainsByComposeId,
|
findDomainsByComposeId,
|
||||||
findProjectById,
|
findProjectById,
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
import { db } from "@/server/db";
|
import { db } from "@/server/db";
|
||||||
import {
|
import { invitation, member, organization } from "@/server/db/schema";
|
||||||
invitation,
|
import { IS_CLOUD } from "@dokploy/server/index";
|
||||||
member,
|
|
||||||
organization,
|
|
||||||
users_temp,
|
|
||||||
} from "@/server/db/schema";
|
|
||||||
import { IS_CLOUD, auth } from "@dokploy/server/index";
|
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { and, desc, eq, exists } from "drizzle-orm";
|
import { and, desc, eq, exists } from "drizzle-orm";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
@@ -45,7 +40,7 @@ export const organizationRouter = createTRPCRouter({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const memberResult = await db.insert(member).values({
|
await db.insert(member).values({
|
||||||
organizationId: result.id,
|
organizationId: result.id,
|
||||||
role: "owner",
|
role: "owner",
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
@@ -142,7 +137,7 @@ export const organizationRouter = createTRPCRouter({
|
|||||||
allInvitations: adminProcedure.query(async ({ ctx }) => {
|
allInvitations: adminProcedure.query(async ({ ctx }) => {
|
||||||
return await db.query.invitation.findMany({
|
return await db.query.invitation.findMany({
|
||||||
where: eq(invitation.organizationId, ctx.session.activeOrganizationId),
|
where: eq(invitation.organizationId, ctx.session.activeOrganizationId),
|
||||||
orderBy: [desc(invitation.status)],
|
orderBy: [desc(invitation.status), desc(invitation.expiresAt)],
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
acceptInvitation: adminProcedure
|
acceptInvitation: adminProcedure
|
||||||
|
|||||||
@@ -1,18 +1,31 @@
|
|||||||
import { apiFindOneUser, apiFindOneUserByAuth } from "@/server/db/schema";
|
import { apiFindOneUser, apiFindOneUserByAuth } from "@/server/db/schema";
|
||||||
import {
|
import {
|
||||||
IS_CLOUD,
|
IS_CLOUD,
|
||||||
|
findOrganizationById,
|
||||||
findUserByAuthId,
|
findUserByAuthId,
|
||||||
findUserById,
|
findUserById,
|
||||||
|
getUserByToken,
|
||||||
removeUserById,
|
removeUserById,
|
||||||
updateUser,
|
updateUser,
|
||||||
verify2FA,
|
verify2FA,
|
||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { db } from "@dokploy/server/db";
|
import { db } from "@dokploy/server/db";
|
||||||
import { account, apiUpdateUser, member } from "@dokploy/server/db/schema";
|
import {
|
||||||
|
account,
|
||||||
|
apiAssignPermissions,
|
||||||
|
apiFindOneToken,
|
||||||
|
apiUpdateUser,
|
||||||
|
member,
|
||||||
|
} from "@dokploy/server/db/schema";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { eq } from "drizzle-orm";
|
import { and, eq } from "drizzle-orm";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc";
|
import {
|
||||||
|
adminProcedure,
|
||||||
|
createTRPCRouter,
|
||||||
|
protectedProcedure,
|
||||||
|
publicProcedure,
|
||||||
|
} from "../trpc";
|
||||||
export const userRouter = createTRPCRouter({
|
export const userRouter = createTRPCRouter({
|
||||||
all: adminProcedure.query(async ({ ctx }) => {
|
all: adminProcedure.query(async ({ ctx }) => {
|
||||||
return await db.query.member.findMany({
|
return await db.query.member.findMany({
|
||||||
@@ -39,14 +52,36 @@ export const userRouter = createTRPCRouter({
|
|||||||
return user;
|
return user;
|
||||||
}),
|
}),
|
||||||
get: protectedProcedure.query(async ({ ctx }) => {
|
get: protectedProcedure.query(async ({ ctx }) => {
|
||||||
return await findUserById(ctx.user.id);
|
const memberResult = await db.query.member.findFirst({
|
||||||
|
where: and(
|
||||||
|
eq(member.userId, ctx.user.id),
|
||||||
|
eq(member.organizationId, ctx.session?.activeOrganizationId || ""),
|
||||||
|
),
|
||||||
|
with: {
|
||||||
|
user: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return memberResult;
|
||||||
}),
|
}),
|
||||||
update: protectedProcedure
|
update: protectedProcedure
|
||||||
.input(apiUpdateUser)
|
.input(apiUpdateUser)
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
return await updateUser(ctx.user.id, input);
|
return await updateUser(ctx.user.id, input);
|
||||||
}),
|
}),
|
||||||
|
getUserByToken: publicProcedure
|
||||||
|
.input(apiFindOneToken)
|
||||||
|
.query(async ({ input }) => {
|
||||||
|
return await getUserByToken(input.token);
|
||||||
|
}),
|
||||||
|
getMetricsToken: protectedProcedure.query(async ({ ctx }) => {
|
||||||
|
const user = await findUserById(ctx.user.ownerId);
|
||||||
|
return {
|
||||||
|
serverIp: user.serverIp,
|
||||||
|
enabledFeatures: user.enablePaidFeatures,
|
||||||
|
metricsConfig: user?.metricsConfig,
|
||||||
|
};
|
||||||
|
}),
|
||||||
remove: protectedProcedure
|
remove: protectedProcedure
|
||||||
.input(
|
.input(
|
||||||
z.object({
|
z.object({
|
||||||
@@ -59,4 +94,28 @@ export const userRouter = createTRPCRouter({
|
|||||||
}
|
}
|
||||||
return await removeUserById(input.userId);
|
return await removeUserById(input.userId);
|
||||||
}),
|
}),
|
||||||
|
assignPermissions: adminProcedure
|
||||||
|
.input(apiAssignPermissions)
|
||||||
|
.mutation(async ({ input, ctx }) => {
|
||||||
|
try {
|
||||||
|
const user = await findUserById(input.id);
|
||||||
|
|
||||||
|
const organization = await findOrganizationById(
|
||||||
|
ctx.session?.activeOrganizationId || "",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (organization?.ownerId !== ctx.user.ownerId) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "UNAUTHORIZED",
|
||||||
|
message: "You are not allowed to assign permissions",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await updateUser(user.id, {
|
||||||
|
...input,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user