1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-10-23 06:53:23 +00:00
comunicmobile/lib/helpers/account_helper.dart

223 lines
6.8 KiB
Dart
Raw Normal View History

2019-04-22 17:16:26 +00:00
import 'package:comunic/helpers/api_helper.dart';
2019-11-01 08:59:05 +00:00
import 'package:comunic/helpers/preferences_helper.dart';
2020-04-20 06:47:08 +00:00
import 'package:comunic/helpers/websocket_helper.dart';
2019-04-22 17:16:26 +00:00
import 'package:comunic/models/api_request.dart';
import 'package:comunic/models/authentication_details.dart';
import 'package:comunic/models/login_tokens.dart';
2019-11-02 17:54:30 +00:00
import 'package:comunic/models/new_account.dart';
2019-04-23 16:11:19 +00:00
import 'package:shared_preferences/shared_preferences.dart';
2019-04-22 17:16:26 +00:00
/// Account helper
///
/// @author Pierre HUBERT
enum AuthResult {
SUCCESS,
TOO_MANY_ATTEMPTS,
NETWORK_ERROR,
INVALID_CREDENTIALS
}
2019-11-02 17:54:30 +00:00
enum CreateAccountResult {
SUCCESS,
ERROR_TOO_MANY_REQUESTS,
ERROR_EXISTING_EMAIL,
ERROR
}
2019-04-22 17:16:26 +00:00
class AccountHelper {
2019-04-23 16:11:19 +00:00
static const _USER_ID_PREFERENCE_NAME = "user_id";
// Current user ID
static int _currentUserID = -1;
/// Checkout whether current user is signed in or not
///
/// Warning : This method MUST BE CALLED AT LEAST ONCE AFTER APP START !!!
Future<bool> signedIn() async {
2019-11-01 08:59:05 +00:00
bool signedIn =
(await PreferencesHelper.getInstance()).getLoginTokens() != null;
2019-04-23 16:11:19 +00:00
// Load current user ID for later use
if (signedIn && _currentUserID == -1) await _loadCurrentUserID();
return signedIn;
}
2019-04-22 17:16:26 +00:00
/// Sign in user
Future<AuthResult> signIn(AuthenticationDetails auth) async {
final request = APIRequest(uri: "account/login");
request.addString("userMail", auth.email);
request.addString("userPassword", auth.password);
final response = await APIHelper().exec(request);
// Handle errors
if (response.code == 401)
return AuthResult.INVALID_CREDENTIALS;
else if (response.code == 429)
return AuthResult.TOO_MANY_ATTEMPTS;
else if (response.code != 200) return AuthResult.NETWORK_ERROR;
2019-04-23 16:11:19 +00:00
// Save login tokens
2019-04-22 17:16:26 +00:00
final tokensObj = response.getObject()["tokens"];
2019-11-01 08:59:05 +00:00
await (await PreferencesHelper.getInstance())
.setLoginTokens(LoginTokens(tokensObj["token1"], tokensObj["token2"]));
2019-04-22 17:16:26 +00:00
2019-04-23 16:11:19 +00:00
// Get current user ID
final userID = await _downloadCurrentUserID();
if (userID == null) {
await signOut(); // We can not stay signed in without current user ID
return AuthResult.NETWORK_ERROR;
}
// Save current user ID
final preferences = await SharedPreferences.getInstance();
await preferences.setInt(_USER_ID_PREFERENCE_NAME, userID);
_currentUserID = userID;
2019-04-22 17:16:26 +00:00
return AuthResult.SUCCESS;
}
2019-04-23 09:48:49 +00:00
/// Sign out user
Future<void> signOut() async {
2019-11-01 08:59:05 +00:00
await (await PreferencesHelper.getInstance()).setLoginTokens(null);
2019-04-23 16:11:19 +00:00
_currentUserID = 0;
2020-04-20 06:47:08 +00:00
// Close current web socket
WebSocketHelper.close();
2019-04-23 09:48:49 +00:00
}
2019-11-02 17:54:30 +00:00
/// Create a new user account
Future<CreateAccountResult> createAccount(NewAccount info) async {
final response = await APIRequest(
uri: "account/create",
needLogin: false,
args: {
"firstName": info.firstName,
"lastName": info.lastName,
"emailAddress": info.email,
"password": info.password,
},
).exec();
switch (response.code) {
case 200:
return CreateAccountResult.SUCCESS;
case 409:
return CreateAccountResult.ERROR_EXISTING_EMAIL;
case 429:
return CreateAccountResult.ERROR_TOO_MANY_REQUESTS;
default:
return CreateAccountResult.ERROR;
}
}
2020-05-03 12:22:06 +00:00
/// Check out whether a given email address exists or not
///
/// Throws in case of failure
static Future<bool> existsMailAccount(String email) async =>
(await APIRequest.withoutLogin("account/exists_email")
.addString("email", email)
.execWithThrow())
.getObject()["exists"];
/// Check out whether security questions have been set for an account or not
///
/// Throws in case of failure
static Future<bool> hasSecurityQuestions(String email) async =>
(await APIRequest.withoutLogin("account/has_security_questions")
2020-05-03 13:35:07 +00:00
.addString("email", email)
.execWithThrow())
2020-05-03 12:22:06 +00:00
.getObject()["defined"];
2020-05-03 13:35:07 +00:00
/// Get the security questions of the user
///
/// Throws in case of failure
static Future<List<String>> getSecurityQuestions(String email) async =>
((await APIRequest.withoutLogin("account/get_security_questions")
.addString("email", email)
.execWithThrow())
.getObject()["questions"])
.cast<String>();
2020-05-03 14:21:36 +00:00
/// Validate given security answers
///
/// Throws an [Exception] in case of failure
///
/// Returns a password reset token in case of success
static Future<String> checkAnswers(
String email, List<String> answers) async =>
(await APIRequest.withoutLogin("account/check_security_answers")
.addString("email", email)
.addString("answers",
answers.map((f) => Uri.encodeComponent(f)).join("&"))
.execWithThrow())
.getObject()["reset_token"];
2020-05-03 14:55:00 +00:00
/// Check a password reset token
///
/// Throws in case failure
static Future<void> validatePasswordResetToken(String token) async =>
await APIRequest.withoutLogin("account/check_password_reset_token")
.addString("token", token)
.execWithThrow();
/// Change account password using password reset token
///
/// Throws an exception in case of failure
static Future<void> changeAccountPassword(
String token, String password) async =>
await APIRequest.withoutLogin("account/reset_user_passwd")
.addString("token", token)
.addString("password", password)
.execWithThrow();
2019-04-23 16:11:19 +00:00
/// Get current user ID from the server
Future<int> _downloadCurrentUserID() async {
final response = await APIRequest(
uri: "user/getCurrentUserID",
needLogin: true,
).exec();
if (response.code != 200) return null;
return response.getObject()["userID"];
}
/// Get the ID of the currently signed in user
Future<void> _loadCurrentUserID() async {
final preferences = await SharedPreferences.getInstance();
_currentUserID = preferences.getInt(_USER_ID_PREFERENCE_NAME);
}
/// Check if current user ID is loaded or not
static bool get isUserIDLoaded => _currentUserID > 0;
2019-04-23 16:11:19 +00:00
/// Get the ID of the currently signed in user
static int getCurrentUserID() {
if (_currentUserID == -1) throw "Current user ID has not been loaded yet!";
return _currentUserID;
}
/// Disconnect all the devices of the current user
///
/// Throws in case of failure
static Future<void> disconnectAllDevices() async {
await APIRequest(uri: "account/disconnect_all_devices", needLogin: true)
.execWithThrow();
}
2020-05-01 08:56:57 +00:00
/// Remove permanently a user account
///
/// Throws in case of failure
static Future<void> deleteAccount(String password) async {
await APIRequest(uri: "account/delete", needLogin: true)
.addString("password", password)
.execWithThrow();
}
2019-04-22 17:16:26 +00:00
}