mirror of
https://github.com/Drop-OSS/drop.git
synced 2025-11-22 04:31:15 +10:00
fix: add no-prisma-delete lint
This commit is contained in:
@ -2,6 +2,7 @@
|
|||||||
import withNuxt from "./.nuxt/eslint.config.mjs";
|
import withNuxt from "./.nuxt/eslint.config.mjs";
|
||||||
import eslintConfigPrettier from "eslint-config-prettier/flat";
|
import eslintConfigPrettier from "eslint-config-prettier/flat";
|
||||||
import vueI18n from "@intlify/eslint-plugin-vue-i18n";
|
import vueI18n from "@intlify/eslint-plugin-vue-i18n";
|
||||||
|
import noPrismaDelete from "./rules/no-prisma-delete.mts";
|
||||||
|
|
||||||
export default withNuxt([
|
export default withNuxt([
|
||||||
eslintConfigPrettier,
|
eslintConfigPrettier,
|
||||||
@ -19,6 +20,7 @@ export default withNuxt([
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
"@intlify/vue-i18n/no-missing-keys": "error",
|
"@intlify/vue-i18n/no-missing-keys": "error",
|
||||||
|
"drop/no-prisma-delete": "error",
|
||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
"vue-i18n": {
|
"vue-i18n": {
|
||||||
@ -29,5 +31,8 @@ export default withNuxt([
|
|||||||
messageSyntaxVersion: "^11.0.0",
|
messageSyntaxVersion: "^11.0.0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
plugins: {
|
||||||
|
drop: { rules: { "no-prisma-delete": noPrismaDelete } },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
32
rules/no-prisma-delete.mts
Normal file
32
rules/no-prisma-delete.mts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import type { TSESLint } from "@typescript-eslint/utils";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
meta: {
|
||||||
|
type: "problem",
|
||||||
|
docs: {
|
||||||
|
description: "Don't use Prisma error-prone .delete function",
|
||||||
|
},
|
||||||
|
messages: {
|
||||||
|
noPrismaDelete:
|
||||||
|
"Prisma .delete(...) function is used. Use .deleteMany(..) and check count instead.",
|
||||||
|
},
|
||||||
|
schema: [],
|
||||||
|
},
|
||||||
|
create(context) {
|
||||||
|
return {
|
||||||
|
CallExpression: function (node) {
|
||||||
|
const funcId = node.callee.property;
|
||||||
|
if (!funcId || funcId.name !== "delete") return;
|
||||||
|
const tableExpr = node.callee.object;
|
||||||
|
if (!tableExpr) return;
|
||||||
|
const prismaExpr = tableExpr.object;
|
||||||
|
if (!prismaExpr || prismaExpr.name !== "prisma") return;
|
||||||
|
context.report({
|
||||||
|
node,
|
||||||
|
messageId: "noPrismaDelete",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
defaultOptions: [],
|
||||||
|
} satisfies TSESLint.RuleModule<"noPrismaDelete">;
|
||||||
@ -17,6 +17,10 @@ export default defineEventHandler<{
|
|||||||
|
|
||||||
const body = await readDropValidatedBody(h3, DeleteInvite);
|
const body = await readDropValidatedBody(h3, DeleteInvite);
|
||||||
|
|
||||||
await prisma.invitation.delete({ where: { id: body.id } });
|
const { count } = await prisma.invitation.deleteMany({
|
||||||
|
where: { id: body.id },
|
||||||
|
});
|
||||||
|
if (count == 0)
|
||||||
|
throw createError({ statusCode: 404, message: "Invitation not found." });
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,7 +7,7 @@ export default defineEventHandler(async (h3) => {
|
|||||||
|
|
||||||
const gameId = getRouterParam(h3, "id")!;
|
const gameId = getRouterParam(h3, "id")!;
|
||||||
|
|
||||||
libraryManager.deleteGame(gameId);
|
await libraryManager.deleteGame(gameId);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
|
|||||||
@ -18,11 +18,13 @@ export default defineEventHandler<{ body: typeof DeleteLibrarySource.infer }>(
|
|||||||
|
|
||||||
const body = await readDropValidatedBody(h3, DeleteLibrarySource);
|
const body = await readDropValidatedBody(h3, DeleteLibrarySource);
|
||||||
|
|
||||||
await prisma.library.delete({
|
const { count } = await prisma.library.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
id: body.id,
|
id: body.id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
if (count == 0)
|
||||||
|
throw createError({ statusCode: 404, message: "Library not found." });
|
||||||
|
|
||||||
libraryManager.removeLibrary(body.id);
|
libraryManager.removeLibrary(body.id);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -13,10 +13,10 @@ export default defineEventHandler(async (h3) => {
|
|||||||
statusMessage: "No id in router params",
|
statusMessage: "No id in router params",
|
||||||
});
|
});
|
||||||
|
|
||||||
const deleted = await prisma.aPIToken.delete({
|
const { count } = await prisma.aPIToken.deleteMany({
|
||||||
where: { id: id, mode: APITokenMode.System },
|
where: { id: id, mode: APITokenMode.System },
|
||||||
})!;
|
})!;
|
||||||
if (!deleted)
|
if (count == 0)
|
||||||
throw createError({ statusCode: 404, statusMessage: "Token not found" });
|
throw createError({ statusCode: 404, statusMessage: "Token not found" });
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -27,6 +27,7 @@ export default defineEventHandler(async (h3) => {
|
|||||||
if (!user)
|
if (!user)
|
||||||
throw createError({ statusCode: 404, statusMessage: "User not found." });
|
throw createError({ statusCode: 404, statusMessage: "User not found." });
|
||||||
|
|
||||||
|
// eslint-disable-next-line drop/no-prisma-delete
|
||||||
await prisma.user.delete({ where: { id: userId } });
|
await prisma.user.delete({ where: { id: userId } });
|
||||||
await userStatsManager.deleteUser();
|
await userStatsManager.deleteUser();
|
||||||
return { success: true };
|
return { success: true };
|
||||||
|
|||||||
@ -84,7 +84,7 @@ export default defineEventHandler<{
|
|||||||
user: true,
|
user: true,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
prisma.invitation.delete({ where: { id: user.invitation } }),
|
prisma.invitation.deleteMany({ where: { id: user.invitation } }),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await userStatsManager.addUser();
|
await userStatsManager.addUser();
|
||||||
|
|||||||
@ -38,16 +38,14 @@ export default defineClientEventHandler(
|
|||||||
if (!game)
|
if (!game)
|
||||||
throw createError({ statusCode: 400, statusMessage: "Invalid game ID" });
|
throw createError({ statusCode: 400, statusMessage: "Invalid game ID" });
|
||||||
|
|
||||||
const save = await prisma.saveSlot.delete({
|
const { count } = await prisma.saveSlot.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
id: {
|
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
gameId: gameId,
|
gameId: gameId,
|
||||||
index: slotIndex,
|
index: slotIndex,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
});
|
});
|
||||||
if (!save)
|
if (count == 0)
|
||||||
throw createError({ statusCode: 404, statusMessage: "Save not found" });
|
throw createError({ statusCode: 404, statusMessage: "Save not found" });
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@ -20,14 +20,14 @@ export default defineEventHandler(async (h3) => {
|
|||||||
userIds.push("system");
|
userIds.push("system");
|
||||||
}
|
}
|
||||||
|
|
||||||
const notification = await prisma.notification.delete({
|
const { count } = await prisma.notification.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
id: notificationId,
|
id: notificationId,
|
||||||
userId: { in: userIds },
|
userId: { in: userIds },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!notification)
|
if (count == 0)
|
||||||
throw createError({
|
throw createError({
|
||||||
statusCode: 400,
|
statusCode: 400,
|
||||||
statusMessage: "Invalid notification ID",
|
statusMessage: "Invalid notification ID",
|
||||||
|
|||||||
@ -13,10 +13,10 @@ export default defineEventHandler(async (h3) => {
|
|||||||
statusMessage: "No id in router params",
|
statusMessage: "No id in router params",
|
||||||
});
|
});
|
||||||
|
|
||||||
const deleted = await prisma.aPIToken.delete({
|
const { count } = await prisma.aPIToken.deleteMany({
|
||||||
where: { id: id, userId: userId, mode: APITokenMode.User },
|
where: { id: id, userId: userId, mode: APITokenMode.User },
|
||||||
})!;
|
})!;
|
||||||
if (!deleted)
|
if (count == 0)
|
||||||
throw createError({ statusCode: 404, statusMessage: "Token not found" });
|
throw createError({ statusCode: 404, statusMessage: "Token not found" });
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -185,15 +185,19 @@ export class ClientHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async removeClient(id: string) {
|
async removeClient(id: string) {
|
||||||
|
const client = await prisma.client.findUnique({ where: { id } });
|
||||||
|
if (!client) return false;
|
||||||
const ca = useCertificateAuthority();
|
const ca = useCertificateAuthority();
|
||||||
await ca.blacklistClient(id);
|
await ca.blacklistClient(id);
|
||||||
|
|
||||||
|
// eslint-disable-next-line drop/no-prisma-delete
|
||||||
await prisma.client.delete({
|
await prisma.client.delete({
|
||||||
where: {
|
where: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await userStatsManager.cacheUserStats();
|
await userStatsManager.cacheUserStats();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -378,25 +378,23 @@ class LibraryManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async deleteGameVersion(gameId: string, version: string) {
|
async deleteGameVersion(gameId: string, version: string) {
|
||||||
await prisma.gameVersion.delete({
|
await prisma.gameVersion.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
gameId_versionName: {
|
|
||||||
gameId: gameId,
|
gameId: gameId,
|
||||||
versionName: version,
|
versionName: version,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await gameSizeManager.deleteGameVersion(gameId, version);
|
await gameSizeManager.deleteGameVersion(gameId, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteGame(gameId: string) {
|
async deleteGame(gameId: string) {
|
||||||
await prisma.game.delete({
|
await prisma.game.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
id: gameId,
|
id: gameId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
gameSizeManager.deleteGame(gameId);
|
await gameSizeManager.deleteGame(gameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getGameVersionSize(
|
async getGameVersionSize(
|
||||||
|
|||||||
@ -124,7 +124,10 @@ class NewsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async delete(id: string) {
|
async delete(id: string) {
|
||||||
const article = await prisma.article.delete({
|
const article = await prisma.article.findUnique({ where: { id } });
|
||||||
|
if (!article) return false;
|
||||||
|
// eslint-disable-next-line drop/no-prisma-delete
|
||||||
|
await prisma.article.delete({
|
||||||
where: { id },
|
where: { id },
|
||||||
});
|
});
|
||||||
if (article.imageObjectId) {
|
if (article.imageObjectId) {
|
||||||
|
|||||||
@ -259,16 +259,10 @@ class FsHashStore {
|
|||||||
*/
|
*/
|
||||||
async delete(id: ObjectReference) {
|
async delete(id: ObjectReference) {
|
||||||
await this.cache.remove(id);
|
await this.cache.remove(id);
|
||||||
|
await prisma.objectHash.deleteMany({
|
||||||
try {
|
|
||||||
// need to catch in case the object doesn't exist
|
|
||||||
await prisma.objectHash.delete({
|
|
||||||
where: {
|
where: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch {
|
|
||||||
/* empty */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,12 +53,16 @@ class ScreenshotManager {
|
|||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
async delete(id: string) {
|
async delete(id: string) {
|
||||||
const deletedScreenshot = await prisma.screenshot.delete({
|
const screenshot = await prisma.screenshot.findUnique({ where: { id } });
|
||||||
|
if (!screenshot) return false;
|
||||||
|
// eslint-disable-next-line drop/no-prisma-delete
|
||||||
|
await prisma.screenshot.delete({
|
||||||
where: {
|
where: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await objectHandler.deleteAsSystem(deletedScreenshot.objectId);
|
await objectHandler.deleteAsSystem(screenshot.objectId);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -43,12 +43,12 @@ export default function createDBSessionHandler(): SessionProvider {
|
|||||||
},
|
},
|
||||||
async removeSession(token) {
|
async removeSession(token) {
|
||||||
await cache.remove(token);
|
await cache.remove(token);
|
||||||
await prisma.session.delete({
|
const { count } = await prisma.session.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
token,
|
token,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return true;
|
return count > 0;
|
||||||
},
|
},
|
||||||
async cleanupSessions() {
|
async cleanupSessions() {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|||||||
@ -101,9 +101,7 @@ class UserLibraryManager {
|
|||||||
|
|
||||||
async collectionRemove(gameId: string, collectionId: string, userId: string) {
|
async collectionRemove(gameId: string, collectionId: string, userId: string) {
|
||||||
// Delete if exists
|
// Delete if exists
|
||||||
return (
|
const { count } = await prisma.collectionEntry.deleteMany({
|
||||||
(
|
|
||||||
await prisma.collectionEntry.deleteMany({
|
|
||||||
where: {
|
where: {
|
||||||
collectionId,
|
collectionId,
|
||||||
gameId,
|
gameId,
|
||||||
@ -111,9 +109,8 @@ class UserLibraryManager {
|
|||||||
userId,
|
userId,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
).count > 0
|
return count > 0;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async collectionCreate(name: string, userId: string) {
|
async collectionCreate(name: string, userId: string) {
|
||||||
@ -133,12 +130,13 @@ class UserLibraryManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async deleteCollection(collectionId: string) {
|
async deleteCollection(collectionId: string) {
|
||||||
await prisma.collection.delete({
|
const { count } = await prisma.collection.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
id: collectionId,
|
id: collectionId,
|
||||||
isDefault: false,
|
isDefault: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
return count > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user