Files
poshmanager/server/models/variableModel.js
2026-06-25 12:05:53 -05:00

142 lines
4.5 KiB
JavaScript

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);
}