mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-01 21:13:09 +00:00
alpha.16 (#3068)
* add support for idmapped mounts to start-sdk * misc fixes * misc fixes * add default to textarea * fix iptables masquerade rule * fix textarea types * more fixes * better logging for rsync * fix tty size * fix wg conf generation for android * disable file mounts on dependencies * mostly there, some styling issues (#3069) * mostly there, some styling issues * fix: address comments (#3070) * fix: address comments * fix: fix * show SSL for any address with secure protocol and ssl added * better sorting and messaging --------- Co-authored-by: Alex Inkin <alexander@inkin.ru> * fixes for nextcloud * allow sidebar navigation during service state traansitions * wip: x-forwarded headers * implement x-forwarded-for proxy * lowercase domain names and fix warning popover bug * fix http2 websockets * fix websocket retry behavior * add arch filters to s9pk pack * use docker for start-cli install * add version range to package signer on registry * fix rcs < 0 * fix user information parsing * refactor service interface getters * disable idmaps * build fixes * update docker login action * streamline build * add start-cli workflow * rename * riscv64gc * fix ui packing * no default features on cli * make cli depend on GIT_HASH * more build fixes * more build fixes * interpolate arch within dockerfile * fix tests * add launch ui to service page plus other small improvements (#3075) * add launch ui to service page plus other small improvements * revert translation disable * add spinner to service list if service is health and loading * chore: some visual tune up * chore: update Taiga UI --------- Co-authored-by: waterplea <alexander@inkin.ru> * fix backups * feat: use arm hosted runners and don't fail when apt package does not exist (#3076) --------- Co-authored-by: Matt Hill <mattnine@protonmail.com> Co-authored-by: Shadowy Super Coder <musashidisciple@proton.me> Co-authored-by: Matt Hill <MattDHill@users.noreply.github.com> Co-authored-by: Alex Inkin <alexander@inkin.ru> Co-authored-by: Remco Ros <remcoros@live.nl>
This commit is contained in:
@@ -109,11 +109,9 @@ export class DropPromise<T> implements Promise<T> {
|
||||
}
|
||||
}
|
||||
|
||||
export class DropGenerator<
|
||||
T = unknown,
|
||||
TReturn = any,
|
||||
TNext = unknown,
|
||||
> implements AsyncGenerator<T, TReturn, TNext> {
|
||||
export class DropGenerator<T = unknown, TReturn = any, TNext = unknown>
|
||||
implements AsyncGenerator<T, TReturn, TNext>
|
||||
{
|
||||
private static dropFns: { [id: number]: () => void } = {}
|
||||
private static registry = new FinalizationRegistry((id: number) => {
|
||||
const drop = DropGenerator.dropFns[id]
|
||||
|
||||
@@ -19,7 +19,7 @@ export const getHostname = (url: string): Hostname | null => {
|
||||
|
||||
type FilterKinds =
|
||||
| "onion"
|
||||
| "local"
|
||||
| "mdns"
|
||||
| "domain"
|
||||
| "ip"
|
||||
| "ipv4"
|
||||
@@ -42,10 +42,10 @@ type VisibilityFilter<V extends "public" | "private"> = V extends "public"
|
||||
: never
|
||||
type KindFilter<K extends FilterKinds> = K extends "onion"
|
||||
? (HostnameInfo & { kind: "onion" }) | KindFilter<Exclude<K, "onion">>
|
||||
: K extends "local"
|
||||
: K extends "mdns"
|
||||
?
|
||||
| (HostnameInfo & { kind: "ip"; hostname: { kind: "local" } })
|
||||
| KindFilter<Exclude<K, "local">>
|
||||
| KindFilter<Exclude<K, "mdns">>
|
||||
: K extends "domain"
|
||||
?
|
||||
| (HostnameInfo & { kind: "ip"; hostname: { kind: "domain" } })
|
||||
@@ -80,11 +80,17 @@ type FilterReturnTy<F extends Filter> = F extends {
|
||||
: Exclude<HostnameInfo, FilterReturnTy<E>>
|
||||
: HostnameInfo
|
||||
|
||||
const defaultFilter = {
|
||||
const nonLocalFilter = {
|
||||
exclude: {
|
||||
kind: ["localhost", "link-local"] as ("localhost" | "link-local")[],
|
||||
},
|
||||
}
|
||||
} as const
|
||||
const publicFilter = {
|
||||
visibility: "public",
|
||||
} as const
|
||||
const onionFilter = {
|
||||
kind: "onion",
|
||||
} as const
|
||||
|
||||
type Formats = "hostname-info" | "urlstring" | "url"
|
||||
type FormatReturnTy<
|
||||
@@ -98,7 +104,7 @@ type FormatReturnTy<
|
||||
? UrlString | FormatReturnTy<F, Exclude<Format, "urlstring">>
|
||||
: never
|
||||
|
||||
export type Filled = {
|
||||
export type Filled<F extends Filter = {}> = {
|
||||
hostnames: HostnameInfo[]
|
||||
|
||||
toUrls: (h: HostnameInfo) => {
|
||||
@@ -106,30 +112,17 @@ export type Filled = {
|
||||
sslUrl: UrlString | null
|
||||
}
|
||||
|
||||
filter: <
|
||||
F extends Filter = typeof defaultFilter,
|
||||
Format extends Formats = "urlstring",
|
||||
>(
|
||||
filter?: F,
|
||||
format: <Format extends Formats = "urlstring">(
|
||||
format?: Format,
|
||||
) => FormatReturnTy<F, Format>[]
|
||||
) => FormatReturnTy<{}, Format>[]
|
||||
|
||||
publicHostnames: HostnameInfo[]
|
||||
onionHostnames: HostnameInfo[]
|
||||
localHostnames: HostnameInfo[]
|
||||
ipHostnames: HostnameInfo[]
|
||||
ipv4Hostnames: HostnameInfo[]
|
||||
ipv6Hostnames: HostnameInfo[]
|
||||
nonIpHostnames: HostnameInfo[]
|
||||
filter: <NewFilter extends Filter>(
|
||||
filter: NewFilter,
|
||||
) => Filled<NewFilter & Filter>
|
||||
|
||||
urls: UrlString[]
|
||||
publicUrls: UrlString[]
|
||||
onionUrls: UrlString[]
|
||||
localUrls: UrlString[]
|
||||
ipUrls: UrlString[]
|
||||
ipv4Urls: UrlString[]
|
||||
ipv6Urls: UrlString[]
|
||||
nonIpUrls: UrlString[]
|
||||
nonLocal: Filled<typeof nonLocalFilter & Filter>
|
||||
public: Filled<typeof publicFilter & Filter>
|
||||
onion: Filled<typeof onionFilter & Filter>
|
||||
}
|
||||
export type FilledAddressInfo = AddressInfo & Filled
|
||||
export type ServiceInterfaceFilled = {
|
||||
@@ -225,7 +218,7 @@ function filterRec(
|
||||
(h) =>
|
||||
invert !==
|
||||
((kind.has("onion") && h.kind === "onion") ||
|
||||
(kind.has("local") &&
|
||||
(kind.has("mdns") &&
|
||||
h.kind === "ip" &&
|
||||
h.hostname.kind === "local") ||
|
||||
(kind.has("domain") &&
|
||||
@@ -258,86 +251,45 @@ export const filledAddress = (
|
||||
}
|
||||
const hostnames = host.hostnameInfo[addressInfo.internalPort] ?? []
|
||||
|
||||
return {
|
||||
...addressInfo,
|
||||
hostnames,
|
||||
toUrls,
|
||||
filter: <
|
||||
F extends Filter = typeof defaultFilter,
|
||||
Format extends Formats = "urlstring",
|
||||
>(
|
||||
filter?: F,
|
||||
format?: Format,
|
||||
) => {
|
||||
const filtered = filterRec(hostnames, filter ?? defaultFilter, false)
|
||||
let res: FormatReturnTy<F, Format>[] = filtered as any
|
||||
if (format === "hostname-info") return res
|
||||
const urls = filtered.flatMap(toUrlArray)
|
||||
if (format === "url") res = urls.map((u) => new URL(u)) as any
|
||||
else res = urls as any
|
||||
return res
|
||||
},
|
||||
get publicHostnames() {
|
||||
return hostnames.filter((h) => h.kind === "onion" || h.public)
|
||||
},
|
||||
get onionHostnames() {
|
||||
return hostnames.filter((h) => h.kind === "onion")
|
||||
},
|
||||
get localHostnames() {
|
||||
return hostnames.filter(
|
||||
(h) => h.kind === "ip" && h.hostname.kind === "local",
|
||||
)
|
||||
},
|
||||
get ipHostnames() {
|
||||
return hostnames.filter(
|
||||
(h) =>
|
||||
h.kind === "ip" &&
|
||||
(h.hostname.kind === "ipv4" || h.hostname.kind === "ipv6"),
|
||||
)
|
||||
},
|
||||
get ipv4Hostnames() {
|
||||
return hostnames.filter(
|
||||
(h) => h.kind === "ip" && h.hostname.kind === "ipv4",
|
||||
)
|
||||
},
|
||||
get ipv6Hostnames() {
|
||||
return hostnames.filter(
|
||||
(h) => h.kind === "ip" && h.hostname.kind === "ipv6",
|
||||
)
|
||||
},
|
||||
get nonIpHostnames() {
|
||||
return hostnames.filter(
|
||||
(h) =>
|
||||
h.kind === "ip" &&
|
||||
h.hostname.kind !== "ipv4" &&
|
||||
h.hostname.kind !== "ipv6",
|
||||
)
|
||||
},
|
||||
get urls() {
|
||||
return this.hostnames.flatMap(toUrlArray)
|
||||
},
|
||||
get publicUrls() {
|
||||
return this.publicHostnames.flatMap(toUrlArray)
|
||||
},
|
||||
get onionUrls() {
|
||||
return this.onionHostnames.flatMap(toUrlArray)
|
||||
},
|
||||
get localUrls() {
|
||||
return this.localHostnames.flatMap(toUrlArray)
|
||||
},
|
||||
get ipUrls() {
|
||||
return this.ipHostnames.flatMap(toUrlArray)
|
||||
},
|
||||
get ipv4Urls() {
|
||||
return this.ipv4Hostnames.flatMap(toUrlArray)
|
||||
},
|
||||
get ipv6Urls() {
|
||||
return this.ipv6Hostnames.flatMap(toUrlArray)
|
||||
},
|
||||
get nonIpUrls() {
|
||||
return this.nonIpHostnames.flatMap(toUrlArray)
|
||||
},
|
||||
function filledAddressFromHostnames<F extends Filter>(
|
||||
hostnames: HostnameInfo[],
|
||||
): Filled<F> & AddressInfo {
|
||||
return {
|
||||
...addressInfo,
|
||||
hostnames,
|
||||
toUrls,
|
||||
format: <Format extends Formats = "urlstring">(format?: Format) => {
|
||||
let res: FormatReturnTy<{}, Format>[] = hostnames as any
|
||||
if (format === "hostname-info") return res
|
||||
const urls = hostnames.flatMap(toUrlArray)
|
||||
if (format === "url") res = urls.map((u) => new URL(u)) as any
|
||||
else res = urls as any
|
||||
return res
|
||||
},
|
||||
filter: <NewFilter extends Filter>(filter: NewFilter) => {
|
||||
return filledAddressFromHostnames<NewFilter & F>(
|
||||
filterRec(hostnames, filter, false),
|
||||
)
|
||||
},
|
||||
get nonLocal(): Filled<typeof nonLocalFilter & F> {
|
||||
return filledAddressFromHostnames<typeof nonLocalFilter & F>(
|
||||
filterRec(hostnames, nonLocalFilter, false),
|
||||
)
|
||||
},
|
||||
get public(): Filled<typeof publicFilter & F> {
|
||||
return filledAddressFromHostnames<typeof publicFilter & F>(
|
||||
filterRec(hostnames, publicFilter, false),
|
||||
)
|
||||
},
|
||||
get onion(): Filled<typeof onionFilter & F> {
|
||||
return filledAddressFromHostnames<typeof onionFilter & F>(
|
||||
filterRec(hostnames, onionFilter, false),
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return filledAddressFromHostnames<{}>(hostnames)
|
||||
}
|
||||
|
||||
const makeInterfaceFilled = async ({
|
||||
|
||||
@@ -18,6 +18,9 @@ export class ComposableRegex {
|
||||
}
|
||||
}
|
||||
|
||||
export const escapeLiteral = (str: string) =>
|
||||
str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
||||
|
||||
// https://ihateregex.io/expr/ipv6/
|
||||
export const ipv6 = new ComposableRegex(
|
||||
/(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/,
|
||||
@@ -69,3 +72,13 @@ export const emailWithName = new ComposableRegex(
|
||||
export const base64 = new ComposableRegex(
|
||||
/(?:[a-zA-Z0-9+\/]{4})*(?:|(?:[a-zA-Z0-9+\/]{3}=)|(?:[a-zA-Z0-9+\/]{2}==)|(?:[a-zA-Z0-9+\/]{1}===))/,
|
||||
)
|
||||
|
||||
//https://rgxdb.com/r/1NUN74O6
|
||||
export const base64Whitespace = new ComposableRegex(
|
||||
/(?:([a-zA-Z0-9+\/]\s*){4})*(?:|(?:([a-zA-Z0-9+\/]\s*){3}=)|(?:([a-zA-Z0-9+\/]\s*){2}==)|(?:([a-zA-Z0-9+\/]\s*){1}===))/,
|
||||
)
|
||||
|
||||
export const pem = (label: string) =>
|
||||
new ComposableRegex(
|
||||
`-----BEGIN ${escapeLiteral(label)}-----\r?\n[a-zA-Z0-9+/\n\r=]*?\r?\n-----END ${escapeLiteral(label)}-----`,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user