mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-19 21:31:33 +00:00
Compare commits
6 Commits
dependabot
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
991fed93ee | ||
|
|
26ab63d0e4 | ||
|
|
03288d2a60 | ||
|
|
1169b68619 | ||
|
|
d3bfd67738 | ||
|
|
d44292cf33 |
@@ -175,7 +175,7 @@
|
||||
"resourceHTTPDescription": "Proxy requests over HTTPS using a fully qualified domain name.",
|
||||
"resourceRaw": "Raw TCP/UDP Resource",
|
||||
"resourceRawDescription": "Proxy requests over raw TCP/UDP using a port number.",
|
||||
"resourceRawDescriptionCloud": "Proxy requests over raw TCP/UDP using a port number. REQUIRES THE USE OF A REMOTE NODE.",
|
||||
"resourceRawDescriptionCloud": "Proxy requests over raw TCP/UDP using a port number. Requires sites to connect to a remote node.",
|
||||
"resourceCreate": "Create Resource",
|
||||
"resourceCreateDescription": "Follow the steps below to create a new resource",
|
||||
"resourceSeeAll": "See All Resources",
|
||||
@@ -1427,6 +1427,7 @@
|
||||
"domainPickerNamespace": "Namespace: {namespace}",
|
||||
"domainPickerShowMore": "Show More",
|
||||
"regionSelectorTitle": "Select Region",
|
||||
"domainPickerRemoteExitNodeWarning": "Provided domains are not supported when sites connect to remote exit nodes. For resources to be availble on remote nodes, use a custom domain instead.",
|
||||
"regionSelectorInfo": "Selecting a region helps us provide better performance for your location. You do not have to be in the same region as your server.",
|
||||
"regionSelectorPlaceholder": "Choose a region",
|
||||
"regionSelectorComingSoon": "Coming Soon",
|
||||
|
||||
@@ -286,14 +286,12 @@ export class TraefikConfigManager {
|
||||
// Check non-wildcard certs for expiry (within 45 days to match
|
||||
// the server-side renewal window in certificate-service)
|
||||
for (const domain of domainsNeedingCerts) {
|
||||
const localState =
|
||||
this.lastLocalCertificateState.get(domain);
|
||||
const localState = this.lastLocalCertificateState.get(domain);
|
||||
if (localState?.expiresAt) {
|
||||
const nowInSeconds = Math.floor(Date.now() / 1000);
|
||||
const secondsUntilExpiry =
|
||||
localState.expiresAt - nowInSeconds;
|
||||
const daysUntilExpiry =
|
||||
secondsUntilExpiry / (60 * 60 * 24);
|
||||
const daysUntilExpiry = secondsUntilExpiry / (60 * 60 * 24);
|
||||
if (daysUntilExpiry < 45) {
|
||||
logger.info(
|
||||
`Fetching certificates due to upcoming expiry for ${domain} (${Math.round(daysUntilExpiry)} days remaining)`
|
||||
@@ -306,18 +304,11 @@ export class TraefikConfigManager {
|
||||
// Also check wildcard certificates for expiry. These are not
|
||||
// included in domainsNeedingCerts since their subdomains are
|
||||
// filtered out, so we must check them separately.
|
||||
for (const [certDomain, state] of this
|
||||
.lastLocalCertificateState) {
|
||||
if (
|
||||
state.exists &&
|
||||
state.wildcard &&
|
||||
state.expiresAt
|
||||
) {
|
||||
for (const [certDomain, state] of this.lastLocalCertificateState) {
|
||||
if (state.exists && state.wildcard && state.expiresAt) {
|
||||
const nowInSeconds = Math.floor(Date.now() / 1000);
|
||||
const secondsUntilExpiry =
|
||||
state.expiresAt - nowInSeconds;
|
||||
const daysUntilExpiry =
|
||||
secondsUntilExpiry / (60 * 60 * 24);
|
||||
const secondsUntilExpiry = state.expiresAt - nowInSeconds;
|
||||
const daysUntilExpiry = secondsUntilExpiry / (60 * 60 * 24);
|
||||
if (daysUntilExpiry < 45) {
|
||||
logger.info(
|
||||
`Fetching certificates due to upcoming expiry for wildcard cert ${certDomain} (${Math.round(daysUntilExpiry)} days remaining)`
|
||||
@@ -405,14 +396,8 @@ export class TraefikConfigManager {
|
||||
// their subdomains were filtered out above.
|
||||
for (const [certDomain, state] of this
|
||||
.lastLocalCertificateState) {
|
||||
if (
|
||||
state.exists &&
|
||||
state.wildcard &&
|
||||
state.expiresAt
|
||||
) {
|
||||
const nowInSeconds = Math.floor(
|
||||
Date.now() / 1000
|
||||
);
|
||||
if (state.exists && state.wildcard && state.expiresAt) {
|
||||
const nowInSeconds = Math.floor(Date.now() / 1000);
|
||||
const secondsUntilExpiry =
|
||||
state.expiresAt - nowInSeconds;
|
||||
const daysUntilExpiry =
|
||||
@@ -572,11 +557,18 @@ export class TraefikConfigManager {
|
||||
config.getRawConfig().server
|
||||
.session_cookie_name,
|
||||
|
||||
// deprecated
|
||||
accessTokenQueryParam:
|
||||
config.getRawConfig().server
|
||||
.resource_access_token_param,
|
||||
|
||||
accessTokenIdHeader:
|
||||
config.getRawConfig().server
|
||||
.resource_access_token_headers.id,
|
||||
|
||||
accessTokenHeader:
|
||||
config.getRawConfig().server
|
||||
.resource_access_token_headers.token,
|
||||
|
||||
resourceSessionRequestParam:
|
||||
config.getRawConfig().server
|
||||
.resource_session_request_param
|
||||
|
||||
@@ -14,7 +14,11 @@ import logger from "@server/logger";
|
||||
import { initPeerAddHandshake, updatePeer } from "../olm/peers";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
import config from "@server/lib/config";
|
||||
import { generateSubnetProxyTargets, SubnetProxyTarget } from "@server/lib/ip";
|
||||
import {
|
||||
formatEndpoint,
|
||||
generateSubnetProxyTargets,
|
||||
SubnetProxyTarget
|
||||
} from "@server/lib/ip";
|
||||
|
||||
export async function buildClientConfigurationForNewtClient(
|
||||
site: Site,
|
||||
@@ -219,8 +223,8 @@ export async function buildTargetConfigurationForNewtClient(siteId: number) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
// Format target into string
|
||||
const formattedTarget = `${target.internalPort}:${target.ip}:${target.port}`;
|
||||
// Format target into string (handles IPv6 bracketing)
|
||||
const formattedTarget = `${target.internalPort}:${formatEndpoint(target.ip, target.port)}`;
|
||||
|
||||
// Add to the appropriate protocol array
|
||||
if (target.protocol === "tcp") {
|
||||
|
||||
@@ -39,11 +39,18 @@ export async function traefikConfigProvider(
|
||||
userSessionCookieName:
|
||||
config.getRawConfig().server.session_cookie_name,
|
||||
|
||||
// deprecated
|
||||
accessTokenQueryParam:
|
||||
config.getRawConfig().server
|
||||
.resource_access_token_param,
|
||||
|
||||
accessTokenIdHeader:
|
||||
config.getRawConfig().server
|
||||
.resource_access_token_headers.id,
|
||||
|
||||
accessTokenHeader:
|
||||
config.getRawConfig().server
|
||||
.resource_access_token_headers.token,
|
||||
|
||||
resourceSessionRequestParam:
|
||||
config.getRawConfig().server
|
||||
.resource_session_request_param
|
||||
|
||||
@@ -1109,6 +1109,9 @@ export default function Page() {
|
||||
<SettingsSectionBody>
|
||||
<DomainPicker
|
||||
orgId={orgId as string}
|
||||
warnOnProvidedDomain={
|
||||
remoteExitNodes.length >= 1
|
||||
}
|
||||
onDomainChange={(res) => {
|
||||
if (!res) return;
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ interface DomainPickerProps {
|
||||
defaultFullDomain?: string | null;
|
||||
defaultSubdomain?: string | null;
|
||||
defaultDomainId?: string | null;
|
||||
warnOnProvidedDomain?: boolean;
|
||||
}
|
||||
|
||||
export default function DomainPicker({
|
||||
@@ -88,7 +89,8 @@ export default function DomainPicker({
|
||||
hideFreeDomain = false,
|
||||
defaultSubdomain,
|
||||
defaultFullDomain,
|
||||
defaultDomainId
|
||||
defaultDomainId,
|
||||
warnOnProvidedDomain = false
|
||||
}: DomainPickerProps) {
|
||||
const { env } = useEnvContext();
|
||||
const api = createApiClient({ env });
|
||||
@@ -689,6 +691,14 @@ export default function DomainPicker({
|
||||
|
||||
{showProvidedDomainSearch && (
|
||||
<div className="space-y-4">
|
||||
{warnOnProvidedDomain && (
|
||||
<Alert variant="warning">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertDescription>
|
||||
{t("domainPickerRemoteExitNodeWarning")}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
{isChecking && (
|
||||
<div className="flex items-center justify-center p-8">
|
||||
<div className="flex items-center space-x-2 text-sm text-muted-foreground">
|
||||
|
||||
@@ -129,6 +129,11 @@ const ResourceInfo = ({ resource }: { resource: Resource }) => {
|
||||
resource.pincode ||
|
||||
resource.whitelist;
|
||||
|
||||
const hasAnyInfo =
|
||||
Boolean(resource.siteName) || Boolean(hasAuthMethods) || !resource.enabled;
|
||||
|
||||
if (!hasAnyInfo) return null;
|
||||
|
||||
const infoContent = (
|
||||
<div className="flex flex-col gap-3">
|
||||
{/* Site Information */}
|
||||
@@ -828,6 +833,12 @@ export default function MemberResourcesPortal({
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<span className="font-medium">Destination:</span>
|
||||
<span className="ml-2 text-muted-foreground">
|
||||
{siteResource.destination}
|
||||
</span>
|
||||
</div>
|
||||
{siteResource.alias && (
|
||||
<div>
|
||||
<span className="font-medium">Alias:</span>
|
||||
@@ -836,14 +847,6 @@ export default function MemberResourcesPortal({
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{siteResource.aliasAddress && (
|
||||
<div>
|
||||
<span className="font-medium">Alias Address:</span>
|
||||
<span className="ml-2 text-muted-foreground">
|
||||
{siteResource.aliasAddress}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<span className="font-medium">Status:</span>
|
||||
<span className={`ml-2 ${siteResource.enabled ? 'text-green-600' : 'text-red-600'}`}>
|
||||
|
||||
Reference in New Issue
Block a user