feat(admin): move integration URLs and credentials to GUI settings
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import 'dotenv/config';
|
||||
import * as http from 'http';
|
||||
import { Pool } from 'pg';
|
||||
import { scrapeAll } from './scraper';
|
||||
import { scrapeAll, FdiskConfig } from './scraper';
|
||||
import { syncToDatabase, syncLehrgangToAtemschutz, syncUntersuchungenToAtemschutz } from './db';
|
||||
|
||||
// In-memory log ring buffer — last 500 lines captured from all modules
|
||||
@@ -52,8 +52,6 @@ async function runSync(force = false): Promise<void> {
|
||||
return;
|
||||
}
|
||||
syncRunning = true;
|
||||
const username = requireEnv('FDISK_USERNAME');
|
||||
const password = requireEnv('FDISK_PASSWORD');
|
||||
|
||||
const pool = new Pool({
|
||||
host: requireEnv('DB_HOST'),
|
||||
@@ -64,10 +62,32 @@ async function runSync(force = false): Promise<void> {
|
||||
});
|
||||
|
||||
try {
|
||||
// Load FDISK config from app_settings, fall back to env vars
|
||||
const settingKeys = ['fdisk_base_url', 'fdisk_id_feuerwehren', 'fdisk_id_instanzen', 'fdisk_username', 'fdisk_password'];
|
||||
const rows = await pool.query(`SELECT key, value FROM app_settings WHERE key = ANY($1)`, [settingKeys]);
|
||||
const dbSettings: Record<string, string> = {};
|
||||
for (const r of rows.rows) { dbSettings[r.key] = r.value as string; }
|
||||
|
||||
const getOrEnv = (key: string, envFallback: string) =>
|
||||
(dbSettings[key] && dbSettings[key] !== '' && dbSettings[key] !== '""') ? dbSettings[key] : envFallback;
|
||||
|
||||
const fdiskConfig: FdiskConfig = {
|
||||
baseUrl: getOrEnv('fdisk_base_url', process.env.FDISK_BASE_URL || 'https://app.fdisk.at'),
|
||||
idFeuerwehren: getOrEnv('fdisk_id_feuerwehren', process.env.FDISK_ID_FEUERWEHREN || '164'),
|
||||
idInstanzen: getOrEnv('fdisk_id_instanzen', process.env.FDISK_ID_INSTANZEN || '2853'),
|
||||
username: getOrEnv('fdisk_username', process.env.FDISK_USERNAME || ''),
|
||||
password: getOrEnv('fdisk_password', process.env.FDISK_PASSWORD || ''),
|
||||
};
|
||||
|
||||
if (!fdiskConfig.username || !fdiskConfig.password) {
|
||||
log('WARN: FDISK username/password not configured in DB or env vars — skipping sync');
|
||||
return;
|
||||
}
|
||||
|
||||
if (force) log('Force mode: ON');
|
||||
log('Starting FDISK sync');
|
||||
|
||||
const { members, ausbildungen, befoerderungen, untersuchungen, fahrgenehmigungen } = await scrapeAll(username, password);
|
||||
const { members, ausbildungen, befoerderungen, untersuchungen, fahrgenehmigungen } = await scrapeAll(fdiskConfig);
|
||||
await syncToDatabase(pool, members, ausbildungen, befoerderungen, untersuchungen, fahrgenehmigungen, force);
|
||||
log(`Sync complete — ${members.length} members, ${ausbildungen.length} Ausbildungen, ${befoerderungen.length} Beförderungen, ${untersuchungen.length} Untersuchungen, ${fahrgenehmigungen.length} Fahrgenehmigungen`);
|
||||
await syncLehrgangToAtemschutz(pool);
|
||||
|
||||
@@ -7,12 +7,20 @@ import {
|
||||
FdiskFahrgenehmigung,
|
||||
} from './types';
|
||||
|
||||
const BASE_URL = process.env.FDISK_BASE_URL ?? 'https://app.fdisk.at';
|
||||
const ID_FEUERWEHREN = process.env.FDISK_ID_FEUERWEHREN ?? '164';
|
||||
const ID_INSTANZEN = process.env.FDISK_ID_INSTANZEN ?? '2853';
|
||||
export interface FdiskConfig {
|
||||
baseUrl: string;
|
||||
idFeuerwehren: string;
|
||||
idInstanzen: string;
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
const LOGIN_URL = `${BASE_URL}/fdisk/module/vws/logins/logins.aspx`;
|
||||
const MEMBERS_URL = `${BASE_URL}/fdisk/module/mgvw/mitgliedschaften/meine_Mitglieder.aspx`;
|
||||
let BASE_URL = process.env.FDISK_BASE_URL ?? 'https://app.fdisk.at';
|
||||
let ID_FEUERWEHREN = process.env.FDISK_ID_FEUERWEHREN ?? '164';
|
||||
let ID_INSTANZEN = process.env.FDISK_ID_INSTANZEN ?? '2853';
|
||||
|
||||
let LOGIN_URL = `${BASE_URL}/fdisk/module/vws/logins/logins.aspx`;
|
||||
let MEMBERS_URL = `${BASE_URL}/fdisk/module/mgvw/mitgliedschaften/meine_Mitglieder.aspx`;
|
||||
|
||||
/**
|
||||
* Maps a raw FDISK status string to a dashboard status value.
|
||||
@@ -173,13 +181,20 @@ async function scrapeKnownMembers(
|
||||
return members;
|
||||
}
|
||||
|
||||
export async function scrapeAll(username: string, password: string): Promise<{
|
||||
export async function scrapeAll(config: FdiskConfig): Promise<{
|
||||
members: FdiskMember[];
|
||||
ausbildungen: FdiskAusbildung[];
|
||||
befoerderungen: FdiskBefoerderung[];
|
||||
untersuchungen: FdiskUntersuchung[];
|
||||
fahrgenehmigungen: FdiskFahrgenehmigung[];
|
||||
}> {
|
||||
// Apply config to module-level variables used by helper functions
|
||||
BASE_URL = config.baseUrl;
|
||||
ID_FEUERWEHREN = config.idFeuerwehren;
|
||||
ID_INSTANZEN = config.idInstanzen;
|
||||
LOGIN_URL = `${BASE_URL}/fdisk/module/vws/logins/logins.aspx`;
|
||||
MEMBERS_URL = `${BASE_URL}/fdisk/module/mgvw/mitgliedschaften/meine_Mitglieder.aspx`;
|
||||
|
||||
const browser = await chromium.launch({
|
||||
headless: true,
|
||||
args: ['--disable-gpu', '--disable-software-rasterizer'],
|
||||
@@ -190,7 +205,7 @@ export async function scrapeAll(username: string, password: string): Promise<{
|
||||
const page = await context.newPage();
|
||||
|
||||
try {
|
||||
await login(page, username, password);
|
||||
await login(page, config.username, config.password);
|
||||
|
||||
// After login, page is on Start.aspx (frameset).
|
||||
// Direct navigation to MitgliedschaftenList.aspx causes a server BLError because
|
||||
|
||||
Reference in New Issue
Block a user