From fbed2e950e3955829001c50d47d61f4486c2c2cf Mon Sep 17 00:00:00 2001 From: jj30462281 Date: Fri, 26 Jan 2024 22:07:08 +0800 Subject: [PATCH 01/24] iSchool login method change --- lib/src/connector/ischool_plus_connector.dart | 91 ++++++++++++------- 1 file changed, 59 insertions(+), 32 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index 4086ccb1..bb2f5600 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -40,63 +40,48 @@ class ISchoolPlusConnector { /// 3. GET https://istudy.ntut.edu.tw/login2.php (It should be. See the comment on step 3) /// 4. do something... static Future login(String account) async { - String result; try { ConnectorParameter parameter; + html.Document tagNode; - List nodes; - final data = { - "apUrl": "https://istudy.ntut.edu.tw/login.php", - "apOu": "ischool_plus_oauth", - "sso": "true", - "datetime1": DateTime.now().millisecondsSinceEpoch.toString() - }; + Map oauthData; + List oauthResponse; + Response jumpResult; // Step 1 - parameter = ConnectorParameter(_ssoLoginUrl); - parameter.data = data; - result = (await Connector.getDataByGet(parameter)); - - tagNode = html.parse(result.toString().trim()); - nodes = tagNode.getElementsByTagName("input"); - data.clear(); - for (final node in nodes) { - final name = node.attributes['name']; - final value = node.attributes['value']; - data[name] = value; - } + oauthData = await getLoginOAuth(); // Step 2 // The `jumpUrl` should be "oauth2Server.do". // If not, it means that the school server has changed. // TODO: Add a validation measurement to check whether Step 1 is died or not. (It should not die if auth is correct) - final jumpUrl = tagNode.getElementsByTagName("form")[0].attributes["action"]; - parameter = ConnectorParameter("${NTUTConnector.host}$jumpUrl"); - parameter.data = data; - - Response jumpResult = (await Connector.getDataByPostResponse(parameter)); - tagNode = html.parse(jumpResult.data.toString().trim()); - nodes = tagNode.getElementsByTagName("a"); + jumpResult = await oauth2Server(oauthData); + tagNode = html.parse(jumpResult.toString().trim()); + oauthResponse = tagNode.getElementsByTagName('a'); + // Step 3 // The redirectUrl is provided by HTML DOM on Step 2. // It should be https://istudy.ntut.edu.tw/login2.php with lot of the parameters. - final redirectUrl = nodes.first.attributes["href"]; - parameter = ConnectorParameter(redirectUrl); - await Connector.getDataByGet(parameter); + await login2(oauthResponse); // Perform retry for cryptic API errors (?). // If the string `connect lost` be found in the response, we will do the retry. // [2023-10-21] We may not need this since the step was changed. // TODO: Remove I-School retry loop since it's outdated. - int retryTimes = 3; do { if (jumpResult.data.toString().contains('connect lost')) { // Take a short delay to avoid being blocked. await Future.delayed(const Duration(milliseconds: 100)); - jumpResult = (await Connector.getDataByPostResponse(parameter)); + oauthData = await getLoginOAuth(); + jumpResult = await oauth2Server(oauthData); + + tagNode = html.parse(jumpResult.toString().trim()); + oauthResponse = tagNode.getElementsByTagName('a'); + + await login2(oauthResponse); } else { break; } @@ -112,6 +97,48 @@ class ISchoolPlusConnector { } } + static Future> getLoginOAuth() async { + Map result = {}; + + final data = { + "apUrl": "https://istudy.ntut.edu.tw/login.php", + "apOu": "ischool_plus_oauth", + "sso": "true", + "datetime1": DateTime.now().millisecondsSinceEpoch.toString() + }; + + final parameter = ConnectorParameter(_ssoLoginUrl); + parameter.data = data; + + final response = (await Connector.getDataByGet(parameter)); + final tagNode = html.parse(response.toString().trim()); + final nodes = tagNode.getElementsByTagName("input"); + + for (final node in nodes) { + final name = node.attributes['name']; + final value = node.attributes['value']; + result[name] = value; + } + + return result; + } + + static Future oauth2Server(Map oauthData) async { + final jumpUrl = oauthData['action']; + final parameter = ConnectorParameter("${NTUTConnector.host}$jumpUrl"); + parameter.data = oauthData; + + Response jumpResult = (await Connector.getDataByPostResponse(parameter)); + return jumpResult; + } + + static Future login2(List nodes) async { + final redirectUrl = nodes.first.attributes["href"]; + final parameter = ConnectorParameter(redirectUrl); + + await Connector.getDataByGet(parameter); + } + static Future>> getCourseFile(String courseId) async { ConnectorParameter parameter; String result; From 8b349f7b83be2fd0c9309d180edeeb948103917b Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sat, 27 Jan 2024 18:30:12 +0800 Subject: [PATCH 02/24] add ischool login test --- .gitignore | 3 + lib/src/connector/ischool_plus_connector.dart | 11 +-- lib/src/task/iplus/iplus_system_task.dart | 2 +- .../ischool_plus_connector_test.dart | 69 +++++++++++++++++++ 4 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 test/ischool_plus_connector_test/ischool_plus_connector_test.dart diff --git a/.gitignore b/.gitignore index 4d458b15..459b432c 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,6 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release + +# Test files +**/test/ischool_plus_connector_test/credential.json \ No newline at end of file diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index bb2f5600..88c69aed 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -39,7 +39,7 @@ class ISchoolPlusConnector { /// 2. POST https://app.ntut.edu.tw/oauth2Server.do (It should be. See the comment on step 2) /// 3. GET https://istudy.ntut.edu.tw/login2.php (It should be. See the comment on step 3) /// 4. do something... - static Future login(String account) async { + static Future login(String account, doFirebaseLogin) async { try { ConnectorParameter parameter; @@ -86,10 +86,11 @@ class ISchoolPlusConnector { break; } } while ((retryTimes--) > 0); - - await FirebaseAnalytics.instance.logLogin( - loginMethod: 'ntut_iplus', - ); + if(doFirebaseLogin){ + await FirebaseAnalytics.instance.logLogin( + loginMethod: 'ntut_iplus', + ); + } return ISchoolPlusConnectorStatus.loginSuccess; } catch (e, stack) { Log.eWithStack(e.toString(), stack); diff --git a/lib/src/task/iplus/iplus_system_task.dart b/lib/src/task/iplus/iplus_system_task.dart index 51b22911..46367745 100644 --- a/lib/src/task/iplus/iplus_system_task.dart +++ b/lib/src/task/iplus/iplus_system_task.dart @@ -21,7 +21,7 @@ class IPlusSystemTask extends NTUTTask { super.onStart(R.current.loginISchoolPlus); final studentId = LocalStorage.instance.getAccount(); - final value = await ISchoolPlusConnector.login(studentId); + final value = await ISchoolPlusConnector.login(studentId, true); super.onEnd(); if (value != ISchoolPlusConnectorStatus.loginSuccess) { diff --git a/test/ischool_plus_connector_test/ischool_plus_connector_test.dart b/test/ischool_plus_connector_test/ischool_plus_connector_test.dart new file mode 100644 index 00000000..154d4e9f --- /dev/null +++ b/test/ischool_plus_connector_test/ischool_plus_connector_test.dart @@ -0,0 +1,69 @@ +// TODO: remove sdk version selector after migrating to null-safety. +// @dart=2.10 +import 'dart:io'; +import 'dart:math'; + +import 'package:cookie_jar/cookie_jar.dart'; +import 'package:dio_cookie_manager/dio_cookie_manager.dart'; +import 'package:flutter_app/debug/log/log.dart'; +import 'package:flutter_app/src/connector/blocked_cookies.dart'; +import 'package:flutter_app/src/connector/core/dio_connector.dart'; +import 'package:flutter_app/src/connector/interceptors/request_interceptor.dart'; +import 'package:flutter_app/src/connector/ischool_plus_connector.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:get/get.dart'; +import 'package:path/path.dart'; +import 'package:tat_core/tat_core.dart'; +import 'dart:developer' as dev; +import 'dart:convert'; +import 'dart:io'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:path_provider/path_provider.dart'; + +Future main() async { + final tempDir = await Directory.systemTemp.createTemp(); + + final appDocDir = join(tempDir.path, '.cookies'); + final CookieJar cookieJar = PersistCookieJar(storage: FileStorage('$appDocDir/.cookies')); + Get.put(cookieJar); + final apiInterceptors = [ + ResponseCookieFilter(blockedCookieNamePatterns: blockedCookieNamePatterns), + CookieManager(cookieJar), + RequestInterceptors(), + ]; + await DioConnector.instance.init(interceptors: apiInterceptors); + final schoolApiService = SchoolApiService(interceptors: apiInterceptors); + + final simpleLoginRepository = SimpleLoginRepository(apiService: schoolApiService); + // final checkSessionRepository = CheckSessionRepository(apiService: schoolApiService); + + final simpleLoginUseCase = SimpleLoginUseCase(simpleLoginRepository); + // final checkSessionIsAliveUseCase = CheckSessionUseCase(checkSessionRepository); + + const credentialFilePath = 'test/ischool_plus_connector_test/credential.json'; + final file = File(credentialFilePath); + final json = jsonDecode(await file.readAsString()); + final userId = json['userId']; + final password = json['password']; + + dev.log('userId: $userId'); + dev.log('password: $password'); + + final Stopwatch stopwatch = Stopwatch()..start(); + test('ntut_login', () async { + final loginCredential = LoginCredential(userId: userId, password: password); + final loginResult = await simpleLoginUseCase(credential: loginCredential); + expect(loginResult.isSuccess, isTrue); + dev.log('ntut login Done Test execution time: ${stopwatch.elapsed}'); + + // final isCurrentSessionAlive = await checkSessionIsAliveUseCase(); + // expect(isCurrentSessionAlive, isTrue); + }); + test('ischool_login', () async { + final result = await ISchoolPlusConnector.login(userId, false); + expect(result, ISchoolPlusConnectorStatus.loginSuccess); + dev.log('ischool login Done Test execution time: ${stopwatch.elapsed}'); + stopwatch.stop(); + }); +} From 286fc4b913d0037c5626c7dccdf4204bf9d771b4 Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sat, 27 Jan 2024 18:35:30 +0800 Subject: [PATCH 03/24] remove outdated I-School retry loop --- lib/src/connector/ischool_plus_connector.dart | 28 ++----------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index 88c69aed..7369e273 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -58,35 +58,13 @@ class ISchoolPlusConnector { jumpResult = await oauth2Server(oauthData); tagNode = html.parse(jumpResult.toString().trim()); oauthResponse = tagNode.getElementsByTagName('a'); - // Step 3 // The redirectUrl is provided by HTML DOM on Step 2. // It should be https://istudy.ntut.edu.tw/login2.php with lot of the parameters. await login2(oauthResponse); - // Perform retry for cryptic API errors (?). - // If the string `connect lost` be found in the response, we will do the retry. - - // [2023-10-21] We may not need this since the step was changed. - // TODO: Remove I-School retry loop since it's outdated. - int retryTimes = 3; - do { - if (jumpResult.data.toString().contains('connect lost')) { - // Take a short delay to avoid being blocked. - await Future.delayed(const Duration(milliseconds: 100)); - oauthData = await getLoginOAuth(); - jumpResult = await oauth2Server(oauthData); - - tagNode = html.parse(jumpResult.toString().trim()); - oauthResponse = tagNode.getElementsByTagName('a'); - - await login2(oauthResponse); - } else { - break; - } - } while ((retryTimes--) > 0); - if(doFirebaseLogin){ + if (doFirebaseLogin) { await FirebaseAnalytics.instance.logLogin( loginMethod: 'ntut_iplus', ); @@ -110,7 +88,7 @@ class ISchoolPlusConnector { final parameter = ConnectorParameter(_ssoLoginUrl); parameter.data = data; - + final response = (await Connector.getDataByGet(parameter)); final tagNode = html.parse(response.toString().trim()); final nodes = tagNode.getElementsByTagName("input"); @@ -136,7 +114,7 @@ class ISchoolPlusConnector { static Future login2(List nodes) async { final redirectUrl = nodes.first.attributes["href"]; final parameter = ConnectorParameter(redirectUrl); - + await Connector.getDataByGet(parameter); } From ee19b64f22beb2ea898e18eb3ac24455a694f183 Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sat, 27 Jan 2024 18:52:00 +0800 Subject: [PATCH 04/24] add session out_of_date error --- lib/src/connector/ischool_plus_connector.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index 7369e273..bffc4bb0 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -72,7 +72,7 @@ class ISchoolPlusConnector { return ISchoolPlusConnectorStatus.loginSuccess; } catch (e, stack) { Log.eWithStack(e.toString(), stack); - return ISchoolPlusConnectorStatus.loginFail; + rethrow; } } @@ -90,6 +90,9 @@ class ISchoolPlusConnector { parameter.data = data; final response = (await Connector.getDataByGet(parameter)); + if(response.contains("重新登入")){ + throw StateError('[TAT] ischool_plus_connector.dart: session out of date'); + } final tagNode = html.parse(response.toString().trim()); final nodes = tagNode.getElementsByTagName("input"); From 7bb6ad27c2e5583c04887db37eba2c541d841390 Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sat, 27 Jan 2024 19:05:54 +0800 Subject: [PATCH 05/24] add retry mechanis, for getLoginOAuth --- lib/src/connector/ischool_plus_connector.dart | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index bffc4bb0..227b7681 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -93,16 +93,26 @@ class ISchoolPlusConnector { if(response.contains("重新登入")){ throw StateError('[TAT] ischool_plus_connector.dart: session out of date'); } - final tagNode = html.parse(response.toString().trim()); - final nodes = tagNode.getElementsByTagName("input"); + int retry=3; + do{ + retry=retry-1; + final tagNode = html.parse(response.toString().trim()); + final nodes = tagNode.getElementsByTagName("input"); - for (final node in nodes) { + for (final node in nodes) { final name = node.attributes['name']; final value = node.attributes['value']; result[name] = value; - } - - return result; + } + if(result.length!=5){ + await Future.delayed(const Duration(milliseconds: 100)); + } + else{ + return result; + } + }while(retry>0); + //throw an error for invaild input + //TODO: maybe add a custom error class for ischool plus retry mechanism } static Future oauth2Server(Map oauthData) async { From 3bb8c486637c230c853b4a666fae176feb22809c Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Fri, 16 Feb 2024 19:11:43 +0800 Subject: [PATCH 06/24] remove unused import from test --- .../ischool_plus_connector_test.dart | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/ischool_plus_connector_test/ischool_plus_connector_test.dart b/test/ischool_plus_connector_test/ischool_plus_connector_test.dart index 154d4e9f..b1963d91 100644 --- a/test/ischool_plus_connector_test/ischool_plus_connector_test.dart +++ b/test/ischool_plus_connector_test/ischool_plus_connector_test.dart @@ -1,11 +1,8 @@ // TODO: remove sdk version selector after migrating to null-safety. // @dart=2.10 import 'dart:io'; -import 'dart:math'; - import 'package:cookie_jar/cookie_jar.dart'; import 'package:dio_cookie_manager/dio_cookie_manager.dart'; -import 'package:flutter_app/debug/log/log.dart'; import 'package:flutter_app/src/connector/blocked_cookies.dart'; import 'package:flutter_app/src/connector/core/dio_connector.dart'; import 'package:flutter_app/src/connector/interceptors/request_interceptor.dart'; @@ -16,10 +13,6 @@ import 'package:path/path.dart'; import 'package:tat_core/tat_core.dart'; import 'dart:developer' as dev; import 'dart:convert'; -import 'dart:io'; -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:path_provider/path_provider.dart'; Future main() async { final tempDir = await Directory.systemTemp.createTemp(); From d88ff18cd1c621a97be4d4aeed6c506e7b8164bc Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Fri, 16 Feb 2024 21:07:06 +0800 Subject: [PATCH 07/24] remove unused parameter --- lib/src/connector/ischool_plus_connector.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index 227b7681..506de3ea 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -80,9 +80,7 @@ class ISchoolPlusConnector { Map result = {}; final data = { - "apUrl": "https://istudy.ntut.edu.tw/login.php", "apOu": "ischool_plus_oauth", - "sso": "true", "datetime1": DateTime.now().millisecondsSinceEpoch.toString() }; From ddcd27cf9849abbeba0f598092e0224814fb4072 Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Fri, 16 Feb 2024 21:51:28 +0800 Subject: [PATCH 08/24] rewrite login methods --- lib/src/connector/ischool_plus_connector.dart | 102 +++++++----------- 1 file changed, 38 insertions(+), 64 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index 506de3ea..4e91e72e 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -41,28 +41,55 @@ class ISchoolPlusConnector { /// 4. do something... static Future login(String account, doFirebaseLogin) async { try { - ConnectorParameter parameter; + final Map oauthData = {}; + final data = { + "apOu": "ischool_plus_oauth", + "datetime1": DateTime.now().millisecondsSinceEpoch.toString() + }; - html.Document tagNode; - Map oauthData; - List oauthResponse; - Response jumpResult; + final parameter = ConnectorParameter(_ssoLoginUrl); + parameter.data = data; + + final response = (await Connector.getDataByGet(parameter)); + if(response.contains("重新登入")){ + throw StateError('[TAT] ischool_plus_connector.dart: session out of date'); + } + + for(int retry=0;true;retry++){ + if(retry == 5) return ISchoolPlusConnectorStatus.loginFail; + final tagNode = html.parse(response.toString().trim()); + final nodes = tagNode.getElementsByTagName("input"); - // Step 1 - oauthData = await getLoginOAuth(); + for (final node in nodes) { + final name = node.attributes['name']; + final value = node.attributes['value']; + oauthData[name] = value; + } + if(oauthData.length==5){ + break; + } + else{ + await Future.delayed(const Duration(milliseconds: 100)); + } + } // Step 2 // The `jumpUrl` should be "oauth2Server.do". // If not, it means that the school server has changed. // TODO: Add a validation measurement to check whether Step 1 is died or not. (It should not die if auth is correct) - jumpResult = await oauth2Server(oauthData); - tagNode = html.parse(jumpResult.toString().trim()); - oauthResponse = tagNode.getElementsByTagName('a'); + final jumpUrl = oauthData['action']; + final jumpParameter = ConnectorParameter("${NTUTConnector.host}$jumpUrl"); + jumpParameter.data = oauthData; + final Response jumpResult = (await Connector.getDataByPostResponse(jumpParameter)); + final tagNode = html.parse(jumpResult.toString().trim()); + final oauthResponse = tagNode.getElementsByTagName('a'); // Step 3 // The redirectUrl is provided by HTML DOM on Step 2. // It should be https://istudy.ntut.edu.tw/login2.php with lot of the parameters. - await login2(oauthResponse); + final redirectUrl = oauthResponse.first.attributes["href"]; + final redirectParameter = ConnectorParameter(redirectUrl); + await Connector.getDataByGet(redirectParameter); if (doFirebaseLogin) { await FirebaseAnalytics.instance.logLogin( @@ -76,59 +103,6 @@ class ISchoolPlusConnector { } } - static Future> getLoginOAuth() async { - Map result = {}; - - final data = { - "apOu": "ischool_plus_oauth", - "datetime1": DateTime.now().millisecondsSinceEpoch.toString() - }; - - final parameter = ConnectorParameter(_ssoLoginUrl); - parameter.data = data; - - final response = (await Connector.getDataByGet(parameter)); - if(response.contains("重新登入")){ - throw StateError('[TAT] ischool_plus_connector.dart: session out of date'); - } - int retry=3; - do{ - retry=retry-1; - final tagNode = html.parse(response.toString().trim()); - final nodes = tagNode.getElementsByTagName("input"); - - for (final node in nodes) { - final name = node.attributes['name']; - final value = node.attributes['value']; - result[name] = value; - } - if(result.length!=5){ - await Future.delayed(const Duration(milliseconds: 100)); - } - else{ - return result; - } - }while(retry>0); - //throw an error for invaild input - //TODO: maybe add a custom error class for ischool plus retry mechanism - } - - static Future oauth2Server(Map oauthData) async { - final jumpUrl = oauthData['action']; - final parameter = ConnectorParameter("${NTUTConnector.host}$jumpUrl"); - parameter.data = oauthData; - - Response jumpResult = (await Connector.getDataByPostResponse(parameter)); - return jumpResult; - } - - static Future login2(List nodes) async { - final redirectUrl = nodes.first.attributes["href"]; - final parameter = ConnectorParameter(redirectUrl); - - await Connector.getDataByGet(parameter); - } - static Future>> getCourseFile(String courseId) async { ConnectorParameter parameter; String result; From d5fb8963c537efaec8001e855589babccde2d8f0 Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sat, 17 Feb 2024 00:06:01 +0800 Subject: [PATCH 09/24] add getSSOIndexResponse function --- lib/src/connector/ischool_plus_connector.dart | 61 ++++++++++--------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index 4e91e72e..dc0d05dc 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -41,46 +41,27 @@ class ISchoolPlusConnector { /// 4. do something... static Future login(String account, doFirebaseLogin) async { try { - final Map oauthData = {}; - final data = { - "apOu": "ischool_plus_oauth", - "datetime1": DateTime.now().millisecondsSinceEpoch.toString() - }; - - final parameter = ConnectorParameter(_ssoLoginUrl); - parameter.data = data; + final ssoIndexResponse = await getSSOIndexResponse(); + if(ssoIndexResponse.isEmpty) return ISchoolPlusConnectorStatus.loginFail; - final response = (await Connector.getDataByGet(parameter)); - if(response.contains("重新登入")){ - throw StateError('[TAT] ischool_plus_connector.dart: session out of date'); - } + final ssoIndexTagNode = html.parse(ssoIndexResponse); + final ssoIndexNodes = ssoIndexTagNode.getElementsByTagName("input"); + final ssoIndexJumpUrl = ssoIndexTagNode.getElementsByTagName("form")[0].attributes["action"]; - for(int retry=0;true;retry++){ - if(retry == 5) return ISchoolPlusConnectorStatus.loginFail; - final tagNode = html.parse(response.toString().trim()); - final nodes = tagNode.getElementsByTagName("input"); - - for (final node in nodes) { + final Map oauthData = {}; + for (final node in ssoIndexNodes) { final name = node.attributes['name']; final value = node.attributes['value']; oauthData[name] = value; - } - if(oauthData.length==5){ - break; - } - else{ - await Future.delayed(const Duration(milliseconds: 100)); - } } - + // Step 2 - // The `jumpUrl` should be "oauth2Server.do". + // The ssoIndexJumpUrl should be "oauth2Server.do". // If not, it means that the school server has changed. // TODO: Add a validation measurement to check whether Step 1 is died or not. (It should not die if auth is correct) - final jumpUrl = oauthData['action']; - final jumpParameter = ConnectorParameter("${NTUTConnector.host}$jumpUrl"); + final jumpParameter = ConnectorParameter("${NTUTConnector.host}$ssoIndexJumpUrl"); jumpParameter.data = oauthData; - final Response jumpResult = (await Connector.getDataByPostResponse(jumpParameter)); + final jumpResult = (await Connector.getDataByPostResponse(jumpParameter)); final tagNode = html.parse(jumpResult.toString().trim()); final oauthResponse = tagNode.getElementsByTagName('a'); @@ -103,6 +84,26 @@ class ISchoolPlusConnector { } } + static Future getSSOIndexResponse() async { + final data = { + "apOu": "ischool_plus_oauth", + "datetime1": DateTime.now().millisecondsSinceEpoch.toString() + }; + for(int retry=0;true;retry++){ + if(retry == 5) return ""; + final parameter = ConnectorParameter(_ssoLoginUrl); + parameter.data = data; + + final response = (await Connector.getDataByGet(parameter)).toString().trim(); + if(response.contains("ssoForm")){ + return response; + } + else{ + await Future.delayed(const Duration(milliseconds: 100)); + } + } + } + static Future>> getCourseFile(String courseId) async { ConnectorParameter parameter; String result; From ec437bc00b5bfc5e94ed0c88266ca410c287a38f Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sat, 17 Feb 2024 00:09:15 +0800 Subject: [PATCH 10/24] remove unnecessary redirection --- lib/src/connector/ischool_plus_connector.dart | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index dc0d05dc..c663e2f7 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -62,22 +62,19 @@ class ISchoolPlusConnector { final jumpParameter = ConnectorParameter("${NTUTConnector.host}$ssoIndexJumpUrl"); jumpParameter.data = oauthData; final jumpResult = (await Connector.getDataByPostResponse(jumpParameter)); - final tagNode = html.parse(jumpResult.toString().trim()); - final oauthResponse = tagNode.getElementsByTagName('a'); - - // Step 3 - // The redirectUrl is provided by HTML DOM on Step 2. - // It should be https://istudy.ntut.edu.tw/login2.php with lot of the parameters. - final redirectUrl = oauthResponse.first.attributes["href"]; - final redirectParameter = ConnectorParameter(redirectUrl); - await Connector.getDataByGet(redirectParameter); if (doFirebaseLogin) { await FirebaseAnalytics.instance.logLogin( loginMethod: 'ntut_iplus', ); } - return ISchoolPlusConnectorStatus.loginSuccess; + + if(jumpResult.statusCode == 302){ + return ISchoolPlusConnectorStatus.loginSuccess; + } + else{ + return ISchoolPlusConnectorStatus.loginFail; + } } catch (e, stack) { Log.eWithStack(e.toString(), stack); rethrow; From e5c566a0f78ed735dd15eb513948161e14c3a10a Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sat, 17 Feb 2024 00:20:38 +0800 Subject: [PATCH 11/24] update comments --- lib/src/connector/ischool_plus_connector.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index c663e2f7..c93ce5e7 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -58,7 +58,10 @@ class ISchoolPlusConnector { // Step 2 // The ssoIndexJumpUrl should be "oauth2Server.do". // If not, it means that the school server has changed. - // TODO: Add a validation measurement to check whether Step 1 is died or not. (It should not die if auth is correct) + // The response status code to this request should result in + // "302" (the page has moved to a new location), which triggers automatic redirection + // feature included in dio connector, thus no further actions needed. + final jumpParameter = ConnectorParameter("${NTUTConnector.host}$ssoIndexJumpUrl"); jumpParameter.data = oauthData; final jumpResult = (await Connector.getDataByPostResponse(jumpParameter)); From 4c02ed7fd0a8457b1226603a15ce353387f055ff Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sat, 17 Feb 2024 00:21:09 +0800 Subject: [PATCH 12/24] dart format --- lib/src/connector/ischool_plus_connector.dart | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index c93ce5e7..e9ffca85 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -42,7 +42,7 @@ class ISchoolPlusConnector { static Future login(String account, doFirebaseLogin) async { try { final ssoIndexResponse = await getSSOIndexResponse(); - if(ssoIndexResponse.isEmpty) return ISchoolPlusConnectorStatus.loginFail; + if (ssoIndexResponse.isEmpty) return ISchoolPlusConnectorStatus.loginFail; final ssoIndexTagNode = html.parse(ssoIndexResponse); final ssoIndexNodes = ssoIndexTagNode.getElementsByTagName("input"); @@ -54,14 +54,14 @@ class ISchoolPlusConnector { final value = node.attributes['value']; oauthData[name] = value; } - + // Step 2 // The ssoIndexJumpUrl should be "oauth2Server.do". // If not, it means that the school server has changed. // The response status code to this request should result in // "302" (the page has moved to a new location), which triggers automatic redirection // feature included in dio connector, thus no further actions needed. - + final jumpParameter = ConnectorParameter("${NTUTConnector.host}$ssoIndexJumpUrl"); jumpParameter.data = oauthData; final jumpResult = (await Connector.getDataByPostResponse(jumpParameter)); @@ -72,10 +72,9 @@ class ISchoolPlusConnector { ); } - if(jumpResult.statusCode == 302){ + if (jumpResult.statusCode == 302) { return ISchoolPlusConnectorStatus.loginSuccess; - } - else{ + } else { return ISchoolPlusConnectorStatus.loginFail; } } catch (e, stack) { @@ -84,21 +83,17 @@ class ISchoolPlusConnector { } } - static Future getSSOIndexResponse() async { - final data = { - "apOu": "ischool_plus_oauth", - "datetime1": DateTime.now().millisecondsSinceEpoch.toString() - }; - for(int retry=0;true;retry++){ - if(retry == 5) return ""; + static Future getSSOIndexResponse() async { + final data = {"apOu": "ischool_plus_oauth", "datetime1": DateTime.now().millisecondsSinceEpoch.toString()}; + for (int retry = 0; true; retry++) { + if (retry == 5) return ""; final parameter = ConnectorParameter(_ssoLoginUrl); parameter.data = data; final response = (await Connector.getDataByGet(parameter)).toString().trim(); - if(response.contains("ssoForm")){ + if (response.contains("ssoForm")) { return response; - } - else{ + } else { await Future.delayed(const Duration(milliseconds: 100)); } } From 7c2b99ad1d96c5037b36d58c604e9cbbb1d23400 Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sat, 17 Feb 2024 00:34:28 +0800 Subject: [PATCH 13/24] add retry mechanism in oauth server request --- lib/src/connector/ischool_plus_connector.dart | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index e9ffca85..1663172f 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -61,22 +61,24 @@ class ISchoolPlusConnector { // The response status code to this request should result in // "302" (the page has moved to a new location), which triggers automatic redirection // feature included in dio connector, thus no further actions needed. - - final jumpParameter = ConnectorParameter("${NTUTConnector.host}$ssoIndexJumpUrl"); - jumpParameter.data = oauthData; - final jumpResult = (await Connector.getDataByPostResponse(jumpParameter)); + for (int retry = 0; true; retry++) { + if (retry == 3) break; + final jumpParameter = ConnectorParameter("${NTUTConnector.host}$ssoIndexJumpUrl"); + jumpParameter.data = oauthData; + final jumpResult = (await Connector.getDataByPostResponse(jumpParameter)); + if (jumpResult.statusCode == 302) { + return ISchoolPlusConnectorStatus.loginSuccess; + } else { + await Future.delayed(const Duration(milliseconds: 100)); + } + } if (doFirebaseLogin) { await FirebaseAnalytics.instance.logLogin( loginMethod: 'ntut_iplus', ); } - - if (jumpResult.statusCode == 302) { - return ISchoolPlusConnectorStatus.loginSuccess; - } else { - return ISchoolPlusConnectorStatus.loginFail; - } + return ISchoolPlusConnectorStatus.loginFail; } catch (e, stack) { Log.eWithStack(e.toString(), stack); rethrow; From 93c79561b2aacf08ebe515fa54103192826fb95b Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sat, 17 Feb 2024 00:36:01 +0800 Subject: [PATCH 14/24] update comments --- lib/src/connector/ischool_plus_connector.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index 1663172f..e88b3175 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -36,9 +36,8 @@ class ISchoolPlusConnector { /// The Authorization Step of ISchool (2023-10-21) /// 1. GET https://app.ntut.edu.tw/ssoIndex.do - /// 2. POST https://app.ntut.edu.tw/oauth2Server.do (It should be. See the comment on step 2) - /// 3. GET https://istudy.ntut.edu.tw/login2.php (It should be. See the comment on step 3) - /// 4. do something... + /// 2_1. POST https://app.ntut.edu.tw/oauth2Server.do (It should be. See the comment on step 2) + /// 2_2. follow the redirection to https://istudy.ntut.edu.tw/login2.php (It should be. See the comment on step 2) static Future login(String account, doFirebaseLogin) async { try { final ssoIndexResponse = await getSSOIndexResponse(); From a790a9ca04dd11e63d8432548f4516fdfb0e15e0 Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sun, 18 Feb 2024 12:31:32 +0800 Subject: [PATCH 15/24] refactoring the retry logic --- lib/src/connector/ischool_plus_connector.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index e88b3175..59c024a2 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -60,8 +60,7 @@ class ISchoolPlusConnector { // The response status code to this request should result in // "302" (the page has moved to a new location), which triggers automatic redirection // feature included in dio connector, thus no further actions needed. - for (int retry = 0; true; retry++) { - if (retry == 3) break; + for (int retry = 0; retry < 3; retry++) { final jumpParameter = ConnectorParameter("${NTUTConnector.host}$ssoIndexJumpUrl"); jumpParameter.data = oauthData; final jumpResult = (await Connector.getDataByPostResponse(jumpParameter)); @@ -86,8 +85,7 @@ class ISchoolPlusConnector { static Future getSSOIndexResponse() async { final data = {"apOu": "ischool_plus_oauth", "datetime1": DateTime.now().millisecondsSinceEpoch.toString()}; - for (int retry = 0; true; retry++) { - if (retry == 5) return ""; + for (int retry = 0; retry < 5; retry++) { final parameter = ConnectorParameter(_ssoLoginUrl); parameter.data = data; @@ -98,6 +96,7 @@ class ISchoolPlusConnector { await Future.delayed(const Duration(milliseconds: 100)); } } + return ""; } static Future>> getCourseFile(String courseId) async { From 68c30d32b99f5214419b700479bc45297d83533f Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sun, 18 Feb 2024 12:33:10 +0800 Subject: [PATCH 16/24] making logEventToFirebase optional --- lib/src/connector/ischool_plus_connector.dart | 4 ++-- lib/src/task/iplus/iplus_system_task.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index 59c024a2..6d96d77b 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -38,7 +38,7 @@ class ISchoolPlusConnector { /// 1. GET https://app.ntut.edu.tw/ssoIndex.do /// 2_1. POST https://app.ntut.edu.tw/oauth2Server.do (It should be. See the comment on step 2) /// 2_2. follow the redirection to https://istudy.ntut.edu.tw/login2.php (It should be. See the comment on step 2) - static Future login(String account, doFirebaseLogin) async { + static Future login(String account, {bool logEventToFirebase = true}) async { try { final ssoIndexResponse = await getSSOIndexResponse(); if (ssoIndexResponse.isEmpty) return ISchoolPlusConnectorStatus.loginFail; @@ -71,7 +71,7 @@ class ISchoolPlusConnector { } } - if (doFirebaseLogin) { + if (logEventToFirebase) { await FirebaseAnalytics.instance.logLogin( loginMethod: 'ntut_iplus', ); diff --git a/lib/src/task/iplus/iplus_system_task.dart b/lib/src/task/iplus/iplus_system_task.dart index 46367745..51b22911 100644 --- a/lib/src/task/iplus/iplus_system_task.dart +++ b/lib/src/task/iplus/iplus_system_task.dart @@ -21,7 +21,7 @@ class IPlusSystemTask extends NTUTTask { super.onStart(R.current.loginISchoolPlus); final studentId = LocalStorage.instance.getAccount(); - final value = await ISchoolPlusConnector.login(studentId, true); + final value = await ISchoolPlusConnector.login(studentId); super.onEnd(); if (value != ISchoolPlusConnectorStatus.loginSuccess) { From 6de23989a4be012519437b570b844a2f72d2829d Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sun, 18 Feb 2024 13:30:08 +0800 Subject: [PATCH 17/24] convert to named argument --- .../ischool_plus_connector_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ischool_plus_connector_test/ischool_plus_connector_test.dart b/test/ischool_plus_connector_test/ischool_plus_connector_test.dart index b1963d91..1b5703d4 100644 --- a/test/ischool_plus_connector_test/ischool_plus_connector_test.dart +++ b/test/ischool_plus_connector_test/ischool_plus_connector_test.dart @@ -54,7 +54,7 @@ Future main() async { // expect(isCurrentSessionAlive, isTrue); }); test('ischool_login', () async { - final result = await ISchoolPlusConnector.login(userId, false); + final result = await ISchoolPlusConnector.login(userId, logEventToFirebase: false); expect(result, ISchoolPlusConnectorStatus.loginSuccess); dev.log('ischool login Done Test execution time: ${stopwatch.elapsed}'); stopwatch.stop(); From ff2f9bc404d7f58fbccd251e679cc170ab7f7d10 Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sun, 18 Feb 2024 14:28:27 +0800 Subject: [PATCH 18/24] remove unnecessary else statement --- lib/src/connector/ischool_plus_connector.dart | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index 6d96d77b..c8bc4216 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -90,11 +90,8 @@ class ISchoolPlusConnector { parameter.data = data; final response = (await Connector.getDataByGet(parameter)).toString().trim(); - if (response.contains("ssoForm")) { - return response; - } else { - await Future.delayed(const Duration(milliseconds: 100)); - } + if (response.contains("ssoForm")) return response; + await Future.delayed(const Duration(milliseconds: 100)); } return ""; } From f69f2c3f01c7f41b44211654dfbab00d744ca266 Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sun, 18 Feb 2024 15:16:49 +0800 Subject: [PATCH 19/24] rewrite login retry mechanism on step 2 --- lib/src/connector/ischool_plus_connector.dart | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index c8bc4216..7d98e608 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -64,11 +64,17 @@ class ISchoolPlusConnector { final jumpParameter = ConnectorParameter("${NTUTConnector.host}$ssoIndexJumpUrl"); jumpParameter.data = oauthData; final jumpResult = (await Connector.getDataByPostResponse(jumpParameter)); - if (jumpResult.statusCode == 302) { - return ISchoolPlusConnectorStatus.loginSuccess; - } else { + if (jumpResult.statusCode != 302) { await Future.delayed(const Duration(milliseconds: 100)); + continue; + } + final login2Parameter = ConnectorParameter(jumpResult.headers['location'][0]); + final login2Result = await Connector.getDataByGet(login2Parameter); + if (login2Result.contains("lost")) { + await Future.delayed(const Duration(milliseconds: 100)); + continue; } + return ISchoolPlusConnectorStatus.loginSuccess; } if (logEventToFirebase) { From aa3b705864a5ad6f0c6dac324bf6d4aca9a2f795 Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Sun, 18 Feb 2024 15:32:37 +0800 Subject: [PATCH 20/24] add log --- lib/src/connector/ischool_plus_connector.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index 7d98e608..199247af 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -1,6 +1,7 @@ // TODO: remove sdk version selector after migrating to null-safety. // @dart=2.10 import 'dart:convert'; +import 'dart:developer'; import 'dart:io'; import 'package:dio/dio.dart'; @@ -65,12 +66,14 @@ class ISchoolPlusConnector { jumpParameter.data = oauthData; final jumpResult = (await Connector.getDataByPostResponse(jumpParameter)); if (jumpResult.statusCode != 302) { + log("[TAT] ischool_plus_connector.dart: failed to get redirection location from oauth2Server, retrying..."); await Future.delayed(const Duration(milliseconds: 100)); continue; } final login2Parameter = ConnectorParameter(jumpResult.headers['location'][0]); final login2Result = await Connector.getDataByGet(login2Parameter); if (login2Result.contains("lost")) { + log("[TAT] ischool_plus_connector.dart: connection lost during redirection, retrying..."); await Future.delayed(const Duration(milliseconds: 100)); continue; } @@ -97,6 +100,7 @@ class ISchoolPlusConnector { final response = (await Connector.getDataByGet(parameter)).toString().trim(); if (response.contains("ssoForm")) return response; + log("[TAT] ischool_plus_connector.dart: failed to get ssoForm, retrying..."); await Future.delayed(const Duration(milliseconds: 100)); } return ""; From a2aa39198e63dcacb0a6868a7fa8414fbc2ba601 Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Wed, 21 Feb 2024 15:11:14 +0800 Subject: [PATCH 21/24] extend ischool connection state --- lib/src/connector/ischool_plus_connector.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index 199247af..b2c97c23 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -17,7 +17,7 @@ import 'package:html/parser.dart' as html; import 'core/connector_parameter.dart'; import 'ntut_connector.dart'; -enum ISchoolPlusConnectorStatus { loginSuccess, loginFail, unknownError } +enum ISchoolPlusConnectorStatus { loginSuccess, loginGetSSOIndexError, loginRedirectionError, unknownError } enum IPlusReturnStatus { success, fail, noPermission } @@ -42,7 +42,7 @@ class ISchoolPlusConnector { static Future login(String account, {bool logEventToFirebase = true}) async { try { final ssoIndexResponse = await getSSOIndexResponse(); - if (ssoIndexResponse.isEmpty) return ISchoolPlusConnectorStatus.loginFail; + if (ssoIndexResponse.isEmpty) return ISchoolPlusConnectorStatus.loginGetSSOIndexError; final ssoIndexTagNode = html.parse(ssoIndexResponse); final ssoIndexNodes = ssoIndexTagNode.getElementsByTagName("input"); @@ -85,7 +85,7 @@ class ISchoolPlusConnector { loginMethod: 'ntut_iplus', ); } - return ISchoolPlusConnectorStatus.loginFail; + return ISchoolPlusConnectorStatus.loginRedirectionError; } catch (e, stack) { Log.eWithStack(e.toString(), stack); rethrow; From 6ba666079e9cce5c56b367b2c3b896557a615cd1 Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Wed, 21 Feb 2024 15:13:24 +0800 Subject: [PATCH 22/24] add error handling --- lib/src/task/iplus/iplus_system_task.dart | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/src/task/iplus/iplus_system_task.dart b/lib/src/task/iplus/iplus_system_task.dart index 51b22911..35cafc5c 100644 --- a/lib/src/task/iplus/iplus_system_task.dart +++ b/lib/src/task/iplus/iplus_system_task.dart @@ -23,9 +23,14 @@ class IPlusSystemTask extends NTUTTask { final studentId = LocalStorage.instance.getAccount(); final value = await ISchoolPlusConnector.login(studentId); super.onEnd(); - - if (value != ISchoolPlusConnectorStatus.loginSuccess) { - return onError(R.current.loginISchoolPlusError); + + switch(value){ + case ISchoolPlusConnectorStatus.loginGetSSOIndexError: + return onError("ischool login get SSO index error"); + case ISchoolPlusConnectorStatus.loginRedirectionError: + return onError("ischool login redirection error"); + default: + break; } } return status; From 6aa53b5dc6202015df53b0c5e212d4f1a6ada368 Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Wed, 21 Feb 2024 15:15:57 +0800 Subject: [PATCH 23/24] update comment --- lib/src/connector/ischool_plus_connector.dart | 16 ++++++++-------- lib/src/task/iplus/iplus_system_task.dart | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/src/connector/ischool_plus_connector.dart b/lib/src/connector/ischool_plus_connector.dart index b2c97c23..7cecce03 100644 --- a/lib/src/connector/ischool_plus_connector.dart +++ b/lib/src/connector/ischool_plus_connector.dart @@ -37,8 +37,8 @@ class ISchoolPlusConnector { /// The Authorization Step of ISchool (2023-10-21) /// 1. GET https://app.ntut.edu.tw/ssoIndex.do - /// 2_1. POST https://app.ntut.edu.tw/oauth2Server.do (It should be. See the comment on step 2) - /// 2_2. follow the redirection to https://istudy.ntut.edu.tw/login2.php (It should be. See the comment on step 2) + /// 2-1. POST https://app.ntut.edu.tw/oauth2Server.do (It should be. See the comment on step 2-1) + /// 2-2. follow the redirection to https://istudy.ntut.edu.tw/login2.php (It should be. See the comment on step 2-2) static Future login(String account, {bool logEventToFirebase = true}) async { try { final ssoIndexResponse = await getSSOIndexResponse(); @@ -55,13 +55,10 @@ class ISchoolPlusConnector { oauthData[name] = value; } - // Step 2 - // The ssoIndexJumpUrl should be "oauth2Server.do". - // If not, it means that the school server has changed. - // The response status code to this request should result in - // "302" (the page has moved to a new location), which triggers automatic redirection - // feature included in dio connector, thus no further actions needed. for (int retry = 0; retry < 3; retry++) { + // Step 2-1 + // The ssoIndexJumpUrl should be "oauth2Server.do", and the response should contain redirection location. + // If not, a retry of getting redirection location will perform. final jumpParameter = ConnectorParameter("${NTUTConnector.host}$ssoIndexJumpUrl"); jumpParameter.data = oauthData; final jumpResult = (await Connector.getDataByPostResponse(jumpParameter)); @@ -70,6 +67,9 @@ class ISchoolPlusConnector { await Future.delayed(const Duration(milliseconds: 100)); continue; } + // Step 2-2 + // The redirect location should be "https://istudy.ntut.edu.tw/login2.php", and the response should not contain + // "connection `lost`", if it does, a retry of getting redirection location will perform. final login2Parameter = ConnectorParameter(jumpResult.headers['location'][0]); final login2Result = await Connector.getDataByGet(login2Parameter); if (login2Result.contains("lost")) { diff --git a/lib/src/task/iplus/iplus_system_task.dart b/lib/src/task/iplus/iplus_system_task.dart index 35cafc5c..d12d2a9d 100644 --- a/lib/src/task/iplus/iplus_system_task.dart +++ b/lib/src/task/iplus/iplus_system_task.dart @@ -23,7 +23,8 @@ class IPlusSystemTask extends NTUTTask { final studentId = LocalStorage.instance.getAccount(); final value = await ISchoolPlusConnector.login(studentId); super.onEnd(); - + + //TODO: generate string for this switch(value){ case ISchoolPlusConnectorStatus.loginGetSSOIndexError: return onError("ischool login get SSO index error"); From bf23aa0e69c8914be695492c8af33cdd96ae8a88 Mon Sep 17 00:00:00 2001 From: James-Lu-none Date: Wed, 21 Feb 2024 15:16:18 +0800 Subject: [PATCH 24/24] dart format --- lib/src/task/iplus/iplus_system_task.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/task/iplus/iplus_system_task.dart b/lib/src/task/iplus/iplus_system_task.dart index d12d2a9d..77ee587a 100644 --- a/lib/src/task/iplus/iplus_system_task.dart +++ b/lib/src/task/iplus/iplus_system_task.dart @@ -25,11 +25,11 @@ class IPlusSystemTask extends NTUTTask { super.onEnd(); //TODO: generate string for this - switch(value){ + switch (value) { case ISchoolPlusConnectorStatus.loginGetSSOIndexError: return onError("ischool login get SSO index error"); case ISchoolPlusConnectorStatus.loginRedirectionError: - return onError("ischool login redirection error"); + return onError("ischool login redirection error"); default: break; }