auto_login.dart 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. import 'dart:convert';
  2. import 'package:auto_route/auto_route.dart';
  3. import 'package:flutter/foundation.dart';
  4. import 'package:telnow_mobile_new/src/api/api_auth_provider.dart';
  5. import 'package:telnow_mobile_new/src/api/jwt_token.dart';
  6. import 'package:telnow_mobile_new/src/layouts/components/template.dart';
  7. import 'package:telnow_mobile_new/src/storage/sharedpreferences/shared_preferences_manager.dart';
  8. import 'package:telnow_mobile_new/src/injector/injector.dart';
  9. import 'package:telnow_mobile_new/src/model/login/login_body.dart';
  10. import 'package:telnow_mobile_new/src/api/api_auth_repository.dart';
  11. import 'package:telnow_mobile_new/src/model/token/token.dart';
  12. import 'package:flutter/material.dart';
  13. import 'package:easy_localization/easy_localization.dart';
  14. import 'package:telnow_mobile_new/src/utils/U.dart';
  15. @RoutePage()
  16. class AutoLoginPage extends StatefulWidget {
  17. const AutoLoginPage({super.key});
  18. @override
  19. State<AutoLoginPage> createState() => _AutoLoginPageState();
  20. }
  21. class _AutoLoginPageState extends State<AutoLoginPage> {
  22. final ApiAuthProvider apiAuthProvider = ApiAuthProvider();
  23. final ApiAuthRepository apiAuthRepository = ApiAuthRepository();
  24. final SharedPreferencesManager sharedPreferencesManager = locator<SharedPreferencesManager>();
  25. Map<String, dynamic>? tokenData;
  26. String companyName = '';
  27. String guestName = '';
  28. bool loading = false;
  29. bool invalidUserLogin = false;
  30. bool onProgress = false;
  31. bool redirectToLoginPage = false;
  32. String progressMsg = 'initializing'.tr();
  33. String newPassword = '';
  34. String confirmPassword = '';
  35. Map <String, String> dData = {};
  36. @override
  37. void initState() {
  38. WidgetsBinding.instance.addPostFrameCallback((_) {
  39. getQueryParam();
  40. getCompanyName();
  41. });
  42. // TODO: implement initState
  43. super.initState();
  44. }
  45. getQueryParam() async {
  46. String url = kIsWeb ? Uri.base.toString() : U.getUrl();
  47. Uri uri = Uri.dataFromString(url);
  48. String prmJson = '';
  49. try {
  50. uri.queryParameters.forEach((k,v) {
  51. switch (k) {
  52. case 'prm':prmJson = U.decodeBase64Url(Uri.decodeComponent(v));
  53. }
  54. });
  55. dData = {
  56. "username": jsonDecode(prmJson)["username"],
  57. "password": jsonDecode(prmJson)["password"]
  58. };
  59. U.clearUrl();
  60. getTokenData();
  61. } catch(e) {
  62. U.showDebugToast(e.toString());
  63. debugPrint("invalid param: $e");
  64. redirectToLoginPage = true;
  65. Future.delayed(Duration.zero, (){
  66. context.router.removeLast();
  67. context.navigateToPath("/app/${U.getAccessCode()}");
  68. });
  69. }
  70. }
  71. getTokenData({int n = 0}) async {
  72. JwtToken jwtToken = JwtToken();
  73. showLoading(context);
  74. try {
  75. Token token = await apiAuthRepository.postLoginUser(LoginBody(dData["username"]!.trim(), dData["password"]!.trim(), "password"));
  76. if (token.error != null) {
  77. closeLoading(context);
  78. showError(context, token.error);
  79. setState(() {
  80. loading = false;
  81. invalidUserLogin = true;
  82. });
  83. return;
  84. }
  85. // var pid = U.getPidFromUrl(context.router.currentUrl);
  86. await sharedPreferencesManager.putString(SharedPreferencesManager.keyAccessToken, token.accessToken!);
  87. await sharedPreferencesManager.putString(SharedPreferencesManager.keyRefreshToken, token.refreshToken!);
  88. String accessToken = sharedPreferencesManager.getString(SharedPreferencesManager.keyAccessToken)!;
  89. var jwt = jwtToken.parseJwtPayLoad(accessToken);
  90. // print(jwt);
  91. var user = await apiAuthProvider.getData('/api/informants/${jwt['userId']}', null, context);
  92. if(user != null){
  93. closeLoading(context);
  94. setState((){
  95. tokenData = jwt;
  96. context.setLocale(Locale(tokenData!['language'].toLowerCase()));
  97. guestName = user['guestName'];
  98. });
  99. }
  100. } catch(e){
  101. closeLoading(context);
  102. debugPrint(e.toString());
  103. U.showDebugToast(e.toString());
  104. getTokenData(n: n + 1);
  105. }
  106. }
  107. getCompanyName() async {
  108. var license = await U.getLicense();
  109. if (license != null && license['companyName'] != null && mounted) {
  110. setState(() {
  111. companyName = license['companyName'];
  112. });
  113. }
  114. }
  115. backToQr() async {
  116. try {
  117. // U.clearAccessCode();
  118. U.clearPreferences().then((value) {
  119. context.router.removeLast();
  120. context.navigateToPath('/qr?new=true');
  121. });
  122. } catch(e) {
  123. debugPrint(e.toString());
  124. U.showDebugToast(e.toString());
  125. }
  126. }
  127. @override
  128. Widget build(BuildContext context) {
  129. return WillPopScope(
  130. onWillPop: (){
  131. return Future.value(true);
  132. },
  133. child: Scaffold(
  134. resizeToAvoidBottomInset: false,
  135. body: redirectToLoginPage ? Container() : Stack(
  136. children: [
  137. Container(
  138. decoration: BoxDecoration(
  139. image: DecorationImage(
  140. image: AssetImage("assets/image/background/background.jpg"),
  141. fit: BoxFit.cover,
  142. )
  143. ),
  144. ),
  145. Container(
  146. width: MediaQuery.of(context).size.width,
  147. height: MediaQuery.of(context).size.height,
  148. decoration: BoxDecoration(
  149. gradient: LinearGradient(
  150. begin: Alignment.topCenter, end: Alignment.bottomCenter,
  151. colors: [
  152. primaryColor.withValues(alpha: 0.50), Colors.black.withValues(alpha: 0.91)
  153. ]
  154. )
  155. ),
  156. child: SingleChildScrollView(
  157. padding: EdgeInsets.fromLTRB(16, 50, 16, 16),
  158. child: Column(
  159. crossAxisAlignment: CrossAxisAlignment.center,
  160. children: [
  161. Container(
  162. margin: EdgeInsets.only(bottom: 100),
  163. child: Row(
  164. children: [
  165. GestureDetector(
  166. child: U.iconsax('arrow-left', color: Colors.white),
  167. onTap: (){
  168. context.router.removeLast();
  169. context.navigateToPath('/qr?new=true');
  170. },
  171. ),
  172. SizedBox(width: 15),
  173. Expanded(
  174. child: GestureDetector(
  175. child: Column(
  176. crossAxisAlignment: CrossAxisAlignment.start,
  177. children: [
  178. Text('buttonBack'.tr(), style: TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500)),
  179. Text('buttonScan'.tr(), style: TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500)),
  180. ],
  181. ),
  182. onTap: () => backToQr(),
  183. ),
  184. ),
  185. Image.asset('assets/image/logo/logo.png', width: 120)
  186. ],
  187. )
  188. ),
  189. !invalidUserLogin ? Column(
  190. children: [
  191. Text('${'welcome'.tr()} $guestName', style: TextStyle(color: Colors.white, fontSize: 16), textAlign: TextAlign.center),
  192. SizedBox(height: 16),
  193. Text('createNewPassText'.tr(), style: TextStyle(color: Colors.white, fontSize: 16), textAlign: TextAlign.center),
  194. ],
  195. ) : Container(),
  196. !invalidUserLogin ? Column(
  197. children: [
  198. SizedBox(height: 80),
  199. loginFieldTemplate(placeholder: 'newPassword'.tr(), value: newPassword, action: (val)=>newPassword = val, isPassword: true, submit: (val)=>loginAction()),
  200. SizedBox(height: 12),
  201. loginFieldTemplate(placeholder: 'confirmPassword'.tr(), value: confirmPassword, action: (val)=>confirmPassword = val, isPassword: true, submit: (val)=>loginAction()),
  202. GestureDetector(
  203. child: Container(
  204. width: double.infinity,
  205. margin: EdgeInsets.only(top: 40, bottom: 60),
  206. padding: EdgeInsets.symmetric(vertical: 16),
  207. decoration: BoxDecoration(
  208. color: primaryColor.withValues(alpha: 0.50),
  209. border: Border.all(color: Colors.white),
  210. borderRadius: BorderRadius.all(Radius.circular(12))
  211. ),
  212. child: !loading ? Text('buttonLogin'.tr(), style: TextStyle(color: Colors.white, fontSize: 17), textAlign: TextAlign.center) : Center(
  213. child: Row(
  214. mainAxisAlignment: MainAxisAlignment.center,
  215. children: [
  216. SizedBox(
  217. width: 22, height: 22, child: CircularProgressIndicator(color: Colors.white),
  218. ),
  219. SizedBox(width: 10,),
  220. onProgress ? Text(progressMsg, style: TextStyle(color: Colors.white, fontSize: 15), textAlign: TextAlign.center) : Container()
  221. ],
  222. ),
  223. ),
  224. ),
  225. onTap: () => loginAction(),
  226. ),
  227. ],
  228. ) : Column(
  229. children: [
  230. Text("Sorry, user login is not valid.", style: TextStyle(color: Colors.white, fontSize: 17), textAlign: TextAlign.center),
  231. Text("Please try again with another QR code.", style: TextStyle(color: Colors.white, fontSize: 17), textAlign: TextAlign.center)
  232. ],
  233. ),
  234. Text(companyName, style: TextStyle(fontSize: 16, color: Colors.white), textAlign: TextAlign.center),
  235. Container(
  236. margin: const EdgeInsets.only(top: 118),
  237. alignment: Alignment.bottomCenter,
  238. child: Text('${'version'.tr()} ${ApiAuthProvider().displayVersion}', style: TextStyle(color: Colors.white, fontSize: 14))
  239. ),
  240. ],
  241. ),
  242. ),
  243. ),
  244. ],
  245. ),
  246. ),
  247. );
  248. }
  249. loginAction() async{
  250. if(!loading && tokenData != null){
  251. if(newPassword.isNotEmpty && confirmPassword.isNotEmpty){
  252. if(newPassword.trim() == confirmPassword.trim()){
  253. setState(() {
  254. loading = true;
  255. onProgress = true;
  256. });
  257. var data = {'oldPassword': dData['password'], 'password': newPassword.trim()};
  258. try {
  259. var res = await apiAuthProvider.patchData('/api/informants/${tokenData!['userId']}/changePassword', data, context);
  260. if (res != null) {
  261. // setState(() => progressMsg = "Initializing...");
  262. String password = tokenData!['related'] && tokenData!['tenantCode'] != null && tokenData!['tenantCode'] != '' ? tokenData!['tenantCode'] + ' ' + data['password'] : data['password'];
  263. LoginBody loginBody = LoginBody(dData['username']!, password, 'password');
  264. Token token = await apiAuthRepository.postLoginUser(loginBody);
  265. if (token.error != null) {
  266. setState(() => loading = false);
  267. showError(context, token.error);
  268. } else {
  269. setState(() => progressMsg = "redirecting".tr());
  270. await U.setChangedPassword(true);
  271. var parsedToken = U.token.parseJwtPayLoad(token.accessToken!);
  272. await sharedPreferencesManager.putString(SharedPreferencesManager.keyAccessToken, token.accessToken!);
  273. await sharedPreferencesManager.putString(SharedPreferencesManager.keyRefreshToken, token.refreshToken!);
  274. await sharedPreferencesManager.putString(SharedPreferencesManager.keyUsername, tokenData!['related'] ? parsedToken['user_name'].split("-").last : dData['username']);
  275. await sharedPreferencesManager.putBool(SharedPreferencesManager.keyIsLogin, true);
  276. await sharedPreferencesManager.putString(SharedPreferencesManager.keyScoope, 'INSIDE');
  277. await sharedPreferencesManager.putInt(SharedPreferencesManager.keyCountRefreshToken, 0);
  278. U.setHidePayload(true);
  279. var pid = U.getAccessCode();
  280. context.router.removeLast();
  281. context.navigateToPath("/app/$pid/menu");
  282. }
  283. }
  284. else{
  285. setState(() => loading = false);
  286. }
  287. } catch(e) {
  288. debugPrint(e.toString());
  289. setState(() => loading = false);
  290. }
  291. }
  292. else{
  293. showError(context, 'checkNewPass'.tr());
  294. }
  295. }
  296. else{
  297. showError(context, 'cannotEmpty'.tr());
  298. }
  299. }
  300. }
  301. }