230 lines
No EOL
10 KiB
HTML
230 lines
No EOL
10 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Comptes Outlook - GMAO{% endblock %}
|
|
{% block content %}
|
|
<div class="container-fluid">
|
|
<h1 class="h3 mb-4"><i class="bi bi-envelope"></i> Comptes Outlook</h1>
|
|
|
|
<div class="row">
|
|
<!-- Formulaire d'ajout / re-authentification -->
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="mb-0"><i class="bi bi-microsoft me-2"></i>Connexion OAuth2 Outlook</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<form id="outlook-auth-form">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
<div class="mb-3">
|
|
<label class="form-label">Email professionnel</label>
|
|
<input type="email" name="email" id="email" class="form-control" required
|
|
placeholder="votre.email@ac-college.fr">
|
|
<div class="form-text">Utilisez votre email professionnel Education Nationale</div>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary" id="submit-btn">
|
|
<span id="btn-text">Se connecter avec Outlook</span>
|
|
<span id="btn-spinner" class="spinner-border spinner-border-sm d-none" role="status"></span>
|
|
</button>
|
|
</form>
|
|
<div id="auth-results" class="mt-3"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card mt-3">
|
|
<div class="card-header">
|
|
<h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Instructions</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<ol>
|
|
<li>Entrez votre email professionnel</li>
|
|
<li>Cliquez sur "Se connecter"</li>
|
|
<li>Un code et un lien s'afficheront</li>
|
|
<li>Cliquez sur le lien Microsoft</li>
|
|
<li>Connectez-vous avec vos identifiants Education Nationale</li>
|
|
<li>Entrez le code affiché sur cette page</li>
|
|
<li>La connexion se finalise automatiquement</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Liste des comptes existants -->
|
|
<div class="col-md-6">
|
|
<h5>Comptes configures</h5>
|
|
{% if accounts %}
|
|
{% for account in accounts %}
|
|
<div class="card mb-3 {% if account.connection_status == 'active' %}border-success{% else %}border-warning{% endif %}">
|
|
<div class="card-header {% if account.connection_status == 'active' %}bg-success{% else %}bg-warning{% endif %} text-white">
|
|
<h6 class="mb-0"><i class="bi bi-envelope"></i> {{ account.email }}</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="mb-1">
|
|
<strong>Statut :</strong>
|
|
{% if account.connection_status == 'active' %}
|
|
<span class="badge bg-success"><i class="bi bi-check-circle"></i> Actif</span>
|
|
{% elif account.connection_status == 'pending' %}
|
|
<span class="badge bg-warning text-dark"><i class="bi bi-clock"></i> En attente</span>
|
|
{% else %}
|
|
<span class="badge bg-secondary">{{ account.connection_status or 'Inconnu' }}</span>
|
|
{% endif %}
|
|
</p>
|
|
{% if account.last_connected_at %}
|
|
<p class="mb-1 text-muted small">
|
|
<i class="bi bi-clock"></i> Derniere connexion : {{ account.last_connected_at|datetime_fmt }}
|
|
</p>
|
|
{% endif %}
|
|
{% if account.refresh_token %}
|
|
<p class="mb-1 small"><i class="bi bi-key"></i> <span class="text-success">Token present</span></p>
|
|
{% else %}
|
|
<p class="mb-1 small"><i class="bi bi-key"></i> <span class="text-danger">Aucun token</span></p>
|
|
{% endif %}
|
|
</div>
|
|
<div class="card-footer d-flex gap-2">
|
|
<form method="POST" action="{{ url_for('outlook_pages.reactivate_account', account_id=account.id) }}" class="d-inline">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
<button type="submit" class="btn btn-sm btn-outline-primary" title="Supprimer et re-authentifier">
|
|
<i class="bi bi-arrow-repeat"></i> Reauthentifier
|
|
</button>
|
|
</form>
|
|
<form method="POST" action="{{ url_for('outlook_pages.delete_account', account_id=account.id) }}" class="d-inline"
|
|
onsubmit="return confirm('Supprimer le compte {{ account.email }} ?');">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
<button type="submit" class="btn btn-sm btn-outline-danger">
|
|
<i class="bi bi-trash"></i> Supprimer
|
|
</button>
|
|
</form>
|
|
<a href="{{ url_for('outlook_pages.account_detail', account_id=account.id) }}" class="btn btn-sm btn-outline-info">
|
|
<i class="bi bi-eye"></i> Details
|
|
</a>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
{% else %}
|
|
<div class="card">
|
|
<div class="card-body text-center py-4">
|
|
<i class="bi bi-envelope display-1 text-muted"></i>
|
|
<p class="text-muted mt-2">Aucun compte Outlook configure.</p>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
let pollInterval = null;
|
|
let accountId = null;
|
|
|
|
document.getElementById('outlook-auth-form').addEventListener('submit', async function(e) {
|
|
e.preventDefault();
|
|
|
|
const email = document.getElementById('email').value;
|
|
const btn = document.getElementById('submit-btn');
|
|
const btnText = document.getElementById('btn-text');
|
|
const spinner = document.getElementById('btn-spinner');
|
|
const results = document.getElementById('auth-results');
|
|
|
|
btn.disabled = true;
|
|
btnText.textContent = 'Connexion en cours...';
|
|
spinner.classList.remove('d-none');
|
|
|
|
try {
|
|
const response = await fetch('/outlook/api/start-auth', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({ email: email })
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.error) {
|
|
results.innerHTML = `<div class="alert alert-danger">${data.error}</div>`;
|
|
btn.disabled = false;
|
|
btnText.textContent = 'Se connecter avec Outlook';
|
|
spinner.classList.add('d-none');
|
|
} else {
|
|
accountId = data.account_id;
|
|
|
|
results.innerHTML = `
|
|
<div class="alert alert-info">
|
|
<h5>Authentification requise</h5>
|
|
<p><strong>Code:</strong> <span class="h4 text-primary">${data.user_code}</span></p>
|
|
<p><a href="${data.verification_uri}" target="_blank" class="btn btn-success">
|
|
<i class="bi bi-box-arrow-up-right"></i> Ouvrir Microsoft
|
|
</a></p>
|
|
<p class="small text-muted">Ce code expire dans ${Math.floor(data.expires_in / 60)} minutes</p>
|
|
</div>
|
|
<div class="alert alert-warning mt-3" id="poll-status">
|
|
<span class="spinner-border spinner-border-sm"></span> En attente de l'autorisation...
|
|
</div>
|
|
`;
|
|
|
|
btnText.textContent = 'Connexion en cours';
|
|
|
|
startPolling(accountId);
|
|
}
|
|
} catch (error) {
|
|
results.innerHTML = `<div class="alert alert-danger">Erreur: ${error.message}</div>`;
|
|
btn.disabled = false;
|
|
btnText.textContent = 'Se connecter avec Outlook';
|
|
spinner.classList.add('d-none');
|
|
}
|
|
});
|
|
|
|
function startPolling(accountId) {
|
|
let attempts = 0;
|
|
const maxAttempts = 60;
|
|
|
|
pollInterval = setInterval(async () => {
|
|
attempts++;
|
|
|
|
if (attempts > maxAttempts) {
|
|
clearInterval(pollInterval);
|
|
document.getElementById('poll-status').innerHTML =
|
|
'<span class="text-danger">Delai expire, veuillez recommencer</span>';
|
|
resetForm();
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await fetch(`/outlook/api/poll-auth/${accountId}`, {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'}
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
clearInterval(pollInterval);
|
|
document.getElementById('poll-status').innerHTML =
|
|
'<span class="text-success"><i class="bi bi-check-circle"></i> Authentification reussie!</span>';
|
|
|
|
setTimeout(() => {
|
|
window.location.href = '/outlook/';
|
|
}, 1500);
|
|
} else if (data.pending) {
|
|
// Toujours en attente
|
|
} else if (data.error) {
|
|
if (data.expired) {
|
|
clearInterval(pollInterval);
|
|
document.getElementById('poll-status').innerHTML =
|
|
'<span class="text-danger">Code expire, veuillez recommencer</span>';
|
|
resetForm();
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Erreur polling:', error);
|
|
}
|
|
}, 5000);
|
|
}
|
|
|
|
function resetForm() {
|
|
const btn = document.getElementById('submit-btn');
|
|
const btnText = document.getElementById('btn-text');
|
|
const spinner = document.getElementById('btn-spinner');
|
|
|
|
btn.disabled = false;
|
|
btnText.textContent = 'Se connecter avec Outlook';
|
|
spinner.classList.add('d-none');
|
|
}
|
|
</script>
|
|
{% endblock %} |