feat: secure home credentials
This commit is contained in:
82
test/settings_service_test.dart
Normal file
82
test/settings_service_test.dart
Normal file
@@ -0,0 +1,82 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:ignis_app/models/home_config.dart';
|
||||
import 'package:ignis_app/services/credentials_storage.dart';
|
||||
import 'package:ignis_app/services/settings_service.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class InMemoryCredentialsStorage implements CredentialsStorage {
|
||||
final Map<String, String> _apiKeys = {};
|
||||
|
||||
@override
|
||||
Future<String?> getApiKey(String homeId) async => _apiKeys[homeId];
|
||||
|
||||
@override
|
||||
Future<void> setApiKey(String homeId, String apiKey) async {
|
||||
_apiKeys[homeId] = apiKey;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteApiKey(String homeId) async {
|
||||
_apiKeys.remove(homeId);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
test(
|
||||
'migrates legacy apiKey from SharedPreferences to credentials storage',
|
||||
() async {
|
||||
final legacyHomes = [
|
||||
{
|
||||
'id': 'home-1',
|
||||
'name': 'Квартира',
|
||||
'url': 'ignis.akokos.ru',
|
||||
'apiKey': 'secret-key',
|
||||
'geofenceEnabled': false,
|
||||
},
|
||||
];
|
||||
SharedPreferences.setMockInitialValues({
|
||||
'ignis_homes': jsonEncode(legacyHomes),
|
||||
});
|
||||
|
||||
final credentials = InMemoryCredentialsStorage();
|
||||
final service = SettingsService(credentialsStorage: credentials);
|
||||
|
||||
final homes = await service.getHomes();
|
||||
|
||||
expect(homes, hasLength(1));
|
||||
expect(homes.single.id, 'home-1');
|
||||
expect(await service.getHomeApiKey('home-1'), 'secret-key');
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final storedHomes =
|
||||
jsonDecode(prefs.getString('ignis_homes')!) as List<dynamic>;
|
||||
expect(storedHomes.single, isNot(containsPair('apiKey', 'secret-key')));
|
||||
},
|
||||
);
|
||||
|
||||
test('stores new api keys outside serialized homes', () async {
|
||||
SharedPreferences.setMockInitialValues({});
|
||||
|
||||
final service = SettingsService(
|
||||
credentialsStorage: InMemoryCredentialsStorage(),
|
||||
);
|
||||
final home = HomeConfig(
|
||||
id: 'home-1',
|
||||
name: 'Квартира',
|
||||
url: 'https://ignis.akokos.ru',
|
||||
);
|
||||
|
||||
await service.upsertHome(home, apiKey: 'secret-key');
|
||||
|
||||
expect(await service.getHomeApiKey('home-1'), 'secret-key');
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final storedHomes =
|
||||
jsonDecode(prefs.getString('ignis_homes')!) as List<dynamic>;
|
||||
expect(storedHomes.single, isNot(contains('apiKey')));
|
||||
});
|
||||
}
|
||||
@@ -7,15 +7,12 @@ import 'package:ignis_app/main.dart';
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
testWidgets('app opens homes screen when no homes are configured',
|
||||
(WidgetTester tester) async {
|
||||
testWidgets('app opens homes screen when no homes are configured', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
SharedPreferences.setMockInitialValues({});
|
||||
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: IgnisApp(),
|
||||
),
|
||||
);
|
||||
await tester.pumpWidget(const ProviderScope(child: IgnisApp()));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('ДОМА'), findsOneWidget);
|
||||
|
||||
Reference in New Issue
Block a user