mirror of
https://github.com/Drop-OSS/drop.git
synced 2026-01-31 15:37:09 +01:00
fix: more eslint stuff
This commit is contained in:
@@ -1,11 +1,8 @@
|
||||
import aclManager from "~/server/internal/acls";
|
||||
import prisma from "~/server/internal/db/database";
|
||||
import libraryManager from "~/server/internal/library";
|
||||
|
||||
export default defineEventHandler(async (h3) => {
|
||||
const allowed = await aclManager.allowSystemACL(h3, [
|
||||
"game:delete",
|
||||
]);
|
||||
const allowed = await aclManager.allowSystemACL(h3, ["game:delete"]);
|
||||
if (!allowed) throw createError({ statusCode: 403 });
|
||||
|
||||
const query = getQuery(h3);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defineEventHandler, createError, readBody } from "h3";
|
||||
import { defineEventHandler, createError } from "h3";
|
||||
import aclManager from "~/server/internal/acls";
|
||||
import newsManager from "~/server/internal/news";
|
||||
import { handleFileUpload } from "~/server/internal/utils/handlefileupload";
|
||||
@@ -21,7 +21,7 @@ export default defineEventHandler(async (h3) => {
|
||||
statusMessage: "Failed to upload file",
|
||||
});
|
||||
|
||||
const [imageId, options, pull, dump] = uploadResult;
|
||||
const [imageId, options, pull, _dump] = uploadResult;
|
||||
|
||||
const title = options.title;
|
||||
const description = options.description;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AuthMec, Invitation } from "@prisma/client";
|
||||
import { AuthMec } from "@prisma/client";
|
||||
import prisma from "~/server/internal/db/database";
|
||||
import { createHashArgon2 } from "~/server/internal/security/simple";
|
||||
import * as jdenticon from "jdenticon";
|
||||
@@ -63,7 +63,7 @@ export default defineEventHandler(async (h3) => {
|
||||
profilePictureId,
|
||||
async () => jdenticon.toPng(user.username, 256),
|
||||
{},
|
||||
[`internal:read`, `${userId}:read`]
|
||||
[`internal:read`, `${userId}:read`],
|
||||
);
|
||||
const [linkMec] = await prisma.$transaction([
|
||||
prisma.linkedAuthMec.create({
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
export default defineEventHandler((h3) => {
|
||||
|
||||
})
|
||||
export default defineEventHandler((_h3) => {});
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import prisma from "~/server/internal/db/database";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
@@ -33,7 +32,7 @@ export default defineEventHandler(async (h3) => {
|
||||
const versionDir = path.join(
|
||||
libraryManager.fetchLibraryPath(),
|
||||
game.libraryBasePath,
|
||||
versionName
|
||||
versionName,
|
||||
);
|
||||
if (!fs.existsSync(versionDir))
|
||||
throw createError({
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import aclManager from "~/server/internal/acls";
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import userLibraryManager from "~/server/internal/userlibrary";
|
||||
|
||||
@@ -20,7 +19,7 @@ export default defineClientEventHandler(async (h3, { fetchUser }) => {
|
||||
const successful = await userLibraryManager.collectionRemove(
|
||||
gameId,
|
||||
id,
|
||||
user.id
|
||||
user.id,
|
||||
);
|
||||
if (!successful)
|
||||
throw createError({
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import aclManager from "~/server/internal/acls";
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import userLibraryManager from "~/server/internal/userlibrary";
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import aclManager from "~/server/internal/acls";
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import userLibraryManager from "~/server/internal/userlibrary";
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import aclManager from "~/server/internal/acls";
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import userLibraryManager from "~/server/internal/userlibrary";
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import aclManager from "~/server/internal/acls";
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import userLibraryManager from "~/server/internal/userlibrary";
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import aclManager from "~/server/internal/acls";
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import userLibraryManager from "~/server/internal/userlibrary";
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import aclManager from "~/server/internal/acls";
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import userLibraryManager from "~/server/internal/userlibrary";
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import aclManager from "~/server/internal/acls";
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import userLibraryManager from "~/server/internal/userlibrary";
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import aclManager from "~/server/internal/acls";
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import userLibraryManager from "~/server/internal/userlibrary";
|
||||
|
||||
@@ -12,6 +11,9 @@ export default defineClientEventHandler(async (h3, { fetchUser }) => {
|
||||
throw createError({ statusCode: 400, statusMessage: "Requires name" });
|
||||
|
||||
// Create the collection using the manager
|
||||
const newCollection = await userLibraryManager.collectionCreate(name, user.id);
|
||||
const newCollection = await userLibraryManager.collectionCreate(
|
||||
name,
|
||||
user.id,
|
||||
);
|
||||
return newCollection;
|
||||
});
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import prisma from "~/server/internal/db/database";
|
||||
import { DropManifest } from "~/server/internal/downloads/manifest";
|
||||
|
||||
export default defineClientEventHandler(async (h3, {}) => {
|
||||
export default defineClientEventHandler(async (h3) => {
|
||||
const query = getQuery(h3);
|
||||
const id = query.id?.toString();
|
||||
if (!id)
|
||||
@@ -23,9 +22,9 @@ export default defineClientEventHandler(async (h3, {}) => {
|
||||
const mappedVersions = versions
|
||||
.map((version) => {
|
||||
if (!version.dropletManifest) return undefined;
|
||||
|
||||
|
||||
const newVersion = { ...version, dropletManifest: undefined };
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error idk why we delete an undefined object
|
||||
delete newVersion.dropletManifest;
|
||||
return {
|
||||
...newVersion,
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
import { ClientCapabilities } from "@prisma/client";
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import { applicationSettings } from "~/server/internal/config/application-configuration";
|
||||
import prisma from "~/server/internal/db/database";
|
||||
|
||||
export default defineClientEventHandler(
|
||||
async (h3, { fetchClient, fetchUser }) => {
|
||||
const client = await fetchClient();
|
||||
if (!client.capabilities.includes(ClientCapabilities.CloudSaves))
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: "Capability not allowed.",
|
||||
});
|
||||
export default defineClientEventHandler(async (_h3, { fetchClient }) => {
|
||||
const client = await fetchClient();
|
||||
if (!client.capabilities.includes(ClientCapabilities.CloudSaves))
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: "Capability not allowed.",
|
||||
});
|
||||
|
||||
const slotLimit = await applicationSettings.get("saveSlotCountLimit");
|
||||
const sizeLimit = await applicationSettings.get("saveSlotSizeLimit");
|
||||
const history = await applicationSettings.get("saveSlotHistoryLimit");
|
||||
return { slotLimit, sizeLimit, history };
|
||||
}
|
||||
);
|
||||
const slotLimit = await applicationSettings.get("saveSlotCountLimit");
|
||||
const sizeLimit = await applicationSettings.get("saveSlotSizeLimit");
|
||||
const history = await applicationSettings.get("saveSlotHistoryLimit");
|
||||
return { slotLimit, sizeLimit, history };
|
||||
});
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import prisma from "~/server/internal/db/database";
|
||||
import userLibraryManager from "~/server/internal/userlibrary";
|
||||
|
||||
export default defineClientEventHandler(async (h3, { fetchUser }) => {
|
||||
export default defineClientEventHandler(async (_h3, { fetchUser }) => {
|
||||
const user = await fetchUser();
|
||||
const library = await userLibraryManager.fetchLibrary(user.id);
|
||||
return library.entries.map((e) => e.game);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export default defineEventHandler((h3) => {
|
||||
export default defineEventHandler((_h3) => {
|
||||
return {
|
||||
appName: "Drop",
|
||||
};
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import notificationSystem from "~/server/internal/notifications";
|
||||
import session from "~/server/internal/session";
|
||||
import { parse as parseCookies } from "cookie-es";
|
||||
import aclManager from "~/server/internal/acls";
|
||||
|
||||
// TODO add web socket sessions for horizontal scaling
|
||||
// Peer ID to user ID
|
||||
const socketSessions: { [key: string]: string } = {};
|
||||
const socketSessions = new Map<string, string>();
|
||||
|
||||
export default defineWebSocketHandler({
|
||||
async open(peer) {
|
||||
@@ -25,7 +23,7 @@ export default defineWebSocketHandler({
|
||||
userIds.push("system");
|
||||
}
|
||||
|
||||
socketSessions[peer.id] = userId;
|
||||
socketSessions.set(peer.id, userId);
|
||||
|
||||
for (const listenUserId of userIds) {
|
||||
notificationSystem.listen(listenUserId, peer.id, (notification) => {
|
||||
@@ -33,8 +31,8 @@ export default defineWebSocketHandler({
|
||||
});
|
||||
}
|
||||
},
|
||||
async close(peer, details) {
|
||||
const userId = socketSessions[peer.id];
|
||||
async close(peer, _details) {
|
||||
const userId = socketSessions.get(peer.id);
|
||||
if (!userId) {
|
||||
console.log(`skipping websocket close for ${peer.id}`);
|
||||
return;
|
||||
@@ -42,6 +40,6 @@ export default defineWebSocketHandler({
|
||||
|
||||
notificationSystem.unlisten(userId, peer.id);
|
||||
notificationSystem.unlisten("system", peer.id); // In case we were listening as 'system'
|
||||
delete socketSessions[peer.id];
|
||||
socketSessions.delete(peer.id);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import session from "~/server/internal/session";
|
||||
import taskHandler, { TaskMessage } from "~/server/internal/tasks";
|
||||
import { parse as parseCookies } from "cookie-es";
|
||||
import taskHandler from "~/server/internal/tasks";
|
||||
import type { MinimumRequestObject } from "~/server/h3";
|
||||
|
||||
// TODO add web socket sessions for horizontal scaling
|
||||
// ID to admin
|
||||
const socketHeaders: { [key: string]: MinimumRequestObject } = {};
|
||||
const socketHeaders = new Map<string, MinimumRequestObject>();
|
||||
|
||||
export default defineWebSocketHandler({
|
||||
async open(peer) {
|
||||
@@ -15,25 +13,26 @@ export default defineWebSocketHandler({
|
||||
return;
|
||||
}
|
||||
|
||||
socketHeaders[peer.id] = {
|
||||
socketHeaders.set(peer.id, {
|
||||
headers: request.headers ?? new Headers(),
|
||||
};
|
||||
});
|
||||
peer.send(`connect`);
|
||||
},
|
||||
message(peer, message) {
|
||||
if (!peer.id) return;
|
||||
if (socketHeaders[peer.id] === undefined) return;
|
||||
const headers = socketHeaders.get(peer.id);
|
||||
if (headers === undefined) return;
|
||||
const text = message.text();
|
||||
if (text.startsWith("connect/")) {
|
||||
const id = text.substring("connect/".length);
|
||||
taskHandler.connect(peer.id, id, peer, socketHeaders[peer.id]);
|
||||
taskHandler.connect(peer.id, id, peer, headers);
|
||||
return;
|
||||
}
|
||||
},
|
||||
close(peer, details) {
|
||||
close(peer, _details) {
|
||||
if (!peer.id) return;
|
||||
if (socketHeaders[peer.id] === undefined) return;
|
||||
delete socketHeaders[peer.id];
|
||||
if (!socketHeaders.has(peer.id)) return;
|
||||
socketHeaders.delete(peer.id);
|
||||
|
||||
taskHandler.disconnectAll(peer.id);
|
||||
},
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import aclManager from "~/server/internal/acls";
|
||||
import clientHandler from "~/server/internal/clients/handler";
|
||||
import prisma from "~/server/internal/db/database";
|
||||
|
||||
export default defineEventHandler(async (h3) => {
|
||||
const userId = await aclManager.getUserIdACL(h3, ["clients:revoke"]);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { APITokenMode } from "@prisma/client";
|
||||
import aclManager, { userACLs } from "~/server/internal/acls";
|
||||
import { userACLDescriptions } from "~/server/internal/acls/descriptions";
|
||||
import prisma from "~/server/internal/db/database";
|
||||
|
||||
export default defineEventHandler(async (h3) => {
|
||||
@@ -25,17 +24,23 @@ export default defineEventHandler(async (h3) => {
|
||||
statusMessage: "Token requires more than zero ACLs",
|
||||
});
|
||||
|
||||
const invalidACLs = acls.filter((e) => userACLs.findIndex((v) => e == v) == -1);
|
||||
if(invalidACLs.length > 0) throw createError({statusCode: 400, statusMessage: `Invalid ACLs: ${invalidACLs.join(", ")}`});
|
||||
const invalidACLs = acls.filter(
|
||||
(e) => userACLs.findIndex((v) => e == v) == -1,
|
||||
);
|
||||
if (invalidACLs.length > 0)
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: `Invalid ACLs: ${invalidACLs.join(", ")}`,
|
||||
});
|
||||
|
||||
const token = await prisma.aPIToken.create({
|
||||
data: {
|
||||
mode: APITokenMode.User,
|
||||
name: name,
|
||||
userId: userId,
|
||||
acls: acls,
|
||||
}
|
||||
})
|
||||
|
||||
return token;
|
||||
const token = await prisma.aPIToken.create({
|
||||
data: {
|
||||
mode: APITokenMode.User,
|
||||
name: name,
|
||||
userId: userId,
|
||||
acls: acls,
|
||||
},
|
||||
});
|
||||
|
||||
return token;
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { APITokenMode, User } from "@prisma/client";
|
||||
import { H3Context, H3Event } from "h3";
|
||||
import { APITokenMode } from "@prisma/client";
|
||||
import prisma from "../db/database";
|
||||
import sessionHandler from "../session";
|
||||
import type { MinimumRequestObject } from "~/server/h3";
|
||||
@@ -98,7 +97,7 @@ class ACLManager {
|
||||
if (!token) return undefined;
|
||||
if (!token.userId)
|
||||
throw new Error(
|
||||
"No userId on user or client token - is something broken?"
|
||||
"No userId on user or client token - is something broken?",
|
||||
);
|
||||
|
||||
for (const acl of acls) {
|
||||
@@ -124,7 +123,7 @@ class ACLManager {
|
||||
|
||||
async allowSystemACL(
|
||||
request: MinimumRequestObject | undefined,
|
||||
acls: SystemACL
|
||||
acls: SystemACL,
|
||||
) {
|
||||
if (!request)
|
||||
throw new Error("Native web requests not available - weird deployment?");
|
||||
@@ -157,13 +156,17 @@ class ACLManager {
|
||||
for (const acl of acls) {
|
||||
if (acl.startsWith(userACLPrefix)) {
|
||||
const rawACL = acl.substring(userACLPrefix.length);
|
||||
const userId = await this.getUserIdACL(request, [rawACL as any]);
|
||||
const userId = await this.getUserIdACL(request, [
|
||||
rawACL as UserACL[number],
|
||||
]);
|
||||
if (!userId) return false;
|
||||
}
|
||||
|
||||
if (acl.startsWith(systemACLPrefix)) {
|
||||
const rawACL = acl.substring(systemACLPrefix.length);
|
||||
const allowed = await this.allowSystemACL(request, [rawACL as any]);
|
||||
const allowed = await this.allowSystemACL(request, [
|
||||
rawACL as SystemACL[number],
|
||||
]);
|
||||
if (!allowed) return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import droplet from "@drop-oss/droplet";
|
||||
import type { CertificateStore} from "./ca-store";
|
||||
import { fsCertificateStore } from "./ca-store";
|
||||
import type { CertificateStore } from "./ca-store";
|
||||
|
||||
export type CertificateBundle = {
|
||||
priv: string;
|
||||
@@ -50,7 +47,7 @@ export class CertificateAuthority {
|
||||
clientId,
|
||||
clientName,
|
||||
caCertificate.cert,
|
||||
caCertificate.priv
|
||||
caCertificate.priv,
|
||||
);
|
||||
const certBundle: CertificateBundle = {
|
||||
priv,
|
||||
@@ -65,7 +62,7 @@ export class CertificateAuthority {
|
||||
|
||||
async fetchClientCertificate(clientId: string) {
|
||||
const isBlacklist = await this.certificateStore.checkBlacklistCertificate(
|
||||
`client:${clientId}`
|
||||
`client:${clientId}`,
|
||||
);
|
||||
if (isBlacklist) return undefined;
|
||||
return await this.certificateStore.fetch(`client:${clientId}`);
|
||||
|
||||
@@ -18,8 +18,8 @@ export const validCapabilities = Object.values(InternalClientCapability);
|
||||
|
||||
export type CapabilityConfiguration = {
|
||||
[InternalClientCapability.PeerAPI]: { endpoints: string[] };
|
||||
[InternalClientCapability.UserStatus]: {};
|
||||
[InternalClientCapability.CloudSaves]: {};
|
||||
[InternalClientCapability.UserStatus]: object;
|
||||
[InternalClientCapability.CloudSaves]: object;
|
||||
};
|
||||
|
||||
class CapabilityManager {
|
||||
@@ -53,7 +53,7 @@ class CapabilityManager {
|
||||
const serverCertificate = await ca.fetchClientCertificate("server");
|
||||
if (!serverCertificate)
|
||||
throw new Error(
|
||||
"CA not initialised properly - server mTLS certificate not present"
|
||||
"CA not initialised properly - server mTLS certificate not present",
|
||||
);
|
||||
const httpsAgent = new https.Agent({
|
||||
key: serverCertificate.priv,
|
||||
@@ -70,7 +70,9 @@ class CapabilityManager {
|
||||
});
|
||||
valid = true;
|
||||
break;
|
||||
} catch {}
|
||||
} catch {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
|
||||
return valid;
|
||||
@@ -81,7 +83,7 @@ class CapabilityManager {
|
||||
|
||||
async validateCapabilityConfiguration(
|
||||
capability: InternalClientCapability,
|
||||
configuration: object
|
||||
configuration: object,
|
||||
) {
|
||||
const validationFunction = this.validationFunctions[capability];
|
||||
if (!validationFunction) return false;
|
||||
@@ -91,7 +93,7 @@ class CapabilityManager {
|
||||
async upsertClientCapability(
|
||||
capability: InternalClientCapability,
|
||||
rawCapability: object,
|
||||
clientId: string
|
||||
clientId: string,
|
||||
) {
|
||||
const upsertFunctions: EnumDictionary<
|
||||
InternalClientCapability,
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useCertificateAuthority } from "~/server/plugins/ca";
|
||||
|
||||
export type EventHandlerFunction<T> = (
|
||||
h3: H3Event<EventHandlerRequest>,
|
||||
utils: ClientUtils
|
||||
utils: ClientUtils,
|
||||
) => Promise<T> | T;
|
||||
|
||||
type ClientUtils = {
|
||||
@@ -25,7 +25,7 @@ export function defineClientEventHandler<T>(handler: EventHandlerFunction<T>) {
|
||||
|
||||
let clientId: string;
|
||||
switch (method) {
|
||||
case "Debug":
|
||||
case "Debug": {
|
||||
if (!import.meta.dev) throw createError({ statusCode: 403 });
|
||||
const client = await prisma.client.findFirst({ select: { id: true } });
|
||||
if (!client)
|
||||
@@ -35,7 +35,8 @@ export function defineClientEventHandler<T>(handler: EventHandlerFunction<T>) {
|
||||
});
|
||||
clientId = client.id;
|
||||
break;
|
||||
case "Nonce":
|
||||
}
|
||||
case "Nonce": {
|
||||
clientId = parts[0];
|
||||
const nonce = parts[1];
|
||||
const signature = parts[2];
|
||||
@@ -59,9 +60,8 @@ export function defineClientEventHandler<T>(handler: EventHandlerFunction<T>) {
|
||||
}
|
||||
|
||||
const certificateAuthority = useCertificateAuthority();
|
||||
const certBundle = await certificateAuthority.fetchClientCertificate(
|
||||
clientId
|
||||
);
|
||||
const certBundle =
|
||||
await certificateAuthority.fetchClientCertificate(clientId);
|
||||
// This does the blacklist check already
|
||||
if (!certBundle)
|
||||
throw createError({
|
||||
@@ -76,11 +76,13 @@ export function defineClientEventHandler<T>(handler: EventHandlerFunction<T>) {
|
||||
statusMessage: "Invalid nonce signature.",
|
||||
});
|
||||
break;
|
||||
default:
|
||||
}
|
||||
default: {
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: "No authentication",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (clientId === undefined)
|
||||
@@ -95,7 +97,7 @@ export function defineClientEventHandler<T>(handler: EventHandlerFunction<T>) {
|
||||
});
|
||||
if (!client)
|
||||
throw new Error(
|
||||
"client util fetch client broke - this should NOT happen"
|
||||
"client util fetch client broke - this should NOT happen",
|
||||
);
|
||||
return client;
|
||||
}
|
||||
@@ -110,7 +112,7 @@ export function defineClientEventHandler<T>(handler: EventHandlerFunction<T>) {
|
||||
|
||||
if (!client)
|
||||
throw new Error(
|
||||
"client util fetch client broke - this should NOT happen"
|
||||
"client util fetch client broke - this should NOT happen",
|
||||
);
|
||||
|
||||
return client.user;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { CertificateBundle } from "./ca";
|
||||
import prisma from "../db/database";
|
||||
import type { Platform } from "@prisma/client";
|
||||
import { useCertificateAuthority } from "~/server/plugins/ca";
|
||||
@@ -10,25 +9,29 @@ export interface ClientMetadata {
|
||||
}
|
||||
|
||||
export class ClientHandler {
|
||||
private temporaryClientTable: {
|
||||
[key: string]: {
|
||||
private temporaryClientTable = new Map<
|
||||
string,
|
||||
{
|
||||
timeout: NodeJS.Timeout;
|
||||
data: ClientMetadata;
|
||||
userId?: string;
|
||||
authToken?: string;
|
||||
};
|
||||
} = {};
|
||||
}
|
||||
>();
|
||||
|
||||
async initiate(metadata: ClientMetadata) {
|
||||
const clientId = randomUUID();
|
||||
|
||||
this.temporaryClientTable[clientId] = {
|
||||
this.temporaryClientTable.set(clientId, {
|
||||
data: metadata,
|
||||
timeout: setTimeout(() => {
|
||||
if (this.temporaryClientTable[clientId])
|
||||
delete this.temporaryClientTable[clientId];
|
||||
}, 1000 * 60 * 10), // 10 minutes
|
||||
};
|
||||
timeout: setTimeout(
|
||||
() => {
|
||||
if (this.temporaryClientTable.has(clientId))
|
||||
this.temporaryClientTable.delete(clientId);
|
||||
},
|
||||
1000 * 60 * 10,
|
||||
), // 10 minutes
|
||||
});
|
||||
|
||||
return clientId;
|
||||
}
|
||||
@@ -38,23 +41,23 @@ export class ClientHandler {
|
||||
}
|
||||
|
||||
async fetchClient(clientId: string) {
|
||||
const entry = this.temporaryClientTable[clientId];
|
||||
const entry = this.temporaryClientTable.get(clientId);
|
||||
if (!entry) return undefined;
|
||||
return entry;
|
||||
}
|
||||
|
||||
async attachUserId(clientId: string, userId: string) {
|
||||
if (!this.temporaryClientTable[clientId])
|
||||
throw new Error("Invalid clientId for attaching userId");
|
||||
this.temporaryClientTable[clientId].userId = userId;
|
||||
const clientTable = this.temporaryClientTable.get(clientId);
|
||||
if (!clientTable) throw new Error("Invalid clientId for attaching userId");
|
||||
clientTable.userId = userId;
|
||||
}
|
||||
|
||||
async generateAuthToken(clientId: string) {
|
||||
const entry = this.temporaryClientTable[clientId];
|
||||
const entry = this.temporaryClientTable.get(clientId);
|
||||
if (!entry) throw new Error("Invalid clientId to generate token");
|
||||
|
||||
const token = randomUUID();
|
||||
this.temporaryClientTable[clientId].authToken = token;
|
||||
entry.authToken = token;
|
||||
|
||||
return token;
|
||||
}
|
||||
@@ -66,7 +69,7 @@ export class ClientHandler {
|
||||
}
|
||||
|
||||
async finialiseClient(id: string) {
|
||||
const metadata = this.temporaryClientTable[id];
|
||||
const metadata = this.temporaryClientTable.get(id);
|
||||
if (!metadata) throw new Error("Invalid client ID");
|
||||
if (!metadata.userId) throw new Error("Un-authorized client ID");
|
||||
|
||||
|
||||
@@ -5,6 +5,5 @@ When a client signs on and registers itself as a peer
|
||||
|
||||
*/
|
||||
|
||||
class DownloadCoordinator {
|
||||
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-extraneous-class, @typescript-eslint/no-unused-vars
|
||||
class DownloadCoordinator {}
|
||||
|
||||
@@ -33,7 +33,7 @@ class ManifestGenerator {
|
||||
key,
|
||||
Object.assign({}, value, { versionName: rootManifest.versionName }),
|
||||
];
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ class ManifestGenerator {
|
||||
if (baseVersion.delta) {
|
||||
// Start at the same index minus one, and keep grabbing them
|
||||
// until we run out or we hit something that isn't a delta
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
for (let i = baseVersion.versionIndex - 1; true; i--) {
|
||||
const currentVersion = await prisma.gameVersion.findFirst({
|
||||
where: {
|
||||
@@ -88,7 +89,7 @@ class ManifestGenerator {
|
||||
const metadata: DropManifestMetadata[] = leastToMost.map((e) => {
|
||||
return {
|
||||
manifest: JSON.parse(
|
||||
e.dropletManifest?.toString() ?? "{}"
|
||||
e.dropletManifest?.toString() ?? "{}",
|
||||
) as DropManifest,
|
||||
versionName: e.versionName,
|
||||
};
|
||||
@@ -96,7 +97,7 @@ class ManifestGenerator {
|
||||
|
||||
const manifest = ManifestGenerator.generateManifestFromMetadata(
|
||||
metadata[0],
|
||||
...metadata.slice(1)
|
||||
...metadata.slice(1),
|
||||
);
|
||||
|
||||
return manifest;
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import prisma from "../db/database";
|
||||
import type { GameVersion} from "@prisma/client";
|
||||
import { Platform } from "@prisma/client";
|
||||
import type { GameVersion } from "@prisma/client";
|
||||
import { fuzzy } from "fast-fuzzy";
|
||||
import { recursivelyReaddir } from "../utils/recursivedirs";
|
||||
import taskHandler from "../tasks";
|
||||
@@ -52,13 +51,13 @@ class LibraryManager {
|
||||
|
||||
async fetchUnimportedGameVersions(
|
||||
libraryBasePath: string,
|
||||
versions: Array<GameVersion>
|
||||
versions: Array<GameVersion>,
|
||||
) {
|
||||
const gameDir = path.join(this.basePath, libraryBasePath);
|
||||
const versionsDirs = fs.readdirSync(gameDir);
|
||||
const importedVersionDirs = versions.map((e) => e.versionName);
|
||||
const unimportedVersions = versionsDirs.filter(
|
||||
(e) => !importedVersionDirs.includes(e)
|
||||
(e) => !importedVersionDirs.includes(e),
|
||||
);
|
||||
|
||||
return unimportedVersions;
|
||||
@@ -89,10 +88,10 @@ class LibraryManager {
|
||||
noVersions: e.versions.length == 0,
|
||||
unimportedVersions: await this.fetchUnimportedGameVersions(
|
||||
e.libraryBasePath,
|
||||
e.versions
|
||||
e.versions,
|
||||
),
|
||||
},
|
||||
}))
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -113,7 +112,7 @@ class LibraryManager {
|
||||
const targetDir = path.join(this.basePath, game.libraryBasePath);
|
||||
if (!fs.existsSync(targetDir))
|
||||
throw new Error(
|
||||
"Game in database, but no physical directory? Something is very very wrong..."
|
||||
"Game in database, but no physical directory? Something is very very wrong...",
|
||||
);
|
||||
const versions = fs.readdirSync(targetDir);
|
||||
const validVersions = versions.filter((versionDir) => {
|
||||
@@ -124,7 +123,7 @@ class LibraryManager {
|
||||
const currentVersions = game.versions.map((e) => e.versionName);
|
||||
|
||||
const unimportedVersions = validVersions.filter(
|
||||
(e) => !currentVersions.includes(e)
|
||||
(e) => !currentVersions.includes(e),
|
||||
);
|
||||
return unimportedVersions;
|
||||
}
|
||||
@@ -138,7 +137,7 @@ class LibraryManager {
|
||||
const targetDir = path.join(
|
||||
this.basePath,
|
||||
game.libraryBasePath,
|
||||
versionName
|
||||
versionName,
|
||||
);
|
||||
if (!fs.existsSync(targetDir)) return undefined;
|
||||
|
||||
@@ -217,7 +216,7 @@ class LibraryManager {
|
||||
delta: boolean;
|
||||
|
||||
umuId: string;
|
||||
}
|
||||
},
|
||||
) {
|
||||
const taskId = `import:${gameId}:${versionName}`;
|
||||
|
||||
@@ -254,7 +253,7 @@ class LibraryManager {
|
||||
(err, manifest) => {
|
||||
if (err) return reject(err);
|
||||
resolve(manifest);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import type {
|
||||
Developer,
|
||||
Publisher} from "@prisma/client";
|
||||
import {
|
||||
MetadataSource,
|
||||
PrismaClient
|
||||
} from "@prisma/client";
|
||||
import type { Developer, Publisher } from "@prisma/client";
|
||||
import { MetadataSource } from "@prisma/client";
|
||||
import prisma from "../db/database";
|
||||
import type {
|
||||
_FetchDeveloperMetadataParams,
|
||||
@@ -17,11 +12,7 @@ import type {
|
||||
PublisherMetadata,
|
||||
} from "./types";
|
||||
import { ObjectTransactionalHandler } from "../objects/transactional";
|
||||
import { PriorityList, PriorityListIndexed } from "../utils/prioritylist";
|
||||
import { GiantBombProvider } from "./giantbomb";
|
||||
import { ManualMetadataProvider } from "./manual";
|
||||
import { PCGamingWikiProvider } from "./pcgamingwiki";
|
||||
import { IGDBProvider } from "./igdb";
|
||||
import { PriorityListIndexed } from "../utils/prioritylist";
|
||||
|
||||
export class MissingMetadataProviderConfig extends Error {
|
||||
private providerName: string;
|
||||
@@ -47,10 +38,10 @@ export abstract class MetadataProvider {
|
||||
abstract search(query: string): Promise<GameMetadataSearchResult[]>;
|
||||
abstract fetchGame(params: _FetchGameMetadataParams): Promise<GameMetadata>;
|
||||
abstract fetchPublisher(
|
||||
params: _FetchPublisherMetadataParams
|
||||
params: _FetchPublisherMetadataParams,
|
||||
): Promise<PublisherMetadata>;
|
||||
abstract fetchDeveloper(
|
||||
params: _FetchDeveloperMetadataParams
|
||||
params: _FetchDeveloperMetadataParams,
|
||||
): Promise<DeveloperMetadata>;
|
||||
}
|
||||
|
||||
@@ -81,6 +72,8 @@ export class MetadataHandler {
|
||||
for (const provider of this.providers.values()) {
|
||||
const queryTransformationPromise = new Promise<
|
||||
InternalGameMetadataResult[]
|
||||
// TODO: fix eslint error
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
>(async (resolve, reject) => {
|
||||
try {
|
||||
const results = await provider.search(query);
|
||||
@@ -89,7 +82,7 @@ export class MetadataHandler {
|
||||
Object.assign({}, result, {
|
||||
sourceId: provider.id(),
|
||||
sourceName: provider.name(),
|
||||
})
|
||||
}),
|
||||
);
|
||||
resolve(mappedResults);
|
||||
} catch (e) {
|
||||
@@ -119,13 +112,13 @@ export class MetadataHandler {
|
||||
sourceId: "manual",
|
||||
sourceName: "Manual",
|
||||
},
|
||||
libraryBasePath
|
||||
libraryBasePath,
|
||||
);
|
||||
}
|
||||
|
||||
async createGame(
|
||||
result: InternalGameMetadataResult,
|
||||
libraryBasePath: string
|
||||
libraryBasePath: string,
|
||||
) {
|
||||
const provider = this.providers.get(result.sourceId);
|
||||
if (!provider)
|
||||
@@ -143,7 +136,7 @@ export class MetadataHandler {
|
||||
|
||||
const [createObject, pullObjects, dumpObjects] = this.objectHandler.new(
|
||||
{},
|
||||
["internal:read"]
|
||||
["internal:read"],
|
||||
);
|
||||
|
||||
let metadata;
|
||||
@@ -197,7 +190,7 @@ export class MetadataHandler {
|
||||
return (await this.fetchDeveloperPublisher(
|
||||
query,
|
||||
"fetchDeveloper",
|
||||
"developer"
|
||||
"developer",
|
||||
)) as Developer;
|
||||
}
|
||||
|
||||
@@ -205,7 +198,7 @@ export class MetadataHandler {
|
||||
return (await this.fetchDeveloperPublisher(
|
||||
query,
|
||||
"fetchPublisher",
|
||||
"publisher"
|
||||
"publisher",
|
||||
)) as Publisher;
|
||||
}
|
||||
|
||||
@@ -214,8 +207,9 @@ export class MetadataHandler {
|
||||
private async fetchDeveloperPublisher(
|
||||
query: string,
|
||||
functionName: "fetchDeveloper" | "fetchPublisher",
|
||||
databaseName: "developer" | "publisher"
|
||||
databaseName: "developer" | "publisher",
|
||||
) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const existing = await (prisma as any)[databaseName].findFirst({
|
||||
where: {
|
||||
metadataOriginalQuery: query,
|
||||
@@ -229,7 +223,7 @@ export class MetadataHandler {
|
||||
|
||||
const [createObject, pullObjects, dumpObjects] = this.objectHandler.new(
|
||||
{},
|
||||
["internal:read"]
|
||||
["internal:read"],
|
||||
);
|
||||
let result: PublisherMetadata;
|
||||
try {
|
||||
@@ -243,6 +237,7 @@ export class MetadataHandler {
|
||||
// If we're successful
|
||||
await pullObjects();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const object = await (prisma as any)[databaseName].create({
|
||||
data: {
|
||||
metadataSource: provider.source(),
|
||||
@@ -262,7 +257,7 @@ export class MetadataHandler {
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`No metadata provider found a ${databaseName} for "${query}"`
|
||||
`No metadata provider found a ${databaseName} for "${query}"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,7 @@ import type {
|
||||
_FetchPublisherMetadataParams,
|
||||
PublisherMetadata,
|
||||
_FetchDeveloperMetadataParams,
|
||||
DeveloperMetadata} from "./types";
|
||||
import {
|
||||
GameMetadataSearchResult
|
||||
DeveloperMetadata,
|
||||
} from "./types";
|
||||
import * as jdenticon from "jdenticon";
|
||||
|
||||
@@ -22,13 +20,11 @@ export class ManualMetadataProvider implements MetadataProvider {
|
||||
source() {
|
||||
return MetadataSource.Manual;
|
||||
}
|
||||
async search(query: string) {
|
||||
async search(_query: string) {
|
||||
return [];
|
||||
}
|
||||
async fetchGame({
|
||||
name,
|
||||
publisher,
|
||||
developer,
|
||||
createObject,
|
||||
}: _FetchGameMetadataParams): Promise<GameMetadata> {
|
||||
const icon = jdenticon.toPng(name, 512);
|
||||
@@ -52,12 +48,12 @@ export class ManualMetadataProvider implements MetadataProvider {
|
||||
};
|
||||
}
|
||||
async fetchPublisher(
|
||||
params: _FetchPublisherMetadataParams
|
||||
_params: _FetchPublisherMetadataParams,
|
||||
): Promise<PublisherMetadata> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
async fetchDeveloper(
|
||||
params: _FetchDeveloperMetadataParams
|
||||
_params: _FetchDeveloperMetadataParams,
|
||||
): Promise<DeveloperMetadata> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { Developer, Publisher } from "@prisma/client";
|
||||
import { MetadataSource } from "@prisma/client";
|
||||
import type { MetadataProvider} from ".";
|
||||
import { MissingMetadataProviderConfig } from ".";
|
||||
import type { MetadataProvider } from ".";
|
||||
import type {
|
||||
GameMetadataSearchResult,
|
||||
_FetchGameMetadataParams,
|
||||
@@ -48,7 +47,7 @@ interface PCGamingWikiCargoResult<T> {
|
||||
cargoquery: [
|
||||
{
|
||||
title: T;
|
||||
}
|
||||
},
|
||||
];
|
||||
error?: {
|
||||
code?: string;
|
||||
@@ -61,8 +60,6 @@ interface PCGamingWikiCargoResult<T> {
|
||||
// Api Docs: https://www.pcgamingwiki.com/wiki/PCGamingWiki:API
|
||||
// Good tool for helping build cargo queries: https://www.pcgamingwiki.com/wiki/Special:CargoQuery
|
||||
export class PCGamingWikiProvider implements MetadataProvider {
|
||||
constructor() {}
|
||||
|
||||
id() {
|
||||
return "pcgamingwiki";
|
||||
}
|
||||
@@ -75,7 +72,7 @@ export class PCGamingWikiProvider implements MetadataProvider {
|
||||
|
||||
private async request<T>(
|
||||
query: URLSearchParams,
|
||||
options?: AxiosRequestConfig
|
||||
options?: AxiosRequestConfig,
|
||||
) {
|
||||
const finalURL = `https://www.pcgamingwiki.com/w/api.php?${query.toString()}`;
|
||||
|
||||
@@ -84,12 +81,12 @@ export class PCGamingWikiProvider implements MetadataProvider {
|
||||
baseURL: "",
|
||||
};
|
||||
const response = await axios.request<PCGamingWikiCargoResult<T>>(
|
||||
Object.assign({}, options, overlay)
|
||||
Object.assign({}, options, overlay),
|
||||
);
|
||||
|
||||
if (response.status !== 200)
|
||||
throw new Error(
|
||||
`Error in pcgamingwiki \nStatus Code: ${response.status}`
|
||||
`Error in pcgamingwiki \nStatus Code: ${response.status}`,
|
||||
);
|
||||
else if (response.data.error !== undefined)
|
||||
throw new Error(`Error in pcgamingwiki, malformed query`);
|
||||
@@ -256,7 +253,7 @@ export class PCGamingWikiProvider implements MetadataProvider {
|
||||
}
|
||||
|
||||
async fetchDeveloper(
|
||||
params: _FetchDeveloperMetadataParams
|
||||
params: _FetchDeveloperMetadataParams,
|
||||
): Promise<DeveloperMetadata> {
|
||||
return await this.fetchPublisher(params);
|
||||
}
|
||||
|
||||
1
server/internal/metadata/types.d.ts
vendored
1
server/internal/metadata/types.d.ts
vendored
@@ -1,6 +1,5 @@
|
||||
import type { Developer, Publisher } from "@prisma/client";
|
||||
import type { TransactionDataType } from "../objects/transactional";
|
||||
import { ObjectTransactionalHandler } from "../objects/transactional";
|
||||
import type { ObjectReference } from "../objects/objectHandler";
|
||||
|
||||
export interface GameMetadataSearchResult {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { triggerAsyncId } from "async_hooks";
|
||||
import prisma from "../db/database";
|
||||
import objectHandler from "../objects";
|
||||
|
||||
@@ -50,7 +49,7 @@ class NewsManager {
|
||||
orderBy?: "asc" | "desc";
|
||||
tags?: string[];
|
||||
search?: string;
|
||||
} = {}
|
||||
} = {},
|
||||
) {
|
||||
return await prisma.article.findMany({
|
||||
where: {
|
||||
@@ -116,7 +115,7 @@ class NewsManager {
|
||||
content?: string;
|
||||
excerpt?: string;
|
||||
image?: string;
|
||||
}
|
||||
},
|
||||
) {
|
||||
return await prisma.article.update({
|
||||
where: { id },
|
||||
|
||||
@@ -15,27 +15,28 @@ export type NotificationCreateArgs = Pick<
|
||||
>;
|
||||
|
||||
class NotificationSystem {
|
||||
private listeners: {
|
||||
[key: string]: Map<string, (notification: Notification) => any>;
|
||||
} = {};
|
||||
private listeners = new Map<
|
||||
string,
|
||||
Map<string, (notification: Notification) => void>
|
||||
>();
|
||||
|
||||
listen(
|
||||
userId: string,
|
||||
id: string,
|
||||
callback: (notification: Notification) => any
|
||||
callback: (notification: Notification) => void,
|
||||
) {
|
||||
this.listeners[userId] ??= new Map();
|
||||
this.listeners[userId].set(id, callback);
|
||||
this.listeners.set(userId, new Map());
|
||||
this.listeners.get(userId)?.set(id, callback);
|
||||
|
||||
this.catchupListener(userId, id);
|
||||
}
|
||||
|
||||
unlisten(userId: string, id: string) {
|
||||
this.listeners[userId].delete(id);
|
||||
this.listeners.get(userId)?.delete(id);
|
||||
}
|
||||
|
||||
private async catchupListener(userId: string, id: string) {
|
||||
const callback = this.listeners[userId].get(id);
|
||||
const callback = this.listeners.get(userId)?.get(id);
|
||||
if (!callback)
|
||||
throw new Error("Failed to catch-up listener: callback does not exist");
|
||||
const notifications = await prisma.notification.findMany({
|
||||
@@ -50,7 +51,7 @@ class NotificationSystem {
|
||||
}
|
||||
|
||||
private async pushNotification(userId: string, notification: Notification) {
|
||||
for (const listener of this.listeners[userId] ?? []) {
|
||||
for (const listener of this.listeners.get(userId) ?? []) {
|
||||
await listener[1](notification);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ObjectBackend } from "./objectHandler";
|
||||
import { LRUCache } from "lru-cache";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { Readable, Stream } from "stream";
|
||||
import { Readable } from "stream";
|
||||
import { createHash } from "crypto";
|
||||
import prisma from "../db/database";
|
||||
|
||||
@@ -40,7 +40,7 @@ export class FsObjectBackend extends ObjectBackend {
|
||||
if (source instanceof Readable) {
|
||||
const outputStream = fs.createWriteStream(objectPath);
|
||||
source.pipe(outputStream, { end: true });
|
||||
await new Promise((r, j) => source.on("end", r));
|
||||
await new Promise((r, _j) => source.on("end", r));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ export class FsObjectBackend extends ObjectBackend {
|
||||
async create(
|
||||
id: string,
|
||||
source: Source,
|
||||
metadata: ObjectMetadata
|
||||
metadata: ObjectMetadata,
|
||||
): Promise<ObjectReference | undefined> {
|
||||
const objectPath = path.join(this.baseObjectPath, id);
|
||||
const metadataPath = path.join(this.baseMetadataPath, `${id}.json`);
|
||||
@@ -104,7 +104,7 @@ export class FsObjectBackend extends ObjectBackend {
|
||||
return true;
|
||||
}
|
||||
async fetchMetadata(
|
||||
id: ObjectReference
|
||||
id: ObjectReference,
|
||||
): Promise<ObjectMetadata | undefined> {
|
||||
const metadataPath = path.join(this.baseMetadataPath, `${id}.json`);
|
||||
if (!fs.existsSync(metadataPath)) return undefined;
|
||||
@@ -113,7 +113,7 @@ export class FsObjectBackend extends ObjectBackend {
|
||||
}
|
||||
async writeMetadata(
|
||||
id: ObjectReference,
|
||||
metadata: ObjectMetadata
|
||||
metadata: ObjectMetadata,
|
||||
): Promise<boolean> {
|
||||
const metadataPath = path.join(this.baseMetadataPath, `${id}.json`);
|
||||
if (!fs.existsSync(metadataPath)) return false;
|
||||
@@ -153,8 +153,6 @@ class FsHashStore {
|
||||
max: 1000, // number of items
|
||||
});
|
||||
|
||||
constructor() {}
|
||||
|
||||
/**
|
||||
* Gets hash of object
|
||||
* @param id
|
||||
@@ -211,6 +209,8 @@ class FsHashStore {
|
||||
id,
|
||||
},
|
||||
});
|
||||
} catch {}
|
||||
} catch {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import { parse as getMimeTypeBuffer } from "file-type-mime";
|
||||
import type { Writable } from "stream";
|
||||
import Stream, { Readable } from "stream";
|
||||
import { Readable } from "stream";
|
||||
import { getMimeType as getMimeTypeStream } from "stream-mime-type";
|
||||
|
||||
export type ObjectReference = string;
|
||||
@@ -50,19 +50,19 @@ export abstract class ObjectBackend {
|
||||
abstract create(
|
||||
id: string,
|
||||
source: Source,
|
||||
metadata: ObjectMetadata
|
||||
metadata: ObjectMetadata,
|
||||
): Promise<ObjectReference | undefined>;
|
||||
abstract createWithWriteStream(
|
||||
id: string,
|
||||
metadata: ObjectMetadata
|
||||
metadata: ObjectMetadata,
|
||||
): Promise<Writable | undefined>;
|
||||
abstract delete(id: ObjectReference): Promise<boolean>;
|
||||
abstract fetchMetadata(
|
||||
id: ObjectReference
|
||||
id: ObjectReference,
|
||||
): Promise<ObjectMetadata | undefined>;
|
||||
abstract writeMetadata(
|
||||
id: ObjectReference,
|
||||
metadata: ObjectMetadata
|
||||
metadata: ObjectMetadata,
|
||||
): Promise<boolean>;
|
||||
abstract fetchHash(id: ObjectReference): Promise<string | undefined>;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ export class ObjectHandler {
|
||||
id: string,
|
||||
sourceFetcher: () => Promise<Source>,
|
||||
metadata: { [key: string]: string },
|
||||
permissions: Array<string>
|
||||
permissions: Array<string>,
|
||||
) {
|
||||
const { source, mime } = await this.fetchMimeType(await sourceFetcher());
|
||||
if (!mime)
|
||||
@@ -112,7 +112,7 @@ export class ObjectHandler {
|
||||
async createWithStream(
|
||||
id: string,
|
||||
metadata: { [key: string]: string },
|
||||
permissions: Array<string>
|
||||
permissions: Array<string>,
|
||||
) {
|
||||
return this.backend.createWithWriteStream(id, {
|
||||
permissions,
|
||||
@@ -194,7 +194,7 @@ export class ObjectHandler {
|
||||
async writeWithPermissions(
|
||||
id: ObjectReference,
|
||||
sourceFetcher: () => Promise<Source>,
|
||||
userId?: string
|
||||
userId?: string,
|
||||
) {
|
||||
const metadata = await this.backend.fetchMetadata(id);
|
||||
if (!metadata) return false;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import prisma from "../internal/db/database";
|
||||
|
||||
export default defineNitroPlugin(async () => {
|
||||
export default defineNitroPlugin(async (_nitro) => {
|
||||
// Ensure system user exists
|
||||
// The system user owns any user-based code
|
||||
// that we want to re-use for the app
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import prisma from "../internal/db/database";
|
||||
|
||||
export default defineNitroPlugin(async () => {
|
||||
export default defineNitroPlugin(async (_nitro) => {
|
||||
const userCount = await prisma.user.count({
|
||||
where: { id: { not: "system" } },
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import { IGDBProvider } from "../internal/metadata/igdb";
|
||||
import { ManualMetadataProvider } from "../internal/metadata/manual";
|
||||
import { PCGamingWikiProvider } from "../internal/metadata/pcgamingwiki";
|
||||
|
||||
export default defineNitroPlugin(async () => {
|
||||
export default defineNitroPlugin(async (_nitro) => {
|
||||
const metadataProviders = [
|
||||
GiantBombProvider,
|
||||
PCGamingWikiProvider,
|
||||
|
||||
Reference in New Issue
Block a user