fix(auth): remove all codes
This commit is contained in:
parent
6496eea162
commit
5ef92e338d
8 changed files with 63 additions and 70 deletions
|
@ -44,7 +44,7 @@ class Code {
|
|||
this.err,
|
||||
});
|
||||
|
||||
factory Code.withError(Object error) {
|
||||
factory Code.withError(Object error, String rawData) {
|
||||
return Code(
|
||||
"",
|
||||
"",
|
||||
|
@ -54,7 +54,7 @@ class Code {
|
|||
Algorithm.sha1,
|
||||
Type.totp,
|
||||
0,
|
||||
"",
|
||||
rawData,
|
||||
err: error,
|
||||
display: CodeDisplay(),
|
||||
);
|
||||
|
@ -143,7 +143,7 @@ class Code {
|
|||
if (rawData.contains("#")) {
|
||||
return Code.fromOTPAuthUrl(rawData.replaceAll("#", '%23'));
|
||||
} else {
|
||||
return Code.withError(e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,11 +258,12 @@ class Code {
|
|||
}
|
||||
|
||||
String get rawDataWithoutDisplay {
|
||||
final updatedIssuer = jsonEncode(issuer);
|
||||
final uri = Uri.parse(
|
||||
"otpauth://${type.name}/$updatedIssuer:$account?algorithm=SHA1&digits=$digits&issuer=$updatedIssuer&period=30&secret=$secret",
|
||||
return jsonEncode(
|
||||
Uri.parse(
|
||||
"$rawData&codeDisplay="
|
||||
"${jsonEncode(display.toJson())}",
|
||||
).toString(),
|
||||
);
|
||||
return uri.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
import 'package:ente_auth/models/code.dart';
|
||||
|
||||
class AllCodes {
|
||||
final List<Code> codes;
|
||||
final AllCodesState state;
|
||||
|
||||
AllCodes({required this.codes, required this.state});
|
||||
}
|
||||
|
||||
enum AllCodesState {
|
||||
value,
|
||||
error,
|
||||
}
|
|
@ -63,9 +63,9 @@ class CodeDisplayStore {
|
|||
isCritical: true,
|
||||
firstButtonOnTap: () async {
|
||||
// traverse through all the codes and edit this tag's value
|
||||
final relevantCodes = (await CodeStore.instance.getAllCodes())
|
||||
.codes
|
||||
.where((element) => element.display.tags.contains(tag));
|
||||
final relevantCodes = (await CodeStore.instance.getAllCodes()).where(
|
||||
(element) => !element.hasError && element.display.tags.contains(tag),
|
||||
);
|
||||
|
||||
final tasks = <Future>[];
|
||||
|
||||
|
@ -99,9 +99,10 @@ class CodeDisplayStore {
|
|||
|
||||
Future<void> editTag(String previousTag, String updatedTag) async {
|
||||
// traverse through all the codes and edit this tag's value
|
||||
final relevantCodes = (await CodeStore.instance.getAllCodes())
|
||||
.codes
|
||||
.where((element) => element.display.tags.contains(previousTag));
|
||||
final relevantCodes = (await CodeStore.instance.getAllCodes()).where(
|
||||
(element) =>
|
||||
!element.hasError && element.display.tags.contains(previousTag),
|
||||
);
|
||||
|
||||
final tasks = <Future>[];
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import 'package:ente_auth/core/event_bus.dart';
|
|||
import 'package:ente_auth/events/codes_updated_event.dart';
|
||||
import 'package:ente_auth/models/authenticator/entity_result.dart';
|
||||
import 'package:ente_auth/models/code.dart';
|
||||
import 'package:ente_auth/models/codes.dart';
|
||||
import 'package:ente_auth/services/authenticator_service.dart';
|
||||
import 'package:ente_auth/store/offline_authenticator_db.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
@ -23,26 +22,25 @@ class CodeStore {
|
|||
_authenticatorService = AuthenticatorService.instance;
|
||||
}
|
||||
|
||||
Future<AllCodes> getAllCodes({AccountMode? accountMode}) async {
|
||||
Future<List<Code>> getAllCodes({AccountMode? accountMode}) async {
|
||||
final mode = accountMode ?? _authenticatorService.getAccountMode();
|
||||
final List<EntityResult> entities =
|
||||
await _authenticatorService.getEntities(mode);
|
||||
final List<Code> codes = [];
|
||||
bool hasError = false;
|
||||
|
||||
for (final entity in entities) {
|
||||
final decodeJson = jsonDecode(entity.rawData);
|
||||
|
||||
late Code code;
|
||||
if (decodeJson is String && decodeJson.startsWith('otpauth://')) {
|
||||
code = Code.fromOTPAuthUrl(decodeJson);
|
||||
} else {
|
||||
code = Code.fromExportJson(decodeJson);
|
||||
}
|
||||
if (code.hasError) {
|
||||
hasError = true;
|
||||
try {
|
||||
final decodeJson = jsonDecode(entity.rawData);
|
||||
|
||||
if (decodeJson is String && decodeJson.startsWith('otpauth://')) {
|
||||
code = Code.fromOTPAuthUrl(decodeJson);
|
||||
} else {
|
||||
code = Code.fromExportJson(decodeJson);
|
||||
}
|
||||
} catch (e) {
|
||||
code = Code.withError(e, entity.rawData);
|
||||
_logger.severe("Could not parse code", code.err);
|
||||
continue;
|
||||
}
|
||||
code.generatedID = entity.generatedID;
|
||||
code.hasSynced = entity.hasSynced;
|
||||
|
@ -64,10 +62,8 @@ class CodeStore {
|
|||
secondCode.account,
|
||||
);
|
||||
});
|
||||
return AllCodes(
|
||||
codes: codes,
|
||||
state: hasError ? AllCodesState.error : AllCodesState.value,
|
||||
);
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
Future<AddResult> addCode(
|
||||
|
@ -79,7 +75,8 @@ class CodeStore {
|
|||
final allCodes = await getAllCodes(accountMode: mode);
|
||||
bool isExistingCode = false;
|
||||
bool hasSameCode = false;
|
||||
for (final existingCode in allCodes.codes) {
|
||||
for (final existingCode in allCodes) {
|
||||
if (existingCode.hasError) continue;
|
||||
if (code.generatedID != null &&
|
||||
existingCode.generatedID == code.generatedID) {
|
||||
isExistingCode = true;
|
||||
|
@ -138,7 +135,8 @@ class CodeStore {
|
|||
|
||||
List<Code> offlineCodes = (await CodeStore.instance
|
||||
.getAllCodes(accountMode: AccountMode.offline))
|
||||
.codes;
|
||||
.where((element) => !element.hasError)
|
||||
.toList();
|
||||
if (offlineCodes.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
@ -149,7 +147,8 @@ class CodeStore {
|
|||
}
|
||||
final List<Code> onlineCodes = (await CodeStore.instance
|
||||
.getAllCodes(accountMode: AccountMode.online))
|
||||
.codes;
|
||||
.where((element) => !element.hasError)
|
||||
.toList();
|
||||
logger.info(
|
||||
'importing ${offlineCodes.length} offline codes with ${onlineCodes.length} online codes',
|
||||
);
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:app_links/app_links.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:ente_auth/core/configuration.dart';
|
||||
import 'package:ente_auth/core/event_bus.dart';
|
||||
import 'package:ente_auth/ente_theme_data.dart';
|
||||
|
@ -10,7 +11,6 @@ import 'package:ente_auth/events/icons_changed_event.dart';
|
|||
import 'package:ente_auth/events/trigger_logout_event.dart';
|
||||
import "package:ente_auth/l10n/l10n.dart";
|
||||
import 'package:ente_auth/models/code.dart';
|
||||
import 'package:ente_auth/models/codes.dart';
|
||||
import 'package:ente_auth/onboarding/model/tag_enums.dart';
|
||||
import 'package:ente_auth/onboarding/view/common/tag_chip.dart';
|
||||
import 'package:ente_auth/onboarding/view/setup_enter_secret_key_page.dart';
|
||||
|
@ -59,7 +59,7 @@ class _HomePageState extends State<HomePage> {
|
|||
final FocusNode searchInputFocusNode = FocusNode();
|
||||
bool _showSearchBox = false;
|
||||
String _searchText = "";
|
||||
AllCodes? _allCodes;
|
||||
List<Code>? _allCodes;
|
||||
List<String> tags = [];
|
||||
List<Code> _filteredCodes = [];
|
||||
StreamSubscription<CodesUpdatedEvent>? _streamSubscription;
|
||||
|
@ -133,9 +133,10 @@ class _HomePageState extends State<HomePage> {
|
|||
final List<Code> issuerMatch = [];
|
||||
final List<Code> accountMatch = [];
|
||||
|
||||
for (final Code codeState in _allCodes!.codes) {
|
||||
if (selectedTag != "" &&
|
||||
!codeState.display.tags.contains(selectedTag)) {
|
||||
for (final Code codeState in _allCodes!) {
|
||||
if (codeState.hasError ||
|
||||
selectedTag != "" &&
|
||||
!codeState.display.tags.contains(selectedTag)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -148,11 +149,12 @@ class _HomePageState extends State<HomePage> {
|
|||
_filteredCodes = issuerMatch;
|
||||
_filteredCodes.addAll(accountMatch);
|
||||
} else {
|
||||
_filteredCodes = _allCodes?.codes
|
||||
.where(
|
||||
_filteredCodes = _allCodes
|
||||
?.where(
|
||||
(element) =>
|
||||
selectedTag == "" ||
|
||||
element.display.tags.contains(selectedTag),
|
||||
!element.hasError &&
|
||||
(selectedTag == "" ||
|
||||
element.display.tags.contains(selectedTag)),
|
||||
)
|
||||
.toList() ??
|
||||
[];
|
||||
|
@ -182,7 +184,7 @@ class _HomePageState extends State<HomePage> {
|
|||
if (code != null) {
|
||||
await CodeStore.instance.addCode(code);
|
||||
// Focus the new code by searching
|
||||
if ((_allCodes?.codes.length ?? 0) > 2) {
|
||||
if ((_allCodes?.where((e) => !e.hasError).length ?? 0) > 2) {
|
||||
_focusNewCode(code);
|
||||
}
|
||||
}
|
||||
|
@ -276,7 +278,7 @@ class _HomePageState extends State<HomePage> {
|
|||
],
|
||||
),
|
||||
floatingActionButton: !_hasLoaded ||
|
||||
(_allCodes?.codes.isEmpty ?? true) ||
|
||||
(_allCodes?.isEmpty ?? true) ||
|
||||
!PreferenceService.instance.hasShownCoachMark()
|
||||
? null
|
||||
: _getFab(),
|
||||
|
@ -293,10 +295,14 @@ class _HomePageState extends State<HomePage> {
|
|||
onManuallySetupTap: _redirectToManualEntryPage,
|
||||
);
|
||||
} else {
|
||||
final anyCodeHasError =
|
||||
_allCodes?.firstWhereOrNull((element) => element.hasError) != null;
|
||||
final indexOffset = anyCodeHasError ? 1 : 0;
|
||||
|
||||
final list = Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (_allCodes?.state == AllCodesState.value)
|
||||
if (!anyCodeHasError)
|
||||
SizedBox(
|
||||
height: 48,
|
||||
child: ListView.separated(
|
||||
|
@ -346,24 +352,21 @@ class _HomePageState extends State<HomePage> {
|
|||
crossAxisCount: (MediaQuery.sizeOf(context).width ~/ 400)
|
||||
.clamp(1, double.infinity)
|
||||
.toInt(),
|
||||
physics: _allCodes?.state == AllCodesState.value
|
||||
? const AlwaysScrollableScrollPhysics()
|
||||
: const NeverScrollableScrollPhysics(),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.only(bottom: 80),
|
||||
itemBuilder: ((context, index) {
|
||||
if (index == 0 && _allCodes?.state == AllCodesState.error) {
|
||||
if (index == 0 && anyCodeHasError) {
|
||||
return const CodeErrorWidget();
|
||||
}
|
||||
final newIndex =
|
||||
index - (_allCodes?.state == AllCodesState.error ? 1 : 0);
|
||||
final newIndex = index - indexOffset;
|
||||
|
||||
return ClipRect(
|
||||
child: CodeWidget(
|
||||
_filteredCodes[newIndex],
|
||||
),
|
||||
);
|
||||
}),
|
||||
itemCount: (_allCodes?.state == AllCodesState.error ? 1 : 0) +
|
||||
_filteredCodes.length,
|
||||
itemCount: _filteredCodes.length + indexOffset,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -173,7 +173,8 @@ Future<void> _exportCodes(BuildContext context, String fileContent) async {
|
|||
Future<String> _getAuthDataForExport() async {
|
||||
final allCodes = await CodeStore.instance.getAllCodes();
|
||||
String data = "";
|
||||
for (final code in allCodes.codes) {
|
||||
for (final code in allCodes) {
|
||||
if (code.hasError) continue;
|
||||
data += "${code.rawDataWithoutDisplay}\n";
|
||||
}
|
||||
|
||||
|
|
|
@ -108,8 +108,9 @@ class SettingsPage extends StatelessWidget {
|
|||
await handleExportClick(context);
|
||||
} else {
|
||||
if (result.action == ButtonAction.second) {
|
||||
bool hasCodes =
|
||||
(await CodeStore.instance.getAllCodes()).codes.isNotEmpty;
|
||||
bool hasCodes = (await CodeStore.instance.getAllCodes())
|
||||
.where((element) => !element.hasError)
|
||||
.isNotEmpty;
|
||||
if (hasCodes) {
|
||||
final hasAuthenticated = await LocalAuthenticationService
|
||||
.instance
|
||||
|
|
|
@ -14,7 +14,7 @@ dependencies:
|
|||
bip39: ^1.0.6 #done
|
||||
bloc: ^8.1.2
|
||||
clipboard: ^0.1.3
|
||||
collection: # dart
|
||||
collection: ^1.18.0 # dart
|
||||
confetti: ^0.7.0
|
||||
connectivity_plus: ^5.0.2
|
||||
convert: ^3.1.1
|
||||
|
|
Loading…
Add table
Reference in a new issue