-
MariaDB Verbindingsfout (" . htmlspecialchars((string)$e->getCode()) . ")
-
" . htmlspecialchars($e->getMessage()) . "
-
- Host:
" . htmlspecialchars(DB_HOST) . "
- Poort:
" . htmlspecialchars(DB_PORT) . "
- Database:
" . htmlspecialchars(DB_NAME) . "
- Gebruiker:
" . htmlspecialchars(DB_USER) . "
+ // Pen Test beveiliging: in live omgeving geen interne IP's of database-details tonen!
+ if (defined('APP_ENV') && APP_ENV === 'live') {
+ die("
+
+
+
⚠️
+
Database Tijdelijk Niet Bereikbaar
+
+ Er kon geen veilige verbinding tot stand worden gebracht met de database. Probeer het over enkele ogenblikken opnieuw.
+
-
- ");
+ ");
+ } else {
+ die("
+
+
+
MariaDB Verbindingsfout (" . htmlspecialchars((string)$e->getCode()) . ")
+
" . htmlspecialchars($e->getMessage()) . "
+
+ Host: " . htmlspecialchars(DB_HOST) . "
+ Poort: " . htmlspecialchars(DB_PORT) . "
+ Database: " . htmlspecialchars(DB_NAME) . "
+ Gebruiker: " . htmlspecialchars(DB_USER) . "
+
+
+
+ ");
+ }
}
}
/**
- * Zorgt ervoor dat alle benodigde tabellen uit schema.sql aanwezig zijn in MariaDB
- * Voert niets uit als de tabellen al bestaan!
+ * Zorgt ervoor dat ALLE benodigde tabellen en kolommen uit schema.sql aanwezig zijn in MariaDB
+ * Voert elke tabel individueel uit zodat ontbrekende tabellen direct aangemaakt worden.
*/
function ensure_tables_exist(PDO $pdo): void {
- try {
- // Controleer of de hoofdtabel 'users' al bestaat
- $result = $pdo->query("SHOW TABLES LIKE 'users'");
- if ($result && $result->rowCount() > 0) {
- // Tabellen bestaan al. Voer eventuele niet-destructieve kolom-upgrades uit indien nodig
- try {
- $pdo->exec("ALTER TABLE tasks MODIFY external_id VARCHAR(255) NULL");
- } catch (Throwable $t) {
- // Kolom bestaat wellicht al of heeft al de juiste lengte
- }
- return;
- }
+ static $tablesChecked = false;
+ if ($tablesChecked) return;
+ $tablesChecked = true;
- // Tabellen ontbreken nog: voer schema.sql uit statement voor statement
+ try {
$schemaFile = file_exists(__DIR__ . '/schema.sql') ? (__DIR__ . '/schema.sql') : (__DIR__ . '/../schema.sql');
if (file_exists($schemaFile)) {
$sql = file_get_contents($schemaFile);
$statements = array_filter(array_map('trim', explode(';', $sql)));
foreach ($statements as $stmt) {
- // Verwijder eventuele SQL commentaren aan het begin
$stmtClean = preg_replace('/^--.*$/m', '', $stmt);
$stmtClean = trim($stmtClean);
if (!empty($stmtClean)) {
- $pdo->exec($stmtClean);
+ try {
+ $pdo->exec($stmtClean);
+ } catch (Throwable $t) {
+ // Stil negeren indien tabel of relatie al bestaat
+ }
}
}
}
- } catch (Exception $e) {
- error_log("Fout bij aanmaken tabellen: " . $e->getMessage());
+
+ // Zorg ervoor dat alle kolommen en upgrades aanwezig zijn
+ $colUpgrades = [
+ "ALTER TABLE tasks MODIFY external_id VARCHAR(255) NULL",
+ "ALTER TABLE tasks ADD COLUMN external_url TEXT NULL AFTER external_id",
+ "ALTER TABLE users ADD COLUMN remember_token VARCHAR(64) NULL AFTER backup_codes",
+ "ALTER TABLE users ADD COLUMN remember_token_expires_at DATETIME NULL AFTER remember_token",
+ "ALTER TABLE users ADD COLUMN notification_settings TEXT NULL AFTER remember_token_expires_at",
+ "ALTER TABLE users ADD COLUMN theme VARCHAR(20) NOT NULL DEFAULT 'dark' AFTER notification_settings",
+ "ALTER TABLE users ADD COLUMN avatar_url VARCHAR(255) NULL AFTER theme",
+ "ALTER TABLE users ADD COLUMN backup_codes TEXT NULL AFTER two_factor_enabled",
+ ];
+ foreach ($colUpgrades as $sql) {
+ try {
+ $pdo->exec($sql);
+ } catch (Throwable $t) {
+ // Stil negeren indien kolom al bestaat
+ }
+ }
+ } catch (Throwable $e) {
+ error_log("Fout bij controleren tabellen: " . $e->getMessage());
}
}
diff --git a/config/index.php b/config/index.php
new file mode 100644
index 0000000..c5903e4
--- /dev/null
+++ b/config/index.php
@@ -0,0 +1,3 @@
+prepare("SELECT * FROM integrations WHERE user_id = ?");
-$stmtInt->execute([$userId]);
$userIntegrations = [];
-foreach ($stmtInt->fetchAll() as $row) {
- $userIntegrations[$row['provider']] = $row;
+try {
+ $stmtInt = $db->prepare("SELECT * FROM integrations WHERE user_id = ?");
+ $stmtInt->execute([$userId]);
+ foreach ($stmtInt->fetchAll() as $row) {
+ $userIntegrations[$row['provider']] = $row;
+ }
+} catch (Throwable $e) {
+ error_log("Fout bij ophalen integraties: " . $e->getMessage());
+ ensure_tables_exist($db);
}
$isOutlookConnected = !empty($userIntegrations['OUTLOOK']['access_token']) && empty($userIntegrations['OUTLOOK']['is_demo_mode']);
@@ -58,12 +63,18 @@ $weekOutlookEvents = [];
$isLiveOutlook = false;
if ($isOutlookConnected) {
- // Haal afspraken op voor het volledige datumbereik van de week
- $weekOutlookEvents = microsoft_fetch_events_range($userId, $weekStart, $weekEnd);
- $isLiveOutlook = true;
+ try {
+ // Haal afspraken op voor het volledige datumbereik van de week
+ $weekOutlookEvents = microsoft_fetch_events_range($userId, $weekStart, $weekEnd);
+ $isLiveOutlook = true;
- // Synchroniseer / reconcilieer Fociz taken direct met actuele Outlook data
- microsoft_reconcile_tasks_with_outlook($userId, $weekStart, $weekEnd, $weekOutlookEvents);
+ // Synchroniseer / reconcilieer Fociz taken direct met actuele Outlook data
+ microsoft_reconcile_tasks_with_outlook($userId, $weekStart, $weekEnd, $weekOutlookEvents);
+ } catch (Throwable $e) {
+ error_log("Outlook synchronisatiefout in planner: " . $e->getMessage());
+ $isLiveOutlook = false;
+ $weekOutlookEvents = [];
+ }
} else {
// Demo data indien Microsoft Outlook nog niet gekoppeld is
$weekOutlookEvents = [
@@ -101,45 +112,64 @@ if ($isOutlookConnected) {
}
// 2. Haal dagplanning op of maak aan voor $selectedDate
-$stmtPlan = $db->prepare("SELECT * FROM daily_plans WHERE user_id = ? AND plan_date = ?");
-$stmtPlan->execute([$userId, $selectedDate]);
-$dailyPlan = $stmtPlan->fetch();
+$dailyPlan = null;
+try {
+ $stmtPlan = $db->prepare("SELECT * FROM daily_plans WHERE user_id = ? AND plan_date = ?");
+ $stmtPlan->execute([$userId, $selectedDate]);
+ $dailyPlan = $stmtPlan->fetch();
-if (!$dailyPlan) {
- $defaultGoal = ($selectedDate === $today) ? 'Mijn belangrijkste doel van vandaag behalen' : 'Focusdoel voor deze dag bepalen';
- $stmtCreatePlan = $db->prepare("
- INSERT INTO daily_plans (user_id, plan_date, focus_goal)
- VALUES (?, ?, ?)
- ");
- $stmtCreatePlan->execute([$userId, $selectedDate, $defaultGoal]);
- $planId = (int)$db->lastInsertId();
- $dailyPlan = ['id' => $planId, 'plan_date' => $selectedDate, 'focus_goal' => $defaultGoal, 'notes' => ''];
+ if (!$dailyPlan) {
+ $defaultGoal = ($selectedDate === $today) ? 'Mijn belangrijkste doel van vandaag behalen' : 'Focusdoel voor deze dag bepalen';
+ $stmtCreatePlan = $db->prepare("
+ INSERT INTO daily_plans (user_id, plan_date, focus_goal)
+ VALUES (?, ?, ?)
+ ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id)
+ ");
+ $stmtCreatePlan->execute([$userId, $selectedDate, $defaultGoal]);
+ $planId = (int)$db->lastInsertId();
+ $dailyPlan = ['id' => $planId, 'plan_date' => $selectedDate, 'focus_goal' => $defaultGoal, 'notes' => ''];
+ }
+} catch (Throwable $e) {
+ error_log("Fout bij dagplanning ophalen/aanmaken: " . $e->getMessage());
+ ensure_tables_exist($db);
+ $dailyPlan = ['id' => 0, 'plan_date' => $selectedDate, 'focus_goal' => 'Mijn belangrijkste doel van vandaag behalen', 'notes' => ''];
}
+$planId = !empty($dailyPlan['id']) ? (int)$dailyPlan['id'] : 0;
+
// 3. Haal taken op voor de geselecteerde dag (vers bijgewerkt na eventuele reconciliatie)
-$stmtTasks = $db->prepare("
- SELECT * FROM tasks
- WHERE user_id = ? AND (daily_plan_id = ? " . ($selectedDate === $today ? "OR daily_plan_id IS NULL" : "") . ")
- ORDER BY is_completed ASC, priority ASC, time_block_start ASC, created_at DESC
-");
-$stmtTasks->execute([$userId, $dailyPlan['id']]);
-$tasks = $stmtTasks->fetchAll();
+$tasks = [];
+try {
+ $stmtTasks = $db->prepare("
+ SELECT * FROM tasks
+ WHERE user_id = ? AND (daily_plan_id = ? " . ($selectedDate === $today ? "OR daily_plan_id IS NULL" : "") . ")
+ ORDER BY is_completed ASC, priority ASC, time_block_start ASC, created_at DESC
+ ");
+ $stmtTasks->execute([$userId, $planId]);
+ $tasks = $stmtTasks->fetchAll() ?: [];
+} catch (Throwable $e) {
+ error_log("Fout bij ophalen taken: " . $e->getMessage());
+}
// 4. Haal weekstatistieken voor taken op (aantal per dag)
-$stmtWeekTasks = $db->prepare("
- SELECT dp.plan_date, COUNT(t.id) as total_tasks, SUM(CASE WHEN t.is_completed = 1 THEN 1 ELSE 0 END) as completed_tasks
- FROM daily_plans dp
- LEFT JOIN tasks t ON t.daily_plan_id = dp.id AND t.user_id = ?
- WHERE dp.user_id = ? AND dp.plan_date BETWEEN ? AND ?
- GROUP BY dp.plan_date
-");
-$stmtWeekTasks->execute([$userId, $userId, $weekStart, $weekEnd]);
$weekTaskStats = [];
-foreach ($stmtWeekTasks->fetchAll() as $row) {
- $weekTaskStats[$row['plan_date']] = [
- 'total' => (int)$row['total_tasks'],
- 'completed' => (int)$row['completed_tasks'],
- ];
+try {
+ $stmtWeekTasks = $db->prepare("
+ SELECT dp.plan_date, COUNT(t.id) as total_tasks, SUM(CASE WHEN t.is_completed = 1 THEN 1 ELSE 0 END) as completed_tasks
+ FROM daily_plans dp
+ LEFT JOIN tasks t ON t.daily_plan_id = dp.id AND t.user_id = ?
+ WHERE dp.user_id = ? AND dp.plan_date BETWEEN ? AND ?
+ GROUP BY dp.plan_date
+ ");
+ $stmtWeekTasks->execute([$userId, $userId, $weekStart, $weekEnd]);
+ foreach ($stmtWeekTasks->fetchAll() as $row) {
+ $weekTaskStats[$row['plan_date']] = [
+ 'total' => (int)$row['total_tasks'],
+ 'completed' => (int)$row['completed_tasks'],
+ ];
+ }
+} catch (Throwable $e) {
+ error_log("Fout bij weekstatistieken ophalen: " . $e->getMessage());
}
// Groepeer Outlook afspraken per datum
@@ -174,9 +204,15 @@ for ($i = 0; $i < 7; $i++) {
}
// 5. Haal Jira issues op voor de snelle import widget
-$jiraData = jira_get_user_issues($userId);
-$jiraIssues = $jiraData['issues'] ?? [];
-$isJiraLive = !empty($jiraData['success']) && empty($jiraData['is_demo']);
+$jiraIssues = [];
+$isJiraLive = false;
+try {
+ $jiraData = jira_get_user_issues($userId);
+ $jiraIssues = $jiraData['issues'] ?? [];
+ $isJiraLive = !empty($jiraData['success']) && empty($jiraData['is_demo']);
+} catch (Throwable $e) {
+ error_log("Fout bij ophalen Jira issues: " . $e->getMessage());
+}
// Filter Outlook events die afkomstig zijn van Fociz taken voor de geselecteerde dag om duplicaten op de tijdlijn te voorkomen
$dayOutlookEvents = $outlookEventsByDate[$selectedDate] ?? [];
diff --git a/roadmap.php b/roadmap.php
index 8412c62..536ae56 100644
--- a/roadmap.php
+++ b/roadmap.php
@@ -27,10 +27,15 @@ if ($selectedStatus !== 'ALL') {
$params[] = $selectedStatus;
}
-$sql .= " ORDER BY r.quarter ASC, r.priority DESC, r.due_date ASC";
-$stmt = $db->prepare($sql);
-$stmt->execute($params);
-$roadmapItems = $stmt->fetchAll();
+$roadmapItems = [];
+try {
+ $stmt = $db->prepare($sql);
+ $stmt->execute($params);
+ $roadmapItems = $stmt->fetchAll() ?: [];
+} catch (Throwable $e) {
+ error_log("Fout bij ophalen roadmap items: " . $e->getMessage());
+ ensure_tables_exist($db);
+}
$quarters = ['Q1', 'Q2', 'Q3', 'Q4'];
?>
diff --git a/users.php b/users.php
index e601a69..db908af 100644
--- a/users.php
+++ b/users.php
@@ -55,15 +55,26 @@ if (isset($_GET['delete_user'])) {
}
// Haal alle gebruikers op
-$users = $db->query("SELECT * FROM users ORDER BY created_at DESC")->fetchAll();
+$users = [];
+try {
+ $users = $db->query("SELECT * FROM users ORDER BY created_at DESC")->fetchAll() ?: [];
+} catch (Throwable $e) {
+ error_log("Fout bij ophalen gebruikers: " . $e->getMessage());
+}
// Haal alle uitnodigingen op
-$invites = $db->query("
- SELECT i.*, u.name as inviter_name
- FROM invites i
- JOIN users u ON i.created_by_id = u.id
- ORDER BY i.created_at DESC
-")->fetchAll();
+$invites = [];
+try {
+ $invites = $db->query("
+ SELECT i.*, u.name as inviter_name
+ FROM invites i
+ JOIN users u ON i.created_by_id = u.id
+ ORDER BY i.created_at DESC
+ ")->fetchAll() ?: [];
+} catch (Throwable $e) {
+ error_log("Fout bij ophalen uitnodigingen: " . $e->getMessage());
+ ensure_tables_exist($db);
+}
$pageTitle = 'Team & Uitnodigingen — Fociz';
require_once __DIR__ . '/includes/header.php';