12 KiB
Fiche soutenance orale — Swifty Companion
Lot 3 du plan de préparation.
Usage : répétition à voix haute, ordre de démo, réponses courtes.
Cartographie détaillée sujet ↔ code : guide-soutenance-realisation.md.
Dépôt /.env/ PC école : fiche-depot-soutenance.md.
Durée type peer-eval : 5 à 15 min selon l’évaluateur — viser 8 min de démo + questions.
Avant d’entrer en soutenance (5 min)
| Check | Action |
|---|---|
| Device | Téléphone chargé, USB débogage ou Wi‑Fi ADB OK |
.env |
Présent dans swiftyCompanion/swifty_companion/.env, pas affiché à l’écran |
| OAuth Intra | App avec scopes public + projects, redirect = REDIRECT_URI du .env |
| Terminal prêt | Dossier swiftyCompanion/swifty_companion |
| Git école | Pas de .env dans git status si on montre le repo |
1. Introduction (~30 s)
À dire (modèle) :
« Swifty Companion est une app Flutter qui se connecte une fois à l’API 42 en OAuth2, puis permet de chercher un login et d’afficher son profil : photo, coordonnées, niveau cursus, skills avec pourcentage, et projets validés ou en échec. Les secrets sont dans un
.envlocal, ignoré par Git. J’ai deux écrans et un seul token réutilisé pour toutes les requêtes API. »
| Point | Détail à mentionner si demandé |
|---|---|
| Sujet | Mobile Initiation v4 — API Intra v2 |
| Stack | Flutter / Dart, flutter_appauth, http, flutter_dotenv |
| Entrée app | lib/main.dart → SearchScreen |
2. Sécurité et fichier .env (~1 min)
Ce que le sujet impose (éliminatoire)
- Identifiants uniquement dans
.envlocal. .envignoré par Git — exposition publique = échec direct.- Le rendu Vogosphere contient
.env.example, pas de vrais secrets.
Où est le fichier qui tourne
swiftyCompanion/swifty_companion/.env
Chargé au démarrage : dotenv.load() dans main.dart, déclaré en asset dans pubspec.yaml.
Les trois variables (à expliquer sans lire les valeurs à l’écran)
| Variable | Rôle | Où la trouver sur l’Intra |
|---|---|---|
CLIENT_ID |
Identifiant de l’app OAuth | Champ UID |
CLIENT_SECRET |
Échange code → tokens | Champ SECRET (privé) |
REDIRECT_URI |
Retour navigateur → app | URI de redirection (ex. com.example.swiftycompanion://callback) |
Scopes (cochés sur l’Intra, pas dans .env) : public + projects — sans projects, les projets du profil renvoient 403.
Phrase clé : « Le correcteur copie .env.example vers .env et met ses propres clés ; mon dépôt Git ne contient jamais le SECRET. »
3. Architecture (~1–2 min)
Les deux vues
| Vue | Fichier | Rôle |
|---|---|---|
| 1 — Recherche | lib/screens/search_screen.dart |
Connexion OAuth, champ login, navigation vers profil |
| 2 — Profil | lib/screens/profile_screen.dart |
Données agrégées, erreur + Réessayer |
Couche services (flux données)
SearchScreen / ProfileScreen
↓
IntraUserService (recherche) IntraProfileService (profil)
↓ ↓
intra_http.dart (GET + gestion 401 / 429)
↓
IntraAuthService.instance (un seul access + refresh)
| Fichier | Responsabilité |
|---|---|
config/intra_config.dart |
URLs API v2 + lecture .env |
services/intra_auth_service.dart |
OAuth, headers Bearer, refresh |
services/intra_user_service.dart |
GET /users?filter[login]= |
services/intra_profile_service.dart |
User + skills (cursus) + projects_users |
services/intra_api_exception.dart |
Erreurs métier → messages UI |
theme/swifty_ui.dart |
Scroll, largeurs max, AppBar commune |
Un seul token OAuth (critère sujet)
- Une fois :
authorizeAndExchangeCode→ access (+ refresh en bonus). - Ensuite : chaque appel API utilise
authHeaders()— pas de nouvelle fenêtre OAuth par recherche.
Singleton : IntraAuthService.instance.
4. Démo guidée — commandes et parcours (~4–6 min)
4.1 Terminal — ce que fait chaque commande
Toujours depuis le package Flutter :
cd ~/chemin/vers/swiftyCompanion/swifty_companion
| Commande | À dire à l’oral |
|---|---|
flutter doctor |
Vérifie SDK Flutter, Android toolchain, device branché — preuve que l’environnement est prêt. |
flutter pub get |
Télécharge les dépendances du pubspec.yaml (flutter_appauth, http, dotenv, …). |
flutter analyze |
Analyse statique Dart — pas d’erreurs bloquantes. |
flutter test |
Lance les tests unitaires / widget (test/widget_test.dart, test/intra_oauth_tokens_test.dart pour le bonus). |
flutter devices |
Liste émulateur ou téléphone — on note l’id pour -d. |
flutter run -d <device> |
Compile, installe et lance l’app en mode debug sur l’appareil. |
Ordre recommandé devant l’évaluateur : flutter test (rapide, visible) → flutter run si l’app n’est pas déjà lancée.
4.2 Parcours écran par écran
| Étape | Action | Ce que tu commentes |
|---|---|---|
| 1 | Lancer l’app | Si .env manquant : message explicite sur l’écran recherche (IntraConfig.isConfigured). |
| 2 | Se connecter avec 42 | Flux OAuth : navigateur / Custom Tab → redirect vers l’app → token stocké en mémoire. |
| 3 | Login valide (ex. un camarade ou toi) | GET filtre login → si trouvé, Navigator.push vers profil. |
| 4 | Profil | Photo, ≥ 4 champs, carte skills (niveau + %), liste projets finished et failed. |
| 5 | Retour (flèche) | Retour vue 1 — session conservée (pas besoin de reconnecter). |
| 6 | Deuxième recherche | Prouve le token unique. |
| 7 | Login invalide zzzzinvalid |
Message clair, pas de crash, pas d’ouverture profil vide. |
| 8 | Mode avion (recherche ou profil) | Erreur réseau ; sur profil, bouton Réessayer. |
| 9 | (Option) Rotation / grand écran | Profil en 2 colonnes si large (LayoutBuilder, breakpoint 720 px). |
Login de démo : prévoir un login qui a des skills et au moins un projet failed visible.
5. Critères obligatoires — réponses « où c’est » (~2 min si questions)
Référence complète : guide-soutenance-realisation.md §3.
| # | Critère | Réponse courte + fichier |
|---|---|---|
| 1 | 2 vues | search_screen.dart + profile_screen.dart |
| 2 | Toutes les erreurs | Exceptions dans intra_api_exception.dart ; catch dans services + UI (search_screen, profile_screen _ErrorBody) |
| 3 | Profil seulement si login existe | Pas de navigation si liste users vide — IntraUserNotFoundException |
| 4 | ≥ 4 infos + photo | _ProfileHeader, _DetailsCard — email, phone, location, wallet, niveau cursus, … |
| 5 | Skills niveau + % | Depuis cursus_users[].skills (pas /experiences) — IntraProfileService._parseSkillsFromCursus |
| 6 | Projets dont failed | projects_users — statuts finished et failed — scope projects |
| 7 | Retour vue 1 | Navigator.pop + AppBar retour |
| 8 | Layout moderne / flexible | swifty_ui.dart — scroll, searchMaxWidth, 2 colonnes profil |
| 9 | Un token, pas un par requête | IntraAuthService.instance + intra_http.dart |
Champs — sur le profil : l’API masque certaines données selon la confidentialité — conforme au sujet.
6. Erreurs et cas limites — quoi montrer
| Cas | Démo | Message / comportement attendu |
|---|---|---|
| Login vide | Rechercher sans texte | « Saisis un login » |
| Login inconnu | zzzzinvalid |
Pas de profil |
| Non connecté | (si évaluateur demande) tenter recherche sans OAuth | Invitation à se connecter |
| Réseau | Mode avion | Message réseau |
| 403 scopes | (expliquer) | Scopes public + projects sur l’app Intra |
| 429 rate limit | (souvent pas en démo) | Retry dans intra_http.dart + cache profil 2 min |
| 401 session | Après refresh impossible | « Session expirée… » — voir bonus |
| Erreur chargement profil | (si réseau flaky) | Écran erreur + Réessayer |
Tu n’es pas obligé de tout rejouer : 2–3 cas bien choisis suffisent souvent.
7. Bonus refresh token (~1–2 min)
Flux à expliquer
Login → access + refresh en mémoire
GET API → 401 Unauthorized
→ POST /oauth/token (grant_type=refresh_token)
→ nouveau access
→ même GET rejoué une fois
Si refresh échoue → IntraUnauthorizedException, l’utilisateur se reconnecte
| Fichier | Rôle |
|---|---|
intra_auth_service.dart |
refreshAccessToken(), _refreshInFlight |
intra_http.dart |
intraApiGet avec retry après refresh |
intra_oauth_tokens.dart |
Parse JSON token — testé dans intra_oauth_tokens_test.dart |
Limite assumée : tokens en mémoire — kill app = nouvelle connexion OAuth (acceptable si tu le dis).
Démo DEBUG (build debug uniquement)
- Connexion OK, une recherche OK.
- Bouton « DEBUG : simuler token expiré » sur
SearchScreen(kDebugMode— absent en release). - Rechercher à nouveau → refresh silencieux → profil sans repasser par le navigateur.
Si évaluateur en release : montrer flutter test sur intra_oauth_tokens_test.dart + expliquer le flux §7.
Bouton DEBUG au rendu final : voir fiche-depot-soutenance.md §8 — garder (visible seulement en debug) ou retirer avant push ; décision à trancher au lot 4.
8. Questions fréquentes — réponses courtes
| Question | Réponse |
|---|---|
Pourquoi pas /experiences pour les skills ? |
Souvent 403 ; le sujet permet les données user / cursus — skills dans cursus_users. |
Pourquoi projects dans les scopes ? |
Endpoint projects_users exige ce scope. |
| Où est le redirect Android ? | AndroidManifest.xml — RedirectUriReceiverActivity ; appAuthRedirectScheme dans build.gradle.kts. |
| Pourquoi des requêtes séquentielles ? | Éviter 429 Too Many Requests sur l’API 42. |
| Cache profil ? | ~2 minutes en mémoire dans IntraProfileService — moins de hits API. |
| Différence dépôt perso / école ? | Perso : docs/ + travail ; école : racine = contenu de swiftyCompanion/ seul. |
| Où est la traduction du sujet ? | Dépôt perso docs/sujets/ — pas dans Vogosphere. |
| Tests ? | widget_test démarre l’app ; bonus : parse token OAuth. |
| WSL vs téléphone ? | OAuth fiable sur device/émulateur Android ; voir stratégie VM école dans la piscine mobile. |
| Que faire si SECRET exposé ? | Régénérer sur l’Intra, mettre à jour .env local, vérifier l’historique Git. |
9. Script condensé (une page — à réciter)
- Intro — Flutter, OAuth une fois, 2 vues,
.envhors Git. flutter test— vert.- Connexion 42 — une fois.
- Recherche OK → profil (photo, champs, skills %, failed).
- Retour → 2ᵉ recherche sans reconnecter.
- Login faux + mode avion.
- Bonus — DEBUG token expiré → recherche OK.
- Rappel — 9 critères, un token,
public+projects,.env.exampledans le repo.
10. Liens utiles (perso)
| Document | Usage |
|---|---|
| guide-soutenance-realisation.md | Tableau sujet ↔ fichiers |
| etape-06-checklist-soutenance.md | Checklist peer-eval |
| etape-07-bonus-token.md | Détail refresh |
| swiftyCompanion/README.md | README correcteurs (rendu) |
Aligné sujet Swifty Companion v4 — lot 3 livré.