Initial
This commit is contained in:
141
server/models/variableModel.js
Normal file
141
server/models/variableModel.js
Normal file
@@ -0,0 +1,141 @@
|
||||
import { db, id, now, visibleClause } from '../db.js';
|
||||
import { customVariableSchema } from '../forms/schemas.js';
|
||||
import { fullVariableCatalog } from '../data/variableCatalog.js';
|
||||
import { decryptSecret, encryptSecret } from '../services/cryptoStore.js';
|
||||
import { camelCustomVariable } from './mappers.js';
|
||||
|
||||
function normalizeVariable(body, existing = {}) {
|
||||
const parsed = customVariableSchema.parse({ ...existing, ...body });
|
||||
return {
|
||||
...parsed,
|
||||
sensitive: Boolean(parsed.sensitive),
|
||||
groupId: parsed.visibility === 'group' ? parsed.groupId || null : null
|
||||
};
|
||||
}
|
||||
|
||||
function visibleCustomVariableRows(userId) {
|
||||
return db.prepare(`
|
||||
SELECT v.*, g.name AS group_name
|
||||
FROM custom_variables v
|
||||
LEFT JOIN groups g ON g.id = v.group_id
|
||||
WHERE ${visibleClause('v')}
|
||||
ORDER BY v.category, v.name
|
||||
`).all(userId, userId);
|
||||
}
|
||||
|
||||
export function listVariableCatalog(userId) {
|
||||
const catalog = fullVariableCatalog();
|
||||
return {
|
||||
...catalog,
|
||||
custom: visibleCustomVariableRows(userId).map((row) => {
|
||||
const includeValue = !Boolean(row.sensitive);
|
||||
const value = includeValue ? decryptSecret(row) : undefined;
|
||||
return camelCustomVariable({ ...row, value }, includeValue);
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
export function listCustomVariables(userId) {
|
||||
return visibleCustomVariableRows(userId).map((row) => {
|
||||
const includeValue = !Boolean(row.sensitive);
|
||||
const value = includeValue ? decryptSecret(row) : undefined;
|
||||
return camelCustomVariable({ ...row, value }, includeValue);
|
||||
});
|
||||
}
|
||||
|
||||
export function listExecutableCustomVariables(userId) {
|
||||
return visibleCustomVariableRows(userId).map((row) => ({
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
value: decryptSecret(row),
|
||||
valueType: row.value_type || 'string',
|
||||
sensitive: Boolean(row.sensitive)
|
||||
}));
|
||||
}
|
||||
|
||||
export function createCustomVariable(body, userId) {
|
||||
const payload = normalizeVariable(body);
|
||||
const encrypted = encryptSecret(payload.value);
|
||||
const variableId = id('var');
|
||||
db.prepare(`
|
||||
INSERT INTO custom_variables (
|
||||
id, name, description, category, value_type, secret_cipher, secret_iv, secret_tag,
|
||||
sensitive, visibility, owner_user_id, group_id, created_by, created_at, updated_at
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`).run(
|
||||
variableId,
|
||||
payload.name,
|
||||
payload.description,
|
||||
payload.category,
|
||||
payload.valueType,
|
||||
encrypted.cipher,
|
||||
encrypted.iv,
|
||||
encrypted.tag,
|
||||
payload.sensitive ? 1 : 0,
|
||||
payload.visibility,
|
||||
userId,
|
||||
payload.groupId,
|
||||
userId,
|
||||
now(),
|
||||
now()
|
||||
);
|
||||
return loadCustomVariable(variableId, userId);
|
||||
}
|
||||
|
||||
export function loadCustomVariable(variableId, userId) {
|
||||
const row = db.prepare(`
|
||||
SELECT v.*, g.name AS group_name
|
||||
FROM custom_variables v
|
||||
LEFT JOIN groups g ON g.id = v.group_id
|
||||
WHERE v.id = ? AND ${visibleClause('v')}
|
||||
`).get(variableId, userId, userId);
|
||||
if (!row) return null;
|
||||
const includeValue = !Boolean(row.sensitive);
|
||||
const value = includeValue ? decryptSecret(row) : undefined;
|
||||
return camelCustomVariable({ ...row, value }, includeValue);
|
||||
}
|
||||
|
||||
export function updateCustomVariable(variableId, body, userId) {
|
||||
const existing = db.prepare(`SELECT * FROM custom_variables WHERE id = ? AND ${visibleClause()}`).get(variableId, userId, userId);
|
||||
if (!existing) return null;
|
||||
const payload = normalizeVariable(body, {
|
||||
name: existing.name,
|
||||
description: existing.description || '',
|
||||
category: existing.category || 'Custom',
|
||||
value: body.value ?? decryptSecret(existing),
|
||||
valueType: existing.value_type || 'string',
|
||||
sensitive: Boolean(existing.sensitive),
|
||||
visibility: existing.visibility,
|
||||
groupId: existing.group_id
|
||||
});
|
||||
const encrypted = body.value === undefined ? {
|
||||
cipher: existing.secret_cipher,
|
||||
iv: existing.secret_iv,
|
||||
tag: existing.secret_tag
|
||||
} : encryptSecret(payload.value);
|
||||
db.prepare(`
|
||||
UPDATE custom_variables
|
||||
SET name = ?, description = ?, category = ?, value_type = ?, secret_cipher = ?, secret_iv = ?,
|
||||
secret_tag = ?, sensitive = ?, visibility = ?, group_id = ?, updated_at = ?
|
||||
WHERE id = ?
|
||||
`).run(
|
||||
payload.name,
|
||||
payload.description,
|
||||
payload.category,
|
||||
payload.valueType,
|
||||
encrypted.cipher,
|
||||
encrypted.iv,
|
||||
encrypted.tag,
|
||||
payload.sensitive ? 1 : 0,
|
||||
payload.visibility,
|
||||
payload.groupId,
|
||||
now(),
|
||||
variableId
|
||||
);
|
||||
return loadCustomVariable(variableId, userId);
|
||||
}
|
||||
|
||||
export function deleteCustomVariable(variableId, userId) {
|
||||
db.prepare(`DELETE FROM custom_variables WHERE id = ? AND ${visibleClause()}`).run(variableId, userId, userId);
|
||||
}
|
||||
Reference in New Issue
Block a user