Add Granite Loader Sheet generator with CARD enrichment
Implement the Granite Team_Device Loader xlsx export feature:
- Add graniteLoaderConfig.js with all 41 columns, groupings, and
operation-type requirements (Change/Add/Delete/Move)
- Add graniteLoaderExport.js for client-side xlsx generation using
the xlsx library
- Add LoaderModal component with operation type selection, column
checkboxes, bulk defaults with per-row overrides, editable preview
table, CARD enrichment integration, and standalone paste-IPs mode
- Add POST /api/card/enrich-batch endpoint for batch IP lookup in
CARD returning EQUIP_INST_ID, hostname, site, ASN, team
- Integrate 'Generate Loader Sheet' button in Ivanti Queue floating
action bar (visible when CARD/GRANITE/DECOM items selected)
- Add card-connectivity-test.js script for verifying CARD API access
2026-05-27 17:18:36 -06:00
|
|
|
#!/usr/bin/env node
|
|
|
|
|
/**
|
|
|
|
|
* CARD API Connectivity Test
|
|
|
|
|
* Tests: token acquisition → teams list → sample asset lookup
|
|
|
|
|
*/
|
2026-05-28 13:44:20 -06:00
|
|
|
require('dns').setDefaultResultOrder('ipv4first');
|
Add Granite Loader Sheet generator with CARD enrichment
Implement the Granite Team_Device Loader xlsx export feature:
- Add graniteLoaderConfig.js with all 41 columns, groupings, and
operation-type requirements (Change/Add/Delete/Move)
- Add graniteLoaderExport.js for client-side xlsx generation using
the xlsx library
- Add LoaderModal component with operation type selection, column
checkboxes, bulk defaults with per-row overrides, editable preview
table, CARD enrichment integration, and standalone paste-IPs mode
- Add POST /api/card/enrich-batch endpoint for batch IP lookup in
CARD returning EQUIP_INST_ID, hostname, site, ASN, team
- Integrate 'Generate Loader Sheet' button in Ivanti Queue floating
action bar (visible when CARD/GRANITE/DECOM items selected)
- Add card-connectivity-test.js script for verifying CARD API access
2026-05-27 17:18:36 -06:00
|
|
|
require('dotenv').config({ path: require('path').join(__dirname, '..', '.env') });
|
|
|
|
|
|
|
|
|
|
const { isConfigured, missingVars, testConnection, getTeams } = require('../helpers/cardApi');
|
|
|
|
|
|
|
|
|
|
async function main() {
|
|
|
|
|
console.log('=== CARD API Connectivity Test ===');
|
|
|
|
|
console.log(`Timestamp: ${new Date().toISOString()}`);
|
|
|
|
|
console.log(`Target: ${process.env.CARD_API_URL}`);
|
|
|
|
|
console.log(`User: ${process.env.CARD_API_USER}`);
|
|
|
|
|
console.log(`TLS Skip: ${process.env.CARD_SKIP_TLS}`);
|
|
|
|
|
console.log('');
|
|
|
|
|
|
|
|
|
|
if (!isConfigured) {
|
|
|
|
|
console.error('FAIL: CARD API not configured. Missing:', missingVars.join(', '));
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 1: Token acquisition
|
|
|
|
|
console.log('1. Acquiring Bearer token...');
|
|
|
|
|
const connResult = await testConnection();
|
|
|
|
|
if (!connResult.ok) {
|
|
|
|
|
console.error(' FAIL:', connResult.error);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
console.log(' OK — token acquired:', connResult.token);
|
|
|
|
|
|
|
|
|
|
// Step 2: List teams
|
|
|
|
|
console.log('2. Fetching teams (GET /api/v1/teams)...');
|
|
|
|
|
const teamsResult = await getTeams();
|
|
|
|
|
console.log(' Status:', teamsResult.status);
|
|
|
|
|
if (!teamsResult.ok) {
|
|
|
|
|
console.error(' FAIL:', teamsResult.body.substring(0, 300));
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let teams;
|
|
|
|
|
try {
|
|
|
|
|
teams = JSON.parse(teamsResult.body);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(' FAIL: Could not parse response:', teamsResult.body.substring(0, 200));
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Array.isArray(teams)) {
|
|
|
|
|
console.log(` OK — ${teams.length} teams found`);
|
|
|
|
|
const sample = teams.slice(0, 8);
|
|
|
|
|
sample.forEach(t => {
|
|
|
|
|
const name = t.name || t.team_name || t.teamName || JSON.stringify(t).substring(0, 60);
|
|
|
|
|
console.log(` • ${name}`);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
console.log(' Response structure:', Object.keys(teams).join(', '));
|
|
|
|
|
console.log(' Preview:', JSON.stringify(teams).substring(0, 200));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('');
|
|
|
|
|
console.log('=== RESULT: PASS — CARD API is reachable and authenticated ===');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
main().catch(err => {
|
|
|
|
|
console.error('ERROR:', err.message);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
});
|