add agent to table

This commit is contained in:
miloschwartz
2025-12-06 21:21:39 -05:00
parent 56d30ad6bd
commit b329dbb585
7 changed files with 110 additions and 91 deletions

View File

@@ -2269,5 +2269,6 @@
"remoteExitNodeRegenerateAndDisconnectConfirmation": "Are you sure you want to regenerate the credentials and disconnect this remote exit node?",
"remoteExitNodeRegenerateAndDisconnectWarning": "This will regenerate the credentials and immediately disconnect the remote exit node. The remote exit node will need to be restarted with the new credentials.",
"remoteExitNodeRegenerateCredentialsConfirmation": "Are you sure you want to regenerate the credentials for this remote exit node?",
"remoteExitNodeRegenerateCredentialsWarning": "This will regenerate the credentials. The remote exit node will stay connected until you manually restart it and use the new credentials."
"remoteExitNodeRegenerateCredentialsWarning": "This will regenerate the credentials. The remote exit node will stay connected until you manually restart it and use the new credentials.",
"agent": "Agent"
}

View File

@@ -15,6 +15,7 @@ import { getNextAvailableClientSubnet } from "@server/lib/ip";
import logger from "@server/logger";
import { rebuildClientAssociationsFromClient } from "./rebuildClientAssociations";
import { sendTerminateClient } from "@server/routers/client/terminate";
import { getUniqueClientName } from "@server/db/names";
export async function calculateUserClientsForOrgs(
userId: string,
@@ -176,6 +177,8 @@ export async function calculateUserClientsForOrgs(
const subnet = newSubnet.split("/")[0];
const updatedSubnet = `${subnet}/${org.subnet.split("/")[1]}`;
const niceId = await getUniqueClientName(orgId);
// Create the client
const [newClient] = await transaction
.insert(clients)
@@ -186,7 +189,8 @@ export async function calculateUserClientsForOrgs(
name: olm.name || "User Client",
subnet: updatedSubnet,
olmId: olm.olmId,
type: "olm"
type: "olm",
niceId
})
.returning();

View File

@@ -129,7 +129,8 @@ function queryClients(orgId: string, accessibleClientIds: number[], filter?: "us
userId: clients.userId,
username: users.username,
userEmail: users.email,
niceId: clients.niceId
niceId: clients.niceId,
agent: olms.agent
})
.from(clients)
.leftJoin(orgs, eq(clients.orgId, orgs.orgId))

View File

@@ -57,7 +57,8 @@ export default async function ClientsPage(props: ClientsPageProps) {
userId: client.userId,
username: client.username,
userEmail: client.userEmail,
niceId: client.niceId
niceId: client.niceId,
agent: client.agent
};
};

View File

@@ -53,7 +53,9 @@ export default async function ClientsPage(props: ClientsPageProps) {
olmUpdateAvailable: client.olmUpdateAvailable || false,
userId: client.userId,
username: client.username,
userEmail: client.userEmail
userEmail: client.userEmail,
niceId: client.niceId,
agent: client.agent
};
};

View File

@@ -41,6 +41,7 @@ export type ClientRow = {
username: string | null;
userEmail: string | null;
niceId: string;
agent: string | null;
};
type ClientTableProps = {
@@ -65,7 +66,6 @@ export default function MachineClientsTable({
const [isRefreshing, startTransition] = useTransition();
const defaultMachineColumnVisibility = {
client: false,
subnet: false,
userId: false,
niceId: false
@@ -226,7 +226,7 @@ export default function MachineClientsTable({
},
{
accessorKey: "client",
friendlyName: t("client"),
friendlyName: t("agent"),
header: ({ column }) => {
return (
<Button
@@ -237,7 +237,7 @@ export default function MachineClientsTable({
)
}
>
{t("client")}
{t("agent")}
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
@@ -247,19 +247,18 @@ export default function MachineClientsTable({
return (
<div className="flex items-center space-x-1">
<Badge variant="secondary">
<div className="flex items-center space-x-2">
<span>Olm</span>
{originalRow.olmVersion && (
<span className="text-xs text-gray-500">
v{originalRow.olmVersion}
</span>
)}
</div>
</Badge>
{originalRow.olmUpdateAvailable && (
<InfoPopup info={t("olmUpdateAvailableInfo")} />
{originalRow.agent && originalRow.olmVersion ? (
<Badge variant="secondary">
{originalRow.agent +
" v" +
originalRow.olmVersion}
</Badge>
) : (
"-"
)}
{/*originalRow.olmUpdateAvailable && (
<InfoPopup info={t("olmUpdateAvailableInfo")} />
)*/}
</div>
);
}

View File

@@ -40,6 +40,8 @@ export type ClientRow = {
userId: string | null;
username: string | null;
userEmail: string | null;
niceId: string;
agent: string | null;
};
type ClientTableProps = {
@@ -60,8 +62,8 @@ export default function UserDevicesTable({ userClients }: ClientTableProps) {
const [isRefreshing, startTransition] = useTransition();
const defaultUserColumnVisibility = {
client: false,
subnet: false
subnet: false,
niceId: false
};
const refreshData = () => {
@@ -123,6 +125,25 @@ export default function UserDevicesTable({ userClients }: ClientTableProps) {
);
}
},
{
accessorKey: "niceId",
friendlyName: t("identifier"),
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() =>
column.toggleSorting(
column.getIsSorted() === "asc"
)
}
>
{t("identifier")}
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
}
},
{
accessorKey: "userEmail",
friendlyName: "User",
@@ -261,7 +282,7 @@ export default function UserDevicesTable({ userClients }: ClientTableProps) {
},
{
accessorKey: "client",
friendlyName: t("client"),
friendlyName: t("agent"),
header: ({ column }) => {
return (
<Button
@@ -272,7 +293,7 @@ export default function UserDevicesTable({ userClients }: ClientTableProps) {
)
}
>
{t("client")}
{t("agent")}
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
@@ -282,19 +303,19 @@ export default function UserDevicesTable({ userClients }: ClientTableProps) {
return (
<div className="flex items-center space-x-1">
<Badge variant="secondary">
<div className="flex items-center space-x-2">
<span>Olm</span>
{originalRow.olmVersion && (
<span className="text-xs text-gray-500">
v{originalRow.olmVersion}
</span>
)}
</div>
</Badge>
{originalRow.olmUpdateAvailable && (
<InfoPopup info={t("olmUpdateAvailableInfo")} />
{originalRow.agent && originalRow.olmVersion ? (
<Badge variant="secondary">
{originalRow.agent +
" v" +
originalRow.olmVersion}
</Badge>
) : (
"-"
)}
{/*originalRow.olmUpdateAvailable && (
<InfoPopup info={t("olmUpdateAvailableInfo")} />
)*/}
</div>
);
}
@@ -320,62 +341,52 @@ export default function UserDevicesTable({ userClients }: ClientTableProps) {
}
];
// Only include actions column if there are rows without userIds
if (hasRowsWithoutUserId) {
baseColumns.push({
id: "actions",
enableHiding: false,
header: () => <span className="p-3"></span>,
cell: ({ row }) => {
const clientRow = row.original;
return !clientRow.userId ? (
<div className="flex items-center gap-2 justify-end">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
className="h-8 w-8 p-0"
>
<span className="sr-only">
Open menu
</span>
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{/* <Link */}
{/* className="block w-full" */}
{/* href={`/${clientRow.orgId}/settings/sites/${clientRow.nice}`} */}
{/* > */}
{/* <DropdownMenuItem> */}
{/* View settings */}
{/* </DropdownMenuItem> */}
{/* </Link> */}
<DropdownMenuItem
onClick={() => {
setSelectedClient(clientRow);
setIsDeleteModalOpen(true);
}}
>
<span className="text-red-500">
Delete
</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<Link
href={`/${clientRow.orgId}/settings/clients/${clientRow.id}`}
>
<Button variant={"outline"}>
Edit
<ArrowRight className="ml-2 w-4 h-4" />
baseColumns.push({
id: "actions",
enableHiding: false,
header: () => <span className="p-3"></span>,
cell: ({ row }) => {
const clientRow = row.original;
return !clientRow.userId ? (
<div className="flex items-center gap-2 justify-end">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
<span className="sr-only">Open menu</span>
<MoreHorizontal className="h-4 w-4" />
</Button>
</Link>
</div>
) : null;
}
});
}
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{/* <Link */}
{/* className="block w-full" */}
{/* href={`/${clientRow.orgId}/settings/sites/${clientRow.nice}`} */}
{/* > */}
{/* <DropdownMenuItem> */}
{/* View settings */}
{/* </DropdownMenuItem> */}
{/* </Link> */}
<DropdownMenuItem
onClick={() => {
setSelectedClient(clientRow);
setIsDeleteModalOpen(true);
}}
>
<span className="text-red-500">Delete</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<Link
href={`/${clientRow.orgId}/settings/clients/${clientRow.id}`}
>
<Button variant={"outline"}>
Edit
<ArrowRight className="ml-2 w-4 h-4" />
</Button>
</Link>
</div>
) : null;
}
});
return baseColumns;
}, [hasRowsWithoutUserId, t]);