refactor: Mejorar la legibilidad del código en la gestión de items y la encriptación de datos
This commit is contained in:
@@ -267,7 +267,10 @@ function decryptJsonFromDb(maybe: any): any {
|
|||||||
const enc = buf.slice(28);
|
const enc = buf.slice(28);
|
||||||
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
||||||
decipher.setAuthTag(tag);
|
decipher.setAuthTag(tag);
|
||||||
const dec = Buffer.concat([decipher.update(enc), decipher.final()]).toString("utf8");
|
const dec = Buffer.concat([
|
||||||
|
decipher.update(enc),
|
||||||
|
decipher.final(),
|
||||||
|
]).toString("utf8");
|
||||||
return JSON.parse(dec);
|
return JSON.parse(dec);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return null;
|
return null;
|
||||||
@@ -1291,28 +1294,61 @@ export const server = createServer(
|
|||||||
|
|
||||||
// GET single item raw (admin) -> /api/dashboard/:guildId/items/:id?raw=1
|
// GET single item raw (admin) -> /api/dashboard/:guildId/items/:id?raw=1
|
||||||
if (req.method === "GET" && itemId) {
|
if (req.method === "GET" && itemId) {
|
||||||
const wantRaw = url.searchParams.get('raw') === '1';
|
const wantRaw = url.searchParams.get("raw") === "1";
|
||||||
if (wantRaw) {
|
if (wantRaw) {
|
||||||
if (process.env.ALLOW_ITEM_RAW !== '1') {
|
if (process.env.ALLOW_ITEM_RAW !== "1") {
|
||||||
res.writeHead(403, applySecurityHeadersForRequest(req, { 'Content-Type':'application/json' }));
|
res.writeHead(
|
||||||
res.end(JSON.stringify({ ok:false, error: 'raw_disabled' }));
|
403,
|
||||||
|
applySecurityHeadersForRequest(req, {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
res.end(JSON.stringify({ ok: false, error: "raw_disabled" }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const it = await prisma.economyItem.findUnique({ where: { id: String(itemId) } });
|
const it = await prisma.economyItem.findUnique({
|
||||||
|
where: { id: String(itemId) },
|
||||||
|
});
|
||||||
if (!it) {
|
if (!it) {
|
||||||
res.writeHead(404, applySecurityHeadersForRequest(req, { 'Content-Type':'application/json' }));
|
res.writeHead(
|
||||||
res.end(JSON.stringify({ ok:false, error:'not_found' }));
|
404,
|
||||||
|
applySecurityHeadersForRequest(req, {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
res.end(JSON.stringify({ ok: false, error: "not_found" }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const props = decryptJsonFromDb(it.props);
|
const props = decryptJsonFromDb(it.props);
|
||||||
const metadata = decryptJsonFromDb(it.metadata);
|
const metadata = decryptJsonFromDb(it.metadata);
|
||||||
res.writeHead(200, applySecurityHeadersForRequest(req, { 'Content-Type':'application/json' }));
|
res.writeHead(
|
||||||
res.end(JSON.stringify({ ok:true, item: { id: it.id, key: it.key, name: it.name, props, metadata } }));
|
200,
|
||||||
|
applySecurityHeadersForRequest(req, {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
res.end(
|
||||||
|
JSON.stringify({
|
||||||
|
ok: true,
|
||||||
|
item: {
|
||||||
|
id: it.id,
|
||||||
|
key: it.key,
|
||||||
|
name: it.name,
|
||||||
|
props,
|
||||||
|
metadata,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.writeHead(500, applySecurityHeadersForRequest(req, { 'Content-Type':'application/json' }));
|
res.writeHead(
|
||||||
res.end(JSON.stringify({ ok:false, error: String(err) }));
|
500,
|
||||||
|
applySecurityHeadersForRequest(req, {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
res.end(JSON.stringify({ ok: false, error: String(err) }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1375,17 +1411,31 @@ export const server = createServer(
|
|||||||
};
|
};
|
||||||
// parse JSON fields if provided as string and encrypt if key present
|
// parse JSON fields if provided as string and encrypt if key present
|
||||||
try {
|
try {
|
||||||
const rawProps = payload.props ? (typeof payload.props === 'string' ? JSON.parse(payload.props) : payload.props) : null;
|
const rawProps = payload.props
|
||||||
const rawMeta = payload.metadata ? (typeof payload.metadata === 'string' ? JSON.parse(payload.metadata) : payload.metadata) : null;
|
? typeof payload.props === "string"
|
||||||
createData.props = getItemEncryptionKey() ? encryptJsonForDb(rawProps) : rawProps;
|
? JSON.parse(payload.props)
|
||||||
createData.metadata = getItemEncryptionKey() ? encryptJsonForDb(rawMeta) : rawMeta;
|
: payload.props
|
||||||
|
: null;
|
||||||
|
const rawMeta = payload.metadata
|
||||||
|
? typeof payload.metadata === "string"
|
||||||
|
? JSON.parse(payload.metadata)
|
||||||
|
: payload.metadata
|
||||||
|
: null;
|
||||||
|
createData.props = getItemEncryptionKey()
|
||||||
|
? encryptJsonForDb(rawProps)
|
||||||
|
: rawProps;
|
||||||
|
createData.metadata = getItemEncryptionKey()
|
||||||
|
? encryptJsonForDb(rawMeta)
|
||||||
|
: rawMeta;
|
||||||
} catch {
|
} catch {
|
||||||
createData.props = null;
|
createData.props = null;
|
||||||
createData.metadata = null;
|
createData.metadata = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const created = await prisma.economyItem.create({ data: createData });
|
const created = await prisma.economyItem.create({
|
||||||
|
data: createData,
|
||||||
|
});
|
||||||
// Return safe summary only (do not include props/metadata)
|
// Return safe summary only (do not include props/metadata)
|
||||||
const safeCreated = {
|
const safeCreated = {
|
||||||
id: created.id,
|
id: created.id,
|
||||||
@@ -1411,14 +1461,24 @@ export const server = createServer(
|
|||||||
return;
|
return;
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
// Prisma unique constraint error code P2002 -> duplicate key
|
// Prisma unique constraint error code P2002 -> duplicate key
|
||||||
if (err && err.code === 'P2002') {
|
if (err && err.code === "P2002") {
|
||||||
res.writeHead(400, applySecurityHeadersForRequest(req, { 'Content-Type':'application/json' }));
|
res.writeHead(
|
||||||
res.end(JSON.stringify({ ok:false, error:'duplicate_key' }));
|
400,
|
||||||
|
applySecurityHeadersForRequest(req, {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
res.end(JSON.stringify({ ok: false, error: "duplicate_key" }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const errMsg = String(err || 'unknown');
|
const errMsg = String(err || "unknown");
|
||||||
res.writeHead(500, applySecurityHeadersForRequest(req, { 'Content-Type':'application/json' }));
|
res.writeHead(
|
||||||
res.end(JSON.stringify({ ok:false, error: errMsg }));
|
500,
|
||||||
|
applySecurityHeadersForRequest(req, {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
res.end(JSON.stringify({ ok: false, error: errMsg }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1459,17 +1519,30 @@ export const server = createServer(
|
|||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
: [];
|
: [];
|
||||||
try {
|
try {
|
||||||
const rawProps = typeof payload.props === 'string' ? JSON.parse(payload.props) : payload.props;
|
const rawProps =
|
||||||
const rawMeta = typeof payload.metadata === 'string' ? JSON.parse(payload.metadata) : payload.metadata;
|
typeof payload.props === "string"
|
||||||
updateData.props = getItemEncryptionKey() ? encryptJsonForDb(rawProps) : rawProps;
|
? JSON.parse(payload.props)
|
||||||
updateData.metadata = getItemEncryptionKey() ? encryptJsonForDb(rawMeta) : rawMeta;
|
: payload.props;
|
||||||
|
const rawMeta =
|
||||||
|
typeof payload.metadata === "string"
|
||||||
|
? JSON.parse(payload.metadata)
|
||||||
|
: payload.metadata;
|
||||||
|
updateData.props = getItemEncryptionKey()
|
||||||
|
? encryptJsonForDb(rawProps)
|
||||||
|
: rawProps;
|
||||||
|
updateData.metadata = getItemEncryptionKey()
|
||||||
|
? encryptJsonForDb(rawMeta)
|
||||||
|
: rawMeta;
|
||||||
} catch {
|
} catch {
|
||||||
updateData.props = null;
|
updateData.props = null;
|
||||||
updateData.metadata = null;
|
updateData.metadata = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const updated = await prisma.economyItem.update({ where: { id }, data: updateData });
|
const updated = await prisma.economyItem.update({
|
||||||
|
where: { id },
|
||||||
|
data: updateData,
|
||||||
|
});
|
||||||
// Return safe summary only (do not include props/metadata)
|
// Return safe summary only (do not include props/metadata)
|
||||||
const safeUpdated = {
|
const safeUpdated = {
|
||||||
id: updated.id,
|
id: updated.id,
|
||||||
@@ -1485,16 +1558,33 @@ export const server = createServer(
|
|||||||
createdAt: updated.createdAt,
|
createdAt: updated.createdAt,
|
||||||
updatedAt: updated.updatedAt,
|
updatedAt: updated.updatedAt,
|
||||||
};
|
};
|
||||||
res.writeHead(200, applySecurityHeadersForRequest(req, { 'Content-Type': 'application/json' }));
|
res.writeHead(
|
||||||
|
200,
|
||||||
|
applySecurityHeadersForRequest(req, {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
})
|
||||||
|
);
|
||||||
res.end(JSON.stringify({ ok: true, item: safeUpdated }));
|
res.end(JSON.stringify({ ok: true, item: safeUpdated }));
|
||||||
return;
|
return;
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err && err.code === 'P2002') {
|
if (err && err.code === "P2002") {
|
||||||
res.writeHead(400, applySecurityHeadersForRequest(req, { 'Content-Type':'application/json' }));
|
res.writeHead(
|
||||||
res.end(JSON.stringify({ ok:false, error:'duplicate_key' }));
|
400,
|
||||||
|
applySecurityHeadersForRequest(req, {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
res.end(
|
||||||
|
JSON.stringify({ ok: false, error: "duplicate_key" })
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
res.writeHead(500, applySecurityHeadersForRequest(req, { 'Content-Type': 'application/json' }));
|
res.writeHead(
|
||||||
|
500,
|
||||||
|
applySecurityHeadersForRequest(req, {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
})
|
||||||
|
);
|
||||||
res.end(JSON.stringify({ ok: false, error: String(err) }));
|
res.end(JSON.stringify({ ok: false, error: String(err) }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user