Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
luckyrat committed Feb 19, 2024
1 parent b8b9da0 commit bda4c94
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 12 deletions.
115 changes: 115 additions & 0 deletions lib/src/kee_vault_model/browser_entry_settings_v1.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import 'dart:convert';
import 'dart:math';
import 'package:collection/collection.dart';
import 'package:kdbx/src/kee_vault_model/browser_entry_settings.dart';
import 'package:kdbx/src/kee_vault_model/entry_matcher_config.dart';
import 'package:kdbx/src/kee_vault_model/enums.dart';
import 'package:kdbx/src/kee_vault_model/field.dart';
import 'package:kdbx/src/kee_vault_model/kee_vault_model.dart';

import '../utils/field_type_utils.dart';
import '../utils/guid_service.dart';
import 'field_matcher_config.dart';
import 'form_field_type.dart';

class BrowserEntrySettingsV1 {
BrowserEntrySettingsV1({
this.version = 1,
Expand Down Expand Up @@ -290,4 +297,112 @@ class BrowserEntrySettingsV1 {
excludeUrls.hashCode ^
fields.hashCode;
}

BrowserEntrySettings convertToV2(IGuidService guidService) {
final List<EntryMatcherConfig> mcList = [
EntryMatcherConfig.forDefaultUrlMatchBehaviour(minimumMatchAccuracy),
if (hide) EntryMatcherConfig(matcherType: EntryMatcherType.Hide)
];

final conf2 = BrowserEntrySettings(
behaviour: behaviour,
authenticationMethods: ['password'],
matcherConfigs: mcList,
includeUrls: includeUrls,
excludeUrls: excludeUrls,
realm: realm,
fields: convertFields(fields, guidService),
);

return conf2;
}

List<Field> convertFields(
List<BrowserFieldModelV1> formFieldList, IGuidService guidService) {
final List<Field> fields = [];
bool usernameFound = false;
bool passwordFound = false;
formFieldList.forEach((ff) {
if (ff.value == '{USERNAME}') {
usernameFound = true;
final mc = !((ff.fieldId?.isNotEmpty ?? false) ||
(ff.name?.isNotEmpty ?? false))
? FieldMatcherConfig(
matcherType: FieldMatcherType.UsernameDefaultHeuristic)
: FieldMatcherConfig.forSingleClientMatch(
ff.fieldId, ff.name, FormFieldType.USERNAME);
final f = Field(
valuePath: 'UserName',
page: max(ff.page, 1),
uuid: guidService.newGuid(),
type: FieldType.Text,
matcherConfigs: [mc],
);
if (ff.placeholderHandling != PlaceholderHandling.Default.name) {
f.placeholderHandling = PlaceholderHandling.values
.firstWhereOrNull((v) => v.name == ff.placeholderHandling);
}
fields.add(f);
} else if (ff.value == '{PASSWORD}') {
passwordFound = true;
final mc = !((ff.fieldId?.isNotEmpty ?? false) ||
(ff.name?.isNotEmpty ?? false))
? FieldMatcherConfig(
matcherType: FieldMatcherType.PasswordDefaultHeuristic)
: FieldMatcherConfig.forSingleClientMatch(
ff.fieldId, ff.name, FormFieldType.PASSWORD);
final f = Field(
valuePath: 'Password',
page: max(ff.page, 1),
uuid: guidService.newGuid(),
type: FieldType.Password,
matcherConfigs: [mc]);
if (ff.placeholderHandling != PlaceholderHandling.Default.name) {
f.placeholderHandling = PlaceholderHandling.values
.firstWhereOrNull((v) => v.name == ff.placeholderHandling);
}
fields.add(f);
} else {
final mc = FieldMatcherConfig.forSingleClientMatch(
ff.fieldId, ff.name, ff.type ?? FormFieldType.TEXT);
final f = Field(
name: ff.displayName,
valuePath: '.',
page: max(ff.page, 1),
uuid: guidService.newGuid(),
type: Utilities.formFieldTypeToFieldType(
ff.type ?? FormFieldType.TEXT),
matcherConfigs: [mc],
value: ff.value);
if (ff.placeholderHandling != PlaceholderHandling.Default.name) {
f.placeholderHandling = PlaceholderHandling.values
.firstWhereOrNull((v) => v.name == ff.placeholderHandling);
}
fields.add(f);
}
});

if (!usernameFound) {
fields.add(Field(
valuePath: 'UserName',
uuid: guidService.newGuid(),
type: FieldType.Text,
matcherConfigs: [
FieldMatcherConfig(
matcherType: FieldMatcherType.UsernameDefaultHeuristic)
]));
}
if (!passwordFound) {
fields.add(Field(
valuePath: 'Password',
uuid: guidService.newGuid(),
type: FieldType.Password,
matcherConfigs: [
FieldMatcherConfig(
matcherType: FieldMatcherType.PasswordDefaultHeuristic)
]));
}

return fields;
}
}
12 changes: 12 additions & 0 deletions lib/src/utils/guid_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'package:uuid/uuid.dart';

abstract class IGuidService {
String newGuid();
}

class GuidService implements IGuidService {
@override
String newGuid() {
return Uuid().v4();
}
}
45 changes: 33 additions & 12 deletions test/browser_entry_settings_test.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import 'package:clock/clock.dart';
import 'package:kdbx/kdbx.dart';
import 'package:kdbx/src/kee_vault_model/browser_entry_settings.dart';
import 'package:kdbx/src/kee_vault_model/browser_entry_settings_v1.dart';
import 'package:kdbx/src/kee_vault_model/enums.dart';
import 'package:kdbx/src/utils/guid_service.dart';
import 'package:logging/logging.dart';
import 'package:logging_appenders/logging_appenders.dart';
import 'package:test/test.dart';
Expand All @@ -10,6 +11,13 @@ import 'internal/test_utils.dart';

final _logger = Logger('browser_entry_settings_test');

class MockGuidService implements IGuidService {
@override
String newGuid() {
return '00000000-0000-0000-0000-000000000000';
}
}

void main() {
Logger.root.level = Level.ALL;
PrintAppender().attachToLogger(Logger.root);
Expand All @@ -28,13 +36,7 @@ void main() {
now = DateTime.fromMillisecondsSinceEpoch(0);
});

testCase(String persistedV2, String expectedResult) async {
//final name = "" + expectedResult + persistedV2;

// final file = await TestUtil.createSimpleFile(proceedSeconds);
// final entry = file.body.rootGroup.getAllEntries().values.first;
// entry.setCustomData("KPRPC JSON", persistedV2);

void testCase(String persistedV2, String expectedResult) {
final bes = BrowserEntrySettings.fromJson(persistedV2,
minimumMatchAccuracy: MatchAccuracy.Domain);
final configV1 = bes.convertToV1();
Expand All @@ -43,23 +45,42 @@ void main() {
expect(sut, expectedResult);
}

void testCaseToV2(String persistedV1, String expectedResult) {
final bes = BrowserEntrySettingsV1.fromJson(persistedV1,
minimumMatchAccuracy: MatchAccuracy.Domain);
final configV2 = bes.convertToV2(MockGuidService());
final sut = configV2.toJson();

expect(sut, expectedResult);
}

group('BrowserEntrySettings', () {
test('config v2->v1', () async {
await testCase(
testCase(
'{"version":2,"altUrls":[],"authenticationMethods":["password"],"matcherConfigs":[{"matcherType":"Url"},{"matcherType":"Hide"}],"fields":[{"page":-1,"valuePath":"Password","uuid":"00000000-0000-0000-0000-000000000000","type":"Password","matcherConfigs":[{"customMatcher":{"ids":["password"],"names":["password"],"types":["password"],"queries":[]}}]},{"page":-1,"valuePath":"UserName","uuid":"00000000-0000-0000-0000-000000000000","type":"Text","matcherConfigs":[{"customMatcher":{"ids":["username"],"names":["username"],"types":["text"],"queries":[]}}]}]}',
'{"version":1,"priority":0,"hide":true,"hTTPRealm":"","formFieldList":[{"displayName":"KeePass password","name":"password","type":"FFTpassword","id":"password","page":-1,"placeholderHandling":"Default","value":"{PASSWORD}"},{"displayName":"KeePass username","name":"username","type":"FFTusername","id":"username","page":-1,"placeholderHandling":"Default","value":"{USERNAME}"}],"alwaysAutoFill":false,"alwaysAutoSubmit":false,"neverAutoFill":false,"neverAutoSubmit":false,"blockDomainOnlyMatch":false,"blockHostnameOnlyMatch":false,"altURLs":[],"regExURLs":[],"blockedURLs":[],"regExBlockedURLs":[]}');

await testCase(
testCase(
'{"version":2,"altUrls":[],"authenticationMethods":["password"],"matcherConfigs":[{"matcherType":"Url"}],"fields":[{"page":-1,"valuePath":"Password","uuid":"00000000-0000-0000-0000-000000000000","type":"Password","matcherConfigs":[{"customMatcher":{"ids":["password"],"names":["password"],"types":["password"],"queries":[]}}]},{"page":-1,"valuePath":"UserName","uuid":"00000000-0000-0000-0000-000000000000","type":"Text","matcherConfigs":[{"customMatcher":{"ids":["username"],"names":["username"],"types":["text"],"queries":[]}}]}]}',
'{"version":1,"priority":0,"hide":false,"hTTPRealm":"","formFieldList":[{"displayName":"KeePass password","name":"password","type":"FFTpassword","id":"password","page":-1,"placeholderHandling":"Default","value":"{PASSWORD}"},{"displayName":"KeePass username","name":"username","type":"FFTusername","id":"username","page":-1,"placeholderHandling":"Default","value":"{USERNAME}"}],"alwaysAutoFill":false,"alwaysAutoSubmit":false,"neverAutoFill":false,"neverAutoSubmit":false,"blockDomainOnlyMatch":false,"blockHostnameOnlyMatch":false,"altURLs":[],"regExURLs":[],"blockedURLs":[],"regExBlockedURLs":[]}');

await testCase(
testCase(
'{"version":2,"altUrls":[],"authenticationMethods":["password"],"matcherConfigs":[{"matcherType":"Url"}],"fields":[{"page":-1,"valuePath":"Password","uuid":"00000000-0000-0000-0000-000000000000","type":"Password","matcherConfigs":[{"customMatcher":{"ids":["password"],"names":["password"],"types":["password"],"queries":[]}}]},{"page":-1,"valuePath":"UserName","uuid":"00000000-0000-0000-0000-000000000000","type":"Text","matcherConfigs":[{"customMatcher":{"ids":["username"],"names":["username"],"types":["text"],"queries":[]}}]}]}',
'{"version":1,"priority":0,"hide":false,"hTTPRealm":"","formFieldList":[{"displayName":"KeePass password","name":"password","type":"FFTpassword","id":"password","page":-1,"placeholderHandling":"Default","value":"{PASSWORD}"},{"displayName":"KeePass username","name":"username","type":"FFTusername","id":"username","page":-1,"placeholderHandling":"Default","value":"{USERNAME}"}],"alwaysAutoFill":false,"alwaysAutoSubmit":false,"neverAutoFill":false,"neverAutoSubmit":false,"blockDomainOnlyMatch":false,"blockHostnameOnlyMatch":false,"altURLs":[],"regExURLs":[],"blockedURLs":[],"regExBlockedURLs":[]}');

await testCase(
testCase(
'{"version":2,"authenticationMethods":["password"],"matcherConfigs":[{"matcherType":"Url"}],"fields":[{"page":-1,"valuePath":"UserName","uuid":"00000000-0000-0000-0000-000000000000","type":"Text","matcherConfigs":[{"matcherType":"UsernameDefaultHeuristic"}]},{"page":-1,"valuePath":"Password","uuid":"00000000-0000-0000-0000-000000000000","type":"Password","matcherConfigs":[{"matcherType":"PasswordDefaultHeuristic"}]}]}',
'{"version":1,"priority":0,"hide":false,"hTTPRealm":"","formFieldList":[{"displayName":"KeePass username","name":"","type":"FFTusername","id":"","page":-1,"placeholderHandling":"Default","value":"{USERNAME}"},{"displayName":"KeePass password","name":"","type":"FFTpassword","id":"","page":-1,"placeholderHandling":"Default","value":"{PASSWORD}"}],"alwaysAutoFill":false,"alwaysAutoSubmit":false,"neverAutoFill":false,"neverAutoSubmit":false,"blockDomainOnlyMatch":false,"blockHostnameOnlyMatch":false,"altURLs":[],"regExURLs":[],"blockedURLs":[],"regExBlockedURLs":[]}');
});

test('config v1->v2', () async {
testCaseToV2(
'{"version":1,"hTTPRealm":"","formFieldList":[{"name":"password","displayName":"KeePass password","value":"{PASSWORD}","type":"FFTpassword","id":"password","page":-1,"placeholderHandling":"Default"},{"name":"username","displayName":"KeePass username","value":"{USERNAME}","type":"FFTradio","id":"username","page":-1,"placeholderHandling":"Default"}],"alwaysAutoFill":false,"neverAutoFill":false,"alwaysAutoSubmit":false,"neverAutoSubmit":false,"priority":0,"altURLs":[],"hide":true,"blockHostnameOnlyMatch":false,"blockDomainOnlyMatch":false}',
'{"version":2,"authenticationMethods":["password"],"matcherConfigs":[{"matcherType":"Url"},{"matcherType":"Hide"}],"fields":[{"page":1,"valuePath":"Password","uuid":"00000000-0000-0000-0000-000000000000","type":"Password","matcherConfigs":[{"customMatcher":{"ids":["password"],"names":["password"],"types":["password"],"queries":[]}}]},{"page":1,"valuePath":"UserName","uuid":"00000000-0000-0000-0000-000000000000","type":"Text","matcherConfigs":[{"customMatcher":{"ids":["username"],"names":["username"],"types":["text"],"queries":[]}}]}],"altUrls":[]}');

// testCase("{\"version\":1,\"hTTPRealm\":\"\",\"formFieldList\":[{\"name\":\"password\",\"displayName\":\"KeePass password\",\"value\":\"{PASSWORD}\",\"type\":\"FFTpassword\",\"id\":\"password\",\"page\":-1,\"placeholderHandling\":\"Default\"},{\"name\":\"username\",\"displayName\":\"KeePass username\",\"value\":\"{USERNAME}\",\"type\":\"FFTradio\",\"id\":\"username\",\"page\":-1,\"placeholderHandling\":\"Default\"}],\"alwaysAutoFill\":false,\"neverAutoFill\":false,\"alwaysAutoSubmit\":false,\"neverAutoSubmit\":false,\"priority\":0,\"altURLs\":[],\"hide\":true,\"blockHostnameOnlyMatch\":false,\"blockDomainOnlyMatch\":false}",

// "{\"version\":2,\"altUrls\":[],\"authenticationMethods\":[\"password\"],\"matcherConfigs\":[{\"matcherType\":\"Url\"},{\"matcherType\":\"Hide\"}],\"fields\":[{\"page\":1,\"valuePath\":\"Password\",\"uuid\":\"00000000-0000-0000-0000-000000000000\",\"type\":\"Password\",\"matcherConfigs\":[{\"customMatcher\":{\"ids\":[\"password\"],\"names\":[\"password\"],\"types\":[\"password\"],\"queries\":[]}}]},{\"page\":1,\"valuePath\":\"UserName\",\"uuid\":\"00000000-0000-0000-0000-000000000000\",\"type\":\"Text\",\"matcherConfigs\":[{\"customMatcher\":{\"ids\":[\"username\"],\"names\":[\"username\"],\"types\":[\"text\"],\"queries\":[]}}]}]}");
});
});
}

0 comments on commit bda4c94

Please sign in to comment.