import { TRPCError } from "@trpc/server"; import type { UsersId } from "~/schemas/public/Users"; import type { NewUsersStorage } from "~/schemas/public/UsersStorage"; import { db, type Querier } from "~/server/db"; import { fetchFiles, retriveFilesSafely } from "../services/storage.service"; export const getMultipleWithRelations = async ({ db, ids, }: { db: Querier; ids: string[]; }) => { const files = await fetchFiles(); const userStorage = await db .selectFrom("users_storage") .selectAll("users_storage") .innerJoin("users", "users.id", "users_storage.userId") .select("users.username") .where( "storageId", "in", files.map((f) => f.id), ) .execute(); return ids .map((id) => { const file = files.find((f) => f.id === id); if (!file) return null; const users = userStorage .filter((us) => us.storageId === id) .map((us) => ({ id: us.userId, username: us.username, })); return { ...file, users, }; }) .filter((f) => f !== null); }; export const retrieveUserFiles = async ({ userId }: { userId: UsersId }) => { try { //all files linked to the user const files = await db .selectFrom("users_storage") .select(["storageId", "from_admin"]) .where("userId", "=", userId) .execute(); const { available, unavailable } = await retriveFilesSafely( files.map((f) => f.storageId), ); //remove entries in users_storage for files that no longer exist in storage await db .deleteFrom("users_storage") .where("userId", "=", userId) .where("storageId", "in", unavailable) .execute(); //merge file metadata with users_storage info const userFiles = files .map((uf) => { const file = available.find((f) => f.id === uf.storageId); if (!file) return null; return { ...file, from_admin: uf.from_admin, }; }) .filter((f) => f !== null); return userFiles; } catch (e) { throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: `Error while getting user storage: ${(e as Error).message}`, }); } }; export const getAllWithFromAdmin = async () => { try { const files = await db .selectFrom("users_storage") .select(["storageId", "from_admin"]) .execute(); const allFiles = await fetchFiles(); const allFilesWithFromAdmin = allFiles.map((file) => { const userStorageEntry = files.find((f) => f.storageId === file.id); return { ...file, from_admin: userStorageEntry ? userStorageEntry.from_admin : true, }; }); return allFilesWithFromAdmin; } catch (e) { throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: `Error while getting user storage: ${(e as Error).message}`, }); } }; export const addUserStorage = async (data: NewUsersStorage) => { try { return await db .insertInto("users_storage") .values(data) .onConflict((oc) => oc.columns(["userId", "storageId"]).doNothing()) .returning("user_storage_id") .executeTakeFirstOrThrow(); } catch (e) { throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: `Error while adding user storage: ${(e as Error).message}`, }); } }; export const deleteUserStorageEntry = async ({ userId, storageId, }: { userId: UsersId; storageId: string; }) => { try { await db .deleteFrom("users_storage") .where("userId", "=", userId) .where("storageId", "=", storageId) .execute(); return "ok"; } catch (e) { throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: `Error while deleting user storage: ${(e as Error).message}`, }); } }; export const purgeFileFromUserStorages = async ({ storageId, }: { storageId: string; }) => { try { await db .deleteFrom("users_storage") .where("storageId", "=", storageId) .execute(); return "ok"; } catch (e) { throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: `Error while deleting user storage: ${(e as Error).message}`, }); } };