123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- import 'package:dio/dio.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter/widgets.dart';
- import 'package:logging/logging.dart';
- import 'package:photos/core/configuration.dart';
- import 'package:photos/core/network.dart';
- import 'package:photos/db/public_keys_db.dart';
- import 'package:photos/models/key_attributes.dart';
- import 'package:photos/models/key_gen_result.dart';
- import 'package:photos/models/public_key.dart';
- import 'package:photos/models/set_keys_request.dart';
- import 'package:photos/models/set_recovery_key_request.dart';
- import 'package:photos/ui/login_page.dart';
- import 'package:photos/ui/ott_verification_page.dart';
- import 'package:photos/ui/password_entry_page.dart';
- import 'package:photos/ui/password_reentry_page.dart';
- import 'package:photos/ui/two_factor_authentication_page.dart';
- import 'package:photos/utils/dialog_util.dart';
- import 'package:photos/utils/toast_util.dart';
- class UserService {
- final _dio = Network.instance.getDio();
- final _logger = Logger("UserAuthenticator");
- final _config = Configuration.instance;
- UserService._privateConstructor();
- static final UserService instance = UserService._privateConstructor();
- Future<void> getOtt(BuildContext context, String email) async {
- final dialog = createProgressDialog(context, "please wait...");
- await dialog.show();
- await _dio.get(
- _config.getHttpEndpoint() + "/users/ott",
- queryParameters: {
- "email": email,
- },
- ).catchError((e) async {
- _logger.severe(e);
- }).then((response) async {
- await dialog.hide();
- if (response != null) {
- if (response.statusCode == 200) {
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (BuildContext context) {
- return OTTVerificationPage();
- },
- ),
- );
- } else if (response.statusCode == 403) {
- showErrorDialog(
- context,
- "please wait...",
- "we are currently not accepting new registrations. you have been added to the waitlist and we will let you know once we are ready for you.",
- );
- }
- } else {
- showGenericErrorDialog(context);
- }
- });
- }
- Future<String> getPublicKey(String email) async {
- try {
- final response = await _dio.get(
- _config.getHttpEndpoint() + "/users/public-key",
- queryParameters: {"email": email},
- options: Options(
- headers: {
- "X-Auth-Token": _config.getToken(),
- },
- ),
- );
- final publicKey = response.data["publicKey"];
- await PublicKeysDB.instance.setKey(PublicKey(email, publicKey));
- return publicKey;
- } on DioError catch (e) {
- _logger.info(e);
- return null;
- }
- }
- Future<void> verifyEmail(BuildContext context, String ott) async {
- final dialog = createProgressDialog(context, "please wait...");
- await dialog.show();
- try {
- final response = await _dio.post(
- _config.getHttpEndpoint() + "/users/verify-email",
- data: {
- "email": _config.getEmail(),
- "ott": ott,
- },
- );
- await dialog.hide();
- if (response != null && response.statusCode == 200) {
- showToast("email verification successful!");
- var page;
- final String twoFASessionID = response.data["twoFactorSessionID"];
- if (twoFASessionID != null && twoFASessionID.isNotEmpty) {
- page = TwoFactorAuthenticationPage(twoFASessionID);
- } else {
- await _saveConfiguration(response);
- if (Configuration.instance.getEncryptedToken() != null) {
- page = PasswordReentryPage();
- } else {
- page = PasswordEntryPage();
- }
- }
- Navigator.of(context).pushAndRemoveUntil(
- MaterialPageRoute(
- builder: (BuildContext context) {
- return page;
- },
- ),
- (route) => route.isFirst,
- );
- } else {
- showErrorDialog(
- context, "oops", "verification failed, please try again");
- }
- } catch (e) {
- await dialog.hide();
- _logger.severe(e);
- showErrorDialog(context, "oops", "verification failed, please try again");
- }
- }
- Future<void> setAttributes(KeyGenResult result) async {
- try {
- final name = _config.getName();
- await _dio.put(
- _config.getHttpEndpoint() + "/users/attributes",
- data: {
- "name": name,
- "keyAttributes": result.keyAttributes.toMap(),
- },
- options: Options(
- headers: {
- "X-Auth-Token": _config.getToken(),
- },
- ),
- );
- await _config.setKey(result.privateKeyAttributes.key);
- await _config.setSecretKey(result.privateKeyAttributes.secretKey);
- await _config.setKeyAttributes(result.keyAttributes);
- } catch (e) {
- _logger.severe(e);
- throw e;
- }
- }
- Future<void> updateKeyAttributes(KeyAttributes keyAttributes) async {
- try {
- final setKeyRequest = SetKeysRequest(
- kekSalt: keyAttributes.kekSalt,
- encryptedKey: keyAttributes.encryptedKey,
- keyDecryptionNonce: keyAttributes.keyDecryptionNonce,
- memLimit: keyAttributes.memLimit,
- opsLimit: keyAttributes.opsLimit,
- );
- await _dio.put(
- _config.getHttpEndpoint() + "/users/keys",
- data: setKeyRequest.toMap(),
- options: Options(
- headers: {
- "X-Auth-Token": _config.getToken(),
- },
- ),
- );
- await _config.setKeyAttributes(keyAttributes);
- } catch (e) {
- _logger.severe(e);
- throw e;
- }
- }
- Future<void> setRecoveryKey(KeyAttributes keyAttributes) async {
- try {
- final setRecoveryKeyRequest = SetRecoveryKeyRequest(
- keyAttributes.masterKeyEncryptedWithRecoveryKey,
- keyAttributes.masterKeyDecryptionNonce,
- keyAttributes.recoveryKeyEncryptedWithMasterKey,
- keyAttributes.recoveryKeyDecryptionNonce,
- );
- await _dio.put(
- _config.getHttpEndpoint() + "/users/recovery-key",
- data: setRecoveryKeyRequest.toMap(),
- options: Options(
- headers: {
- "X-Auth-Token": _config.getToken(),
- },
- ),
- );
- await _config.setKeyAttributes(keyAttributes);
- } catch (e) {
- _logger.severe(e);
- throw e;
- }
- }
- Future<void> verifyTwoFactor(
- BuildContext context, String sessionID, String code) async {
- final dialog = createProgressDialog(context, "authenticating...");
- await dialog.show();
- try {
- final response = await _dio.post(
- _config.getHttpEndpoint() + "/users/two-factor/verify",
- data: {
- "sessionID": sessionID,
- "code": code,
- },
- );
- await dialog.hide();
- if (response != null && response.statusCode == 200) {
- showToast("authentication successful!");
- await _saveConfiguration(response);
- Navigator.of(context).pushAndRemoveUntil(
- MaterialPageRoute(
- builder: (BuildContext context) {
- return PasswordReentryPage();
- },
- ),
- (route) => route.isFirst,
- );
- } else {
- showErrorDialog(
- context, "oops", "authentication failed, please try again");
- }
- } on DioError catch (e) {
- await dialog.hide();
- _logger.severe(e);
- if (e.response != null && e.response.statusCode == 404) {
- showToast("session expired");
- Navigator.of(context).pushAndRemoveUntil(
- MaterialPageRoute(
- builder: (BuildContext context) {
- return LoginPage();
- },
- ),
- (route) => route.isFirst,
- );
- } else {
- showErrorDialog(context, "incorrect code",
- "authentication failed, please try again");
- }
- } catch (e) {
- await dialog.hide();
- _logger.severe(e);
- showErrorDialog(
- context, "oops", "authentication failed, please try again");
- }
- }
- Future<void> _saveConfiguration(Response response) async {
- await Configuration.instance.setUserID(response.data["id"]);
- if (response.data["encryptedToken"] != null) {
- await Configuration.instance
- .setEncryptedToken(response.data["encryptedToken"]);
- await Configuration.instance.setKeyAttributes(
- KeyAttributes.fromMap(response.data["keyAttributes"]));
- } else {
- await Configuration.instance.setToken(response.data["token"]);
- }
- }
- }
|