login method
override
Authenticates a user with NTUT Portal credentials.
Sets the JSESSIONID cookie in the app.ntut.edu.tw domain for subsequent authenticated requests. This session cookie is shared across all services.
Returns user profile information including name, email, and avatar filename.
Throws LoginException on failure with a LoginFailure indicating the reason (wrong credentials, account locked, password expired, etc.).
Implementation
@override
Future<UserDto> login(String username, String password) async {
final response = await _portalDio.post(
'login.do',
queryParameters: {'muid': username, 'mpassword': password},
);
final body = jsonDecode(response.data);
if (!body['success']) {
final String? errorMsg = body['errorMsg'];
final bool resetPwd = body['resetPwd'] ?? false;
throw LoginException(
switch (errorMsg) {
final msg? when msg.contains('密碼錯誤') => .wrongCredentials,
final msg? when msg.contains('已被鎖住') => .accountLocked,
final msg? when msg.contains('密碼已過期') && resetPwd => .passwordExpired,
final msg? when msg.contains('驗證手機') => .mobileVerificationRequired,
_ => .unknown,
},
message: errorMsg?.isNotEmpty == true ? errorMsg : null,
);
}
final String? passwordExpiredRemind = body['passwordExpiredRemind'];
// Normalize empty strings to null for consistency
String? normalizeEmpty(String? value) =>
value?.isNotEmpty == true ? value : null;
return (
name: normalizeEmpty(body['givenName']),
avatarFilename: normalizeEmpty(body['userPhoto']),
email: normalizeEmpty(body['userMail']),
passwordExpiresInDays: passwordExpiredRemind != null
? int.tryParse(passwordExpiredRemind)
: null,
);
}