Compare commits

..

2 Commits

2 changed files with 53 additions and 17 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ $tenantId = !empty($_GET['tenant_id'])
: (!empty($savedSettings['tenant_id']) ? $savedSettings['tenant_id'] : fociz_env('MICROSOFT_TENANT_ID', 'common')); : (!empty($savedSettings['tenant_id']) ? $savedSettings['tenant_id'] : fociz_env('MICROSOFT_TENANT_ID', 'common'));
if (empty($clientId)) { if (empty($clientId)) {
header('Location: /integrations.php?error=missing_ms_client_id'); header('Location: /integrations.php?error=' . urlencode('Vul eerst de Application (Client) ID en het Client Secret in bij de Outlook instellingen om te koppelen met Microsoft 365.'));
exit; exit;
} }
+50 -14
View File
@@ -3,12 +3,13 @@
* Fociz Integraties Hub (Microsoft Outlook, Microsoft Teams, Atlassian Jira) * Fociz Integraties Hub (Microsoft Outlook, Microsoft Teams, Atlassian Jira)
*/ */
require_once __DIR__ . '/includes/header.php'; require_once __DIR__ . '/includes/auth.php';
require_once __DIR__ . '/includes/integrations/microsoft.php'; require_once __DIR__ . '/includes/integrations/microsoft.php';
require_once __DIR__ . '/includes/integrations/jira.php'; require_once __DIR__ . '/includes/integrations/jira.php';
$user = require_auth();
$db = get_db_connection(); $db = get_db_connection();
$userId = $currentUser['id']; $userId = $user['id'];
$message = null; $message = null;
$messageType = 'success'; $messageType = 'success';
@@ -22,7 +23,7 @@ if (!empty($_GET['success'])) {
$messageType = 'error'; $messageType = 'error';
} }
// POST Verwerking // POST Verwerking VÓÓR het inladen van header.php zodat HTTP redirects altijd werken
if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$provider = strtoupper(trim($_POST['provider'] ?? '')); $provider = strtoupper(trim($_POST['provider'] ?? ''));
$action = $_POST['action'] ?? 'save'; $action = $_POST['action'] ?? 'save';
@@ -31,18 +32,21 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($action === 'disconnect') { if ($action === 'disconnect') {
if ($provider === 'OUTLOOK') { if ($provider === 'OUTLOOK') {
microsoft_disconnect($userId); microsoft_disconnect($userId);
$message = "Microsoft Outlook is succesvol ontkoppeld."; header('Location: /integrations.php?success=' . urlencode('Microsoft Outlook is succesvol ontkoppeld.'));
exit;
} elseif ($provider === 'JIRA') { } elseif ($provider === 'JIRA') {
jira_disconnect($userId); jira_disconnect($userId);
$message = "Atlassian Jira is succesvol ontkoppeld."; header('Location: /integrations.php?success=' . urlencode('Atlassian Jira is succesvol ontkoppeld.'));
exit;
} }
} }
// 2. Outlook Opslaan // 2. Outlook Opslaan of Koppelen
elseif ($provider === 'OUTLOOK') { elseif ($provider === 'OUTLOOK') {
$clientId = trim($_POST['client_id'] ?? ''); $clientId = trim($_POST['client_id'] ?? '');
$clientSecret = trim($_POST['client_secret'] ?? ''); $clientSecret = trim($_POST['client_secret'] ?? '');
$tenantId = trim($_POST['tenant_id'] ?? 'common'); $tenantId = trim($_POST['tenant_id'] ?? 'common');
if (empty($tenantId)) $tenantId = 'common';
$isDemo = isset($_POST['is_demo_mode']) ? 1 : 0; $isDemo = isset($_POST['is_demo_mode']) ? 1 : 0;
// Haal bestaande tokens op // Haal bestaande tokens op
@@ -71,13 +75,23 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
last_sync_at = NOW() last_sync_at = NOW()
"); ");
$stmt->execute([$userId, $isDemo, json_encode($newSettings)]); $stmt->execute([$userId, $isDemo, json_encode($newSettings)]);
$message = "Instellingen voor Microsoft Outlook zijn opgeslagen.";
// Als gebruiker direct op 'Koppel nu' klikte // Als gebruiker direct op 'Koppel nu' klikte
if ($action === 'connect_oauth') { if ($action === 'connect_oauth') {
if (empty($clientId)) {
$message = "Vul eerst de Application (Client) ID in van uw Azure App Registratie.";
$messageType = 'error';
} elseif (empty($clientSecret)) {
$message = "Vul eerst het Client Secret in van uw Azure App Registratie.";
$messageType = 'error';
} else {
header("Location: /auth/oauth_microsoft.php?client_id=" . urlencode($clientId) . "&tenant_id=" . urlencode($tenantId)); header("Location: /auth/oauth_microsoft.php?client_id=" . urlencode($clientId) . "&tenant_id=" . urlencode($tenantId));
exit; exit;
} }
} else {
$message = "Instellingen voor Microsoft Outlook zijn succesvol opgeslagen.";
$messageType = 'success';
}
} }
// 3. Teams Opslaan // 3. Teams Opslaan
@@ -121,9 +135,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$accountName = $testRes['user']['displayName'] ?? 'Jira Gebruiker'; $accountName = $testRes['user']['displayName'] ?? 'Jira Gebruiker';
$accountId = $testRes['user']['accountId'] ?? ''; $accountId = $testRes['user']['accountId'] ?? '';
$message = "Verbinding met Jira geslaagd! Ingelogd als: {$accountName}"; $message = "Verbinding met Jira geslaagd! Ingelogd als: {$accountName}";
$messageType = 'success';
} }
} else { } else {
$message = "Jira instellingen opgeslagen."; $message = "Jira instellingen opgeslagen.";
$messageType = 'success';
} }
$newSettings = [ $newSettings = [
@@ -149,6 +165,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
} }
} }
// Laad nu pas de HTML header in
require_once __DIR__ . '/includes/header.php';
// Haal huidige configuraties op // Haal huidige configuraties op
$stmtConfigs = $db->prepare("SELECT * FROM integrations WHERE user_id = ?"); $stmtConfigs = $db->prepare("SELECT * FROM integrations WHERE user_id = ?");
$stmtConfigs->execute([$userId]); $stmtConfigs->execute([$userId]);
@@ -300,42 +319,59 @@ $redirectUri = rtrim(APP_URL, '/') . '/auth/callback_microsoft.php';
<input type="hidden" name="provider" value="OUTLOOK"> <input type="hidden" name="provider" value="OUTLOOK">
<div> <div>
<label class="block text-[10px] font-semibold text-slate-400 mb-0.5">Application (Client) ID</label> <label class="block text-[10px] font-semibold text-slate-400 mb-0.5">
Application (Client) ID <span class="text-blue-400">*</span>
</label>
<input <input
type="text" type="text"
name="client_id" name="client_id"
value="<?= htmlspecialchars($outlookSettings['client_id'] ?? fociz_env('MICROSOFT_CLIENT_ID', '')) ?>" value="<?= htmlspecialchars($outlookSettings['client_id'] ?? fociz_env('MICROSOFT_CLIENT_ID', '')) ?>"
placeholder="e.g. 11111111-2222-3333-4444-555555555555" placeholder="bijv. e8f498c1-1234-4567-89ab-cdef01234567"
class="w-full bg-slate-950 border border-slate-800 rounded-lg px-2.5 py-1.5 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-blue-500 font-mono" class="w-full bg-slate-950 border border-slate-800 rounded-lg px-2.5 py-1.5 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-blue-500 font-mono"
> >
<p class="text-[10px] text-slate-500 mt-0.5">Te vinden op de Overzichtspagina (Overview) van uw Azure App Registratie.</p>
</div> </div>
<div> <div>
<label class="block text-[10px] font-semibold text-slate-400 mb-0.5">Client Secret</label> <label class="block text-[10px] font-semibold text-slate-400 mb-0.5">
Client Secret (Geheim) <span class="text-blue-400">*</span>
</label>
<div class="relative"> <div class="relative">
<input <input
type="password" type="password"
id="msClientSecret" id="msClientSecret"
name="client_secret" name="client_secret"
value="<?= !empty($outlookSettings['client_secret']) ? '••••••••••••••••' : htmlspecialchars(fociz_env('MICROSOFT_CLIENT_SECRET', '')) ?>" value="<?= !empty($outlookSettings['client_secret']) ? '••••••••••••••••' : htmlspecialchars(fociz_env('MICROSOFT_CLIENT_SECRET', '')) ?>"
placeholder="Client Secret Value" placeholder="Plak hier de Waarde (Value) van uw Client Secret"
class="w-full bg-slate-950 border border-slate-800 rounded-lg px-2.5 py-1.5 pr-8 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-blue-500 font-mono" class="w-full bg-slate-950 border border-slate-800 rounded-lg px-2.5 py-1.5 pr-8 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-blue-500 font-mono"
> >
<button type="button" onclick="togglePasswordVisibility('msClientSecret')" class="absolute right-2 top-2 text-slate-500 hover:text-slate-300"> <button type="button" onclick="togglePasswordVisibility('msClientSecret')" class="absolute right-2 top-2 text-slate-500 hover:text-slate-300">
<i data-lucide="eye" class="w-3.5 h-3.5"></i> <i data-lucide="eye" class="w-3.5 h-3.5"></i>
</button> </button>
</div> </div>
<p class="text-[10px] text-slate-500 mt-0.5">Aangemaakt onder <em>Certificaten en geheimen &gt; Nieuw clientgeheim</em> (kopieer de <strong>Waarde / Value</strong>).</p>
</div> </div>
<div> <div>
<label class="block text-[10px] font-semibold text-slate-400 mb-0.5">Directory (Tenant) ID</label> <div class="flex items-center justify-between mb-0.5">
<label class="text-[10px] font-semibold text-slate-400">Directory (Tenant) ID</label>
<span class="text-[9px] text-blue-400 font-semibold bg-blue-500/10 px-1.5 py-0.5 rounded">Standaard: common</span>
</div>
<input <input
type="text" type="text"
name="tenant_id" name="tenant_id"
value="<?= htmlspecialchars($outlookSettings['tenant_id'] ?? fociz_env('MICROSOFT_TENANT_ID', 'common')) ?>" value="<?= htmlspecialchars(!empty($outlookSettings['tenant_id']) ? $outlookSettings['tenant_id'] : 'common') ?>"
placeholder="common of specifiek GUID" placeholder="common of organizations"
class="w-full bg-slate-950 border border-slate-800 rounded-lg px-2.5 py-1.5 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-blue-500 font-mono" class="w-full bg-slate-950 border border-slate-800 rounded-lg px-2.5 py-1.5 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-blue-500 font-mono"
> >
<div class="text-[10px] text-slate-400 mt-1.5 leading-relaxed bg-slate-950/80 p-2.5 rounded-lg border border-slate-800/80 space-y-1">
<p class="font-semibold text-slate-300 flex items-center space-x-1">
<span>💡 Wat moet hier staan?</span>
</p>
<p>• Laat simpelweg <code>common</code> staan (werkt voor elk Microsoft account).</p>
<p>• Of vul <code>organizations</code> in voor elk zakelijk Microsoft 365 werkaccount.</p>
<p>• U hoeft alleen uw specifieke Tenant GUID in te vullen als uw Azure app is ingesteld op <em>Single tenant (Alleen mijn eigen organisatie)</em>.</p>
</div>
</div> </div>
<label class="flex items-center space-x-2 text-xs text-slate-300 pt-1"> <label class="flex items-center space-x-2 text-xs text-slate-300 pt-1">