Skip to content

Commit

Permalink
feat(oauth): added pages to link our account with microsoft, spotify …
Browse files Browse the repository at this point in the history
…google and discord oauth (only microsoft fonctional)
  • Loading branch information
sambrus authored and mathieu-brl committed Dec 10, 2024
1 parent 647ea2f commit 18a059a
Show file tree
Hide file tree
Showing 9 changed files with 232 additions and 53 deletions.
Binary file modified client_mobile/assets/images/google.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client_mobile/assets/images/spotify_green.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion client_mobile/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Future<void> main() async {
routes: [
GoRoute(
path: '/',
builder: (context, state) => HomePage(),
builder: (context, state) => const HomePage(),
),
GoRoute(
path: '/login',
Expand Down
74 changes: 24 additions & 50 deletions client_mobile/lib/pages/dashboard/dashboard.dart
Original file line number Diff line number Diff line change
@@ -1,70 +1,44 @@
import 'package:client_mobile/data/action.dart';
import 'package:client_mobile/services/login/auth_service.dart';
import 'package:client_mobile/widgets/action_button.dart';
import 'package:client_mobile/widgets/reaction_button.dart';
import 'package:client_mobile/pages/dashboard/service_connection.dart';
import 'package:client_mobile/pages/dashboard/workflow.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

class DashboardPage extends StatefulWidget {
const DashboardPage({super.key});

@override
State<DashboardPage> createState() => _DashboardPageState();
_DashboardPageState createState() => _DashboardPageState();
}

class _DashboardPageState extends State<DashboardPage> {
WorkflowActionReaction? action;
WorkflowActionReaction? reaction;
int _currentIndex = 0; // Pour suivre l'index actuel

void onActionSelected(WorkflowActionReaction selected, String serviceName) {
setState(() {
action = selected;
action!.serviceName = serviceName;
});
}
final List<Widget> _pages = [
WorkflowPage(), // Votre page actuelle avec les boutons Action et Réaction
ServiceConnectionPage(), // Une nouvelle page pour la connexion des services
];

void onReactionSelected(WorkflowActionReaction selected, String serviceName) {
void _onTabTapped(int index) {
setState(() {
reaction = selected;
reaction!.serviceName = serviceName;
_currentIndex = index;
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
const SizedBox(height: 50),
ActionButton(onActionSelected: onActionSelected, action: action),
const SizedBox(height: 30),
ReactionButton(
onActionSelected: onReactionSelected, reaction: reaction),
const SizedBox(height: 50),
ElevatedButton(
onPressed: () async {
if (action == null || reaction == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Please refer an action and a reaction"),
backgroundColor: Colors.red,
),
);
} else {
print("create workflow");
}
},
child: const Text("Create"))
body: _pages[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: _onTabTapped,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'Services',
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
bool hasLogout = await AuthService.logout();
if (hasLogout) context.pushReplacement("/login");
},
tooltip: 'Logout',
child: const Icon(Icons.login),
),
);
}
}
}
100 changes: 100 additions & 0 deletions client_mobile/lib/pages/dashboard/service_connection.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import 'dart:io';

import 'package:client_mobile/services/microsoft/microsoft_auth_service.dart';
import 'package:client_mobile/widgets/sign_in_button.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

class ServiceConnectionPage extends StatefulWidget {
const ServiceConnectionPage({super.key});

@override
State<ServiceConnectionPage> createState() => _ServiceConnectionPageState();
}

class _ServiceConnectionPageState extends State<ServiceConnectionPage> {
FlutterSecureStorage secureStorage = const FlutterSecureStorage();

String? microsoftToken;

@override
void initState() {
super.initState();
_loadMicrosoftToken();
}

Future<void> _loadMicrosoftToken() async {
String? token = await secureStorage.read(key: "microsoft_access_token");
print("token microsoft : $token");
setState(() {
microsoftToken = token;
});
}

@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
if (microsoftToken == null)
SignInButton(
onPressed: () async {
MicrosoftAuthService.auth(context);
await _loadMicrosoftToken();
},
label: "Link with Microsoft",
image: Image.asset(
"assets/images/microsoft.png",
width: 40,
height: 30,
),
)
else
GestureDetector(
onTap: () async {
await secureStorage.delete(key: "microsoft_access_token");
setState(() {
microsoftToken = null;
});
},
child: const Text(
"✅ Microsoft is already linked",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.green),
),
),
SignInButton(
onPressed: () {},
label: "Link with Spotify",
image: Image.asset(
"assets/images/spotify_green.png",
width: 40,
height: 30,
),
),
SignInButton(
onPressed: () {},
label: "Link with Google",
image: Image.asset(
"assets/images/google.png",
width: 40,
height: 30,
),
),
SignInButton(
onPressed: () {},
label: "Link with Discord",
image: Image.asset(
"assets/images/discord.png",
width: 40,
height: 30,
),
),
],
),
);
}
}
70 changes: 70 additions & 0 deletions client_mobile/lib/pages/dashboard/workflow.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import 'package:client_mobile/data/action.dart';
import 'package:client_mobile/services/login/auth_service.dart';
import 'package:client_mobile/widgets/action_button.dart';
import 'package:client_mobile/widgets/reaction_button.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

class WorkflowPage extends StatefulWidget {
const WorkflowPage({super.key});

@override
State<WorkflowPage> createState() => _WorkflowPageState();
}

class _WorkflowPageState extends State<WorkflowPage> {
WorkflowActionReaction? action;
WorkflowActionReaction? reaction;

void onActionSelected(WorkflowActionReaction selected, String serviceName) {
setState(() {
action = selected;
action!.serviceName = serviceName;
});
}

void onReactionSelected(WorkflowActionReaction selected, String serviceName) {
setState(() {
reaction = selected;
reaction!.serviceName = serviceName;
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
const SizedBox(height: 50),
ActionButton(onActionSelected: onActionSelected, action: action),
const SizedBox(height: 30),
ReactionButton(
onActionSelected: onReactionSelected, reaction: reaction),
const SizedBox(height: 50),
ElevatedButton(
onPressed: () async {
if (action == null || reaction == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Please refer an action and a reaction"),
backgroundColor: Colors.red,
),
);
} else {
print("create workflow");
}
},
child: const Text("Create"))
],
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
bool hasLogout = await AuthService.logout();
if (hasLogout) context.pushReplacement("/login");
},
tooltip: 'Logout',
child: const Icon(Icons.login),
),
);
}
}
36 changes: 35 additions & 1 deletion client_mobile/lib/services/microsoft/microsoft_auth_service.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import 'dart:convert';

import 'package:aad_oauth/model/config.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter/material.dart';
import 'package:aad_oauth/aad_oauth.dart';
import '../../main.dart';
import 'package:http/http.dart' as http;

class MicrosoftAuthService {
static final String clientId = dotenv.env["VITE_MICROSOFT_CLIENT_ID"] ?? "";
Expand All @@ -12,6 +15,18 @@ class MicrosoftAuthService {
static const String authority = "https://login.microsoftonline.com/common";
static const FlutterSecureStorage secureStorage = FlutterSecureStorage();

static Future<bool> linkToken(String token) async {
String baseUrl = dotenv.env["BACKEND_BASE_URL"] ?? "http://localhost:8080";
final response = await http.post(
Uri.parse('$baseUrl/oauth/microsoft'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({"token": token}),
);

print("code retourné : ${response.statusCode}");
return response.statusCode == 200;
}

static Future<void> auth(BuildContext context) async {
final Config config = Config(
tenant: "common",
Expand All @@ -31,7 +46,26 @@ class MicrosoftAuthService {
),
),
(r) async {
await secureStorage.write(key: 'microsoft_access_token', value: r.accessToken);
bool hasLinked = await linkToken(r.accessToken!);

if (hasLinked) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Microsoft link avec succès !"),
backgroundColor: Colors.black,
),
);
await secureStorage.write(
key: 'microsoft_access_token', value: r.accessToken);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Microsoft authentification failed."),
backgroundColor: Colors.red,
),
);
}

print("access token = : ${r.accessToken}");
},
);
Expand Down
2 changes: 1 addition & 1 deletion client_mobile/lib/widgets/sign_in_button.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';

class SignInButton extends StatelessWidget {
const SignInButton(
SignInButton(
{super.key, required this.label, this.image, this.onPressed});

final String label;
Expand Down
1 change: 1 addition & 0 deletions client_mobile/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ flutter:
- .env.mobile
- assets/images/microsoft.png
- assets/images/spotify.png
- assets/images/spotify_green.png
- assets/images/google.png
- assets/images/discord.png
# - images/a_dot_burr.jpeg
Expand Down

0 comments on commit 18a059a

Please sign in to comment.