Compare commits

...

3 Commits

Author SHA1 Message Date
Owen
dd1f7ba544 Make crowdsec --crowdsec 2026-05-14 21:46:26 -07:00
Owen
b414f04cce Remove funding 2026-05-14 21:20:34 -07:00
Owen
6e4a28f227 Add site information as well 2026-05-14 18:02:42 -07:00
3 changed files with 93 additions and 10 deletions

3
.github/FUNDING.yml vendored
View File

@@ -1,3 +0,0 @@
# These are supported funding model platforms
github: [fosrl]

View File

@@ -4,6 +4,7 @@ import (
"crypto/rand" "crypto/rand"
"embed" "embed"
"encoding/base64" "encoding/base64"
"flag"
"fmt" "fmt"
"io" "io"
"io/fs" "io/fs"
@@ -68,6 +69,9 @@ const (
func main() { func main() {
crowdsecFlag := flag.Bool("crowdsec", false, "Enable the CrowdSec installation prompt")
flag.Parse()
// print a banner about prerequisites - opening port 80, 443, 51820, and 21820 on the VPS and firewall and pointing your domain to the VPS IP with a records. Docs are at http://localhost:3000/Getting%20Started/dns-networking // print a banner about prerequisites - opening port 80, 443, 51820, and 21820 on the VPS and firewall and pointing your domain to the VPS IP with a records. Docs are at http://localhost:3000/Getting%20Started/dns-networking
fmt.Println("Welcome to the Pangolin installer!") fmt.Println("Welcome to the Pangolin installer!")
@@ -206,7 +210,7 @@ func main() {
} }
} }
if !checkIsCrowdsecInstalledInCompose() { if *crowdsecFlag && !checkIsCrowdsecInstalledInCompose() {
fmt.Println("\n=== CrowdSec Install ===") fmt.Println("\n=== CrowdSec Install ===")
// check if crowdsec is installed // check if crowdsec is installed
if readBool("Would you like to install CrowdSec?", false) { if readBool("Would you like to install CrowdSec?", false) {

View File

@@ -1,6 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { db } from "@server/db"; import { db, DB_TYPE } from "@server/db";
import { and, eq, or, inArray } from "drizzle-orm"; import { and, eq, or, inArray, sql } from "drizzle-orm";
import { import {
resources, resources,
userResources, userResources,
@@ -12,7 +12,9 @@ import {
resourceWhitelist, resourceWhitelist,
siteResources, siteResources,
userSiteResources, userSiteResources,
roleSiteResources roleSiteResources,
siteNetworks,
sites
} from "@server/db"; } from "@server/db";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
@@ -159,9 +161,21 @@ export async function getUserResources(
tcpPortRangeString: string | null; tcpPortRangeString: string | null;
udpPortRangeString: string | null; udpPortRangeString: string | null;
disableIcmp: boolean | null; disableIcmp: boolean | null;
siteIds: number[];
siteNames: string[];
siteNiceIds: string[];
siteAddresses: (string | null)[];
siteOnlines: boolean[];
}> = []; }> = [];
if (accessibleSiteResourceIds.length > 0) { if (accessibleSiteResourceIds.length > 0) {
siteResourcesData = await db const aggCol = <T>(column: any) => {
if (DB_TYPE === "sqlite") {
return sql<T>`json_group_array(${column})`;
}
return sql<T>`COALESCE(array_agg(${column}) FILTER (WHERE ${sites.siteId} IS NOT NULL), '{}')`;
};
const siteResourcesRaw = await db
.select({ .select({
siteResourceId: siteResources.siteResourceId, siteResourceId: siteResources.siteResourceId,
name: siteResources.name, name: siteResources.name,
@@ -176,9 +190,19 @@ export async function getUserResources(
aliasAddress: siteResources.aliasAddress, aliasAddress: siteResources.aliasAddress,
tcpPortRangeString: siteResources.tcpPortRangeString, tcpPortRangeString: siteResources.tcpPortRangeString,
udpPortRangeString: siteResources.udpPortRangeString, udpPortRangeString: siteResources.udpPortRangeString,
disableIcmp: siteResources.disableIcmp disableIcmp: siteResources.disableIcmp,
siteIds: aggCol<number[]>(sites.siteId),
siteNames: aggCol<string[]>(sites.name),
siteNiceIds: aggCol<string[]>(sites.niceId),
siteAddresses: aggCol<(string | null)[]>(sites.address),
siteOnlines: aggCol<boolean[]>(sites.online)
}) })
.from(siteResources) .from(siteResources)
.leftJoin(
siteNetworks,
eq(siteResources.networkId, siteNetworks.networkId)
)
.leftJoin(sites, eq(siteNetworks.siteId, sites.siteId))
.where( .where(
and( and(
inArray( inArray(
@@ -188,7 +212,55 @@ export async function getUserResources(
eq(siteResources.orgId, orgId), eq(siteResources.orgId, orgId),
eq(siteResources.enabled, true) eq(siteResources.enabled, true)
) )
); )
.groupBy(siteResources.siteResourceId);
siteResourcesData = siteResourcesRaw.map((row: any) => {
if (DB_TYPE !== "sqlite") {
return row;
}
const siteIdsRaw = JSON.parse(row.siteIds) as (number | null)[];
const siteNamesRaw = JSON.parse(row.siteNames) as (
| string
| null
)[];
const siteNiceIdsRaw = JSON.parse(row.siteNiceIds) as (
| string
| null
)[];
const siteAddressesRaw = JSON.parse(row.siteAddresses) as (
| string
| null
)[];
const siteOnlinesRaw = JSON.parse(row.siteOnlines) as (
| 0
| 1
| null
)[];
const siteIds: number[] = [];
const siteNames: string[] = [];
const siteNiceIds: string[] = [];
const siteAddresses: (string | null)[] = [];
const siteOnlines: boolean[] = [];
for (let i = 0; i < siteIdsRaw.length; i++) {
if (siteIdsRaw[i] == null) continue;
siteIds.push(siteIdsRaw[i] as number);
siteNames.push((siteNamesRaw[i] ?? "") as string);
siteNiceIds.push((siteNiceIdsRaw[i] ?? "") as string);
siteAddresses.push(siteAddressesRaw[i] ?? null);
siteOnlines.push(siteOnlinesRaw[i] === 1);
}
return {
...row,
siteIds,
siteNames,
siteNiceIds,
siteAddresses,
siteOnlines
};
});
} }
// Check for password, pincode, and whitelist protection for each resource // Check for password, pincode, and whitelist protection for each resource
@@ -269,6 +341,11 @@ export async function getUserResources(
tcpPortRangeString: siteResource.tcpPortRangeString, tcpPortRangeString: siteResource.tcpPortRangeString,
udpPortRangeString: siteResource.udpPortRangeString, udpPortRangeString: siteResource.udpPortRangeString,
disableIcmp: siteResource.disableIcmp, disableIcmp: siteResource.disableIcmp,
siteIds: siteResource.siteIds,
siteNames: siteResource.siteNames,
siteNiceIds: siteResource.siteNiceIds,
siteAddresses: siteResource.siteAddresses,
siteOnlines: siteResource.siteOnlines,
type: "site" as const type: "site" as const
}; };
}); });
@@ -319,6 +396,11 @@ export type GetUserResourcesResponse = {
enabled: boolean; enabled: boolean;
alias: string | null; alias: string | null;
aliasAddress: string | null; aliasAddress: string | null;
siteIds: number[];
siteNames: string[];
siteNiceIds: string[];
siteAddresses: (string | null)[];
siteOnlines: boolean[];
type: "site"; type: "site";
}>; }>;
}; };