V 0.1.0 Added barebones for creating nginx conf and reworked registration during deploy
This commit is contained in:
parent
6d3036c285
commit
19457d97ae
238
package-lock.json
generated
238
package-lock.json
generated
@ -16,6 +16,7 @@
|
||||
"@eslint/js": "^9.18.0",
|
||||
"@playwright/test": "^1.49.1",
|
||||
"@sveltejs/adapter-auto": "^6.0.0",
|
||||
"@sveltejs/adapter-node": "^5.2.12",
|
||||
"@sveltejs/kit": "^2.16.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||
"@vitest/browser": "^3.2.3",
|
||||
@ -404,6 +405,126 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@rollup/plugin-commonjs": {
|
||||
"version": "28.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.6.tgz",
|
||||
"integrity": "sha512-XSQB1K7FUU5QP+3lOQmVCE3I0FcbbNvmNT4VJSj93iUjayaARrTQeoRdiYQoftAJBLrR9t2agwAd3ekaTgHNlw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.0.1",
|
||||
"commondir": "^1.0.1",
|
||||
"estree-walker": "^2.0.2",
|
||||
"fdir": "^6.2.0",
|
||||
"is-reference": "1.2.1",
|
||||
"magic-string": "^0.30.3",
|
||||
"picomatch": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0 || 14 >= 14.17"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^2.68.0||^3.0.0||^4.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-commonjs/node_modules/estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@rollup/plugin-commonjs/node_modules/is-reference": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
|
||||
"integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-json": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz",
|
||||
"integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-node-resolve": {
|
||||
"version": "16.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.1.tgz",
|
||||
"integrity": "sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.0.1",
|
||||
"@types/resolve": "1.20.2",
|
||||
"deepmerge": "^4.2.2",
|
||||
"is-module": "^1.0.0",
|
||||
"resolve": "^1.22.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^2.78.0||^3.0.0||^4.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/pluginutils": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.2.0.tgz",
|
||||
"integrity": "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"picomatch": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/pluginutils/node_modules/estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.44.1",
|
||||
"cpu": [
|
||||
@ -444,6 +565,22 @@
|
||||
"@sveltejs/kit": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/adapter-node": {
|
||||
"version": "5.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-5.2.12.tgz",
|
||||
"integrity": "sha512-0bp4Yb3jKIEcZWVcJC/L1xXp9zzJS4hDwfb4VITAkfT4OVdkspSHsx7YhqJDbb2hgLl6R9Vs7VQR+fqIVOxPUQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rollup/plugin-commonjs": "^28.0.1",
|
||||
"@rollup/plugin-json": "^6.1.0",
|
||||
"@rollup/plugin-node-resolve": "^16.0.0",
|
||||
"rollup": "^4.9.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@sveltejs/kit": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/kit": {
|
||||
"version": "2.22.2",
|
||||
"dev": true,
|
||||
@ -592,6 +729,13 @@
|
||||
"undici-types": "~7.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
||||
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.35.0",
|
||||
"dev": true,
|
||||
@ -1173,6 +1317,13 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/commondir": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"dev": true,
|
||||
@ -1651,6 +1802,16 @@
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
"version": "6.0.2",
|
||||
"dev": true,
|
||||
@ -1686,6 +1847,19 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"dev": true,
|
||||
@ -1717,6 +1891,22 @@
|
||||
"node": ">=0.8.19"
|
||||
}
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.16.1",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
|
||||
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"hasown": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"dev": true,
|
||||
@ -1736,6 +1926,13 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-module": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
|
||||
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"dev": true,
|
||||
@ -2053,6 +2250,13 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/pathe": {
|
||||
"version": "2.0.3",
|
||||
"dev": true,
|
||||
@ -2328,6 +2532,27 @@
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.10",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
|
||||
"integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-core-module": "^2.16.0",
|
||||
"path-parse": "^1.0.7",
|
||||
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"resolve": "bin/resolve"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-from": {
|
||||
"version": "4.0.0",
|
||||
"dev": true,
|
||||
@ -2525,6 +2750,19 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-preserve-symlinks-flag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte": {
|
||||
"version": "5.34.8",
|
||||
"dev": true,
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
"@eslint/js": "^9.18.0",
|
||||
"@playwright/test": "^1.49.1",
|
||||
"@sveltejs/adapter-auto": "^6.0.0",
|
||||
"@sveltejs/adapter-node": "^5.2.12",
|
||||
"@sveltejs/kit": "^2.16.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||
"@vitest/browser": "^3.2.3",
|
||||
|
||||
30
src/lib/server/broker-utils/FileSystem/Endpoint.ts
Normal file
30
src/lib/server/broker-utils/FileSystem/Endpoint.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import type { IEndpointFS } from "$lib/server/broker-utils/FileSystem/endpoints/endpoints"
|
||||
|
||||
export class EndpointBrokerManager {
|
||||
|
||||
private static initialized = false
|
||||
private static endpoints: Map<string, IEndpointFS>
|
||||
private static lastNginxReload: Date = new Date()
|
||||
|
||||
public static get ready() {
|
||||
return EndpointBrokerManager.initialized
|
||||
}
|
||||
|
||||
public static init() {
|
||||
// TODO: Read all files
|
||||
|
||||
// TODO: QUICK parse them
|
||||
|
||||
// TODO: Initialize a file watcher
|
||||
|
||||
}
|
||||
|
||||
|
||||
public async getEndpointByName(name: string): IEndpoint {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
import { type ISSLTerminationBroker, type SSLTerminationChanges } from "$lib/server/classes/endpoints/ssl-termination-endpoint";
|
||||
import type { NginxProtocol } from "$lib/server/enums/protocols";
|
||||
|
||||
export class SSLTerminationBroker implements ISSLTerminationBroker {
|
||||
|
||||
private static initialized = false
|
||||
|
||||
async init(): Promise<void> {
|
||||
|
||||
if (SSLTerminationBroker.initialized) {
|
||||
// UGLY: more specific
|
||||
throw new Error("SSLTerminationBroker was already initialized")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
async createSSLTerminationSimple(
|
||||
name: string,
|
||||
servicePort: number,
|
||||
serviceEndpoint: string,
|
||||
certificateURI: string,
|
||||
privateKeyURI: string
|
||||
): Promise<SSLTermination> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
|
||||
async createSSLTerminationComplete(
|
||||
name: string,
|
||||
sslPort: number,
|
||||
clearPort: number,
|
||||
servicePort: number,
|
||||
serviceEndpoint: string,
|
||||
certificateURI: string,
|
||||
privateKeyURI: string
|
||||
): Promise<SSLTermination> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
async getSSLTerminationByName(name: string): Promise<SSLTermination | null> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
async modifySSLTerminationByName(name: string, changes: SSLTerminationChanges): Promise<SSLTermination> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
async deleteSSLTerminationByName(name: string): Promise<SSLTermination | null> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
async getAllSSLTerminations(): Promise<SSLTermination[]> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
import { EndpointType } from "$lib/server/enums/endpoints";
|
||||
import type { FileStats } from "$lib/server/utils/filesystem-utils";
|
||||
|
||||
export interface IEndpointFS {
|
||||
|
||||
/**
|
||||
* Specifies which Enpoint this is
|
||||
*/
|
||||
type: EndpointType
|
||||
/** File name */
|
||||
name: string
|
||||
/**
|
||||
* File stats,
|
||||
* useful to understand
|
||||
* whether the file has been actually
|
||||
* parsed by nginx during last reload
|
||||
*/
|
||||
stats: FileStats
|
||||
/** File path */
|
||||
path: string
|
||||
/** Hash of the file */
|
||||
hash: string
|
||||
|
||||
/** converts the IEndpoint to */
|
||||
toConf(): string
|
||||
|
||||
ports(): number[]
|
||||
|
||||
}
|
||||
|
||||
export type FSHeader = {
|
||||
name: string,
|
||||
stats: FileStats
|
||||
path: string,
|
||||
hash: string
|
||||
}
|
||||
|
||||
@ -0,0 +1,198 @@
|
||||
import { EndpointType } from "$lib/server/enums/endpoints"
|
||||
import { httpVersion, proxyProtocol, secureProtocol, type NginxProtocol } from "$lib/server/enums/protocols"
|
||||
import { validatePort } from "$lib/server/utils/ports-utils"
|
||||
import type { Stats } from "fs"
|
||||
import type { FSHeader, IEndpointFS } from "./endpoints"
|
||||
import { createHeader } from "../utils"
|
||||
|
||||
export class SSLTerminationFS implements IEndpointFS {
|
||||
|
||||
private static __type = EndpointType.SSL_TERMINATION
|
||||
|
||||
public get type() {
|
||||
return SSLTerminationFS.__type
|
||||
}
|
||||
|
||||
|
||||
public name: string
|
||||
public stats: Stats
|
||||
public path: string
|
||||
public hash: string
|
||||
public sslPort: number
|
||||
public clearPort: number
|
||||
public servicePort: number
|
||||
public serviceEndpoint: string
|
||||
public protocol: NginxProtocol
|
||||
public certificateURI: string
|
||||
public privateKeyURI: string
|
||||
|
||||
|
||||
|
||||
constructor(
|
||||
name: string,
|
||||
stats: Stats,
|
||||
path: string,
|
||||
hash: string,
|
||||
sslPort: number,
|
||||
clearPort: number,
|
||||
servicePort: number,
|
||||
serviceEndpoint: string,
|
||||
protocol: NginxProtocol,
|
||||
certificateURI: string,
|
||||
privateKeyURI: string
|
||||
) {
|
||||
|
||||
validatePort(sslPort)
|
||||
validatePort(clearPort)
|
||||
validatePort(servicePort)
|
||||
|
||||
this.name = name
|
||||
this.stats = stats
|
||||
this.path = path
|
||||
this.hash = hash
|
||||
this.sslPort = sslPort
|
||||
this.clearPort = clearPort
|
||||
this.servicePort = servicePort
|
||||
this.serviceEndpoint = serviceEndpoint
|
||||
this.protocol = protocol
|
||||
this.certificateURI = certificateURI
|
||||
this.privateKeyURI = privateKeyURI
|
||||
|
||||
}
|
||||
|
||||
toConf(): string {
|
||||
|
||||
const HEADER = this.createHeader()
|
||||
const SSL_SERVER = this.createSSLServer()
|
||||
const CLEAR_SERVER = this.createClearServer()
|
||||
|
||||
const CONF = HEADER + SSL_SERVER + CLEAR_SERVER
|
||||
|
||||
return CONF
|
||||
}
|
||||
|
||||
ports(): number[]{
|
||||
|
||||
return [
|
||||
this.sslPort,
|
||||
this.clearPort
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
public static parseConf(fsHeader: FSHeader, conf: string) : SSLTerminationFS {
|
||||
// TODO: parse header
|
||||
}
|
||||
|
||||
|
||||
private createHeader() {
|
||||
return createHeader(
|
||||
this,
|
||||
[
|
||||
{
|
||||
key: "NAME",
|
||||
value: this.name
|
||||
},
|
||||
{
|
||||
key: "PROTOCOL",
|
||||
value: this.protocol
|
||||
},
|
||||
{
|
||||
key: "SSL_PORT",
|
||||
value: this.sslPort
|
||||
},
|
||||
{
|
||||
key: "CLEAR_PORT",
|
||||
value: this.clearPort
|
||||
},
|
||||
{
|
||||
key: "SERVICE_PORT",
|
||||
value: this.servicePort
|
||||
},
|
||||
{
|
||||
key: "SERVICE_ENDPOINT",
|
||||
value: this.serviceEndpoint
|
||||
},
|
||||
{
|
||||
key: "CERTIFICATE_PATH",
|
||||
value: this.certificateURI
|
||||
},
|
||||
{
|
||||
key: "KEY_PATH",
|
||||
value: this.privateKeyURI
|
||||
}
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
// UGLY: refactor into a flexible method
|
||||
private createSSLServer() {
|
||||
|
||||
const CLEAR_PROTOCOL = `${this.protocol}`
|
||||
const HTTP_VERSION = httpVersion(this.protocol)
|
||||
const PROXY_OPTION = proxyProtocol(this.protocol)
|
||||
|
||||
// UGLY: put to constants
|
||||
let conf = [
|
||||
"server {\n",
|
||||
"\tmore_clear_headers Server;\n",
|
||||
`\tlisten ${this.sslPort};`
|
||||
]
|
||||
|
||||
if (HTTP_VERSION !== 1) {
|
||||
conf.push(
|
||||
`\thttp${HTTP_VERSION} on;`
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: check if we should support less protocols
|
||||
conf.push(
|
||||
"\n",
|
||||
"\tlocation / {",
|
||||
`\t\t${PROXY_OPTION} ${CLEAR_PROTOCOL}://127.0.0.1:${this.clearPort};`,
|
||||
"\t}",
|
||||
"\n",
|
||||
`ssl_certificate ${this.certificateURI};`,
|
||||
`ssl_certificate_key ${this.privateKeyURI};`,
|
||||
"\tssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;",
|
||||
"\n",
|
||||
"}"
|
||||
)
|
||||
|
||||
return conf.join("\n")
|
||||
}
|
||||
|
||||
private createClearServer() {
|
||||
|
||||
const SSL_PROTOCOL = secureProtocol(this.protocol)
|
||||
const HTTP_VERSION = httpVersion(this.protocol)
|
||||
const PROXY_OPTION = proxyProtocol(this.protocol)
|
||||
|
||||
// UGLY: put to constants
|
||||
let conf = [
|
||||
"server {\n",
|
||||
"\tmore_clear_headers Server;\n",
|
||||
`\tlisten ${this.clearPort};`
|
||||
]
|
||||
|
||||
if (HTTP_VERSION !== 1) {
|
||||
conf.push(
|
||||
`\thttp${HTTP_VERSION} on;`
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: check if we should support less protocols
|
||||
conf.push(
|
||||
"\n",
|
||||
"\tlocation / {",
|
||||
`\t\t${PROXY_OPTION} ${SSL_PROTOCOL}://${this.serviceEndpoint}:${this.servicePort};`,
|
||||
"\t}",
|
||||
"\n",
|
||||
"}"
|
||||
)
|
||||
|
||||
return conf.join("\n")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
77
src/lib/server/broker-utils/FileSystem/utils.ts
Normal file
77
src/lib/server/broker-utils/FileSystem/utils.ts
Normal file
@ -0,0 +1,77 @@
|
||||
import { EndpointType, matchEndpoint } from "$lib/server/enums/endpoints"
|
||||
import type { FSHeader, IEndpointFS } from "./endpoints/endpoints"
|
||||
import { SSLTerminationFS } from "./endpoints/ssltermination-fs"
|
||||
|
||||
export const HEADER_BOUNDARY = "**********************************************************"
|
||||
export const HEADER_UPPER = `/*${HEADER_BOUNDARY}`
|
||||
export const HEADER_LOWER = `${HEADER_BOUNDARY}*/`
|
||||
|
||||
export type HeaderKeyValueFS = {
|
||||
key: string,
|
||||
value: any
|
||||
}
|
||||
|
||||
export function parseConf(
|
||||
fsHeader: FSHeader,
|
||||
conf: string
|
||||
): IEndpointFS {
|
||||
|
||||
const TYPE = parseDefaultConf(conf)
|
||||
|
||||
switch (TYPE) {
|
||||
|
||||
case EndpointType.SSL_TERMINATION:
|
||||
return SSLTerminationFS.parseConf(fsHeader, conf)
|
||||
default:
|
||||
// TODO: add manual endpoint
|
||||
}
|
||||
}
|
||||
|
||||
export function createHeader(endpoint: IEndpointFS, variables?: HeaderKeyValueFS[]): string {
|
||||
|
||||
if (!variables) {
|
||||
variables = []
|
||||
}
|
||||
|
||||
let header = [
|
||||
HEADER_UPPER,
|
||||
"SSL-SNIFFER AUTOMATICALLY GENERATED",
|
||||
`TYPE: ${endpoint.type}`,
|
||||
HEADER_BOUNDARY
|
||||
]
|
||||
|
||||
for (const variable of variables) {
|
||||
header.push(
|
||||
`${variable.key}: ${variable.value}`
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
header.push(HEADER_LOWER)
|
||||
return header.join("\n")
|
||||
|
||||
}
|
||||
|
||||
function parseDefaultConf(conf: string): EndpointType {
|
||||
/** Row (remember array order) where we find the type */
|
||||
const TYPE_DATA_ROW = 2
|
||||
/** What separator was used */
|
||||
const TYPE_DATA_SEPARATOR = " "
|
||||
/** Whether the value is on the left(0) of right(1) */
|
||||
const TYPE_DATA_ARRAY_POSITION = 1
|
||||
const DEFAULT_LABEL = EndpointType.MANUAL
|
||||
|
||||
const confLines = conf.split("\n")
|
||||
|
||||
if (confLines.length < 4 ) {
|
||||
return matchEndpoint(DEFAULT_LABEL)
|
||||
}
|
||||
|
||||
//
|
||||
const label = confLines[TYPE_DATA_ROW]
|
||||
.split(TYPE_DATA_SEPARATOR)[TYPE_DATA_ARRAY_POSITION]
|
||||
|
||||
return matchEndpoint(label)
|
||||
|
||||
|
||||
}
|
||||
@ -4,7 +4,5 @@ export interface IEndpoint {
|
||||
|
||||
type: EndpointType
|
||||
name: string
|
||||
path: string
|
||||
hash: string
|
||||
|
||||
}
|
||||
@ -1,9 +1,7 @@
|
||||
import { EndpointType } from "$lib/server/enums/endpoints"
|
||||
import type { NginxProtocol } from "$lib/server/enums/protocols"
|
||||
import { doesFileExist } from "$lib/server/utils/filesystem-utils"
|
||||
import { isPortAvailable, validatePort } from "$lib/server/utils/ports-utils"
|
||||
import type { init } from "../../../hooks.server"
|
||||
import type { IEndpoint } from "./endpoints"
|
||||
import { validatePort } from "$lib/server/utils/ports-utils"
|
||||
import type { IEndpoint } from "./endpoints-interfaces"
|
||||
|
||||
// TODO: inherit from a super class
|
||||
export interface ISSLTerminationBroker {
|
||||
@ -63,12 +61,14 @@ export interface ISSLTerminationBroker {
|
||||
* discouraged in favor of the Factory methods as it does
|
||||
* more checks than this class
|
||||
*/
|
||||
export class SSLTermination implements IEndpoint {
|
||||
export class SSLTermination implements IEndpoint {
|
||||
|
||||
private static _type: EndpointType = EndpointType.SSL_TERMINATION
|
||||
private static __type = EndpointType.SSL_TERMINATION
|
||||
|
||||
public path: string
|
||||
public hash: string
|
||||
public get type() {
|
||||
return SSLTermination.__type
|
||||
}
|
||||
|
||||
public name: string
|
||||
public sslPort: number
|
||||
public clearPort: number
|
||||
@ -78,14 +78,10 @@ export class SSLTermination implements IEndpoint {
|
||||
public certificateURI: string
|
||||
public privateKeyURI: string
|
||||
|
||||
public get type() {
|
||||
return SSLTermination._type
|
||||
}
|
||||
|
||||
|
||||
constructor(
|
||||
name: string,
|
||||
path: string,
|
||||
hash: string,
|
||||
sslPort: number,
|
||||
clearPort: number,
|
||||
servicePort: number,
|
||||
@ -100,8 +96,6 @@ export class SSLTermination implements IEndpoint {
|
||||
validatePort(servicePort)
|
||||
|
||||
this.name = name
|
||||
this.path = path
|
||||
this.hash = hash
|
||||
this.sslPort = sslPort
|
||||
this.clearPort = clearPort
|
||||
this.servicePort = servicePort
|
||||
@ -115,7 +109,7 @@ export class SSLTermination implements IEndpoint {
|
||||
|
||||
}
|
||||
|
||||
type SSLTerminationChanges = {
|
||||
export type SSLTerminationChanges = {
|
||||
name?: string,
|
||||
sslPort?: number,
|
||||
clearPort?: number,
|
||||
@ -126,6 +120,8 @@ type SSLTerminationChanges = {
|
||||
privateKeyURI?: string
|
||||
}
|
||||
|
||||
|
||||
|
||||
export class SSLTerminationEndpointApp {
|
||||
|
||||
private static initialized: boolean = false
|
||||
@ -1,6 +1,17 @@
|
||||
export enum EndpointType {
|
||||
|
||||
SSL_TERMINATION = "SSL-Termination",
|
||||
SSL_TERMINATION = "SSLTermination",
|
||||
MANUAL = "Manual"
|
||||
|
||||
}
|
||||
|
||||
export function matchEndpoint(label: string) {
|
||||
|
||||
switch(label) {
|
||||
|
||||
case "SSLTermination":
|
||||
return EndpointType.SSL_TERMINATION
|
||||
default:
|
||||
return EndpointType.MANUAL
|
||||
}
|
||||
}
|
||||
@ -3,4 +3,31 @@ export enum NginxProtocol {
|
||||
HTTP2 = "http",
|
||||
QUIC = "http",
|
||||
GRPC = "grpc"
|
||||
}
|
||||
}
|
||||
|
||||
// UGLY: move these fnction into utils
|
||||
export function httpVersion(protocol: NginxProtocol): number {
|
||||
|
||||
switch(protocol) {
|
||||
case NginxProtocol.HTTP2:
|
||||
case NginxProtocol.GRPC:
|
||||
return 2
|
||||
case NginxProtocol.QUIC:
|
||||
return 3
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
export function secureProtocol(protocol: NginxProtocol) {
|
||||
return `${protocol}s`
|
||||
}
|
||||
|
||||
export function proxyProtocol(protocol: NginxProtocol) {
|
||||
switch(protocol) {
|
||||
case NginxProtocol.GRPC:
|
||||
return "grpc_pass"
|
||||
default:
|
||||
return "proxy_pass"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import type { OpenMode } from 'node:fs';
|
||||
import { Stats, type OpenMode } from 'node:fs';
|
||||
import * as Node from 'node:fs/promises';
|
||||
|
||||
export type FileStats = Stats
|
||||
|
||||
export class FileHandle {
|
||||
|
||||
@ -38,6 +39,16 @@ export class FileHandle {
|
||||
|
||||
}
|
||||
|
||||
public async lastChange() {
|
||||
const stats = await Node.stat(this.path)
|
||||
return stats.mtime
|
||||
}
|
||||
|
||||
public async getStats() {
|
||||
const stats = await Node.stat(this.path)
|
||||
return stats
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
114
src/routes/api/program/register/+server.ts
Normal file
114
src/routes/api/program/register/+server.ts
Normal file
@ -0,0 +1,114 @@
|
||||
import { error, json, redirect, text, type Cookies } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types';
|
||||
import { UserApp, User } from '$lib/server/classes/users';
|
||||
import { SessionApp, Session } from '$lib/server/classes/sessions';
|
||||
import { AppData } from '$lib/server/classes/appdata';
|
||||
import { logger } from '$lib/server/utils/logger';
|
||||
import { DEBUG } from '$lib/server/utils/constants';
|
||||
|
||||
/***********************************************************
|
||||
*
|
||||
* Author: Christian Risi 26/06/2025
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
***********************************************************/
|
||||
|
||||
export const POST: RequestHandler = async ({ request, locals, cookies }) => {
|
||||
|
||||
const req: Request = request
|
||||
const local: App.Locals = locals
|
||||
const cookie: Cookies = cookies
|
||||
|
||||
const session = local.session
|
||||
|
||||
if (DEBUG) {
|
||||
return redirect(307, "api/register")
|
||||
}
|
||||
|
||||
if (!session) {
|
||||
// The user is not providing credentials
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/403
|
||||
return error(401, "Unauthorized")
|
||||
}
|
||||
|
||||
|
||||
let userJson: { username: string, password: string }
|
||||
let tmpJSON: any
|
||||
|
||||
try {
|
||||
tmpJSON = await req.json()
|
||||
} catch {
|
||||
return error(400, "Bad Request")
|
||||
}
|
||||
|
||||
if (!tmpJSON.username || !tmpJSON.password) {
|
||||
return error(400, "Bad Request")
|
||||
}
|
||||
|
||||
userJson = tmpJSON
|
||||
|
||||
// If this fails, should be a 400?
|
||||
let user: User
|
||||
try {
|
||||
user = await UserApp.createUser(
|
||||
userJson.username,
|
||||
userJson.password
|
||||
)
|
||||
} catch {
|
||||
return error(400, "The user already exists")
|
||||
}
|
||||
|
||||
|
||||
let newSession
|
||||
try {
|
||||
newSession = SessionApp.createSessionFromUserID(
|
||||
user.userID
|
||||
)
|
||||
} catch(err){
|
||||
logger.debug(`error: ${err}`, "API Register")
|
||||
return error(500, "Internal Server Error")
|
||||
}
|
||||
|
||||
|
||||
const sessionCookie = await new AppData(
|
||||
newSession,
|
||||
user
|
||||
).toCookie()
|
||||
|
||||
cookie.set(
|
||||
"session",
|
||||
sessionCookie,
|
||||
{
|
||||
path: "/"
|
||||
}
|
||||
)
|
||||
|
||||
const res = new Response(
|
||||
null,
|
||||
{
|
||||
status: 201,
|
||||
statusText: "Created",
|
||||
}
|
||||
)
|
||||
|
||||
return res
|
||||
|
||||
}
|
||||
|
||||
export const fallback: RequestHandler = async ({ request }) => {
|
||||
|
||||
// TODO: return method not allowed
|
||||
const res = new Response(
|
||||
null,
|
||||
{
|
||||
status: 405,
|
||||
statusText: "Method Not Allowed",
|
||||
headers: {
|
||||
Allow: "POST"
|
||||
}
|
||||
}
|
||||
)
|
||||
return res
|
||||
};
|
||||
@ -1,9 +1,10 @@
|
||||
import { error, json, text, type Cookies } from '@sveltejs/kit';
|
||||
import { error, json, redirect, text, type Cookies } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types';
|
||||
import { UserApp, User } from '$lib/server/classes/users';
|
||||
import { SessionApp, Session } from '$lib/server/classes/sessions';
|
||||
import { AppData } from '$lib/server/classes/appdata';
|
||||
import { logger } from '$lib/server/utils/logger';
|
||||
import { DEBUG } from '$lib/server/utils/constants';
|
||||
|
||||
/***********************************************************
|
||||
*
|
||||
@ -22,6 +23,10 @@ export const POST: RequestHandler = async ({ request, locals, cookies }) => {
|
||||
|
||||
const session = local.session
|
||||
|
||||
if (!DEBUG) {
|
||||
return redirect(307, "api/program/register")
|
||||
}
|
||||
|
||||
if (session) {
|
||||
// The user is providing valid credentials
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/403
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user