Compare commits
2 Commits
df6dadee6f
...
35b8fa24f5
| Author | SHA1 | Date | |
|---|---|---|---|
| 35b8fa24f5 | |||
| 291fb761c7 |
@@ -516,7 +516,7 @@ require_once __DIR__ . '/includes/header.php';
|
||||
<div class="flex items-start space-x-2.5">
|
||||
<span class="w-5 h-5 rounded-full bg-sky-500/20 text-sky-600 dark:text-sky-400 flex items-center justify-center font-bold text-[10px] flex-shrink-0 mt-0.5">3</span>
|
||||
<div>
|
||||
<strong class="text-slate-900 dark:text-white">API Permissions:</strong> Ga naar <em>API permissions</em> → <em>Add a permission</em> → <em>Microsoft Graph</em> → <strong>Delegated permissions</strong> → Vink aan: <code class="text-sky-600 dark:text-sky-400">User.Read</code> en <code class="text-sky-600 dark:text-sky-400">Calendars.ReadWrite</code>.
|
||||
<strong class="text-slate-900 dark:text-white">API Permissions:</strong> Ga naar <em>API permissions</em> → <em>Add a permission</em> → <em>Microsoft Graph</em> → <strong>Delegated permissions</strong> → Vink aan: <code class="text-sky-600 dark:text-sky-400">User.Read</code>, <code class="text-sky-600 dark:text-sky-400">Calendars.ReadWrite</code>, <code class="text-sky-600 dark:text-sky-400">Mail.ReadWrite</code> en <code class="text-sky-600 dark:text-sky-400">Mail.Send</code>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -138,7 +138,14 @@ $saveStmt = $db->prepare("
|
||||
");
|
||||
$saveStmt->execute([$user['id'], $accessToken, $refreshToken, json_encode($newSettings)]);
|
||||
|
||||
// 8. Succesvol terugkeren naar de Persoonlijke Profiel Hub
|
||||
header('Location: /profile.php?success=' . urlencode("Microsoft Outlook succesvol gekoppeld als {$accountEmail}!"));
|
||||
// 8. Succesvol terugkeren naar de gewenste pagina of het Persoonlijk Profiel
|
||||
$returnTo = $_SESSION['ms_oauth_return_to'] ?? '/profile.php';
|
||||
unset($_SESSION['ms_oauth_return_to']);
|
||||
|
||||
$redirectUrl = ($returnTo === '/mail.php')
|
||||
? '/mail.php?success=' . urlencode("Microsoft Outlook 365 e-mail & agenda succesvol gekoppeld als {$accountEmail}!")
|
||||
: '/profile.php?success=' . urlencode("Microsoft Outlook succesvol gekoppeld als {$accountEmail}!");
|
||||
|
||||
header('Location: ' . $redirectUrl);
|
||||
exit;
|
||||
|
||||
|
||||
@@ -43,8 +43,17 @@ $state = generate_oauth_state((int)$user['id']);
|
||||
$_SESSION['ms_oauth_state'] = $state;
|
||||
$_SESSION['ms_oauth_user_id'] = (int)$user['id'];
|
||||
|
||||
// Onthoud eventuele gewenste terugkeerpagina (bijv. /mail.php)
|
||||
if (!empty($_GET['return_to'])) {
|
||||
$_SESSION['ms_oauth_return_to'] = trim($_GET['return_to']);
|
||||
} else {
|
||||
unset($_SESSION['ms_oauth_return_to']);
|
||||
}
|
||||
|
||||
$forceConsent = !empty($_GET['reconsent']) || !empty($_GET['force']);
|
||||
|
||||
// Stuur gebruiker door naar Microsoft login
|
||||
$authUrl = microsoft_get_auth_url($clientId, $redirectUri, $tenantId, $state);
|
||||
$authUrl = microsoft_get_auth_url($clientId, $redirectUri, $tenantId, $state, $forceConsent);
|
||||
header("Location: {$authUrl}");
|
||||
exit;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ require_once __DIR__ . '/../../config/database.php';
|
||||
const MS_OAUTH_AUTHORIZE_URL = 'https://login.microsoftonline.com/%s/oauth2/v2.0/authorize';
|
||||
const MS_OAUTH_TOKEN_URL = 'https://login.microsoftonline.com/%s/oauth2/v2.0/token';
|
||||
const MS_GRAPH_BASE_URL = 'https://graph.microsoft.com/v1.0';
|
||||
const MS_DEFAULT_SCOPES = 'offline_access User.Read Calendars.ReadWrite Mail.ReadWrite Mail.Send';
|
||||
const MS_DEFAULT_SCOPES = 'offline_access User.Read Calendars.ReadWrite Mail.ReadWrite Mail.Send OnlineMeetings.ReadWrite';
|
||||
|
||||
/**
|
||||
* Haalt de centrale Microsoft App Registratie configuratie op (Client ID, Secret, Tenant ID)
|
||||
@@ -125,7 +125,7 @@ function microsoft_get_app_config(): array {
|
||||
/**
|
||||
* Genereert de Microsoft OAuth2 login URL
|
||||
*/
|
||||
function microsoft_get_auth_url(string $clientId, string $redirectUri, string $tenantId = '', string $state = ''): string {
|
||||
function microsoft_get_auth_url(string $clientId, string $redirectUri, string $tenantId = '', string $state = '', bool $forceConsent = false): string {
|
||||
$tenant = (!empty($tenantId) && $tenantId !== 'common') ? trim($tenantId) : 'planningsagenda.nl';
|
||||
$baseUrl = sprintf(MS_OAUTH_AUTHORIZE_URL, urlencode($tenant));
|
||||
|
||||
@@ -136,7 +136,7 @@ function microsoft_get_auth_url(string $clientId, string $redirectUri, string $t
|
||||
'response_mode' => 'query',
|
||||
'scope' => MS_DEFAULT_SCOPES,
|
||||
'state' => $state,
|
||||
'prompt' => 'select_account',
|
||||
'prompt' => $forceConsent ? 'consent' : 'select_account',
|
||||
];
|
||||
|
||||
return $baseUrl . '?' . http_build_query($params);
|
||||
@@ -1038,16 +1038,26 @@ function microsoft_fetch_inbox_messages(int $userId, int $limit = 25, bool $unre
|
||||
]);
|
||||
|
||||
if ($res['status'] !== 200 || !isset($res['json']['value'])) {
|
||||
error_log("Microsoft fetch inbox error: HTTP {$res['status']} - " . ($res['error'] ?? json_encode($res['json'])));
|
||||
// Val terug op demo data indien API fout optreedt
|
||||
$graphError = $res['json']['error']['message'] ?? ($res['error'] ?? 'HTTP ' . $res['status']);
|
||||
$graphCode = $res['json']['error']['code'] ?? '';
|
||||
error_log("Microsoft fetch inbox error: HTTP {$res['status']} [{$graphCode}] - {$graphError}");
|
||||
|
||||
$demo = microsoft_get_mail_demo_data();
|
||||
$needsReconsent = ($res['status'] === 403 || stripos($graphError, 'access') !== false || stripos($graphError, 'privilege') !== false || stripos($graphError, 'denied') !== false || stripos($graphError, 'consent') !== false);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'is_demo' => true,
|
||||
'messages' => array_slice($demo, 0, $limit),
|
||||
'unread_count' => count(array_filter($demo, function($m) { return empty($m['is_read']); })),
|
||||
'total_count' => count($demo),
|
||||
'warning' => 'Kon live e-mails niet ophalen van Microsoft Graph. Demomodus actief.',
|
||||
'warning' => $needsReconsent
|
||||
? 'Je Microsoft koppeling mist machtiging voor e-mail (Mail.ReadWrite). Autoriseer opnieuw om je inbox live in te laden.'
|
||||
: 'Kon live e-mails niet ophalen van Microsoft Graph (' . $graphError . '). Demomodus actief.',
|
||||
'needs_reconsent' => $needsReconsent,
|
||||
'graph_error' => $graphError,
|
||||
'graph_code' => $graphCode,
|
||||
'http_status' => $res['status'],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -16,18 +16,33 @@ $inboxData = microsoft_fetch_inbox_messages($userId, 30);
|
||||
$messages = $inboxData['messages'] ?? [];
|
||||
$isDemo = !empty($inboxData['is_demo']);
|
||||
$unreadCount = (int)($inboxData['unread_count'] ?? 0);
|
||||
$warning = $inboxData['warning'] ?? '';
|
||||
$needsReconsent = !empty($inboxData['needs_reconsent']);
|
||||
|
||||
// Controleer status
|
||||
$stmtInt = $db->prepare("SELECT * FROM integrations WHERE user_id = ? AND provider = 'OUTLOOK' AND is_enabled = 1");
|
||||
$stmtInt->execute([$userId]);
|
||||
$outlookInt = $stmtInt->fetch();
|
||||
$isLiveOutlook = !empty($outlookInt['access_token']) && empty($outlookInt['is_demo_mode']);
|
||||
$isOutlookConfigured = !empty($outlookInt['access_token']) && empty($outlookInt['is_demo_mode']);
|
||||
$isLiveMail = $isOutlookConfigured && !$isDemo;
|
||||
|
||||
$jsonMessages = json_encode($messages, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);
|
||||
?>
|
||||
|
||||
<div class="max-w-7xl mx-auto space-y-6">
|
||||
|
||||
<?php if (!empty($_GET['success'])): ?>
|
||||
<div class="p-4 rounded-2xl bg-emerald-50 dark:bg-emerald-950/40 border border-emerald-200 dark:border-emerald-800/60 flex items-center space-x-2.5 text-xs text-emerald-800 dark:text-emerald-200 shadow-2xs">
|
||||
<i data-lucide="check-circle-2" class="w-4 h-4 text-emerald-600 dark:text-emerald-400 flex-shrink-0"></i>
|
||||
<span><?= htmlspecialchars($_GET['success']) ?></span>
|
||||
</div>
|
||||
<?php elseif (!empty($_GET['error'])): ?>
|
||||
<div class="p-4 rounded-2xl bg-rose-50 dark:bg-rose-950/40 border border-rose-200 dark:border-rose-800/60 flex items-center space-x-2.5 text-xs text-rose-800 dark:text-rose-200 shadow-2xs">
|
||||
<i data-lucide="alert-circle" class="w-4 h-4 text-rose-600 dark:text-rose-400 flex-shrink-0"></i>
|
||||
<span><?= htmlspecialchars($_GET['error']) ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Top Banner: Status & Snelle Acties -->
|
||||
<div class="fociz-card p-6 sm:p-7 relative overflow-hidden">
|
||||
<div class="flex flex-col lg:flex-row lg:items-center justify-between gap-4">
|
||||
@@ -35,8 +50,10 @@ $jsonMessages = json_encode($messages, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_Q
|
||||
<div class="flex items-center space-x-2 text-sky-600 dark:text-sky-400 text-xs font-bold uppercase tracking-wider mb-1">
|
||||
<i data-lucide="mail" class="w-4 h-4"></i>
|
||||
<span>Microsoft Outlook 365 • Inbox</span>
|
||||
<?php if ($isLiveOutlook): ?>
|
||||
<?php if ($isLiveMail): ?>
|
||||
<span class="px-2.5 py-0.5 rounded-full text-[10px] font-extrabold bg-emerald-50 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300 ring-1 ring-emerald-500/30">LIVE VERBONDEN</span>
|
||||
<?php elseif ($isOutlookConfigured && $isDemo): ?>
|
||||
<span class="px-2.5 py-0.5 rounded-full text-[10px] font-extrabold bg-amber-50 text-amber-700 dark:bg-amber-500/15 dark:text-amber-300 ring-1 ring-amber-500/30">E-MAIL MACHTIGING VEREIST</span>
|
||||
<?php else: ?>
|
||||
<span class="px-2.5 py-0.5 rounded-full text-[10px] font-bold bg-amber-50 text-amber-700 dark:bg-amber-500/15 dark:text-amber-300 ring-1 ring-amber-500/30">DEMO INBOX</span>
|
||||
<?php endif; ?>
|
||||
@@ -56,10 +73,10 @@ $jsonMessages = json_encode($messages, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_Q
|
||||
<span>Vernieuwen</span>
|
||||
</button>
|
||||
|
||||
<?php if (!$isLiveOutlook): ?>
|
||||
<a href="/profile.php" class="flex items-center space-x-1.5 px-4 py-2 rounded-xl bg-gradient-to-r from-sky-600 to-indigo-600 hover:from-sky-500 hover:to-indigo-500 text-white text-xs font-bold transition shadow-sm shadow-sky-600/20">
|
||||
<?php if (!$isLiveMail): ?>
|
||||
<a href="/auth/oauth_microsoft.php?reconsent=1&return_to=/mail.php" class="flex items-center space-x-1.5 px-4 py-2 rounded-xl bg-gradient-to-r from-sky-600 to-indigo-600 hover:from-sky-500 hover:to-indigo-500 text-white text-xs font-bold transition shadow-sm shadow-sky-600/20">
|
||||
<i data-lucide="link-2" class="w-3.5 h-3.5"></i>
|
||||
<span>Live Outlook Koppelen</span>
|
||||
<span><?= $isOutlookConfigured ? 'Machtigingen Bijwerken' : 'Live Outlook Koppelen' ?></span>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<a href="https://outlook.office.com/mail/" target="_blank" rel="noopener noreferrer" class="flex items-center space-x-1.5 px-3.5 py-2 rounded-xl bg-sky-50 dark:bg-sky-950/40 text-sky-700 dark:text-sky-300 border border-sky-200 dark:border-sky-800/60 text-xs font-bold transition hover:bg-sky-100">
|
||||
@@ -70,13 +87,30 @@ $jsonMessages = json_encode($messages, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_Q
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!$isLiveOutlook): ?>
|
||||
<?php if ($isOutlookConfigured && $isDemo): ?>
|
||||
<div class="mt-5 p-4 rounded-2xl bg-amber-50/90 dark:bg-amber-950/40 border border-amber-300 dark:border-amber-700/60 flex flex-col sm:flex-row sm:items-center justify-between gap-4 text-xs text-amber-900 dark:text-amber-200 shadow-2xs">
|
||||
<div class="flex items-start sm:items-center space-x-3">
|
||||
<div class="w-8 h-8 rounded-xl bg-amber-500/20 text-amber-600 dark:text-amber-400 flex items-center justify-center flex-shrink-0 font-bold">
|
||||
<i data-lucide="shield-alert" class="w-4 h-4"></i>
|
||||
</div>
|
||||
<div>
|
||||
<span class="font-bold block text-amber-950 dark:text-amber-100">E-mail permissie ontbreekt (Herautorisatie vereist)</span>
|
||||
<span class="text-[11px] text-amber-800 dark:text-amber-300">
|
||||
Je Microsoft account is gekoppeld voor je agenda, maar het huidige token heeft nog geen toestemming voor e-mail (<code class="font-mono bg-amber-100 dark:bg-amber-900/60 px-1 py-0.5 rounded text-[10px]">Mail.ReadWrite</code>). Klik op <strong>Machtigingen Bijwerken</strong> om eenmalig toestemming te verlenen.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<a href="/auth/oauth_microsoft.php?reconsent=1&return_to=/mail.php" class="px-4 py-2 rounded-xl bg-amber-600 hover:bg-amber-500 text-white font-bold text-xs shadow-xs transition whitespace-nowrap flex-shrink-0 text-center cursor-pointer">
|
||||
Machtigingen Bijwerken →
|
||||
</a>
|
||||
</div>
|
||||
<?php elseif (!$isOutlookConfigured): ?>
|
||||
<div class="mt-5 p-3.5 rounded-2xl bg-amber-50/80 dark:bg-amber-950/30 border border-amber-200 dark:border-amber-900/40 flex items-center justify-between gap-3 text-xs text-amber-900 dark:text-amber-200">
|
||||
<div class="flex items-center space-x-2.5">
|
||||
<i data-lucide="info" class="w-4 h-4 text-amber-600 dark:text-amber-400 flex-shrink-0"></i>
|
||||
<span>Je bekijkt momenteel een interactieve demonstratieset. Koppel je zakelijke Microsoft 365 account via Profiel om al je live zakelijke e-mails in te laden.</span>
|
||||
<span>Je bekijkt momenteel een interactieve demonstratieset. Koppel je zakelijke Microsoft 365 account om al je live zakelijke e-mails in te laden.</span>
|
||||
</div>
|
||||
<a href="/auth/oauth_microsoft.php" class="font-bold underline hover:text-amber-700 dark:hover:text-amber-100 flex-shrink-0">Nu koppelen →</a>
|
||||
<a href="/auth/oauth_microsoft.php?return_to=/mail.php" class="font-bold underline hover:text-amber-700 dark:hover:text-amber-100 flex-shrink-0">Nu koppelen →</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
+8
-1
@@ -234,10 +234,12 @@ try {
|
||||
// 5b. Haal recente e-mails op voor de Outlook E-mail Widget
|
||||
$recentEmails = [];
|
||||
$unreadEmailCount = 0;
|
||||
$mailNeedsReconsent = false;
|
||||
try {
|
||||
$mailData = microsoft_fetch_inbox_messages($userId, 5);
|
||||
$recentEmails = $mailData['messages'] ?? [];
|
||||
$unreadEmailCount = (int)($mailData['unread_count'] ?? 0);
|
||||
$mailNeedsReconsent = !empty($mailData['needs_reconsent']);
|
||||
} catch (Throwable $e) {
|
||||
error_log("Fout bij ophalen recente e-mails in planner: " . $e->getMessage());
|
||||
}
|
||||
@@ -934,7 +936,12 @@ for ($h = $startHour; $h <= $endHour; $h++) {
|
||||
<h3 class="text-xs font-bold text-slate-900 dark:text-white uppercase tracking-wider">
|
||||
Outlook E-mail
|
||||
</h3>
|
||||
<?php if ($unreadEmailCount > 0): ?>
|
||||
<?php if ($mailNeedsReconsent): ?>
|
||||
<a href="/auth/oauth_microsoft.php?reconsent=1&return_to=/planner.php" class="px-2 py-0.5 rounded-full text-[10px] font-bold bg-amber-50 dark:bg-amber-500/15 text-amber-700 dark:text-amber-400 border border-amber-200 dark:border-amber-500/30 hover:underline flex items-center space-x-1" title="Klik om e-mail toestemming te verlenen bij Microsoft">
|
||||
<i data-lucide="shield-alert" class="w-3 h-3 text-amber-600"></i>
|
||||
<span>Machtiging vereist →</span>
|
||||
</a>
|
||||
<?php elseif ($unreadEmailCount > 0): ?>
|
||||
<span class="px-2 py-0.5 rounded-full text-[10px] font-bold bg-rose-50 dark:bg-rose-500/15 text-rose-700 dark:text-rose-400 border border-rose-200 dark:border-rose-500/30">
|
||||
<?= $unreadEmailCount ?> ongelezen
|
||||
</span>
|
||||
|
||||
+4
-4
@@ -651,7 +651,7 @@ require_once __DIR__ . '/includes/header.php';
|
||||
</div>
|
||||
<div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<h2 class="text-base sm:text-lg font-bold text-slate-900 dark:text-white tracking-tight">Mijn Microsoft 365 Agenda</h2>
|
||||
<h2 class="text-base sm:text-lg font-bold text-slate-900 dark:text-white tracking-tight">Mijn Microsoft 365 (Agenda & E-mail)</h2>
|
||||
<?php if ($isOutlookConnected): ?>
|
||||
<span class="px-2.5 py-0.5 rounded-full bg-teal-50 dark:bg-teal-500/15 border border-teal-200 dark:border-teal-500/30 text-teal-700 dark:text-teal-400 text-[10px] font-semibold flex items-center space-x-1">
|
||||
<span class="w-1.5 h-1.5 rounded-full bg-teal-500 animate-pulse"></span>
|
||||
@@ -663,14 +663,14 @@ require_once __DIR__ . '/includes/header.php';
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<p class="text-xs text-slate-500 dark:text-slate-400">Synchroniseer uw agenda-afspraken automatisch met uw dagplanning</p>
|
||||
<p class="text-xs text-slate-500 dark:text-slate-400">Synchroniseer uw agenda-afspraken en zakelijke Outlook e-mails met Fociz</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($isOutlookConnected): ?>
|
||||
<div class="flex items-center space-x-2">
|
||||
<a href="/auth/oauth_microsoft.php" class="px-3 py-1.5 rounded-xl bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-300 border border-slate-200 dark:border-slate-700 text-xs font-medium transition" title="Opnieuw autoriseren bij Microsoft">
|
||||
Opnieuw Verbinden
|
||||
<a href="/auth/oauth_microsoft.php?reconsent=1" class="px-3 py-1.5 rounded-xl bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-300 border border-slate-200 dark:border-slate-700 text-xs font-medium transition" title="Machtigingen bijwerken bij Microsoft (inclusief Mail.ReadWrite)">
|
||||
Machtigingen Bijwerken
|
||||
</a>
|
||||
<form method="POST" onsubmit="return confirm('Weet u zeker dat u uw Microsoft Outlook agenda wilt ontkoppelen?');">
|
||||
<input type="hidden" name="action" value="disconnect_outlook">
|
||||
|
||||
Reference in New Issue
Block a user