import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_translate/flutter_translate.dart'; import 'package:logger/logger.dart'; import 'package:validators/sanitizers.dart'; import 'package:validators/validators.dart'; import '../../core/services/session_service.dart'; import '../../core/services/storage_service.dart'; import '../../locator.dart'; import '../enums/error_code.dart'; import '../enums/viewstate.dart'; import '../error/rest_service_exception.dart'; import '../error/service_exception.dart'; import '../models/rest/create_apikey_response.dart'; import '../services/user_service.dart'; import '../util/logger.dart'; import 'base_model.dart'; class LoginModel extends BaseModel { TextEditingController _uriController = TextEditingController(); final TextEditingController _userNameController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); final TextEditingController _apiKeyController = TextEditingController(); TextEditingController get uriController => _uriController; TextEditingController get userNameController => _userNameController; TextEditingController get passwordController => _passwordController; TextEditingController get apiKeyController => _apiKeyController; final SessionService _sessionService = locator(); final StorageService _storageService = locator(); final UserService _userService = locator(); final Logger _logger = getLogger(); bool useCredentialsLogin = true; String? errorMessage; void toggleLoginMethod() { setStateView(ViewState.busy); useCredentialsLogin = !useCredentialsLogin; setStateView(ViewState.idle); } void init() async { bool hasLastUrl = await _storageService.hasLastUrl(); if (hasLastUrl) { setStateView(ViewState.busy); var s = await (_storageService.retrieveLastUrl() as FutureOr); if (s.isNotEmpty) { _uriController = TextEditingController(text: s); } setStateView(ViewState.idle); } } Future login() async { var url = uriController.text; var username = userNameController.text; var password = passwordController.text; var apiKey = apiKeyController.text; setStateView(ViewState.busy); url = trim(url); username = trim(username); if (url.isEmpty) { errorMessage = translate('login.errors.empty_url'); setStateView(ViewState.idle); return false; } if (!url.contains("https://") && !url.contains("http://")) { errorMessage = translate('login.errors.no_protocol'); setStateView(ViewState.idle); return false; } bool validUri = Uri.parse(url).isAbsolute; if (!validUri || !isURL(url)) { errorMessage = translate('login.errors.invalid_url'); setStateView(ViewState.idle); return false; } if (useCredentialsLogin) { if (username.isEmpty) { errorMessage = translate('login.errors.empty_username'); setStateView(ViewState.idle); return false; } if (password.isEmpty) { errorMessage = translate('login.errors.empty_password'); setStateView(ViewState.idle); return false; } } else { if (apiKey.isEmpty) { errorMessage = translate('login.errors.empty_apikey'); setStateView(ViewState.idle); return false; } } var success = false; try { if (useCredentialsLogin) { CreateApiKeyResponse apiKeyResponse = await _userService.createApiKey( url, username, password, 'apikey', 'fbmobile-${DateTime.now().millisecondsSinceEpoch}'); var newKey = apiKeyResponse.data['new_key']; if (newKey != null) { success = await _sessionService.login(url, newKey); } else { throw ServiceException( code: ErrorCode.invalidApiKey, message: translate('login.errors.invalid_api_key')); } } else { _sessionService.setApiConfig(url, apiKey); await _userService.checkAccessLevelIsAtLeastApiKey(); success = await _sessionService.login(url, apiKey); } errorMessage = null; } catch (e) { if (e is RestServiceException) { if (e.statusCode == HttpStatus.unauthorized) { errorMessage = translate('login.errors.wrong_credentials'); } else if (e.statusCode != HttpStatus.unauthorized && e.statusCode == HttpStatus.forbidden) { errorMessage = translate('login.errors.forbidden'); } else if (e.statusCode == HttpStatus.notFound) { errorMessage = translate('api.incompatible_error_not_found'); } if (e.statusCode == HttpStatus.badRequest) { errorMessage = translate('api.bad_request', args: {'reason': e.responseBody.message}); } else { errorMessage = translate('api.general_rest_error'); } } else if (e is ServiceException && e.code == ErrorCode.invalidApiKey) { errorMessage = translate('login.errors.invalid_api_key'); } else if (e is ServiceException && e.code == ErrorCode.socketError) { errorMessage = translate('api.socket_error'); } else if (e is ServiceException && e.code == ErrorCode.socketTimeout) { errorMessage = translate('api.socket_timeout'); } else { errorMessage = translate('app.unknown_error'); _sessionService.logout(); setStateView(ViewState.idle); _logger.e('An unknown error occurred', error: e); rethrow; } if (errorMessage!.isNotEmpty) { _sessionService.logout(); } setStateView(ViewState.idle); return success; } return success; } }