fix: incorrect perms when deleting objects

This commit is contained in:
Huskydog9988
2025-04-11 19:32:30 -04:00
parent dc89ff95d8
commit 228d109692
5 changed files with 39 additions and 12 deletions

View File

@ -35,7 +35,7 @@ export default defineEventHandler(async (h3) => {
throw createError({ statusCode: 400, statusMessage: "Image not found" }); throw createError({ statusCode: 400, statusMessage: "Image not found" });
game.mImageLibrary.splice(imageIndex, 1); game.mImageLibrary.splice(imageIndex, 1);
await objectHandler.deleteWithPermission(imageId); await objectHandler.deleteAsServer(imageId);
if (game.mBannerId === imageId) { if (game.mBannerId === imageId) {
game.mBannerId = game.mImageLibrary[0]; game.mBannerId = game.mImageLibrary[0];

View File

@ -5,7 +5,6 @@ import * as jdenticon from "jdenticon";
import objectHandler from "~/server/internal/objects"; import objectHandler from "~/server/internal/objects";
import { type } from "arktype"; import { type } from "arktype";
import { randomUUID } from "node:crypto"; import { randomUUID } from "node:crypto";
import { writeNonLiteralDefaultMessage } from "arktype/internal/parser/shift/operator/default.ts";
const userValidator = type({ const userValidator = type({
username: "string >= 5", username: "string >= 5",
@ -64,7 +63,7 @@ export default defineEventHandler(async (h3) => {
profilePictureId, profilePictureId,
async () => jdenticon.toPng(user.username, 256), async () => jdenticon.toPng(user.username, 256),
{}, {},
[`internal:read`, `${userId}:delete`] [`internal:read`, `${userId}:read`]
); );
const [linkMec] = await prisma.$transaction([ const [linkMec] = await prisma.$transaction([
prisma.linkedAuthMec.create({ prisma.linkedAuthMec.create({

View File

@ -129,7 +129,7 @@ class NewsManager {
where: { id }, where: { id },
}); });
if (article.image) { if (article.image) {
return await objectHandler.deleteWithPermission(article.image); return await objectHandler.deleteAsServer(article.image);
} }
return true; return true;
} }

View File

@ -122,8 +122,8 @@ export class ObjectHandler {
/** /**
* Fetches object, but also checks if user has perms to access it * Fetches object, but also checks if user has perms to access it
* @param id * @param id object id
* @param userId * @param userId user to check, or act as anon user
* @returns * @returns
*/ */
async fetchWithPermissions(id: ObjectReference, userId?: string) { async fetchWithPermissions(id: ObjectReference, userId?: string) {
@ -154,6 +154,12 @@ export class ObjectHandler {
return object; return object;
} }
/**
* Fetch object hash, but also checks if user has perms to access it
* @param id object id
* @param userId user to check, or act as anon user
* @returns
*/
async fetchHashWithWithPermissions(id: ObjectReference, userId?: string) { async fetchHashWithWithPermissions(id: ObjectReference, userId?: string) {
const metadata = await this.backend.fetchMetadata(id); const metadata = await this.backend.fetchMetadata(id);
if (!metadata) return; if (!metadata) return;
@ -176,11 +182,18 @@ export class ObjectHandler {
return await this.backend.fetchHash(id); return await this.backend.fetchHash(id);
} }
// If we need to fetch a remote resource, it doesn't make sense /**
// to immediately fetch the object, *then* check permissions. *
// Instead the caller can pass a simple anonymous funciton, like * @param id object id
// () => $dropFetch('/my-image'); * @param sourceFetcher callback used to provide image
// And if we actually have permission to write, it fetches it then. * @param userId user to check, or act as anon user
* @returns
* @description If we need to fetch a remote resource, it doesn't make sense
* to immediately fetch the object, *then* check permissions.
* Instead the caller can pass a simple anonymous funciton, like
* () => $dropFetch('/my-image');
* And if we actually have permission to write, it fetches it then.
*/
async writeWithPermissions( async writeWithPermissions(
id: ObjectReference, id: ObjectReference,
sourceFetcher: () => Promise<Source>, sourceFetcher: () => Promise<Source>,
@ -213,6 +226,12 @@ export class ObjectHandler {
return result; return result;
} }
/**
*
* @param id object id
* @param userId user to check, or act as anon user
* @returns
*/
async deleteWithPermission(id: ObjectReference, userId?: string) { async deleteWithPermission(id: ObjectReference, userId?: string) {
const metadata = await this.backend.fetchMetadata(id); const metadata = await this.backend.fetchMetadata(id);
if (!metadata) return false; if (!metadata) return false;
@ -238,4 +257,13 @@ export class ObjectHandler {
const result = await this.backend.delete(id); const result = await this.backend.delete(id);
return result; return result;
} }
/**
* Deletes object without checking permission
* @param id
* @returns
*/
async deleteAsServer(id: ObjectReference) {
return await this.backend.delete(id);
}
} }

View File

@ -62,7 +62,7 @@ class SaveManager {
await Promise.all([hashPromise, uploadStream]); await Promise.all([hashPromise, uploadStream]);
if (!hash) { if (!hash) {
await objectHandler.deleteWithPermission(newSaveObjectId, userId); await objectHandler.deleteAsServer(newSaveObjectId);
throw createError({ throw createError({
statusCode: 500, statusCode: 500,
statusMessage: "Hash failed to generate", statusMessage: "Hash failed to generate",