mirror of
https://github.com/fosrl/pangolin.git
synced 2026-06-11 01:53:58 +00:00
use resource name in ssh/rdp/vnc page meta
This commit is contained in:
@@ -58,6 +58,7 @@ export async function getBrowserTarget(
|
||||
authToken: browserGatewayTarget.authToken,
|
||||
resourceId: resources.resourceId,
|
||||
niceId: resources.niceId,
|
||||
name: resources.name,
|
||||
orgId: resources.orgId,
|
||||
pamMode: resources.pamMode,
|
||||
authDaemonMode: resources.authDaemonMode
|
||||
@@ -93,7 +94,8 @@ export async function getBrowserTarget(
|
||||
authDaemonMode: browserTarget.authDaemonMode,
|
||||
orgId: browserTarget.orgId,
|
||||
resourceId: browserTarget.resourceId,
|
||||
niceId: browserTarget.niceId
|
||||
niceId: browserTarget.niceId,
|
||||
name: browserTarget.name
|
||||
},
|
||||
success: true,
|
||||
error: false,
|
||||
|
||||
@@ -5,6 +5,7 @@ export type GetBrowserTargetResponse = {
|
||||
orgId: string;
|
||||
resourceId: number;
|
||||
niceId: string;
|
||||
name: string;
|
||||
pamMode: "passthrough" | "push" | null;
|
||||
authDaemonMode: "site" | "remote" | "native" | null;
|
||||
};
|
||||
|
||||
@@ -1,34 +1,17 @@
|
||||
import { headers } from "next/headers";
|
||||
import { priv } from "@app/lib/api";
|
||||
import { AxiosResponse } from "axios";
|
||||
import { GetBrowserTargetResponse } from "@server/routers/browserGatewayTarget";
|
||||
import { generateBrowserGatewayMetadata } from "@app/lib/browserGatewayMetadata";
|
||||
import { getBrowserTargetForRequest } from "@app/lib/getBrowserTargetForRequest";
|
||||
import RdpClient from "./RdpClient";
|
||||
import AuthFooter from "@app/components/AuthFooter";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const metadata = {
|
||||
title: "RDP"
|
||||
};
|
||||
export async function generateMetadata() {
|
||||
return generateBrowserGatewayMetadata("RDP");
|
||||
}
|
||||
|
||||
export default async function RdpPage() {
|
||||
const headersList = await headers();
|
||||
const host = headersList.get("host") || "";
|
||||
const hostname = host.split(":")[0];
|
||||
|
||||
let target: GetBrowserTargetResponse | null = null;
|
||||
const error: string | null = null;
|
||||
|
||||
try {
|
||||
const res = await priv.get<AxiosResponse<GetBrowserTargetResponse>>(
|
||||
`/resource/browser-target?fullDomain=${encodeURIComponent(hostname)}`
|
||||
);
|
||||
target = res.data.data;
|
||||
console.log("Fetched browser target:", target);
|
||||
} catch (error) {
|
||||
console.error("Error fetching browser target:", error);
|
||||
error = "No resource found for this domain";
|
||||
}
|
||||
const { target } = await getBrowserTargetForRequest();
|
||||
const error = target ? null : "No resource found for this domain";
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col">
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { headers } from "next/headers";
|
||||
import { priv } from "@app/lib/api";
|
||||
import { generateBrowserGatewayMetadata } from "@app/lib/browserGatewayMetadata";
|
||||
import { getBrowserTargetForRequest } from "@app/lib/getBrowserTargetForRequest";
|
||||
import { AxiosResponse } from "axios";
|
||||
import { GetBrowserTargetResponse } from "@server/routers/browserGatewayTarget";
|
||||
import SshClient from "./SshClient";
|
||||
@@ -99,14 +101,12 @@ function generateEphemeralKeyPair(): {
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const metadata = {
|
||||
title: "SSH"
|
||||
};
|
||||
export async function generateMetadata() {
|
||||
return generateBrowserGatewayMetadata("SSH");
|
||||
}
|
||||
|
||||
export default async function SshPage() {
|
||||
const headersList = await headers();
|
||||
const host = headersList.get("host") || "";
|
||||
const hostname = host.split(":")[0];
|
||||
const cookieHeader = headersList.get("cookie") || "";
|
||||
|
||||
let target: GetBrowserTargetResponse | null = null;
|
||||
@@ -114,49 +114,44 @@ export default async function SshPage() {
|
||||
let privateKey: string | null = null;
|
||||
let error: string | null = null;
|
||||
|
||||
try {
|
||||
const res = await priv.get<AxiosResponse<GetBrowserTargetResponse>>(
|
||||
`/resource/browser-target?fullDomain=${encodeURIComponent(hostname)}`
|
||||
);
|
||||
target = res.data.data;
|
||||
const { target: browserTarget } = await getBrowserTargetForRequest();
|
||||
target = browserTarget;
|
||||
|
||||
if (target.pamMode === "push") {
|
||||
try {
|
||||
const { privateKeyPem, publicKeyOpenSSH } =
|
||||
generateEphemeralKeyPair();
|
||||
privateKey = privateKeyPem;
|
||||
const res = await priv.post<AxiosResponse<SignSshKeyResponse>>(
|
||||
`/org/${target.orgId}/ssh/sign-key`,
|
||||
{
|
||||
publicKey: publicKeyOpenSSH,
|
||||
resourceId: target.resourceId,
|
||||
type: "public"
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Cookie: cookieHeader
|
||||
}
|
||||
}
|
||||
);
|
||||
signedKeyData = res.data.data;
|
||||
|
||||
const messageIds =
|
||||
signedKeyData.messageIds.length > 0
|
||||
? signedKeyData.messageIds
|
||||
: signedKeyData.messageId
|
||||
? [signedKeyData.messageId]
|
||||
: [];
|
||||
|
||||
await waitForRoundTripCompletion(messageIds, cookieHeader);
|
||||
} catch (err) {
|
||||
console.error("Error signing SSH key:", err);
|
||||
error =
|
||||
"Failed to sign SSH key for PAM push authentication. Did you sign in as a user?";
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error fetching browser target:", err);
|
||||
if (!target) {
|
||||
error = "No resource found for this domain";
|
||||
} else if (target.pamMode === "push") {
|
||||
try {
|
||||
const { privateKeyPem, publicKeyOpenSSH } =
|
||||
generateEphemeralKeyPair();
|
||||
privateKey = privateKeyPem;
|
||||
const res = await priv.post<AxiosResponse<SignSshKeyResponse>>(
|
||||
`/org/${target.orgId}/ssh/sign-key`,
|
||||
{
|
||||
publicKey: publicKeyOpenSSH,
|
||||
resourceId: target.resourceId,
|
||||
type: "public"
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Cookie: cookieHeader
|
||||
}
|
||||
}
|
||||
);
|
||||
signedKeyData = res.data.data;
|
||||
|
||||
const messageIds =
|
||||
signedKeyData.messageIds.length > 0
|
||||
? signedKeyData.messageIds
|
||||
: signedKeyData.messageId
|
||||
? [signedKeyData.messageId]
|
||||
: [];
|
||||
|
||||
await waitForRoundTripCompletion(messageIds, cookieHeader);
|
||||
} catch (err) {
|
||||
console.error("Error signing SSH key:", err);
|
||||
error =
|
||||
"Failed to sign SSH key for PAM push authentication. Did you sign in as a user?";
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,33 +1,17 @@
|
||||
import { headers } from "next/headers";
|
||||
import { priv } from "@app/lib/api";
|
||||
import { AxiosResponse } from "axios";
|
||||
import { GetBrowserTargetResponse } from "@server/routers/browserGatewayTarget";
|
||||
import { generateBrowserGatewayMetadata } from "@app/lib/browserGatewayMetadata";
|
||||
import { getBrowserTargetForRequest } from "@app/lib/getBrowserTargetForRequest";
|
||||
import VncClient from "./VncClient";
|
||||
import AuthFooter from "@app/components/AuthFooter";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const metadata = {
|
||||
title: "VNC"
|
||||
};
|
||||
export async function generateMetadata() {
|
||||
return generateBrowserGatewayMetadata("VNC");
|
||||
}
|
||||
|
||||
export default async function VncPage() {
|
||||
const headersList = await headers();
|
||||
const host = headersList.get("host") || "";
|
||||
const hostname = host.split(":")[0];
|
||||
|
||||
let target: GetBrowserTargetResponse | null = null;
|
||||
const error: string | null = null;
|
||||
|
||||
try {
|
||||
const res = await priv.get<AxiosResponse<GetBrowserTargetResponse>>(
|
||||
`/resource/browser-target?fullDomain=${encodeURIComponent(hostname)}`
|
||||
);
|
||||
target = res.data.data;
|
||||
} catch (error) {
|
||||
console.error("Error fetching browser target:", error);
|
||||
error = "No resource found for this domain";
|
||||
}
|
||||
const { target } = await getBrowserTargetForRequest();
|
||||
const error = target ? null : "No resource found for this domain";
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col">
|
||||
|
||||
13
src/lib/browserGatewayMetadata.ts
Normal file
13
src/lib/browserGatewayMetadata.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { getBrowserTargetForRequest } from "@app/lib/getBrowserTargetForRequest";
|
||||
import type { Metadata } from "next";
|
||||
|
||||
export async function generateBrowserGatewayMetadata(
|
||||
protocol: "SSH" | "RDP" | "VNC"
|
||||
): Promise<Metadata> {
|
||||
const { target } = await getBrowserTargetForRequest();
|
||||
return {
|
||||
title: target?.name
|
||||
? `${protocol} - ${target.name}`
|
||||
: `${protocol} - Pangolin`
|
||||
};
|
||||
}
|
||||
20
src/lib/getBrowserTargetForRequest.ts
Normal file
20
src/lib/getBrowserTargetForRequest.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { priv } from "@app/lib/api";
|
||||
import { GetBrowserTargetResponse } from "@server/routers/browserGatewayTarget";
|
||||
import { AxiosResponse } from "axios";
|
||||
import { headers } from "next/headers";
|
||||
import { cache } from "react";
|
||||
|
||||
export const getBrowserTargetForRequest = cache(async () => {
|
||||
const headersList = await headers();
|
||||
const host = headersList.get("host") || "";
|
||||
const hostname = host.split(":")[0];
|
||||
|
||||
try {
|
||||
const res = await priv.get<AxiosResponse<GetBrowserTargetResponse>>(
|
||||
`/resource/browser-target?fullDomain=${encodeURIComponent(hostname)}`
|
||||
);
|
||||
return { target: res.data.data };
|
||||
} catch {
|
||||
return { target: null };
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user