// ignore_for_file: avoid_print, use_build_context_synchronously import 'package:filcnaplo/utils/jwt.dart'; import 'package:filcnaplo_kreta_api/providers/absence_provider.dart'; import 'package:filcnaplo_kreta_api/providers/event_provider.dart'; import 'package:filcnaplo_kreta_api/providers/exam_provider.dart'; import 'package:filcnaplo_kreta_api/providers/grade_provider.dart'; import 'package:filcnaplo_kreta_api/providers/homework_provider.dart'; import 'package:filcnaplo_kreta_api/providers/message_provider.dart'; import 'package:filcnaplo_kreta_api/providers/note_provider.dart'; import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart'; import 'package:filcnaplo/api/providers/user_provider.dart'; import 'package:filcnaplo/api/providers/database_provider.dart'; import 'package:filcnaplo/models/settings.dart'; import 'package:filcnaplo/models/user.dart'; import 'package:filcnaplo_kreta_api/client/api.dart'; import 'package:filcnaplo_kreta_api/client/client.dart'; import 'package:filcnaplo_kreta_api/models/student.dart'; import 'package:filcnaplo_kreta_api/models/week.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:filcnaplo/api/nonce.dart'; enum LoginState { missingFields, invalidGrant, failed, normal, inProgress, success } Nonce getNonce(String nonce, String username, String instituteCode) { Nonce nonceEncoder = Nonce(key: [98, 97, 83, 115, 120, 79, 119, 108, 85, 49, 106, 77], nonce: nonce); nonceEncoder.encode(instituteCode.toUpperCase() + nonce + username.toUpperCase()); return nonceEncoder; } Future loginApi({ required String username, required String password, required String instituteCode, required BuildContext context, void Function(User)? onLogin, void Function()? onSuccess, }) async { Provider.of(context, listen: false).userAgent = Provider.of(context, listen: false).config.userAgent; Map headers = { "content-type": "application/x-www-form-urlencoded", }; String nonceStr = await Provider.of(context, listen: false).getAPI(KretaAPI.nonce, json: false); Nonce nonce = getNonce(nonceStr, username, instituteCode); headers.addAll(nonce.header()); Map? res = await Provider.of(context, listen: false).postAPI(KretaAPI.login, headers: headers, body: User.loginBody( username: username, password: password, instituteCode: instituteCode, )); if (res != null) { if (res.containsKey("error")) { if (res["error"] == "invalid_grant") { return LoginState.invalidGrant; } } else { if (res.containsKey("access_token")) { try { Provider.of(context, listen: false).accessToken = res["access_token"]; Map? studentJson = await Provider.of(context, listen: false).getAPI(KretaAPI.student(instituteCode)); Student student = Student.fromJson(studentJson!); var user = User( username: username, password: password, instituteCode: instituteCode, name: student.name, student: student, role: JwtUtils.getRoleFromJWT(res["access_token"])!, ); if (onLogin != null) onLogin(user); // Store User in the database await Provider.of(context, listen: false).store.storeUser(user); Provider.of(context, listen: false).addUser(user); Provider.of(context, listen: false).setUser(user.id); // Get user data try { await Future.wait([ Provider.of(context, listen: false).fetch(), Provider.of(context, listen: false).fetch(week: Week.current()), Provider.of(context, listen: false).fetch(), Provider.of(context, listen: false).fetch(), Provider.of(context, listen: false).fetchAll(), Provider.of(context, listen: false).fetch(), Provider.of(context, listen: false).fetch(), Provider.of(context, listen: false).fetch(), ]); } catch (error) { print("WARNING: failed to fetch user data: $error"); } if (onSuccess != null) onSuccess(); return LoginState.success; } catch (error) { print("ERROR: loginApi: $error"); // maybe check debug mode // ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("ERROR: $error"))); return LoginState.failed; } } } } return LoginState.failed; }