Files
poshmanager/server/controllers/applicationController.js
2026-06-25 12:05:53 -05:00

95 lines
3.8 KiB
JavaScript

import { applicationImportSchema, applicationSchema } from '../forms/schemas.js';
import {
createApplication,
deleteApplication,
listApplications,
loadApplication,
recordVersionCheck,
updateApplication
} from '../models/applicationModel.js';
import { getGraphConnection } from '../models/graphModel.js';
import { getGraphMobileApp } from '../services/graphService.js';
import { fetchLatestVersion, mapGraphAppToCatalog } from '../services/appVersionService.js';
import { runCatalogChecks } from '../services/catalogWorker.js';
export function index(req, res) {
res.json(listApplications(req.user.id));
}
export function create(req, res) {
const parsed = applicationSchema.safeParse(req.body);
if (!parsed.success) return res.status(400).json({ error: 'Invalid application payload' });
res.status(201).json(createApplication(parsed.data, req.user.id));
}
export function show(req, res) {
const application = loadApplication(req.params.id, req.user.id);
if (!application) return res.status(404).json({ error: 'Application not found' });
res.json(application);
}
export function update(req, res) {
const parsed = applicationSchema.safeParse(req.body);
if (!parsed.success) return res.status(400).json({ error: 'Invalid application payload' });
const application = updateApplication(req.params.id, parsed.data, req.user.id);
if (!application) return res.status(404).json({ error: 'Application not found' });
res.json(application);
}
export function destroy(req, res) {
deleteApplication(req.params.id, req.user.id);
res.status(204).end();
}
// Look up the upstream version from the configured source and store it. The
// update state (whether a newer version exists) is recomputed on read.
export async function checkUpdate(req, res) {
const application = loadApplication(req.params.id, req.user.id);
if (!application) return res.status(404).json({ error: 'Application not found' });
try {
const result = await fetchLatestVersion(application);
const updated = recordVersionCheck(req.params.id, req.user.id, {
latestKnownVersion: result.version || application.latestKnownVersion,
message: result.message || ''
});
res.json({ application: updated, check: result });
} catch (error) {
recordVersionCheck(req.params.id, req.user.id, { latestKnownVersion: application.latestKnownVersion, message: error.message });
res.status(400).json({ error: error.message });
}
}
// Run an upstream check for every auto-check application now (admin trigger).
export async function checkAll(req, res) {
try {
const summary = await runCatalogChecks();
res.json({ summary, applications: listApplications(req.user.id) });
} catch (error) {
res.status(400).json({ error: error.message });
}
}
// Adopt an existing tenant Win32 app into the catalog (migration aid). Read-only
// Graph access; no write-back gate required.
export async function importFromTenant(req, res) {
const parsed = applicationImportSchema.safeParse(req.body);
if (!parsed.success) return res.status(400).json({ error: 'connectionId and graphAppId are required' });
const connection = getGraphConnection(parsed.data.connectionId, req.user.id, true);
if (!connection) return res.status(404).json({ error: 'Graph connection not found' });
try {
const graphApp = await getGraphMobileApp(connection, parsed.data.graphAppId);
const mapped = mapGraphAppToCatalog(graphApp);
const application = createApplication({
...mapped,
graphConnectionId: parsed.data.connectionId,
versionSource: 'manual',
visibility: parsed.data.visibility,
groupId: parsed.data.groupId,
notes: `Adopted from Intune mobileApp ${parsed.data.graphAppId}.`
}, req.user.id);
res.status(201).json(application);
} catch (error) {
res.status(400).json({ error: error.message });
}
}