From 14dcba8ee3dd050061a8c0dde3ea4d1e4b725180 Mon Sep 17 00:00:00 2001 From: jihunchoi Date: Sat, 27 Apr 2024 16:06:47 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20#85-=EB=B0=94=EB=80=90=20=EC=84=9C?= =?UTF-8?q?=EB=B2=84=20=EC=9D=91=EB=8B=B5=20=EB=B0=8F=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=EB=A1=9C=EC=A7=81=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20signup=20api=20=EC=9A=94=EC=B2=AD=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=EC=99=80=20=EB=B0=A9=EB=B2=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/models/api_fail_response.dart | 9 ++++ ...esponse.dart => api_success_response.dart} | 6 +-- .../lib/screens/signup/signup_service.dart | 42 +++++++------------ .../lib/services/auth_service.dart | 25 ++++------- 4 files changed, 35 insertions(+), 47 deletions(-) create mode 100644 front/capstone_front/lib/models/api_fail_response.dart rename front/capstone_front/lib/models/{api_response.dart => api_success_response.dart} (67%) diff --git a/front/capstone_front/lib/models/api_fail_response.dart b/front/capstone_front/lib/models/api_fail_response.dart new file mode 100644 index 0000000000..91f9d2d62e --- /dev/null +++ b/front/capstone_front/lib/models/api_fail_response.dart @@ -0,0 +1,9 @@ +class ApiFailResponse { + final String success; + final String message; + + ApiFailResponse({ + required this.success, + required this.message, + }); +} diff --git a/front/capstone_front/lib/models/api_response.dart b/front/capstone_front/lib/models/api_success_response.dart similarity index 67% rename from front/capstone_front/lib/models/api_response.dart rename to front/capstone_front/lib/models/api_success_response.dart index d35147ec17..9d9ec37406 100644 --- a/front/capstone_front/lib/models/api_response.dart +++ b/front/capstone_front/lib/models/api_success_response.dart @@ -1,9 +1,9 @@ -class ApiResponse { +class ApiSuccessResponse { final String success; - final String? message; + final String message; final Map response; - ApiResponse({ + ApiSuccessResponse({ required this.success, required this.message, required this.response, diff --git a/front/capstone_front/lib/screens/signup/signup_service.dart b/front/capstone_front/lib/screens/signup/signup_service.dart index c14944484b..651fd50a12 100644 --- a/front/capstone_front/lib/screens/signup/signup_service.dart +++ b/front/capstone_front/lib/screens/signup/signup_service.dart @@ -1,5 +1,7 @@ +import 'dart:convert'; import 'dart:ui'; +import 'package:capstone_front/models/api_success_response.dart'; import 'package:capstone_front/screens/signup/college_department.dart'; import 'package:capstone_front/screens/signup/signup_email_screen.dart'; import 'package:capstone_front/screens/signup/signup_util.dart'; @@ -15,6 +17,7 @@ import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; Map userInfo = { + 'uuid': '', 'id': '', 'pw': '', 'pwRe': '', @@ -26,36 +29,20 @@ Map userInfo = { int selectedPageIndex = 0; Future signup() async { - try { - // UserCredential credential = - // await FirebaseAuth.instance.createUserWithEmailAndPassword( - // email: '${userInfo['id']}@kookmin.ac.kr', - // password: userInfo['pw']!, - // ); - // await credential.user!.sendEmailVerification(); - - // TODO 우리 서버에 signup 요청 여기서 - // signupInfo 에는 실제 유저에게 입력받은 정보가 들어가야함 - - // final Map signupInfo = { - // // "uuid": credential.user!.uid, - // "uuid": 'messi', - // "email": 'jihunchoi@kookmin.ac.kr', - // "name": 'jihun', - // "country": 'korea', - // "phoneNumber": '010-8276-8291', - // "major": "sw", - // }; - // var response = AuthService.signUp(signupInfo); - - // response의 결과에 따라 성공, 실패, 이유 띄워야함 + Map userData = { + 'uuid': userInfo['uuid'], + 'email': "${userInfo['id']}@kookmin.ac.kr", + 'name': 'messi', + 'country': userInfo['country'], + 'phoneNumber': '010-8276-8291', + 'major': userInfo['department'], + }; + var isSucceed = await AuthService.signUp(userData); + if (isSucceed) { return 'success'; - } on FirebaseAuthException catch (e) { - return e.code; - } catch (e) { - return e.toString(); } + throw Exception('there is something problem while signup'); } Future sendEmailAuth(String email, String pw) async { @@ -86,6 +73,7 @@ Future isEmailAuth(String email, String pw) async { if (user!.emailVerified) { user = credential.user; + userInfo['uuid'] = user!.uid; return "success"; } else { return "email"; diff --git a/front/capstone_front/lib/services/auth_service.dart b/front/capstone_front/lib/services/auth_service.dart index b2636dabd5..f4541cdd71 100644 --- a/front/capstone_front/lib/services/auth_service.dart +++ b/front/capstone_front/lib/services/auth_service.dart @@ -1,5 +1,7 @@ import 'dart:convert'; +import 'package:capstone_front/models/api_fail_response.dart'; +import 'package:capstone_front/models/api_success_response.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:http/http.dart' as http; import 'package:crypto/crypto.dart'; @@ -8,21 +10,10 @@ class AuthService { static String baseUrl = dotenv.get('BASE_URL'); static final List key = base64Decode(dotenv.get('HMAC_SECRET')); - static Future> signUp( - Map userInfo) async { + static Future signUp(Map userInfo) async { var hmacSha256 = Hmac(sha256, key); final url = Uri.parse('$baseUrl/user/signup'); - var dummy = { - "uuid": "string", - "email": "aㅁqazzaamclub4@kookmin.ac.kr", - "name": "string", - "country": "string", - "phoneNumber": "010-8276-8291", - "major": "string" - }; - - // var json = jsonEncode(dummy); var json = jsonEncode(userInfo); var bytes = utf8.encode(json); var digest = hmacSha256.convert(bytes); @@ -37,15 +28,15 @@ class AuthService { body: json, ); - final String decodedBody = utf8.decode(response.bodyBytes); - final Map res = jsonDecode(decodedBody); - if (response.statusCode != 201) { + final String decodedBody = utf8.decode(response.bodyBytes); + final ApiFailResponse apiFailResponse = jsonDecode(decodedBody); print('Request failed with status: ${response.statusCode}.'); - print('Request failed with status: ${response.body}'); + print('Request failed with status: ${apiFailResponse.message}'); + return false; } - return res; + return true; } static Future> signIn(Map info) async { From aff2f2d7e4c2e4060ef976b59a3d9ca2c8d0e6b6 Mon Sep 17 00:00:00 2001 From: jihunchoi Date: Sat, 27 Apr 2024 19:05:41 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20#85-=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=99=84=EB=A3=8C=20=EB=B0=8F=20?= =?UTF-8?q?token=20storage=EC=97=90=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/models/api_fail_response.dart | 9 +++++- .../lib/models/api_success_response.dart | 7 ++++- .../lib/screens/login/login_screen.dart | 13 ++++++-- .../lib/screens/signup/signup_service.dart | 2 ++ .../lib/services/auth_service.dart | 30 ++++++++++++++----- 5 files changed, 50 insertions(+), 11 deletions(-) diff --git a/front/capstone_front/lib/models/api_fail_response.dart b/front/capstone_front/lib/models/api_fail_response.dart index 91f9d2d62e..050e65f268 100644 --- a/front/capstone_front/lib/models/api_fail_response.dart +++ b/front/capstone_front/lib/models/api_fail_response.dart @@ -1,9 +1,16 @@ class ApiFailResponse { - final String success; + final bool success; final String message; + final String code; ApiFailResponse({ required this.success, required this.message, + required this.code, }); + + ApiFailResponse.fromJson(Map json) + : success = json['success'] as bool, + message = json['message'] as String, + code = json['code'] as String; } diff --git a/front/capstone_front/lib/models/api_success_response.dart b/front/capstone_front/lib/models/api_success_response.dart index 9d9ec37406..125b8fbfdd 100644 --- a/front/capstone_front/lib/models/api_success_response.dart +++ b/front/capstone_front/lib/models/api_success_response.dart @@ -1,5 +1,5 @@ class ApiSuccessResponse { - final String success; + final bool success; final String message; final Map response; @@ -8,4 +8,9 @@ class ApiSuccessResponse { required this.message, required this.response, }); + + ApiSuccessResponse.fromJson(Map json) + : success = json['success'] as bool, + message = json['message'] as String, + response = json['response']; } diff --git a/front/capstone_front/lib/screens/login/login_screen.dart b/front/capstone_front/lib/screens/login/login_screen.dart index ff32df4bcb..07d79f34cb 100644 --- a/front/capstone_front/lib/screens/login/login_screen.dart +++ b/front/capstone_front/lib/screens/login/login_screen.dart @@ -1,3 +1,4 @@ +import 'package:capstone_front/services/auth_service.dart'; import 'package:capstone_front/services/login_service.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:firebase_auth/firebase_auth.dart'; @@ -58,12 +59,20 @@ class _LoginScreenState extends State { '${_userInfo[0]}@kookmin.ac.kr', _userInfo[1]); switch (result) { case "success": - makeToast("로그인에 성공하였습니다"); await storage.write(key: 'isLogin', value: 'true'); await storage.write( key: 'userEmail', value: '${_userInfo[0]}@kookmin.ac.kr'); - context.go('/'); + var uuid = await storage.read(key: 'uuid'); + var isLogined = await AuthService.signIn({ + "uuid": uuid, + "email": '${_userInfo[0]}@kookmin.ac.kr', + }); + if (isLogined) { + makeToast("로그인에 성공하였습니다"); + context.go('/'); + } + case "email": makeToast("이메일이 인증되지 않았습니다"); case "invalid-credential": diff --git a/front/capstone_front/lib/screens/signup/signup_service.dart b/front/capstone_front/lib/screens/signup/signup_service.dart index 651fd50a12..25dab5e2f4 100644 --- a/front/capstone_front/lib/screens/signup/signup_service.dart +++ b/front/capstone_front/lib/screens/signup/signup_service.dart @@ -63,6 +63,7 @@ Future sendEmailAuth(String email, String pw) async { } Future isEmailAuth(String email, String pw) async { + FlutterSecureStorage storage = const FlutterSecureStorage(); try { UserCredential credential = await FirebaseAuth.instance .signInWithEmailAndPassword(email: email, password: pw); @@ -74,6 +75,7 @@ Future isEmailAuth(String email, String pw) async { if (user!.emailVerified) { user = credential.user; userInfo['uuid'] = user!.uid; + await storage.write(key: 'uuid', value: user.uid); return "success"; } else { return "email"; diff --git a/front/capstone_front/lib/services/auth_service.dart b/front/capstone_front/lib/services/auth_service.dart index f4541cdd71..876405581c 100644 --- a/front/capstone_front/lib/services/auth_service.dart +++ b/front/capstone_front/lib/services/auth_service.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:capstone_front/models/api_fail_response.dart'; import 'package:capstone_front/models/api_success_response.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:http/http.dart' as http; import 'package:crypto/crypto.dart'; @@ -39,7 +40,8 @@ class AuthService { return true; } - static Future> signIn(Map info) async { + static Future signIn(Map info) async { + FlutterSecureStorage storage = const FlutterSecureStorage(); var hmacSha256 = Hmac(sha256, key); final url = Uri.parse('$baseUrl/user/signin'); @@ -58,14 +60,28 @@ class AuthService { ); final String decodedBody = utf8.decode(response.bodyBytes); - final Map res = jsonDecode(decodedBody); - - if (response.statusCode != 200) { - print('Request failed with status: ${response.statusCode}.'); - print('Request failed with status: ${response.body}'); + final Map jsonMap = jsonDecode(decodedBody); + if (response.statusCode == 200) { + final ApiSuccessResponse apiSuccessResponse = + ApiSuccessResponse.fromJson(jsonMap); + print('apiSuccessResponse'); + print(apiSuccessResponse); + await storage.write( + key: 'accessToken', + value: apiSuccessResponse.response['accessToken'], + ); + await storage.write( + key: 'refreshToken', + value: apiSuccessResponse.response['refreshToken'], + ); + } else { + final ApiFailResponse apiFailResponse = ApiFailResponse.fromJson(jsonMap); + print(response.statusCode); + print(apiFailResponse.message); + throw Exception("fail to get toekns"); } - return res; + return true; } static Future> reissue( From b4ba8aabd0fd7526f5031e28061fa7eea60d0a46 Mon Sep 17 00:00:00 2001 From: jihunchoi Date: Sat, 27 Apr 2024 19:10:51 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20#85-reissue=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/services/auth_service.dart | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/front/capstone_front/lib/services/auth_service.dart b/front/capstone_front/lib/services/auth_service.dart index 876405581c..be5ba516d3 100644 --- a/front/capstone_front/lib/services/auth_service.dart +++ b/front/capstone_front/lib/services/auth_service.dart @@ -84,25 +84,42 @@ class AuthService { return true; } - static Future> reissue( - Map refreshTokenObj) async { + static void reissue() async { + FlutterSecureStorage storage = const FlutterSecureStorage(); + final url = Uri.parse('$baseUrl/auth/reissue'); + final refreshToken = storage.read(key: 'refreshToken'); final response = await http.post( url, headers: { 'Content-Type': 'application/json; charset=UTF-8', }, - body: jsonEncode(refreshTokenObj), + body: jsonEncode({ + "refreshToekn": refreshToken, + }), ); final String decodedBody = utf8.decode(response.bodyBytes); - final Map res = jsonDecode(decodedBody); - - if (response.statusCode != 200) { - print('Request failed with status: ${response.statusCode}.'); + final Map jsonMap = jsonDecode(decodedBody); + if (response.statusCode == 200) { + final ApiSuccessResponse apiSuccessResponse = + ApiSuccessResponse.fromJson(jsonMap); + print('apiSuccessResponse'); + print(apiSuccessResponse); + await storage.write( + key: 'accessToken', + value: apiSuccessResponse.response['accessToken'], + ); + await storage.write( + key: 'refreshToken', + value: apiSuccessResponse.response['refreshToken'], + ); + } else { + final ApiFailResponse apiFailResponse = ApiFailResponse.fromJson(jsonMap); + print(response.statusCode); + print(apiFailResponse.message); + throw Exception("fail to get toekns"); } - - return res; } } From 798bba0226408fc27bdadabee37bb6e52f35a9f9 Mon Sep 17 00:00:00 2001 From: jihunchoi Date: Sat, 27 Apr 2024 22:54:30 +0900 Subject: [PATCH 4/5] =?UTF-8?q?refactor:=20#85-print=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/capstone_front/lib/services/auth_service.dart | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/front/capstone_front/lib/services/auth_service.dart b/front/capstone_front/lib/services/auth_service.dart index be5ba516d3..2eaaa982b7 100644 --- a/front/capstone_front/lib/services/auth_service.dart +++ b/front/capstone_front/lib/services/auth_service.dart @@ -64,8 +64,6 @@ class AuthService { if (response.statusCode == 200) { final ApiSuccessResponse apiSuccessResponse = ApiSuccessResponse.fromJson(jsonMap); - print('apiSuccessResponse'); - print(apiSuccessResponse); await storage.write( key: 'accessToken', value: apiSuccessResponse.response['accessToken'], @@ -105,8 +103,6 @@ class AuthService { if (response.statusCode == 200) { final ApiSuccessResponse apiSuccessResponse = ApiSuccessResponse.fromJson(jsonMap); - print('apiSuccessResponse'); - print(apiSuccessResponse); await storage.write( key: 'accessToken', value: apiSuccessResponse.response['accessToken'], @@ -119,7 +115,7 @@ class AuthService { final ApiFailResponse apiFailResponse = ApiFailResponse.fromJson(jsonMap); print(response.statusCode); print(apiFailResponse.message); - throw Exception("fail to get toekns"); + throw Exception("fail to reissue"); } } } From bebff669bcaf0a97f1df784da3ac586064b90751 Mon Sep 17 00:00:00 2001 From: jihunchoi Date: Sun, 28 Apr 2024 00:59:25 +0900 Subject: [PATCH 5/5] =?UTF-8?q?feat:=20#85-signup=20=EC=9C=84=EC=B9=98=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20uuid=20=EC=96=BB=EB=8A=94=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/screens/signup/signup_service.dart | 6 +++++- .../lib/screens/signup/singup_password_screen.dart | 11 ++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/front/capstone_front/lib/screens/signup/signup_service.dart b/front/capstone_front/lib/screens/signup/signup_service.dart index ddcb324c2b..f30e0f09f9 100644 --- a/front/capstone_front/lib/screens/signup/signup_service.dart +++ b/front/capstone_front/lib/screens/signup/signup_service.dart @@ -35,7 +35,7 @@ Future signup() async { Map userData = { 'uuid': userInfo['uuid'], 'email': "${userInfo['id']}@kookmin.ac.kr", - 'name': 'messi', + 'name': userInfo['name'], 'country': userInfo['country'], 'phoneNumber': '010-8276-8291', 'major': userInfo['department'], @@ -49,12 +49,16 @@ Future signup() async { } Future sendEmailAuth(String email, String pw) async { + FlutterSecureStorage storage = const FlutterSecureStorage(); + try { credential = await FirebaseAuth.instance.createUserWithEmailAndPassword( email: '${userInfo['id']}@kookmin.ac.kr', password: userInfo['pw']!, ); + userInfo['uuid'] = credential.user!.uid; + await storage.write(key: 'uuid', value: credential.user!.uid); await credential.user?.sendEmailVerification(); return "success"; diff --git a/front/capstone_front/lib/screens/signup/singup_password_screen.dart b/front/capstone_front/lib/screens/signup/singup_password_screen.dart index 326aa3d7f4..1b7cdf81b4 100644 --- a/front/capstone_front/lib/screens/signup/singup_password_screen.dart +++ b/front/capstone_front/lib/screens/signup/singup_password_screen.dart @@ -56,15 +56,8 @@ class _SignupPasswordScreenState extends State { await sendEmailAuth(userInfo['id']!, userInfo['pw']!); // 파이어베이스에 계정 생성 완료, 인증 메일 전송 완료 if (result == "success") { - print(userInfo['id']); - print(userInfo['pw']); - print(userInfo['name']); - print(userInfo['studentNum']); - print(userInfo['college']); - print(userInfo['department']); - print(userInfo['country']); - - // Todo: 서버로 회원가입된 내역 전송 + // 우리 서버로 회원가입 요청 + await signup(); showDialog( context: context,