merge: integrate dev branch, resolve package.json and lockfile conflicts
Co-authored-by: ajnart <49837342+ajnart@users.noreply.github.com>
This commit is contained in:
1 parent
1e438ec3c3
commit
6cbf72462a
117 files changed
+4495
-1648
No files matched your search
@@ -32,7 +32,7 @@
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"@types/bcrypt": "6.0.0",
|
||||
"eslint": "^9.39.3",
|
||||
"eslint": "^9.39.4",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import bcrypt from "bcrypt";
|
||||
import { createHmac, hkdfSync } from "node:crypto";
|
||||
|
||||
import { createId } from "@homarr/common";
|
||||
import { env } from "@homarr/common/env";
|
||||
import { decryptSecret, encryptSecret } from "@homarr/common/server";
|
||||
import { fetchWithTrustedCertificatesAsync } from "@homarr/core/infrastructure/http";
|
||||
import { createLogger } from "@homarr/core/infrastructure/logs";
|
||||
@@ -9,29 +10,22 @@ import { createGetSetChannel } from "@homarr/redis";
|
||||
|
||||
const logger = createLogger({ module: "imageProxy" });
|
||||
|
||||
const createHashChannel = (hash: `${string}.${string}`) => createGetSetChannel<string>(`image-proxy:hash:${hash}`);
|
||||
const createHmacChannel = (hmac: `${string}.${string}`) => createGetSetChannel<string>(`image-proxy:hmac:${hmac}`);
|
||||
const createUrlByIdChannel = (id: string) =>
|
||||
createGetSetChannel<{
|
||||
url: `${string}.${string}`;
|
||||
headers: `${string}.${string}`;
|
||||
}>(`image-proxy:url:${id}`);
|
||||
const saltChannel = createGetSetChannel<string>("image-proxy:salt");
|
||||
|
||||
export class ImageProxy {
|
||||
private static salt: string | null = null;
|
||||
private async getOrCreateSaltAsync(): Promise<string> {
|
||||
if (ImageProxy.salt) return ImageProxy.salt;
|
||||
const existingSalt = await saltChannel.getAsync();
|
||||
if (existingSalt) {
|
||||
ImageProxy.salt = existingSalt;
|
||||
return existingSalt;
|
||||
}
|
||||
private static hmacKey: Buffer<ArrayBuffer> | null = null;
|
||||
|
||||
const salt = await bcrypt.genSalt(10);
|
||||
logger.debug("Generated new salt for image proxy", { salt });
|
||||
ImageProxy.salt = salt;
|
||||
await saltChannel.setAsync(salt);
|
||||
return salt;
|
||||
/**
|
||||
* Generate secure key for image-proxy from encryption key
|
||||
*/
|
||||
private static getHmacKey(): Buffer<ArrayBuffer> {
|
||||
this.hmacKey ??= Buffer.from(hkdfSync("sha256", env.SECRET_ENCRYPTION_KEY, "", "image-proxy", 32));
|
||||
return this.hmacKey;
|
||||
}
|
||||
|
||||
public async createImageAsync(url: string, headers?: Record<string, string>): Promise<string> {
|
||||
@@ -106,20 +100,18 @@ export class ImageProxy {
|
||||
}
|
||||
|
||||
private async getExistingIdAsync(url: string, headers: Record<string, string> | undefined): Promise<string | null> {
|
||||
const salt = await this.getOrCreateSaltAsync();
|
||||
const urlHash = await bcrypt.hash(url, salt);
|
||||
const headerHash = await bcrypt.hash(JSON.stringify(headers ?? null), salt);
|
||||
const urlHash = this.hashSecret(url);
|
||||
const headerHash = this.hashSecret(JSON.stringify(headers ?? null));
|
||||
|
||||
const channel = createHashChannel(`${urlHash}.${headerHash}`);
|
||||
const channel = createHmacChannel(`${urlHash}.${headerHash}`);
|
||||
return await channel.getAsync();
|
||||
}
|
||||
|
||||
private async storeImageAsync(id: string, url: string, headers: Record<string, string> | undefined): Promise<void> {
|
||||
const salt = await this.getOrCreateSaltAsync();
|
||||
const urlHash = await bcrypt.hash(url, salt);
|
||||
const headerHash = await bcrypt.hash(JSON.stringify(headers ?? null), salt);
|
||||
const urlHash = this.hashSecret(url);
|
||||
const headerHash = this.hashSecret(JSON.stringify(headers ?? null));
|
||||
|
||||
const hashChannel = createHashChannel(`${urlHash}.${headerHash}`);
|
||||
const hashChannel = createHmacChannel(`${urlHash}.${headerHash}`);
|
||||
const urlHeaderChannel = createUrlByIdChannel(id);
|
||||
await urlHeaderChannel.setAsync({
|
||||
url: encryptSecret(url),
|
||||
@@ -134,6 +126,10 @@ export class ImageProxy {
|
||||
});
|
||||
}
|
||||
|
||||
private hashSecret(value: string): string {
|
||||
return createHmac("sha256", ImageProxy.getHmacKey()).update(value).digest("hex");
|
||||
}
|
||||
|
||||
private redactUrl(url: string): string {
|
||||
const urlObject = new URL(url);
|
||||
|
||||
|
||||
Reference in new issue
Block a user