import 'dart:io'; import 'package:dio/dio.dart'; import 'package:maxkey_flutter/persistent.dart'; import 'package:maxkey_flutter/utils.dart'; typedef ExpectedErrorHandler = void Function(String msg); class AuthnService { final Dio _dio; AuthnService(this._dio); /// 获取 state 类型 Future get() async { try { LOGGER.i("AuthnService.get(): "); LOGGER.i("GET: /login/get?_allow_anonymous=true"); final res = await _dio.get( "/login/get?_allow_anonymous=true", queryParameters: {"remember_me": true}, ); return res.data["data"]["state"]; } catch (err) { LOGGER.e("AuthnService.get(): "); LOGGER.e(err); } return null; } /// 短信验证码 Future produceOtp({ required ExpectedErrorHandler expectedErrorHandler, required String mobile, }) async { try { LOGGER.i("AuthnService.produceOtp(): "); LOGGER.i("GET: /login/sendotp/$mobile?_allow_anonymous=true"); final res = await _dio.get( "/login/sendotp/$mobile?_allow_anonymous=true", queryParameters: {"mobile": mobile}, ); if (res.data["code"] != 0) { final msg = res.data["message"] ?? "验证码发送失败"; expectedErrorHandler(msg); LOGGER.w(msg); return false; } return true; } catch (err) { LOGGER.e("AuthnService.produceOtp(): "); LOGGER.e(err); } return false; } /// 账密登录 Future loginNormal({ required ExpectedErrorHandler expectedErrorHandler, required String state, required String username, required String password, required String captcha, }) async { try { LOGGER.i("AuthnService.loginNormal(): "); LOGGER.i("POST: /login/signin?_allow_anonymous=true"); final res = await _dio.post( "/login/signin?_allow_anonymous=true", data: { "authType": "app", "state": state, "username": username, "password": password, "captcha": captcha, "remeberMe": true, }, ); if (res.data["code"] != 0) { final msg = res.data["message"] ?? "登录失败"; expectedErrorHandler(msg); LOGGER.w(msg); return false; } await onlineAuth( token: res.data["data"]["token"], onlineTicket: res.data["data"]["ticket"], username: res.data["data"]["username"], ); return true; } catch (err) { LOGGER.e("AuthnService.loginNormal(): "); LOGGER.e(err); } return false; } Future scanCode({ required ExpectedErrorHandler expectedErrorHandler, required String code, }) async { LOGGER.i("AuthnService.scanCode(): "); final token = MaxKeyPersistent.instance.token; if (token == null) { LOGGER.i("未登录"); expectedErrorHandler("未登录"); return false; } try { LOGGER.i("POST: /login/scanCode"); final res = await _dio.post( "/login/scanCode", data: {"jwtToken": token, "code": code}, ); if (res.data["code"] != 0) { final msg = res.data["message"] ?? "扫码登录失败"; expectedErrorHandler(msg); LOGGER.w(msg); return false; } return true; } catch (err) { LOGGER.e("AuthnService.scanCode(): "); LOGGER.e(err); } return false; } Future onlineAuth({ required String token, required String onlineTicket, required String username, }) async { await MaxKeyPersistent.instance.setUser(username); await MaxKeyPersistent.instance.setToken(token); _dio.options.headers[HttpHeaders.authorizationHeader] = token; } bool localAuth() { final token = MaxKeyPersistent.instance.token; if (token == null) return false; _dio.options.headers[HttpHeaders.authorizationHeader] = token; return true; } /// 登出并清除本地缓存的 token Future logout() async { try { LOGGER.i("AuthnService.logout(): "); LOGGER.i("GET: /logout"); await _dio.get("/logout").timeout(const Duration(seconds: 5)); } catch (err) { LOGGER.e("AuthnService.logout(): "); LOGGER.e(err); } _dio.options.headers.remove(HttpHeaders.authorizationHeader); await MaxKeyPersistent.instance.clearToken(); } }