Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Ajouter l'authentification #21

Merged
merged 1 commit into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,8 @@ app.*.map.json

# Example
**/example/pubspec.lock

# Env
**/env.*.json
**/env.json
!**/env.template.json
8 changes: 6 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"type": "dart",
"args": [
"--flavor",
"development"
"development",
"--dart-define-from-file",
"env.development.json"
]
},
{
Expand All @@ -18,7 +20,9 @@
"type": "dart",
"args": [
"--flavor",
"production"
"production",
"--dart-define-from-file",
"env.json"
]
},
{
Expand Down
3 changes: 3 additions & 0 deletions app/env.template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"API_URL": "X"
}
1 change: 1 addition & 0 deletions app/ios/Flutter/Debug.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
1 change: 1 addition & 0 deletions app/ios/Flutter/Release.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
44 changes: 44 additions & 0 deletions app/ios/Podfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '12.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}

def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end

File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end

require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

flutter_ios_podfile_setup

target 'Runner' do
use_frameworks!
use_modular_headers!

flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end

post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end
29 changes: 29 additions & 0 deletions app/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
PODS:
- Flutter (1.0.0)
- flutter_secure_storage (6.0.0):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS

DEPENDENCIES:
- Flutter (from `Flutter`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)

EXTERNAL SOURCES:
Flutter:
:path: Flutter
flutter_secure_storage:
:path: ".symlinks/plugins/flutter_secure_storage/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"

SPEC CHECKSUMS:
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46

PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796

COCOAPODS: 1.15.2
172 changes: 157 additions & 15 deletions app/ios/Runner.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions app/ios/Runner.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 38 additions & 3 deletions app/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,50 @@
// ignore_for_file: do_not_use_environment

import 'dart:ui';

import 'package:agir/src/app.dart';
import 'package:app/src/app.dart';
import 'package:app/src/fonctionnalites/authentification/domain/authentification_statut_manager.dart';
import 'package:app/src/fonctionnalites/authentification/infrastructure/adapters/api_url.dart';
import 'package:app/src/fonctionnalites/authentification/infrastructure/adapters/authentification_api_adapter.dart';
import 'package:app/src/fonctionnalites/authentification/infrastructure/adapters/authentification_api_client.dart';
import 'package:app/src/fonctionnalites/authentification/infrastructure/adapters/authentification_token_storage.dart';
import 'package:dsfr/dsfr.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

void main() {
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();

_registerErrorHandlers();

runApp(const App());
const apiUrlKey = 'API_URL';
const apiUrl = String.fromEnvironment(apiUrlKey);
if (apiUrl.isEmpty) {
throw Exception(apiUrlKey);
}

final authentificationStatusManager = AuthentificationStatutManager();

final authentificationTokenStorage = AuthentificationTokenStorage(
secureStorage: const FlutterSecureStorage(
aOptions: AndroidOptions(encryptedSharedPreferences: true),
),
authentificationStatusManager: authentificationStatusManager,
);

await authentificationTokenStorage.initialise();

runApp(
App(
authentificationRepository: AuthentificationApiAdapter(
apiClient: AuthentificationApiClient(
apiUrl: ApiUrl(Uri.parse(apiUrl)),
authentificationTokenStorage: authentificationTokenStorage,
),
),
authentificationStatusManager: authentificationStatusManager,
),
);
}

void _registerErrorHandlers() {
Expand Down
57 changes: 49 additions & 8 deletions app/lib/src/app.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,57 @@
import 'package:agir/src/router/app_router.dart';
import 'package:app/src/fonctionnalites/authentification/domain/authentification_statut_manager.dart';
import 'package:app/src/fonctionnalites/authentification/domain/ports/authentification_repository.dart';
import 'package:app/src/fonctionnalites/se_connecter/bloc/se_connecter_bloc.dart';
import 'package:app/src/router/app_router.dart';
import 'package:dsfr/dsfr.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';

class App extends StatelessWidget {
const App({super.key});
class App extends StatefulWidget {
const App({
required this.authentificationStatusManager,
required this.authentificationRepository,
super.key,
});

final AuthentificationStatutManager authentificationStatusManager;
final AuthentificationRepository authentificationRepository;

@override
State<App> createState() => _AppState();
}

class _AppState extends State<App> {
late final GoRouter _goRouter;

@override
void initState() {
super.initState();
_goRouter = goRouter(
authentificationStatusManager: widget.authentificationStatusManager,
);
}

@override
Widget build(final BuildContext context) => MaterialApp.router(
routerConfig: goRouter(),
theme: ThemeData(
colorSchemeSeed: DsfrColors.blueFranceSun113,
scaffoldBackgroundColor: Colors.white,
Widget build(final BuildContext context) =>
RepositoryProvider<AuthentificationRepository>.value(
value: widget.authentificationRepository,
child: MultiBlocProvider(
providers: [
BlocProvider(
create: (final context) => SeConnecterBloc(
authentificationRepository: widget.authentificationRepository,
),
),
],
child: MaterialApp.router(
routerConfig: _goRouter,
theme: ThemeData(
colorSchemeSeed: DsfrColors.blueFranceSun113,
scaffoldBackgroundColor: Colors.white,
appBarTheme: const AppBarTheme(backgroundColor: Colors.white),
),
),
),
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
enum AuthentificationStatut {
inconnu,
connecte,
pasConnecte,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'dart:async';
import 'package:app/src/fonctionnalites/authentification/domain/authentification_statut.dart';

class AuthentificationStatutManager {
AuthentificationStatut _statut = AuthentificationStatut.inconnu;

final _controller = StreamController<AuthentificationStatut>();

void gererAuthentificationStatut(final AuthentificationStatut statut) {
_statut = statut;
_controller.add(_statut);
}

AuthentificationStatut statutActuel() => _statut;

Stream<AuthentificationStatut> statutModifie() => _controller.stream;

Future<void> dispose() async {
await _controller.close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import 'package:equatable/equatable.dart';

class InformationDeConnexion extends Equatable {
const InformationDeConnexion({
required this.adresseMail,
required this.motDePasse,
});

final String adresseMail;
final String motDePasse;

@override
List<Object?> get props => [adresseMail, motDePasse];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import 'package:app/src/fonctionnalites/authentification/domain/information_de_connexion.dart';

abstract interface class AuthentificationRepository {
Future<void> connectionDemandee(
final InformationDeConnexion informationDeConnexion,
);
Future<void> deconnectionDemandee();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'package:equatable/equatable.dart';

class ApiUrl extends Equatable {
const ApiUrl(this.valeur);

final Uri valeur;

@override
List<Object?> get props => [valeur];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'dart:async';
import 'dart:convert';

import 'package:app/src/fonctionnalites/authentification/domain/information_de_connexion.dart';
import 'package:app/src/fonctionnalites/authentification/domain/ports/authentification_repository.dart';
import 'package:app/src/fonctionnalites/authentification/infrastructure/adapters/authentification_api_client.dart';

class AuthentificationApiAdapter implements AuthentificationRepository {
AuthentificationApiAdapter({
required final AuthentificationApiClient apiClient,
}) : _apiClient = apiClient;

final AuthentificationApiClient _apiClient;

@override
Future<void> connectionDemandee(
final InformationDeConnexion informationDeConnexion,
) async {
final response = await _apiClient.post(
Uri.parse('/utilisateurs/login'),
body: {
'email': informationDeConnexion.adresseMail,
'mot_de_passe': informationDeConnexion.motDePasse,
},
);
if (response.statusCode == 201) {
final json = jsonDecode(response.body) as Map<String, dynamic>;
final token = json['token'] as String;
final utilisateur = json['utilisateur'] as Map<String, dynamic>;
final utilisateurId = utilisateur['id'] as String;
await _apiClient.sauvegarderTokenEtUtilisateurId(token, utilisateurId);
} else {
return;
}
}

@override
Future<void> deconnectionDemandee() async {
await _apiClient.supprimerTokenEtUtilisateurId();
}
}
Loading