first commit
This commit is contained in:
16
lib/services/auth_interface.dart
Normal file
16
lib/services/auth_interface.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
///
|
||||
///
|
||||
///
|
||||
abstract interface class AuthInterface {
|
||||
/// Проверка авторизации
|
||||
Future<bool> get isAuth;
|
||||
|
||||
/// Получение токена
|
||||
Future<String?> get token;
|
||||
|
||||
/// Авторизация
|
||||
Future<String?> login(String email);
|
||||
|
||||
/// Отправка кода
|
||||
Future<bool> sendCode(String code, String uid);
|
||||
}
|
||||
72
lib/services/auth_service.dart
Normal file
72
lib/services/auth_service.dart
Normal file
@@ -0,0 +1,72 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:dio_smart_retry/dio_smart_retry.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:remever/common/resources.dart';
|
||||
import 'package:remever/common/services/api_client.dart';
|
||||
import 'package:remever/common/storage.dart';
|
||||
import 'package:remever/common/typedef.dart';
|
||||
import 'package:remever/services/auth_interface.dart';
|
||||
|
||||
///
|
||||
/// Сервис авторизации
|
||||
///
|
||||
|
||||
@Singleton(as: AuthInterface)
|
||||
final class AuthService implements AuthInterface {
|
||||
@override
|
||||
Future<bool> get isAuth async => await token != null;
|
||||
|
||||
@override
|
||||
Future<String?> get token async {
|
||||
final String? accessToken = await authSecStorage.read(
|
||||
key: StorageKeys.accessToken,
|
||||
);
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> login(String email) async {
|
||||
try {
|
||||
final Response<dynamic> result = await apiClient.post(
|
||||
'/auth/email/send',
|
||||
options: Options()..disableRetry = true,
|
||||
data: <String, dynamic>{'email': email.toLowerCase()},
|
||||
);
|
||||
|
||||
final Json response = Json.from(result.data);
|
||||
|
||||
if (response['success'] == false) return null;
|
||||
|
||||
return response['result']['authUid'];
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> sendCode(String code, String uid) async {
|
||||
try {
|
||||
final Response<dynamic> result = await apiClient.post(
|
||||
'/auth/code/login',
|
||||
options: Options()..disableRetry = true,
|
||||
data: <String, dynamic>{'authUid': uid, 'confirmCode': code},
|
||||
);
|
||||
|
||||
final Json response = Json.from(result.data);
|
||||
|
||||
final bool success = response['success'] ?? false;
|
||||
|
||||
if (success) {
|
||||
await authSecStorage.write(
|
||||
key: StorageKeys.accessToken,
|
||||
value: response['result']['token'],
|
||||
);
|
||||
}
|
||||
|
||||
return success;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
4
lib/services/core/core_service.dart
Normal file
4
lib/services/core/core_service.dart
Normal file
@@ -0,0 +1,4 @@
|
||||
///
|
||||
/// Базовый сервис для сервисов, которые не будут меняться от проекта к проекту
|
||||
///
|
||||
abstract class CoreService {}
|
||||
52
lib/services/core/enc_keys_service.dart
Normal file
52
lib/services/core/enc_keys_service.dart
Normal file
@@ -0,0 +1,52 @@
|
||||
// Dart imports:
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:hive_ce/hive.dart';
|
||||
import 'package:remever/common/storage.dart';
|
||||
|
||||
import 'core_service.dart';
|
||||
|
||||
///
|
||||
/// Сервис для работы с ключами шифрования
|
||||
///
|
||||
class EncKeysService extends CoreService {
|
||||
///
|
||||
/// Получение ключа для шифрования
|
||||
///
|
||||
Future<String> getRawKey(String keyFor) async {
|
||||
String? encKey = await hiveKeysStorage.read(key: keyFor);
|
||||
|
||||
if (encKey == null) {
|
||||
final List<int> hiveKey = Hive.generateSecureKey();
|
||||
|
||||
encKey = base64UrlEncode(hiveKey);
|
||||
|
||||
await hiveKeysStorage.write(key: keyFor, value: encKey);
|
||||
}
|
||||
|
||||
return encKey;
|
||||
}
|
||||
|
||||
///
|
||||
/// Получение ключа шифрования
|
||||
///
|
||||
/// Если ключа ранее не существовало - он будет создан
|
||||
///
|
||||
Future<Uint8List> getKey(String keyFor) async {
|
||||
String? encKey = await getRawKey(keyFor);
|
||||
|
||||
return base64Url.decode(encKey);
|
||||
}
|
||||
|
||||
///
|
||||
/// Получение ключа шифрования в виде строки
|
||||
///
|
||||
/// Если ключа ранее не существовало - он будет создан
|
||||
///
|
||||
Future<String> getStringKey(String keyFor) async {
|
||||
final Uint8List key = await getKey(keyFor);
|
||||
|
||||
return String.fromCharCodes(key);
|
||||
}
|
||||
}
|
||||
42
lib/services/core/lang_service.dart
Normal file
42
lib/services/core/lang_service.dart
Normal file
@@ -0,0 +1,42 @@
|
||||
import 'package:remever/common/resources.dart';
|
||||
import 'package:remever/common/storage.dart';
|
||||
import 'package:remever/i18n/strings.g.dart';
|
||||
import 'package:remever/interfaces/warmup_service.dart';
|
||||
|
||||
import 'core_service.dart';
|
||||
|
||||
///
|
||||
/// Сервис для работы с языками приложения
|
||||
///
|
||||
class LangService extends CoreService implements IWarmupService {
|
||||
///
|
||||
/// Установка языка при первом запуске
|
||||
///
|
||||
@override
|
||||
Future<void> init() async {
|
||||
final AppLocale deviceLocale = await LocaleSettings.useDeviceLocale();
|
||||
AppLocale? locale = hiveLang.get(StorageKeys.langCode);
|
||||
|
||||
if (locale == null) {
|
||||
LocaleSettings.setLocale(deviceLocale);
|
||||
|
||||
hiveLang.put(StorageKeys.langCode, deviceLocale);
|
||||
} else {
|
||||
LocaleSettings.setLocale(locale);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Получение текущей локали
|
||||
///
|
||||
AppLocale get locale =>
|
||||
hiveLang.get(StorageKeys.langCode, defaultValue: AppLocale.en)!;
|
||||
|
||||
///
|
||||
/// Запись и установка языка
|
||||
///
|
||||
Future<void> setLanguage(AppLocale locale) async {
|
||||
await hiveLang.put(StorageKeys.langCode, locale);
|
||||
LocaleSettings.setLocale(locale);
|
||||
}
|
||||
}
|
||||
48
lib/services/core/theme_service.dart
Normal file
48
lib/services/core/theme_service.dart
Normal file
@@ -0,0 +1,48 @@
|
||||
// Flutter imports:
|
||||
import 'package:flutter/material.dart' show ThemeMode;
|
||||
import 'package:remever/common/resources.dart';
|
||||
import 'package:remever/common/storage.dart';
|
||||
import 'package:remever/components/extensions/theme_mode.dart';
|
||||
import 'package:remever/interfaces/warmup_service.dart';
|
||||
|
||||
import 'core_service.dart';
|
||||
|
||||
///
|
||||
/// Сервис для работы с темой приложения
|
||||
///
|
||||
class ThemeService extends CoreService implements IWarmupService {
|
||||
@override
|
||||
Future<void> init() async {
|
||||
final ThemeMode? theme = hiveTheme.get(StorageKeys.themeKey);
|
||||
|
||||
if (theme == null) {
|
||||
await hiveTheme.put(StorageKeys.themeKey, ThemeMode.light);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Получение текущего значения для темы
|
||||
///
|
||||
/// По-умолчанию - светлый
|
||||
///
|
||||
ThemeMode get themeMode {
|
||||
return hiveTheme.get(StorageKeys.themeKey, defaultValue: ThemeMode.light)!;
|
||||
}
|
||||
|
||||
///
|
||||
/// Обновление темы приложения
|
||||
///
|
||||
/// [oldThemeMode] должно быть текущее значение темы. Автоматически будет
|
||||
/// вызван метод {inversed}
|
||||
///
|
||||
Future<void> update(ThemeMode oldThemeMode) async {
|
||||
return updateInversed(oldThemeMode.inversed);
|
||||
}
|
||||
|
||||
///
|
||||
/// Обновление темы приложения
|
||||
///
|
||||
Future<void> updateInversed(ThemeMode themeMode) async {
|
||||
return hiveTheme.put(StorageKeys.themeKey, themeMode);
|
||||
}
|
||||
}
|
||||
106
lib/services/warmup_service.dart
Normal file
106
lib/services/warmup_service.dart
Normal file
@@ -0,0 +1,106 @@
|
||||
// Dart imports:
|
||||
import 'dart:async';
|
||||
|
||||
// Flutter imports:
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive_ce/hive.dart';
|
||||
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:remever/common/resources.dart';
|
||||
import 'package:remever/components/notifiers/app_settings.dart';
|
||||
import 'package:remever/components/notifiers/home_screen_data.dart';
|
||||
import 'package:remever/helpers/hive_creator.dart';
|
||||
import 'package:remever/i18n/strings.g.dart';
|
||||
import 'package:remever/interfaces/warmup_service.dart';
|
||||
import 'package:remever/models/adapters/app_locale_adapter.dart';
|
||||
import 'package:remever/models/adapters/theme_mode_adapter.dart';
|
||||
|
||||
import '../inject.dart';
|
||||
import 'core/enc_keys_service.dart';
|
||||
import 'core/lang_service.dart';
|
||||
import 'core/theme_service.dart';
|
||||
|
||||
///
|
||||
/// Сервис прогрева приложения
|
||||
///
|
||||
@Singleton()
|
||||
class WarmupService {
|
||||
WarmupService(this._themeService, this._langService, this._encKeysService);
|
||||
|
||||
/// Сервисы
|
||||
final ThemeService _themeService;
|
||||
final LangService _langService;
|
||||
final EncKeysService _encKeysService;
|
||||
|
||||
/// [Completer] для прогрева приложения
|
||||
final Completer<bool> _firstStartCompleter = Completer<bool>();
|
||||
Completer<bool> get firstStartCompleter => _firstStartCompleter;
|
||||
|
||||
@PostConstruct(preResolve: true)
|
||||
Future<void> common() async {
|
||||
await _registerHiveAdapters();
|
||||
await _openHiveBoxes();
|
||||
await _registerNotifiers();
|
||||
}
|
||||
|
||||
///
|
||||
/// Инициализация для запуска приложения
|
||||
///
|
||||
Future<void> firstStart() async {
|
||||
await _setStoragesValue();
|
||||
}
|
||||
|
||||
///
|
||||
/// Проставнока изначальных значений хранилищ
|
||||
///
|
||||
Future<void> _setStoragesValue() async {
|
||||
final List<IWarmupService> services = <IWarmupService>[
|
||||
_themeService,
|
||||
_langService,
|
||||
];
|
||||
|
||||
for (final IWarmupService service in services) {
|
||||
await service.init();
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Регистрация [Hive] адаптеров
|
||||
///
|
||||
Future<void> _registerHiveAdapters() async {
|
||||
Hive.registerAdapter<ThemeMode>(ThemeModeAdapter());
|
||||
Hive.registerAdapter<AppLocale>(AppLocaleAdapter());
|
||||
}
|
||||
|
||||
///
|
||||
/// Открытие [Hive] хранилищ
|
||||
///
|
||||
Future<void> _openHiveBoxes() async {
|
||||
final Map<String, HiveCreator<dynamic>> storageNames =
|
||||
<String, HiveCreator<dynamic>>{
|
||||
Storage.storageAuth: HiveCreator<String>(),
|
||||
Storage.hiveThemeMode: HiveCreator<ThemeMode>(),
|
||||
Storage.hiveLang: HiveCreator<AppLocale>(),
|
||||
};
|
||||
|
||||
for (MapEntry<String, HiveCreator<dynamic>> storage
|
||||
in storageNames.entries) {
|
||||
final String name = storage.key;
|
||||
final Uint8List key = await _encKeysService.getKey(name);
|
||||
|
||||
await storage.value.open(name, HiveAesCipher(key));
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Регистрация нотификаторов
|
||||
///
|
||||
Future<void> _registerNotifiers() async {
|
||||
getIt.registerLazySingleton<AppSettingsNotifier>(
|
||||
() => AppSettingsNotifier(debugMode: kDebugMode),
|
||||
);
|
||||
|
||||
getIt.registerLazySingleton<CollectionData>(() => CollectionData());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user