mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-05-25 02:12:13 +00:00
login using login token
This commit is contained in:
parent
105129023a
commit
f735070a7c
25 changed files with 431 additions and 211 deletions
22
lib/core/bridge/wrapper/key_manager.dart
Normal file
22
lib/core/bridge/wrapper/key_manager.dart
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// This file is automatically generated, so please do not edit it.
|
||||
// @generated by `flutter_rust_bridge`@ 2.12.0.
|
||||
|
||||
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||
|
||||
import '../../frb_generated.dart';
|
||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
|
||||
class FlutterKeyManager {
|
||||
const FlutterKeyManager();
|
||||
|
||||
static Future<Uint8List> getLoginToken() => RustLib.instance.api
|
||||
.crateBridgeWrapperKeyManagerFlutterKeyManagerGetLoginToken();
|
||||
|
||||
@override
|
||||
int get hashCode => 0;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is FlutterKeyManager && runtimeType == other.runtimeType;
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import 'bridge.dart';
|
||||
import 'bridge/callbacks.dart';
|
||||
import 'bridge/wrapper/key_manager.dart';
|
||||
import 'bridge/wrapper/user_discovery.dart';
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
|
@ -70,7 +71,7 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> {
|
|||
String get codegenVersion => '2.12.0';
|
||||
|
||||
@override
|
||||
int get rustContentHash => 1680338106;
|
||||
int get rustContentHash => 1007286393;
|
||||
|
||||
static const kDefaultExternalLibraryLoaderConfig =
|
||||
ExternalLibraryLoaderConfig(
|
||||
|
|
@ -82,6 +83,9 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> {
|
|||
}
|
||||
|
||||
abstract class RustLibApi extends BaseApi {
|
||||
Future<Uint8List>
|
||||
crateBridgeWrapperKeyManagerFlutterKeyManagerGetLoginToken();
|
||||
|
||||
Future<Uint8List>
|
||||
crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryGetCurrentVersion();
|
||||
|
||||
|
|
@ -165,7 +169,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
|
||||
@override
|
||||
Future<Uint8List>
|
||||
crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryGetCurrentVersion() {
|
||||
crateBridgeWrapperKeyManagerFlutterKeyManagerGetLoginToken() {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
|
|
@ -181,6 +185,39 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
decodeSuccessData: sse_decode_list_prim_u_8_strict,
|
||||
decodeErrorData: sse_decode_AnyhowException,
|
||||
),
|
||||
constMeta:
|
||||
kCrateBridgeWrapperKeyManagerFlutterKeyManagerGetLoginTokenConstMeta,
|
||||
argValues: [],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta
|
||||
get kCrateBridgeWrapperKeyManagerFlutterKeyManagerGetLoginTokenConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "flutter_key_manager_get_login_token",
|
||||
argNames: [],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<Uint8List>
|
||||
crateBridgeWrapperUserDiscoveryFlutterUserDiscoveryGetCurrentVersion() {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
final serializer = SseSerializer(generalizedFrbRustBinding);
|
||||
pdeCallFfi(
|
||||
generalizedFrbRustBinding,
|
||||
serializer,
|
||||
funcId: 2,
|
||||
port: port_,
|
||||
);
|
||||
},
|
||||
codec: SseCodec(
|
||||
decodeSuccessData: sse_decode_list_prim_u_8_strict,
|
||||
decodeErrorData: sse_decode_AnyhowException,
|
||||
),
|
||||
constMeta:
|
||||
kCrateBridgeWrapperUserDiscoveryFlutterUserDiscoveryGetCurrentVersionConstMeta,
|
||||
argValues: [],
|
||||
|
|
@ -211,7 +248,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
pdeCallFfi(
|
||||
generalizedFrbRustBinding,
|
||||
serializer,
|
||||
funcId: 2,
|
||||
funcId: 3,
|
||||
port: port_,
|
||||
);
|
||||
},
|
||||
|
|
@ -254,7 +291,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
pdeCallFfi(
|
||||
generalizedFrbRustBinding,
|
||||
serializer,
|
||||
funcId: 3,
|
||||
funcId: 4,
|
||||
port: port_,
|
||||
);
|
||||
},
|
||||
|
|
@ -296,7 +333,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
pdeCallFfi(
|
||||
generalizedFrbRustBinding,
|
||||
serializer,
|
||||
funcId: 4,
|
||||
funcId: 5,
|
||||
port: port_,
|
||||
);
|
||||
},
|
||||
|
|
@ -334,7 +371,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
pdeCallFfi(
|
||||
generalizedFrbRustBinding,
|
||||
serializer,
|
||||
funcId: 5,
|
||||
funcId: 6,
|
||||
port: port_,
|
||||
);
|
||||
},
|
||||
|
|
@ -375,7 +412,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
pdeCallFfi(
|
||||
generalizedFrbRustBinding,
|
||||
serializer,
|
||||
funcId: 6,
|
||||
funcId: 7,
|
||||
port: port_,
|
||||
);
|
||||
},
|
||||
|
|
@ -499,7 +536,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
pdeCallFfi(
|
||||
generalizedFrbRustBinding,
|
||||
serializer,
|
||||
funcId: 7,
|
||||
funcId: 8,
|
||||
port: port_,
|
||||
);
|
||||
},
|
||||
|
|
@ -564,7 +601,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
pdeCallFfi(
|
||||
generalizedFrbRustBinding,
|
||||
serializer,
|
||||
funcId: 8,
|
||||
funcId: 9,
|
||||
port: port_,
|
||||
);
|
||||
},
|
||||
|
|
@ -1183,6 +1220,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
return dco_decode_init_config(raw);
|
||||
}
|
||||
|
||||
@protected
|
||||
FlutterKeyManager dco_decode_flutter_key_manager(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
final arr = raw as List<dynamic>;
|
||||
if (arr.length != 0)
|
||||
throw Exception('unexpected arr length: expect 0 but see ${arr.length}');
|
||||
return FlutterKeyManager();
|
||||
}
|
||||
|
||||
@protected
|
||||
FlutterUserDiscovery dco_decode_flutter_user_discovery(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
|
|
@ -1378,6 +1424,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
return (sse_decode_init_config(deserializer));
|
||||
}
|
||||
|
||||
@protected
|
||||
FlutterKeyManager sse_decode_flutter_key_manager(
|
||||
SseDeserializer deserializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
return FlutterKeyManager();
|
||||
}
|
||||
|
||||
@protected
|
||||
FlutterUserDiscovery sse_decode_flutter_user_discovery(
|
||||
SseDeserializer deserializer,
|
||||
|
|
@ -1821,6 +1875,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
|||
sse_encode_init_config(self, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_flutter_key_manager(
|
||||
FlutterKeyManager self,
|
||||
SseSerializer serializer,
|
||||
) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_flutter_user_discovery(
|
||||
FlutterUserDiscovery self,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import 'bridge.dart';
|
||||
import 'bridge/callbacks.dart';
|
||||
import 'bridge/wrapper/key_manager.dart';
|
||||
import 'bridge/wrapper/user_discovery.dart';
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
|
@ -119,6 +120,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
|||
@protected
|
||||
InitConfig dco_decode_box_autoadd_init_config(dynamic raw);
|
||||
|
||||
@protected
|
||||
FlutterKeyManager dco_decode_flutter_key_manager(dynamic raw);
|
||||
|
||||
@protected
|
||||
FlutterUserDiscovery dco_decode_flutter_user_discovery(dynamic raw);
|
||||
|
||||
|
|
@ -204,6 +208,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
|||
@protected
|
||||
InitConfig sse_decode_box_autoadd_init_config(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
FlutterKeyManager sse_decode_flutter_key_manager(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
FlutterUserDiscovery sse_decode_flutter_user_discovery(
|
||||
SseDeserializer deserializer,
|
||||
|
|
@ -397,6 +406,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
|||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_flutter_key_manager(
|
||||
FlutterKeyManager self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_flutter_user_discovery(
|
||||
FlutterUserDiscovery self,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import 'bridge.dart';
|
||||
import 'bridge/callbacks.dart';
|
||||
import 'bridge/wrapper/key_manager.dart';
|
||||
import 'bridge/wrapper/user_discovery.dart';
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
|
@ -121,6 +122,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
|||
@protected
|
||||
InitConfig dco_decode_box_autoadd_init_config(dynamic raw);
|
||||
|
||||
@protected
|
||||
FlutterKeyManager dco_decode_flutter_key_manager(dynamic raw);
|
||||
|
||||
@protected
|
||||
FlutterUserDiscovery dco_decode_flutter_user_discovery(dynamic raw);
|
||||
|
||||
|
|
@ -206,6 +210,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
|||
@protected
|
||||
InitConfig sse_decode_box_autoadd_init_config(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
FlutterKeyManager sse_decode_flutter_key_manager(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
FlutterUserDiscovery sse_decode_flutter_user_discovery(
|
||||
SseDeserializer deserializer,
|
||||
|
|
@ -399,6 +408,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
|||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_flutter_key_manager(
|
||||
FlutterKeyManager self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_flutter_user_discovery(
|
||||
FlutterUserDiscovery self,
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class AppState {
|
|||
static bool isInBackgroundTask = false;
|
||||
static bool allowErrorTrackingViaSentry = false;
|
||||
static bool gotMessageFromServer = false;
|
||||
static int latestAppVersionId = 110;
|
||||
static int latestAppVersionId = 111;
|
||||
}
|
||||
|
||||
class AppGlobalKeys {
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ void main() async {
|
|||
unawaited(StartupGuard.markAppStartup());
|
||||
|
||||
var storageError = await twonlyMinimumInitialization();
|
||||
unawaited(initFCMService());
|
||||
await initFCMService();
|
||||
|
||||
var userExists = false;
|
||||
|
||||
|
|
@ -185,6 +185,13 @@ Future<void> runMigrations() async {
|
|||
}
|
||||
});
|
||||
}
|
||||
if (userService.currentUser.appVersion < 111) {
|
||||
await UserService.update((u) {
|
||||
u
|
||||
..appVersion = 111
|
||||
..canUseLoginTokenForAuth = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> postStartupTasks() async {
|
||||
|
|
|
|||
|
|
@ -128,6 +128,9 @@ class UserData {
|
|||
@JsonKey(defaultValue: true)
|
||||
bool updateFCMToken = true;
|
||||
|
||||
@JsonKey(defaultValue: true)
|
||||
bool canUseLoginTokenForAuth = true;
|
||||
|
||||
// --- BACKUP ---
|
||||
|
||||
DateTime? nextTimeToShowBackupNotice;
|
||||
|
|
|
|||
|
|
@ -1248,66 +1248,6 @@ class ApplicationData_GetUserById extends $pb.GeneratedMessage {
|
|||
void clearUserId() => $_clearField(1);
|
||||
}
|
||||
|
||||
class ApplicationData_UpdatePlanOptions extends $pb.GeneratedMessage {
|
||||
factory ApplicationData_UpdatePlanOptions({
|
||||
$core.bool? autoRenewal,
|
||||
}) {
|
||||
final result = create();
|
||||
if (autoRenewal != null) result.autoRenewal = autoRenewal;
|
||||
return result;
|
||||
}
|
||||
|
||||
ApplicationData_UpdatePlanOptions._();
|
||||
|
||||
factory ApplicationData_UpdatePlanOptions.fromBuffer(
|
||||
$core.List<$core.int> data,
|
||||
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromBuffer(data, registry);
|
||||
factory ApplicationData_UpdatePlanOptions.fromJson($core.String json,
|
||||
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromJson(json, registry);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||
_omitMessageNames ? '' : 'ApplicationData.UpdatePlanOptions',
|
||||
package:
|
||||
const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'),
|
||||
createEmptyInstance: create)
|
||||
..aOB(1, _omitFieldNames ? '' : 'autoRenewal')
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
ApplicationData_UpdatePlanOptions clone() => deepCopy();
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
ApplicationData_UpdatePlanOptions copyWith(
|
||||
void Function(ApplicationData_UpdatePlanOptions) updates) =>
|
||||
super.copyWith((message) =>
|
||||
updates(message as ApplicationData_UpdatePlanOptions))
|
||||
as ApplicationData_UpdatePlanOptions;
|
||||
|
||||
@$core.override
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static ApplicationData_UpdatePlanOptions create() =>
|
||||
ApplicationData_UpdatePlanOptions._();
|
||||
@$core.override
|
||||
ApplicationData_UpdatePlanOptions createEmptyInstance() => create();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static ApplicationData_UpdatePlanOptions getDefault() => _defaultInstance ??=
|
||||
$pb.GeneratedMessage.$_defaultFor<ApplicationData_UpdatePlanOptions>(
|
||||
create);
|
||||
static ApplicationData_UpdatePlanOptions? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool get autoRenewal => $_getBF(0);
|
||||
@$pb.TagNumber(1)
|
||||
set autoRenewal($core.bool value) => $_setBool(0, value);
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasAutoRenewal() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearAutoRenewal() => $_clearField(1);
|
||||
}
|
||||
|
||||
class ApplicationData_GetAvailablePlans extends $pb.GeneratedMessage {
|
||||
factory ApplicationData_GetAvailablePlans() => create();
|
||||
|
||||
|
|
@ -2178,7 +2118,7 @@ enum ApplicationData_ApplicationData {
|
|||
deprecated16,
|
||||
deprecated17,
|
||||
removeAdditionalUser,
|
||||
updatePlanOptions,
|
||||
deprecated19,
|
||||
downloadDone,
|
||||
getSignedPrekeyByUserid,
|
||||
updateSignedPrekey,
|
||||
|
|
@ -2209,7 +2149,7 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
ApplicationData_Deprecated? deprecated16,
|
||||
ApplicationData_Deprecated? deprecated17,
|
||||
ApplicationData_RemoveAdditionalUser? removeAdditionalUser,
|
||||
ApplicationData_UpdatePlanOptions? updatePlanOptions,
|
||||
ApplicationData_Deprecated? deprecated19,
|
||||
ApplicationData_DownloadDone? downloadDone,
|
||||
ApplicationData_GetSignedPreKeyByUserId? getSignedPrekeyByUserid,
|
||||
ApplicationData_UpdateSignedPreKey? updateSignedPrekey,
|
||||
|
|
@ -2241,7 +2181,7 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
if (deprecated17 != null) result.deprecated17 = deprecated17;
|
||||
if (removeAdditionalUser != null)
|
||||
result.removeAdditionalUser = removeAdditionalUser;
|
||||
if (updatePlanOptions != null) result.updatePlanOptions = updatePlanOptions;
|
||||
if (deprecated19 != null) result.deprecated19 = deprecated19;
|
||||
if (downloadDone != null) result.downloadDone = downloadDone;
|
||||
if (getSignedPrekeyByUserid != null)
|
||||
result.getSignedPrekeyByUserid = getSignedPrekeyByUserid;
|
||||
|
|
@ -2283,7 +2223,7 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
16: ApplicationData_ApplicationData.deprecated16,
|
||||
17: ApplicationData_ApplicationData.deprecated17,
|
||||
18: ApplicationData_ApplicationData.removeAdditionalUser,
|
||||
19: ApplicationData_ApplicationData.updatePlanOptions,
|
||||
19: ApplicationData_ApplicationData.deprecated19,
|
||||
20: ApplicationData_ApplicationData.downloadDone,
|
||||
22: ApplicationData_ApplicationData.getSignedPrekeyByUserid,
|
||||
23: ApplicationData_ApplicationData.updateSignedPrekey,
|
||||
|
|
@ -2380,10 +2320,9 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
18, _omitFieldNames ? '' : 'removeAdditionalUser',
|
||||
protoName: 'removeAdditionalUser',
|
||||
subBuilder: ApplicationData_RemoveAdditionalUser.create)
|
||||
..aOM<ApplicationData_UpdatePlanOptions>(
|
||||
19, _omitFieldNames ? '' : 'updatePlanOptions',
|
||||
protoName: 'updatePlanOptions',
|
||||
subBuilder: ApplicationData_UpdatePlanOptions.create)
|
||||
..aOM<ApplicationData_Deprecated>(19, _omitFieldNames ? '' : 'deprecated19',
|
||||
protoName: 'deprecated_19',
|
||||
subBuilder: ApplicationData_Deprecated.create)
|
||||
..aOM<ApplicationData_DownloadDone>(
|
||||
20, _omitFieldNames ? '' : 'downloadDone',
|
||||
protoName: 'downloadDone',
|
||||
|
|
@ -2672,16 +2611,15 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
$_ensure(14);
|
||||
|
||||
@$pb.TagNumber(19)
|
||||
ApplicationData_UpdatePlanOptions get updatePlanOptions => $_getN(15);
|
||||
ApplicationData_Deprecated get deprecated19 => $_getN(15);
|
||||
@$pb.TagNumber(19)
|
||||
set updatePlanOptions(ApplicationData_UpdatePlanOptions value) =>
|
||||
$_setField(19, value);
|
||||
set deprecated19(ApplicationData_Deprecated value) => $_setField(19, value);
|
||||
@$pb.TagNumber(19)
|
||||
$core.bool hasUpdatePlanOptions() => $_has(15);
|
||||
$core.bool hasDeprecated19() => $_has(15);
|
||||
@$pb.TagNumber(19)
|
||||
void clearUpdatePlanOptions() => $_clearField(19);
|
||||
void clearDeprecated19() => $_clearField(19);
|
||||
@$pb.TagNumber(19)
|
||||
ApplicationData_UpdatePlanOptions ensureUpdatePlanOptions() => $_ensure(15);
|
||||
ApplicationData_Deprecated ensureDeprecated19() => $_ensure(15);
|
||||
|
||||
@$pb.TagNumber(20)
|
||||
ApplicationData_DownloadDone get downloadDone => $_getN(16);
|
||||
|
|
|
|||
|
|
@ -447,13 +447,13 @@ const ApplicationData$json = {
|
|||
'10': 'deprecated17'
|
||||
},
|
||||
{
|
||||
'1': 'updatePlanOptions',
|
||||
'1': 'deprecated_19',
|
||||
'3': 19,
|
||||
'4': 1,
|
||||
'5': 11,
|
||||
'6': '.client_to_server.ApplicationData.UpdatePlanOptions',
|
||||
'6': '.client_to_server.ApplicationData.Deprecated',
|
||||
'9': 0,
|
||||
'10': 'updatePlanOptions'
|
||||
'10': 'deprecated19'
|
||||
},
|
||||
{
|
||||
'1': 'downloadDone',
|
||||
|
|
@ -561,7 +561,6 @@ const ApplicationData$json = {
|
|||
ApplicationData_ChangeUsername$json,
|
||||
ApplicationData_UpdateGoogleFcmToken$json,
|
||||
ApplicationData_GetUserById$json,
|
||||
ApplicationData_UpdatePlanOptions$json,
|
||||
ApplicationData_GetAvailablePlans$json,
|
||||
ApplicationData_GetAddAccountsInvites$json,
|
||||
ApplicationData_GetCurrentPlanInfos$json,
|
||||
|
|
@ -636,14 +635,6 @@ const ApplicationData_GetUserById$json = {
|
|||
],
|
||||
};
|
||||
|
||||
@$core.Deprecated('Use applicationDataDescriptor instead')
|
||||
const ApplicationData_UpdatePlanOptions$json = {
|
||||
'1': 'UpdatePlanOptions',
|
||||
'2': [
|
||||
{'1': 'auto_renewal', '3': 1, '4': 1, '5': 8, '10': 'autoRenewal'},
|
||||
],
|
||||
};
|
||||
|
||||
@$core.Deprecated('Use applicationDataDescriptor instead')
|
||||
const ApplicationData_GetAvailablePlans$json = {
|
||||
'1': 'GetAvailablePlans',
|
||||
|
|
@ -788,48 +779,47 @@ final $typed_data.Uint8List applicationDataDescriptor = $convert.base64Decode(
|
|||
'dGVkSABSDGRlcHJlY2F0ZWQxNRJTCg1kZXByZWNhdGVkXzE2GBAgASgLMiwuY2xpZW50X3RvX3'
|
||||
'NlcnZlci5BcHBsaWNhdGlvbkRhdGEuRGVwcmVjYXRlZEgAUgxkZXByZWNhdGVkMTYSUwoNZGVw'
|
||||
'cmVjYXRlZF8xNxgRIAEoCzIsLmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLkRlcH'
|
||||
'JlY2F0ZWRIAFIMZGVwcmVjYXRlZDE3EmMKEXVwZGF0ZVBsYW5PcHRpb25zGBMgASgLMjMuY2xp'
|
||||
'ZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuVXBkYXRlUGxhbk9wdGlvbnNIAFIRdXBkYX'
|
||||
'RlUGxhbk9wdGlvbnMSVAoMZG93bmxvYWREb25lGBQgASgLMi4uY2xpZW50X3RvX3NlcnZlci5B'
|
||||
'cHBsaWNhdGlvbkRhdGEuRG93bmxvYWREb25lSABSDGRvd25sb2FkRG9uZRJ1ChdnZXRTaWduZW'
|
||||
'RQcmVrZXlCeVVzZXJpZBgWIAEoCzI5LmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRh'
|
||||
'LkdldFNpZ25lZFByZUtleUJ5VXNlcklkSABSF2dldFNpZ25lZFByZWtleUJ5VXNlcmlkEmYKEn'
|
||||
'VwZGF0ZVNpZ25lZFByZWtleRgXIAEoCzI0LmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25E'
|
||||
'YXRhLlVwZGF0ZVNpZ25lZFByZUtleUgAUhJ1cGRhdGVTaWduZWRQcmVrZXkSVwoNZGVsZXRlQW'
|
||||
'Njb3VudBgYIAEoCzIvLmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLkRlbGV0ZUFj'
|
||||
'Y291bnRIAFINZGVsZXRlQWNjb3VudBJOCgpyZXBvcnRVc2VyGBkgASgLMiwuY2xpZW50X3RvX3'
|
||||
'NlcnZlci5BcHBsaWNhdGlvbkRhdGEuUmVwb3J0VXNlckgAUgpyZXBvcnRVc2VyEloKDmNoYW5n'
|
||||
'ZVVzZXJuYW1lGBogASgLMjAuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuQ2hhbm'
|
||||
'dlVXNlcm5hbWVIAFIOY2hhbmdlVXNlcm5hbWUSUQoLaXBhUHVyY2hhc2UYGyABKAsyLS5jbGll'
|
||||
'bnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5JUEFQdXJjaGFzZUgAUgtpcGFQdXJjaGFzZR'
|
||||
'JXCg1pcGFGb3JjZUNoZWNrGBwgASgLMi8uY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRh'
|
||||
'dGEuSVBBRm9yY2VDaGVja0gAUg1pcGFGb3JjZUNoZWNrEmwKFHJlbW92ZUFkZGl0aW9uYWxVc2'
|
||||
'VyGBIgASgLMjYuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuUmVtb3ZlQWRkaXRp'
|
||||
'b25hbFVzZXJIAFIUcmVtb3ZlQWRkaXRpb25hbFVzZXISYwoRYWRkQWRkaXRpb25hbFVzZXIYHS'
|
||||
'ABKAsyMy5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5BZGRBZGRpdGlvbmFsVXNl'
|
||||
'ckgAUhFhZGRBZGRpdGlvbmFsVXNlchJZCg9zZXRfbG9naW5fdG9rZW4YHiABKAsyLy5jbGllbn'
|
||||
'RfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5TZXRMb2dpblRva2VuSABSDXNldExvZ2luVG9r'
|
||||
'ZW4aagoLVGV4dE1lc3NhZ2USFwoHdXNlcl9pZBgBIAEoA1IGdXNlcklkEhIKBGJvZHkYAyABKA'
|
||||
'xSBGJvZHkSIAoJcHVzaF9kYXRhGAQgASgMSABSCHB1c2hEYXRhiAEBQgwKCl9wdXNoX2RhdGEa'
|
||||
'LwoRR2V0VXNlckJ5VXNlcm5hbWUSGgoIdXNlcm5hbWUYASABKAlSCHVzZXJuYW1lGiwKDkNoYW'
|
||||
'5nZVVzZXJuYW1lEhoKCHVzZXJuYW1lGAEgASgJUgh1c2VybmFtZRo1ChRVcGRhdGVHb29nbGVG'
|
||||
'Y21Ub2tlbhIdCgpnb29nbGVfZmNtGAEgASgJUglnb29nbGVGY20aJgoLR2V0VXNlckJ5SWQSFw'
|
||||
'oHdXNlcl9pZBgBIAEoA1IGdXNlcklkGjYKEVVwZGF0ZVBsYW5PcHRpb25zEiEKDGF1dG9fcmVu'
|
||||
'ZXdhbBgBIAEoCFILYXV0b1JlbmV3YWwaEwoRR2V0QXZhaWxhYmxlUGxhbnMaFwoVR2V0QWRkQW'
|
||||
'Njb3VudHNJbnZpdGVzGhUKE0dldEN1cnJlbnRQbGFuSW5mb3MaLwoUUmVtb3ZlQWRkaXRpb25h'
|
||||
'bFVzZXISFwoHdXNlcl9pZBgBIAEoA1IGdXNlcklkGi0KEkdldFByZWtleXNCeVVzZXJJZBIXCg'
|
||||
'd1c2VyX2lkGAEgASgDUgZ1c2VySWQaMgoXR2V0U2lnbmVkUHJlS2V5QnlVc2VySWQSFwoHdXNl'
|
||||
'cl9pZBgBIAEoA1IGdXNlcklkGpsBChJVcGRhdGVTaWduZWRQcmVLZXkSKAoQc2lnbmVkX3ByZW'
|
||||
'tleV9pZBgBIAEoA1IOc2lnbmVkUHJla2V5SWQSIwoNc2lnbmVkX3ByZWtleRgCIAEoDFIMc2ln'
|
||||
'bmVkUHJla2V5EjYKF3NpZ25lZF9wcmVrZXlfc2lnbmF0dXJlGAMgASgMUhVzaWduZWRQcmVrZX'
|
||||
'lTaWduYXR1cmUaNQoMRG93bmxvYWREb25lEiUKDmRvd25sb2FkX3Rva2VuGAEgASgMUg1kb3du'
|
||||
'bG9hZFRva2VuGk4KClJlcG9ydFVzZXISKAoQcmVwb3J0ZWRfdXNlcl9pZBgBIAEoA1IOcmVwb3'
|
||||
'J0ZWRVc2VySWQSFgoGcmVhc29uGAIgASgJUgZyZWFzb24acQoLSVBBUHVyY2hhc2USHQoKcHJv'
|
||||
'ZHVjdF9pZBgBIAEoCVIJcHJvZHVjdElkEhYKBnNvdXJjZRgCIAEoCVIGc291cmNlEisKEXZlcm'
|
||||
'lmaWNhdGlvbl9kYXRhGAMgASgJUhB2ZXJpZmljYXRpb25EYXRhGg8KDUlQQUZvcmNlQ2hlY2sa'
|
||||
'DwoNRGVsZXRlQWNjb3VudBosChFBZGRBZGRpdGlvbmFsVXNlchIXCgd1c2VyX2lkGAEgASgDUg'
|
||||
'Z1c2VySWQaMAoNU2V0TG9naW5Ub2tlbhIfCgtsb2dpbl90b2tlbhgBIAEoDFIKbG9naW5Ub2tl'
|
||||
'bhoMCgpEZXByZWNhdGVkQhEKD0FwcGxpY2F0aW9uRGF0YQ==');
|
||||
'JlY2F0ZWRIAFIMZGVwcmVjYXRlZDE3ElMKDWRlcHJlY2F0ZWRfMTkYEyABKAsyLC5jbGllbnRf'
|
||||
'dG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5EZXByZWNhdGVkSABSDGRlcHJlY2F0ZWQxORJUCg'
|
||||
'xkb3dubG9hZERvbmUYFCABKAsyLi5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5E'
|
||||
'b3dubG9hZERvbmVIAFIMZG93bmxvYWREb25lEnUKF2dldFNpZ25lZFByZWtleUJ5VXNlcmlkGB'
|
||||
'YgASgLMjkuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuR2V0U2lnbmVkUHJlS2V5'
|
||||
'QnlVc2VySWRIAFIXZ2V0U2lnbmVkUHJla2V5QnlVc2VyaWQSZgoSdXBkYXRlU2lnbmVkUHJla2'
|
||||
'V5GBcgASgLMjQuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuVXBkYXRlU2lnbmVk'
|
||||
'UHJlS2V5SABSEnVwZGF0ZVNpZ25lZFByZWtleRJXCg1kZWxldGVBY2NvdW50GBggASgLMi8uY2'
|
||||
'xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuRGVsZXRlQWNjb3VudEgAUg1kZWxldGVB'
|
||||
'Y2NvdW50Ek4KCnJlcG9ydFVzZXIYGSABKAsyLC5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW'
|
||||
'9uRGF0YS5SZXBvcnRVc2VySABSCnJlcG9ydFVzZXISWgoOY2hhbmdlVXNlcm5hbWUYGiABKAsy'
|
||||
'MC5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5DaGFuZ2VVc2VybmFtZUgAUg5jaG'
|
||||
'FuZ2VVc2VybmFtZRJRCgtpcGFQdXJjaGFzZRgbIAEoCzItLmNsaWVudF90b19zZXJ2ZXIuQXBw'
|
||||
'bGljYXRpb25EYXRhLklQQVB1cmNoYXNlSABSC2lwYVB1cmNoYXNlElcKDWlwYUZvcmNlQ2hlY2'
|
||||
'sYHCABKAsyLy5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5JUEFGb3JjZUNoZWNr'
|
||||
'SABSDWlwYUZvcmNlQ2hlY2sSbAoUcmVtb3ZlQWRkaXRpb25hbFVzZXIYEiABKAsyNi5jbGllbn'
|
||||
'RfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5SZW1vdmVBZGRpdGlvbmFsVXNlckgAUhRyZW1v'
|
||||
'dmVBZGRpdGlvbmFsVXNlchJjChFhZGRBZGRpdGlvbmFsVXNlchgdIAEoCzIzLmNsaWVudF90b1'
|
||||
'9zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLkFkZEFkZGl0aW9uYWxVc2VySABSEWFkZEFkZGl0aW9u'
|
||||
'YWxVc2VyElkKD3NldF9sb2dpbl90b2tlbhgeIAEoCzIvLmNsaWVudF90b19zZXJ2ZXIuQXBwbG'
|
||||
'ljYXRpb25EYXRhLlNldExvZ2luVG9rZW5IAFINc2V0TG9naW5Ub2tlbhpqCgtUZXh0TWVzc2Fn'
|
||||
'ZRIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySWQSEgoEYm9keRgDIAEoDFIEYm9keRIgCglwdXNoX2'
|
||||
'RhdGEYBCABKAxIAFIIcHVzaERhdGGIAQFCDAoKX3B1c2hfZGF0YRovChFHZXRVc2VyQnlVc2Vy'
|
||||
'bmFtZRIaCgh1c2VybmFtZRgBIAEoCVIIdXNlcm5hbWUaLAoOQ2hhbmdlVXNlcm5hbWUSGgoIdX'
|
||||
'Nlcm5hbWUYASABKAlSCHVzZXJuYW1lGjUKFFVwZGF0ZUdvb2dsZUZjbVRva2VuEh0KCmdvb2ds'
|
||||
'ZV9mY20YASABKAlSCWdvb2dsZUZjbRomCgtHZXRVc2VyQnlJZBIXCgd1c2VyX2lkGAEgASgDUg'
|
||||
'Z1c2VySWQaEwoRR2V0QXZhaWxhYmxlUGxhbnMaFwoVR2V0QWRkQWNjb3VudHNJbnZpdGVzGhUK'
|
||||
'E0dldEN1cnJlbnRQbGFuSW5mb3MaLwoUUmVtb3ZlQWRkaXRpb25hbFVzZXISFwoHdXNlcl9pZB'
|
||||
'gBIAEoA1IGdXNlcklkGi0KEkdldFByZWtleXNCeVVzZXJJZBIXCgd1c2VyX2lkGAEgASgDUgZ1'
|
||||
'c2VySWQaMgoXR2V0U2lnbmVkUHJlS2V5QnlVc2VySWQSFwoHdXNlcl9pZBgBIAEoA1IGdXNlck'
|
||||
'lkGpsBChJVcGRhdGVTaWduZWRQcmVLZXkSKAoQc2lnbmVkX3ByZWtleV9pZBgBIAEoA1IOc2ln'
|
||||
'bmVkUHJla2V5SWQSIwoNc2lnbmVkX3ByZWtleRgCIAEoDFIMc2lnbmVkUHJla2V5EjYKF3NpZ2'
|
||||
'5lZF9wcmVrZXlfc2lnbmF0dXJlGAMgASgMUhVzaWduZWRQcmVrZXlTaWduYXR1cmUaNQoMRG93'
|
||||
'bmxvYWREb25lEiUKDmRvd25sb2FkX3Rva2VuGAEgASgMUg1kb3dubG9hZFRva2VuGk4KClJlcG'
|
||||
'9ydFVzZXISKAoQcmVwb3J0ZWRfdXNlcl9pZBgBIAEoA1IOcmVwb3J0ZWRVc2VySWQSFgoGcmVh'
|
||||
'c29uGAIgASgJUgZyZWFzb24acQoLSVBBUHVyY2hhc2USHQoKcHJvZHVjdF9pZBgBIAEoCVIJcH'
|
||||
'JvZHVjdElkEhYKBnNvdXJjZRgCIAEoCVIGc291cmNlEisKEXZlcmlmaWNhdGlvbl9kYXRhGAMg'
|
||||
'ASgJUhB2ZXJpZmljYXRpb25EYXRhGg8KDUlQQUZvcmNlQ2hlY2saDwoNRGVsZXRlQWNjb3VudB'
|
||||
'osChFBZGRBZGRpdGlvbmFsVXNlchIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySWQaMAoNU2V0TG9n'
|
||||
'aW5Ub2tlbhIfCgtsb2dpbl90b2tlbhgBIAEoDFIKbG9naW5Ub2tlbhoMCgpEZXByZWNhdGVkQh'
|
||||
'EKD0FwcGxpY2F0aW9uRGF0YQ==');
|
||||
|
||||
@$core.Deprecated('Use responseDescriptor instead')
|
||||
const Response$json = {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:libsignal_protocol_dart/src/ecc/ed25519.dart';
|
||||
import 'package:mutex/mutex.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:twonly/core/bridge/wrapper/key_manager.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/locator.dart';
|
||||
import 'package:twonly/src/constants/secure_storage.keys.dart';
|
||||
|
|
@ -450,6 +451,21 @@ class ApiService {
|
|||
await onAuthenticated();
|
||||
} else {
|
||||
unawaited(onAuthenticated());
|
||||
|
||||
try {
|
||||
Log.info('Switching authentication to login token');
|
||||
final loginToken = await FlutterKeyManager.getLoginToken();
|
||||
final res = await _setLoginToken(loginToken);
|
||||
if (res.isSuccess) {
|
||||
Log.info('Switch was successfully.');
|
||||
await UserService.update((u) => u.canUseLoginTokenForAuth = true);
|
||||
await SecureStorage.instance.delete(
|
||||
key: SecureStorageKeys.apiAuthToken,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
Log.error(e);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -466,9 +482,51 @@ class ApiService {
|
|||
return false;
|
||||
}
|
||||
|
||||
Future<bool> tryAuthenticateWithLoginToken() async {
|
||||
try {
|
||||
final loginToken = await FlutterKeyManager.getLoginToken();
|
||||
|
||||
final authenticate = Handshake_AuthenticateWithLoginToken()
|
||||
..userId = Int64(userService.currentUser.userId)
|
||||
..appVersion = (await PackageInfo.fromPlatform()).version
|
||||
..deviceId = Int64(userService.currentUser.deviceId)
|
||||
..inBackground = AppState.isInBackgroundTask
|
||||
..secretLoginToken = loginToken.toList();
|
||||
|
||||
final handshake = Handshake()..authenticateWithLoginToken = authenticate;
|
||||
final req = createClientToServerFromHandshake(handshake);
|
||||
|
||||
final result = await sendRequestSync(req, authenticated: false);
|
||||
|
||||
if (result.isSuccess) {
|
||||
Log.info('websocket is authenticated');
|
||||
isAuthenticated = true;
|
||||
if (AppState.isInBackgroundTask) {
|
||||
await onAuthenticated();
|
||||
} else {
|
||||
unawaited(onAuthenticated());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (result.isError) {
|
||||
if (result.error != ErrorCode.AuthTokenNotValid &&
|
||||
result.error != ErrorCode.ForegroundSessionConnected) {
|
||||
Log.error(
|
||||
'got error while authenticating to the server: ${result.error}',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
Log.error(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> authenticate() async {
|
||||
return lockAuthentication.protect(() async {
|
||||
if (isAuthenticated) return;
|
||||
|
||||
if (await getSignalIdentity() == null) {
|
||||
Log.error('Signal identity not found.');
|
||||
return;
|
||||
|
|
@ -476,6 +534,11 @@ class ApiService {
|
|||
|
||||
if (!userService.isUserCreated) return;
|
||||
|
||||
if (userService.currentUser.canUseLoginTokenForAuth) {
|
||||
await tryAuthenticateWithLoginToken();
|
||||
return;
|
||||
}
|
||||
|
||||
if (await tryAuthenticateWithToken()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -542,6 +605,8 @@ class ApiService {
|
|||
|
||||
final signedPreKey = (await signalStore.loadSignedPreKeys())[0];
|
||||
|
||||
final loginToken = await FlutterKeyManager.getLoginToken();
|
||||
|
||||
final register = Handshake_Register()
|
||||
..username = username
|
||||
..publicIdentityKey = (await signalStore.getIdentityKeyPair())
|
||||
|
|
@ -552,6 +617,7 @@ class ApiService {
|
|||
..signedPrekeySignature = signedPreKey.signature
|
||||
..signedPrekeyId = Int64(signedPreKey.id)
|
||||
..langCode = ui.PlatformDispatcher.instance.locale.languageCode
|
||||
..loginToken = loginToken
|
||||
..proofOfWork = Int64(proofOfWorkResult)
|
||||
..isIos = Platform.isIOS;
|
||||
|
||||
|
|
@ -617,6 +683,13 @@ class ApiService {
|
|||
return sendRequestSync(req, ensureRetransmission: true);
|
||||
}
|
||||
|
||||
Future<Result> _setLoginToken(List<int> token) async {
|
||||
final get = ApplicationData_SetLoginToken()..loginToken = token;
|
||||
final appData = ApplicationData()..setLoginToken = get;
|
||||
final req = createClientToServerFromApplicationData(appData);
|
||||
return sendRequestSync(req);
|
||||
}
|
||||
|
||||
Future<Response_UserData?> getUserData(String username) async {
|
||||
final get = ApplicationData_GetUserByUsername()..username = username;
|
||||
final appData = ApplicationData()..getUserByUsername = get;
|
||||
|
|
@ -645,13 +718,6 @@ class ApiService {
|
|||
return null;
|
||||
}
|
||||
|
||||
Future<Result> updatePlanOptions(bool autoRenewal) async {
|
||||
final get = ApplicationData_UpdatePlanOptions()..autoRenewal = autoRenewal;
|
||||
final appData = ApplicationData()..updatePlanOptions = get;
|
||||
final req = createClientToServerFromApplicationData(appData);
|
||||
return sendRequestSync(req);
|
||||
}
|
||||
|
||||
Future<Result> removeAdditionalUser(Int64 userId) async {
|
||||
final get = ApplicationData_RemoveAdditionalUser()..userId = userId;
|
||||
final appData = ApplicationData()..removeAdditionalUser = get;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:background_downloader/background_downloader.dart';
|
||||
import 'package:clock/clock.dart';
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
|
|
@ -12,7 +10,6 @@ import 'package:http/http.dart' as http;
|
|||
import 'package:mutex/mutex.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/locator.dart';
|
||||
import 'package:twonly/src/constants/secure_storage.keys.dart';
|
||||
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||
import 'package:twonly/src/database/tables/messages.table.dart';
|
||||
import 'package:twonly/src/database/twonly.db.dart';
|
||||
|
|
@ -21,12 +18,12 @@ import 'package:twonly/src/model/protobuf/client/generated/data.pb.dart';
|
|||
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||
import 'package:twonly/src/services/api/mediafiles/media_background.api.dart';
|
||||
import 'package:twonly/src/services/api/messages.api.dart';
|
||||
import 'package:twonly/src/services/api/utils.api.dart';
|
||||
import 'package:twonly/src/services/flame.service.dart';
|
||||
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
|
||||
import 'package:twonly/src/utils/exclusive_access.utils.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:twonly/src/utils/secure_storage.dart';
|
||||
import 'package:workmanager/workmanager.dart' hide TaskStatus;
|
||||
|
||||
final lockRetransmission = Mutex();
|
||||
|
|
@ -620,22 +617,17 @@ Future<void> _uploadUploadRequest(MediaFileService media) async {
|
|||
return null;
|
||||
}
|
||||
|
||||
final apiAuthTokenRaw = await SecureStorage.instance.read(
|
||||
key: SecureStorageKeys.apiAuthToken,
|
||||
);
|
||||
|
||||
if (apiAuthTokenRaw == null) {
|
||||
Log.error('api auth token not defined.');
|
||||
return null;
|
||||
}
|
||||
final apiAuthToken = uint8ListToHex(base64Decode(apiAuthTokenRaw));
|
||||
|
||||
final apiUrl =
|
||||
'http${apiService.apiSecure}://${apiService.apiHost}/api/upload';
|
||||
|
||||
// try {
|
||||
Log.info('Starting upload from ${media.mediaFile.mediaId}');
|
||||
|
||||
final headers = await getAuthenticationHeader();
|
||||
if (headers == null) {
|
||||
Log.error('Auth headers are empty. Returning');
|
||||
return;
|
||||
}
|
||||
|
||||
final task = UploadTask.fromFile(
|
||||
taskId: 'upload_${media.mediaFile.mediaId}',
|
||||
displayName: media.mediaFile.type.name,
|
||||
|
|
@ -643,9 +635,7 @@ Future<void> _uploadUploadRequest(MediaFileService media) async {
|
|||
url: apiUrl,
|
||||
priority: 0,
|
||||
retries: 10,
|
||||
headers: {
|
||||
'x-twonly-auth-token': apiAuthToken,
|
||||
},
|
||||
headers: headers,
|
||||
);
|
||||
|
||||
final connectivityResult = await Connectivity().checkConnectivity();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:fixnum/fixnum.dart';
|
||||
import 'package:twonly/core/bridge/wrapper/key_manager.dart';
|
||||
import 'package:twonly/locator.dart';
|
||||
import 'package:twonly/src/constants/secure_storage.keys.dart';
|
||||
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||
import 'package:twonly/src/database/twonly.db.dart';
|
||||
import 'package:twonly/src/model/protobuf/api/websocket/client_to_server.pb.dart'
|
||||
|
|
@ -14,6 +18,9 @@ import 'package:twonly/src/model/protobuf/client/generated/messages.pbserver.dar
|
|||
import 'package:twonly/src/services/api/messages.api.dart';
|
||||
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
||||
import 'package:twonly/src/services/signal/session.signal.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:twonly/src/utils/secure_storage.dart';
|
||||
|
||||
class Result<T, E> {
|
||||
Result.error(this.error) : value = null;
|
||||
|
|
@ -106,3 +113,36 @@ Future<bool> importSignalContactAndCreateRequest(
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<Map<String, String>?> getAuthenticationHeader() async {
|
||||
var headers = <String, String>{};
|
||||
|
||||
if (userService.currentUser.canUseLoginTokenForAuth) {
|
||||
final loginToken = await FlutterKeyManager.getLoginToken();
|
||||
|
||||
headers = {
|
||||
'x-twonly-user-id': userService.currentUser.userId
|
||||
.toRadixString(16)
|
||||
.padLeft(16, '0')
|
||||
.toUpperCase(),
|
||||
'x-twonly-login-token': uint8ListToHex(loginToken),
|
||||
};
|
||||
} else {
|
||||
final apiAuthTokenRaw = await SecureStorage.instance.read(
|
||||
key: SecureStorageKeys.apiAuthToken,
|
||||
);
|
||||
|
||||
if (apiAuthTokenRaw == null) {
|
||||
Log.error('api auth token not defined.');
|
||||
return null;
|
||||
}
|
||||
|
||||
final apiAuthToken = uint8ListToHex(base64Decode(apiAuthTokenRaw));
|
||||
|
||||
headers = {
|
||||
'x-twonly-auth-token': apiAuthToken,
|
||||
};
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ Future<void> initializeBackgroundTaskManager() async {
|
|||
void callbackDispatcher() {
|
||||
Workmanager().executeTask((task, inputData) async {
|
||||
SentryWidgetsFlutterBinding.ensureInitialized();
|
||||
await AppEnvironment.init();
|
||||
switch (task) {
|
||||
case 'eu.twonly.periodic_task':
|
||||
// if (await initBackgroundExecution()) {
|
||||
|
|
@ -58,7 +59,6 @@ Future<bool> initBackgroundExecution() async {
|
|||
return false;
|
||||
}
|
||||
|
||||
await AppEnvironment.init();
|
||||
AppState.isInBackgroundTask = true;
|
||||
|
||||
if (await StartupGuard.isAppStarting()) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import 'dart:math';
|
|||
import 'package:cryptography_flutter_plus/cryptography_flutter_plus.dart';
|
||||
import 'package:cryptography_plus/cryptography_plus.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/constants/routes.keys.dart';
|
||||
import 'package:twonly/src/constants/secure_storage.keys.dart';
|
||||
import 'package:twonly/src/localization/generated/app_localizations.dart';
|
||||
|
|
@ -266,8 +266,7 @@ Future<void> showLocalPushNotificationWithoutUserId(
|
|||
}
|
||||
|
||||
Future<String?> getAvatarIcon(int contactId) async {
|
||||
final directory = await getApplicationCacheDirectory();
|
||||
final avatarsDirectory = Directory('${directory.path}/avatars');
|
||||
final avatarsDirectory = Directory('${AppEnvironment.cacheDir}/avatars');
|
||||
final filePath = '${avatarsDirectory.path}/$contactId.png';
|
||||
final file = File(filePath);
|
||||
if (file.existsSync()) {
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ Future<void> initFCMService() async {
|
|||
@pragma('vm:entry-point')
|
||||
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||
SentryWidgetsFlutterBinding.ensureInitialized();
|
||||
await AppEnvironment.init();
|
||||
final isInitialized = await initBackgroundExecution();
|
||||
Log.info('Handling a background message: ${message.messageId}');
|
||||
await handleRemoteMessage(message);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import 'dart:io';
|
|||
import 'package:clock/clock.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
|
||||
class Sticker {
|
||||
|
|
@ -21,8 +21,7 @@ class Sticker {
|
|||
}
|
||||
|
||||
Future<List<Sticker>> getStickerIndex() async {
|
||||
final directory = await getApplicationCacheDirectory();
|
||||
final indexFile = File('${directory.path}/stickers.json');
|
||||
final indexFile = File('${AppEnvironment.cacheDir}/stickers.json');
|
||||
var res = <Sticker>[];
|
||||
|
||||
if (indexFile.existsSync() && kReleaseMode) {
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import 'package:emoji_picker_flutter/emoji_picker_flutter.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/locator.dart';
|
||||
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||
import 'package:twonly/src/database/twonly.db.dart';
|
||||
|
|
@ -131,8 +131,7 @@ class _MessageInputState extends State<MessageInput> {
|
|||
_currentDuration = 0;
|
||||
});
|
||||
await HapticFeedback.heavyImpact();
|
||||
final audioTmpPath =
|
||||
'${(await getApplicationCacheDirectory()).path}/recording.m4a';
|
||||
final audioTmpPath = '${AppEnvironment.cacheDir}/recording.m4a';
|
||||
unawaited(
|
||||
recorderController.record(
|
||||
path: audioTmpPath,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:fixnum/fixnum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -11,6 +9,7 @@ import 'package:twonly/locator.dart';
|
|||
import 'package:twonly/src/constants/routes.keys.dart';
|
||||
import 'package:twonly/src/constants/secure_storage.keys.dart';
|
||||
import 'package:twonly/src/model/protobuf/api/http/http_requests.pb.dart';
|
||||
import 'package:twonly/src/services/api/utils.api.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:twonly/src/utils/secure_storage.dart';
|
||||
|
|
@ -57,16 +56,18 @@ class _ContactUsState extends State<ContactUsView> {
|
|||
Log.error('api auth token not defined.');
|
||||
return null;
|
||||
}
|
||||
final apiAuthToken = uint8ListToHex(base64Decode(apiAuthTokenRaw));
|
||||
|
||||
final apiUrl =
|
||||
'http${apiService.apiSecure}://${apiService.apiHost}/api/upload';
|
||||
|
||||
final requestMultipart = http.MultipartRequest(
|
||||
'POST',
|
||||
Uri.parse(apiUrl),
|
||||
);
|
||||
requestMultipart.headers['x-twonly-auth-token'] = apiAuthToken;
|
||||
final requestMultipart = http.MultipartRequest('POST', Uri.parse(apiUrl));
|
||||
|
||||
final headers = await getAuthenticationHeader();
|
||||
if (headers == null) {
|
||||
Log.error('Auth headers are empty. Returning');
|
||||
return null;
|
||||
}
|
||||
|
||||
requestMultipart.headers.addAll(headers);
|
||||
|
||||
requestMultipart.files.add(
|
||||
http.MultipartFile.fromBytes(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
use crate::error::{Result, TwonlyError};
|
||||
use crate::keys::KeyManager;
|
||||
use crate::secure_storage::{self, SecureStorage};
|
||||
use aes_gcm::aead::rand_core::RngCore;
|
||||
use aes_gcm::aead::{Aead, KeyInit, OsRng};
|
||||
use aes_gcm::{Aes256Gcm, Nonce};
|
||||
use mdk_core::key_packages;
|
||||
use scrypt::{scrypt, Params};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
|
@ -21,11 +23,16 @@ impl BackupPasswordKeys {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_password(password: &str, salt: &str) -> Result<Self> {
|
||||
pub(crate) fn from_password(password: &str, username: &str) -> Result<Self> {
|
||||
let params = Params::new(17, 8, 1)?;
|
||||
let mut output = [0u8; 64];
|
||||
|
||||
scrypt(password.as_bytes(), salt.as_bytes(), ¶ms, &mut output)?;
|
||||
scrypt(
|
||||
password.as_bytes(),
|
||||
username.as_bytes(),
|
||||
¶ms,
|
||||
&mut output,
|
||||
)?;
|
||||
|
||||
let mut backup_id = [0u8; 32];
|
||||
let mut encryption_key = [0u8; 32];
|
||||
|
|
@ -34,21 +41,13 @@ impl BackupPasswordKeys {
|
|||
|
||||
Ok(Self::new(backup_id, encryption_key))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Zeroize, ZeroizeOnDrop, Serialize, Deserialize)]
|
||||
pub(crate) struct BackupPlainTextContent {
|
||||
pub(crate) user_id: i64,
|
||||
pub(crate) key_manager: KeyManager,
|
||||
}
|
||||
|
||||
impl BackupPlainTextContent {
|
||||
fn get_encrypted_backup(&self) -> Result<Vec<u8>> {
|
||||
let Some(keys) = &self.key_manager.backup_password else {
|
||||
fn encrypt_key_manager(key_manager: KeyManager) -> Result<Vec<u8>> {
|
||||
let Some(keys) = &key_manager.backup_password else {
|
||||
return Err(TwonlyError::Generic("No backup password".into()));
|
||||
};
|
||||
|
||||
let serialized_bytes = postcard::to_allocvec(&self)?;
|
||||
let serialized_bytes = postcard::to_allocvec(&key_manager)?;
|
||||
|
||||
let key = aes_gcm::Key::<Aes256Gcm>::from_slice(&keys.encryption_key);
|
||||
let cipher = Aes256Gcm::new(key);
|
||||
|
|
@ -66,10 +65,11 @@ impl BackupPlainTextContent {
|
|||
Ok(encrypted_bytes)
|
||||
}
|
||||
|
||||
pub(crate) fn from_encrypted_backup(
|
||||
pub(crate) fn restore_key_manager(
|
||||
secure_storage: SecureStorage,
|
||||
encrypted_bytes: &[u8],
|
||||
keys: &BackupPasswordKeys,
|
||||
) -> Result<Self> {
|
||||
) -> Result<()> {
|
||||
if encrypted_bytes.len() < 12 {
|
||||
return Err(TwonlyError::Generic(
|
||||
"Invalid encrypted backup length".into(),
|
||||
|
|
@ -84,10 +84,22 @@ impl BackupPlainTextContent {
|
|||
|
||||
let decrypted_bytes = cipher.decrypt(nonce, ciphertext)?;
|
||||
|
||||
Ok(postcard::from_bytes(&decrypted_bytes)?)
|
||||
let key_manager: KeyManager = postcard::from_bytes(&decrypted_bytes)?;
|
||||
|
||||
key_manager.store_to_keychain(&secure_storage)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Zeroize, ZeroizeOnDrop, Serialize, Deserialize)]
|
||||
pub(crate) struct BackupPlainTextContent {
|
||||
pub(crate) user_id: i64,
|
||||
pub(crate) key_manager: KeyManager,
|
||||
}
|
||||
|
||||
impl BackupPlainTextContent {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
|||
12
rust/src/bridge/wrapper/key_manager.rs
Normal file
12
rust/src/bridge/wrapper/key_manager.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
use crate::error::Result;
|
||||
use crate::{bridge::get_twonly_flutter, keys::KeyManager};
|
||||
|
||||
pub struct FlutterKeyManager {}
|
||||
|
||||
impl FlutterKeyManager {
|
||||
pub async fn get_login_token() -> Result<Vec<u8>> {
|
||||
let ctx = get_twonly_flutter()?;
|
||||
let key_manager = KeyManager::try_from_keychain(&ctx.secure_storage)?;
|
||||
Ok(key_manager.main_key.get_login_token().to_vec())
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1,2 @@
|
|||
pub mod key_manager;
|
||||
pub mod user_discovery;
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ impl Context {
|
|||
Err(err) => {
|
||||
tracing::error!("{err}");
|
||||
if rust_db_path.exists() {
|
||||
tracing::error!("Rust Database exsist, while the key manager not. This must be a secure storage error.");
|
||||
tracing::error!("Rust Database exists, while the key manager not. This must be a secure storage error.");
|
||||
return Err(TwonlyError::SecureStorageError);
|
||||
}
|
||||
tracing::info!("Generating a new key manager.");
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ flutter_rust_bridge::frb_generated_boilerplate!(
|
|||
default_rust_auto_opaque = RustAutoOpaqueMoi,
|
||||
);
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0";
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1680338106;
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1007286393;
|
||||
|
||||
// Section: executor
|
||||
|
||||
|
|
@ -46,6 +46,21 @@ flutter_rust_bridge::frb_generated_default_handler!();
|
|||
|
||||
// Section: wire_funcs
|
||||
|
||||
fn wire__crate__bridge__wrapper__key_manager__flutter_key_manager_get_login_token_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
|
||||
rust_vec_len_: i32,
|
||||
data_len_: i32,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec,_,_,_>(flutter_rust_bridge::for_generated::TaskInfo{ debug_name: "flutter_key_manager_get_login_token", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal }, move || {
|
||||
let message = unsafe { flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_, rust_vec_len_, data_len_) };
|
||||
let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message);
|
||||
deserializer.end(); move |context| async move {
|
||||
transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>((move || async move {
|
||||
let output_ok = crate::bridge::wrapper::key_manager::FlutterKeyManager::get_login_token().await?; Ok(output_ok)
|
||||
})().await)
|
||||
} })
|
||||
}
|
||||
fn wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_get_current_version_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
|
||||
|
|
@ -729,6 +744,13 @@ impl SseDecode for bool {
|
|||
}
|
||||
}
|
||||
|
||||
impl SseDecode for crate::bridge::wrapper::key_manager::FlutterKeyManager {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||
return crate::bridge::wrapper::key_manager::FlutterKeyManager {};
|
||||
}
|
||||
}
|
||||
|
||||
impl SseDecode for crate::bridge::wrapper::user_discovery::FlutterUserDiscovery {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||
|
|
@ -917,14 +939,15 @@ fn pde_ffi_dispatcher_primary_impl(
|
|||
) {
|
||||
// Codec=Pde (Serialization + dispatch), see doc to use other codecs
|
||||
match func_id {
|
||||
1 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_get_current_version_impl(port, ptr, rust_vec_len, data_len),
|
||||
2 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_get_new_messages_impl(port, ptr, rust_vec_len, data_len),
|
||||
3 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_handle_new_messages_impl(port, ptr, rust_vec_len, data_len),
|
||||
4 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_initialize_or_update_impl(port, ptr, rust_vec_len, data_len),
|
||||
5 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_should_request_new_messages_impl(port, ptr, rust_vec_len, data_len),
|
||||
6 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_update_verification_state_for_user_impl(port, ptr, rust_vec_len, data_len),
|
||||
7 => wire__crate__bridge__callbacks__init_flutter_callbacks_impl(port, ptr, rust_vec_len, data_len),
|
||||
8 => wire__crate__bridge__initialize_twonly_flutter_impl(port, ptr, rust_vec_len, data_len),
|
||||
1 => wire__crate__bridge__wrapper__key_manager__flutter_key_manager_get_login_token_impl(port, ptr, rust_vec_len, data_len),
|
||||
2 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_get_current_version_impl(port, ptr, rust_vec_len, data_len),
|
||||
3 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_get_new_messages_impl(port, ptr, rust_vec_len, data_len),
|
||||
4 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_handle_new_messages_impl(port, ptr, rust_vec_len, data_len),
|
||||
5 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_initialize_or_update_impl(port, ptr, rust_vec_len, data_len),
|
||||
6 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_should_request_new_messages_impl(port, ptr, rust_vec_len, data_len),
|
||||
7 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_update_verification_state_for_user_impl(port, ptr, rust_vec_len, data_len),
|
||||
8 => wire__crate__bridge__callbacks__init_flutter_callbacks_impl(port, ptr, rust_vec_len, data_len),
|
||||
9 => wire__crate__bridge__initialize_twonly_flutter_impl(port, ptr, rust_vec_len, data_len),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -966,6 +989,23 @@ impl flutter_rust_bridge::IntoIntoDart<FrbWrapper<crate::bridge::AnnouncedUser>>
|
|||
}
|
||||
}
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
impl flutter_rust_bridge::IntoDart for crate::bridge::wrapper::key_manager::FlutterKeyManager {
|
||||
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
|
||||
Vec::<u8>::new().into_dart()
|
||||
}
|
||||
}
|
||||
impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive
|
||||
for crate::bridge::wrapper::key_manager::FlutterKeyManager
|
||||
{
|
||||
}
|
||||
impl flutter_rust_bridge::IntoIntoDart<crate::bridge::wrapper::key_manager::FlutterKeyManager>
|
||||
for crate::bridge::wrapper::key_manager::FlutterKeyManager
|
||||
{
|
||||
fn into_into_dart(self) -> crate::bridge::wrapper::key_manager::FlutterKeyManager {
|
||||
self
|
||||
}
|
||||
}
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
impl flutter_rust_bridge::IntoDart
|
||||
for crate::bridge::wrapper::user_discovery::FlutterUserDiscovery
|
||||
{
|
||||
|
|
@ -1073,6 +1113,11 @@ impl SseEncode for bool {
|
|||
}
|
||||
}
|
||||
|
||||
impl SseEncode for crate::bridge::wrapper::key_manager::FlutterKeyManager {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {}
|
||||
}
|
||||
|
||||
impl SseEncode for crate::bridge::wrapper::user_discovery::FlutterUserDiscovery {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {}
|
||||
|
|
|
|||
|
|
@ -40,12 +40,12 @@ impl MainKey {
|
|||
/// Download token required to download a backup.
|
||||
/// This ensures that the user who tries to download the backup must have knowledge over the
|
||||
/// main key
|
||||
pub fn backup_download_token(&self) -> [u8; 32] {
|
||||
pub fn get_backup_download_token(&self) -> [u8; 32] {
|
||||
self.derive_key(b"backup_download_token")
|
||||
}
|
||||
|
||||
/// Uses as a password to authenitcate agains the server
|
||||
pub fn server_auth_token(&self) -> [u8; 32] {
|
||||
pub fn get_login_token(&self) -> [u8; 32] {
|
||||
self.derive_key(b"server_auth_token")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use crate::error::TwonlyError;
|
|||
pub(crate) use crate::keys::identity_key::IdentityKey;
|
||||
pub(crate) use crate::keys::main_key::{DatabaseKey, MainKey};
|
||||
use crate::secure_storage::SecureStorage;
|
||||
use aes_gcm::Aes256Gcm;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
|
|
@ -14,6 +15,7 @@ const KEY_MANAGER_ID: &str = "twonly_key_manager";
|
|||
|
||||
#[derive(Debug, PartialEq, Zeroize, ZeroizeOnDrop, Serialize, Deserialize)]
|
||||
pub(crate) struct KeyManager {
|
||||
pub(crate) user_id: Option<i64>,
|
||||
pub(crate) main_key: MainKey,
|
||||
pub(crate) identity_keys: Vec<IdentityKey>,
|
||||
pub(crate) backup_password: Option<BackupPasswordKeys>,
|
||||
|
|
@ -25,6 +27,7 @@ impl KeyManager {
|
|||
main_key: MainKey::generate(),
|
||||
identity_keys: vec![],
|
||||
backup_password: None,
|
||||
user_id: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue