Initial
This commit is contained in:
148
server/models/applicationModel.js
Normal file
148
server/models/applicationModel.js
Normal file
@@ -0,0 +1,148 @@
|
||||
import { db, id, now, visibleClause } from '../db.js';
|
||||
import { applicationSchema } from '../forms/schemas.js';
|
||||
import { evaluateUpdateState } from '../services/appVersionService.js';
|
||||
|
||||
function camelApplication(row) {
|
||||
if (!row) return null;
|
||||
const base = {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
vendor: row.vendor || '',
|
||||
publisher: row.publisher || '',
|
||||
currentVersion: row.current_version || '',
|
||||
latestKnownVersion: row.latest_known_version || '',
|
||||
versionSource: row.version_source || 'manual',
|
||||
versionSourceRef: row.version_source_ref || '',
|
||||
graphConnectionId: row.graph_connection_id || null,
|
||||
currentGraphAppId: row.current_graph_app_id || '',
|
||||
autoCheck: Boolean(row.auto_check),
|
||||
lastCheckedAt: row.last_checked_at || '',
|
||||
lastCheckMessage: row.last_check_message || '',
|
||||
notes: row.notes || '',
|
||||
visibility: row.visibility,
|
||||
ownerUserId: row.owner_user_id,
|
||||
groupId: row.group_id,
|
||||
groupName: row.group_name || null,
|
||||
deploymentCount: row.deployment_count ?? 0,
|
||||
createdAt: row.created_at,
|
||||
updatedAt: row.updated_at
|
||||
};
|
||||
// Surface the computed update state so callers don't re-derive it.
|
||||
base.updateState = evaluateUpdateState(base);
|
||||
return base;
|
||||
}
|
||||
|
||||
function scopedGroupId(payload) {
|
||||
return payload.visibility === 'group' ? payload.groupId || null : null;
|
||||
}
|
||||
|
||||
export function listApplications(userId) {
|
||||
return db.prepare(`
|
||||
SELECT a.*, g.name AS group_name,
|
||||
(SELECT COUNT(*) FROM intune_deployments d WHERE d.application_id = a.id) AS deployment_count
|
||||
FROM applications a
|
||||
LEFT JOIN groups g ON g.id = a.group_id
|
||||
WHERE ${visibleClause('a')}
|
||||
ORDER BY a.name
|
||||
`).all(userId, userId).map(camelApplication);
|
||||
}
|
||||
|
||||
export function loadApplication(applicationId, userId) {
|
||||
const row = db.prepare(`
|
||||
SELECT a.*, g.name AS group_name,
|
||||
(SELECT COUNT(*) FROM intune_deployments d WHERE d.application_id = a.id) AS deployment_count
|
||||
FROM applications a
|
||||
LEFT JOIN groups g ON g.id = a.group_id
|
||||
WHERE a.id = ? AND ${visibleClause('a')}
|
||||
`).get(applicationId, userId, userId);
|
||||
return camelApplication(row);
|
||||
}
|
||||
|
||||
export function createApplication(body, userId) {
|
||||
const payload = applicationSchema.parse(body);
|
||||
const applicationId = id('app');
|
||||
db.prepare(`
|
||||
INSERT INTO applications (
|
||||
id, name, vendor, publisher, current_version, latest_known_version, version_source,
|
||||
version_source_ref, graph_connection_id, current_graph_app_id, auto_check, notes,
|
||||
visibility, owner_user_id, group_id, created_by, created_at, updated_at
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`).run(
|
||||
applicationId,
|
||||
payload.name,
|
||||
payload.vendor,
|
||||
payload.publisher,
|
||||
payload.currentVersion,
|
||||
payload.latestKnownVersion,
|
||||
payload.versionSource,
|
||||
payload.versionSourceRef,
|
||||
payload.graphConnectionId || null,
|
||||
payload.currentGraphAppId,
|
||||
payload.autoCheck ? 1 : 0,
|
||||
payload.notes,
|
||||
payload.visibility,
|
||||
userId,
|
||||
scopedGroupId(payload),
|
||||
userId,
|
||||
now(),
|
||||
now()
|
||||
);
|
||||
return loadApplication(applicationId, userId);
|
||||
}
|
||||
|
||||
export function updateApplication(applicationId, body, userId) {
|
||||
const existing = loadApplication(applicationId, userId);
|
||||
if (!existing) return null;
|
||||
const payload = applicationSchema.parse({ ...existing, ...body });
|
||||
db.prepare(`
|
||||
UPDATE applications
|
||||
SET name = ?, vendor = ?, publisher = ?, current_version = ?, latest_known_version = ?,
|
||||
version_source = ?, version_source_ref = ?, graph_connection_id = ?, current_graph_app_id = ?,
|
||||
auto_check = ?, notes = ?, visibility = ?, group_id = ?, updated_at = ?
|
||||
WHERE id = ?
|
||||
`).run(
|
||||
payload.name,
|
||||
payload.vendor,
|
||||
payload.publisher,
|
||||
payload.currentVersion,
|
||||
payload.latestKnownVersion,
|
||||
payload.versionSource,
|
||||
payload.versionSourceRef,
|
||||
payload.graphConnectionId || null,
|
||||
payload.currentGraphAppId,
|
||||
payload.autoCheck ? 1 : 0,
|
||||
payload.notes,
|
||||
payload.visibility,
|
||||
scopedGroupId(payload),
|
||||
now(),
|
||||
applicationId
|
||||
);
|
||||
return loadApplication(applicationId, userId);
|
||||
}
|
||||
|
||||
export function deleteApplication(applicationId, userId) {
|
||||
db.prepare(`DELETE FROM applications WHERE id = ? AND ${visibleClause()}`).run(applicationId, userId, userId);
|
||||
}
|
||||
|
||||
// Record the outcome of an upstream version check on the catalog entry.
|
||||
export function recordVersionCheck(applicationId, userId, { latestKnownVersion, message }) {
|
||||
const existing = loadApplication(applicationId, userId);
|
||||
if (!existing) return null;
|
||||
applyVersionCheck(applicationId, { latestKnownVersion: latestKnownVersion ?? existing.latestKnownVersion, message });
|
||||
return loadApplication(applicationId, userId);
|
||||
}
|
||||
|
||||
// System-level write used by the background worker (no visibility scope).
|
||||
export function applyVersionCheck(applicationId, { latestKnownVersion, message }) {
|
||||
db.prepare(`
|
||||
UPDATE applications
|
||||
SET latest_known_version = COALESCE(?, latest_known_version), last_checked_at = ?, last_check_message = ?, updated_at = ?
|
||||
WHERE id = ?
|
||||
`).run(latestKnownVersion ?? null, now(), message || '', now(), applicationId);
|
||||
}
|
||||
|
||||
// Applications opted into automatic upstream version checks. System context.
|
||||
export function listAutoCheckApplications() {
|
||||
return db.prepare('SELECT * FROM applications WHERE auto_check = 1').all().map(camelApplication);
|
||||
}
|
||||
Reference in New Issue
Block a user