mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2024-11-10 19:03:12 +00:00
feat: Allow skipping the server provider token when recovering
This commit is contained in:
parent
894d23bb7c
commit
8fe0de0c9e
|
@ -138,7 +138,8 @@
|
|||
"cpu_title": "CPU Usage",
|
||||
"network_title": "Network Usage",
|
||||
"in": "In",
|
||||
"out": "Out"
|
||||
"out": "Out",
|
||||
"unsupported": "You can't view resource usage charts without the server provider token."
|
||||
},
|
||||
"server": {
|
||||
"card_title": "Server",
|
||||
|
@ -511,6 +512,9 @@
|
|||
"provider_connected": "Connect to {}",
|
||||
"provider_connected_description": "Enter your token with access to {}:",
|
||||
"provider_connected_placeholder": "{} token",
|
||||
"login_later": "Log in later",
|
||||
"server_provider_unknown": "Unknown server provider",
|
||||
"server_provider_unknown_description": "Your server provider is not recognized. You can continue without entering its API token.",
|
||||
"confirm_server": "Confirm server",
|
||||
"confirm_server_description": "Found your server! Confirm it is the right one:",
|
||||
"confirm_server_accept": "Yes! That's it",
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/generic_result.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_status.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
|
@ -74,7 +75,7 @@ class VolumesBloc extends Bloc<VolumesEvent, VolumesState> {
|
|||
bool isLoaded = false;
|
||||
|
||||
Future<Price?> getPricePerGb() async {
|
||||
if (ProvidersController.currentServerProvider == null) {
|
||||
if (!(ProvidersController.currentServerProvider?.isAuthorized ?? false)) {
|
||||
return null;
|
||||
}
|
||||
Price? price;
|
||||
|
@ -92,33 +93,36 @@ class VolumesBloc extends Bloc<VolumesEvent, VolumesState> {
|
|||
final VolumesServerLoaded event,
|
||||
final Emitter<VolumesState> emit,
|
||||
) async {
|
||||
if (ProvidersController.currentServerProvider == null) {
|
||||
if (getIt<ApiConnectionRepository>().currentConnectionStatus ==
|
||||
ConnectionStatus.nonexistent) {
|
||||
return;
|
||||
}
|
||||
|
||||
emit(VolumesLoading());
|
||||
|
||||
final volumesResult =
|
||||
await ProvidersController.currentServerProvider!.getVolumes();
|
||||
late final GenericResult<List<ServerProviderVolume>>? volumesResult;
|
||||
|
||||
if (!volumesResult.success || volumesResult.data.isEmpty) {
|
||||
emit(VolumesInitial());
|
||||
return;
|
||||
if (ProvidersController.currentServerProvider?.isAuthorized ?? false) {
|
||||
volumesResult =
|
||||
await ProvidersController.currentServerProvider?.getVolumes();
|
||||
} else {
|
||||
volumesResult = null;
|
||||
}
|
||||
|
||||
final serverVolumes = getIt<ApiConnectionRepository>().apiData.volumes.data;
|
||||
|
||||
if (serverVolumes == null) {
|
||||
if (serverVolumes == null &&
|
||||
volumesResult != null &&
|
||||
volumesResult.data.isNotEmpty) {
|
||||
emit(VolumesLoading(providerVolumes: volumesResult.data));
|
||||
return;
|
||||
} else {
|
||||
} else if (serverVolumes != null) {
|
||||
emit(
|
||||
VolumesLoaded(
|
||||
diskStatus: DiskStatus.fromVolumes(
|
||||
serverVolumes,
|
||||
volumesResult.data,
|
||||
volumesResult?.data ?? [],
|
||||
),
|
||||
providerVolumes: volumesResult.data,
|
||||
providerVolumes: volumesResult?.data ?? [],
|
||||
serverVolumesHashCode: Object.hashAll(serverVolumes),
|
||||
),
|
||||
);
|
||||
|
@ -186,6 +190,9 @@ class VolumesBloc extends Bloc<VolumesEvent, VolumesState> {
|
|||
if (state is! VolumesLoaded) {
|
||||
return;
|
||||
}
|
||||
if (ProvidersController.currentServerProvider?.isAuthorized ?? false) {
|
||||
return;
|
||||
}
|
||||
getIt<NavigationService>().showSnackBar(
|
||||
'storage.extending_volume_started'.tr(),
|
||||
);
|
||||
|
|
|
@ -52,6 +52,8 @@ class MetricsCubit extends Cubit<MetricsState> {
|
|||
Duration(seconds: state.period.stepPeriodInSeconds),
|
||||
() => load(state.period),
|
||||
);
|
||||
} on MetricsUnsupportedException {
|
||||
emit(MetricsUnsupported(period));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,15 @@ class MetricsLoadException implements Exception {
|
|||
final String message;
|
||||
}
|
||||
|
||||
class MetricsUnsupportedException implements Exception {
|
||||
MetricsUnsupportedException(this.message);
|
||||
final String message;
|
||||
}
|
||||
|
||||
class MetricsRepository {
|
||||
Future<MetricsLoaded> getMetrics(final Period period) async {
|
||||
if (ProvidersController.currentServerProvider == null) {
|
||||
throw MetricsLoadException('Server Provider data is null');
|
||||
if (!(ProvidersController.currentServerProvider?.isAuthorized ?? false)) {
|
||||
throw MetricsUnsupportedException('Server Provider data is null');
|
||||
}
|
||||
|
||||
final DateTime end = DateTime.now();
|
||||
|
|
|
@ -29,3 +29,12 @@ class MetricsLoaded extends MetricsState {
|
|||
@override
|
||||
List<Object?> get props => [period, metrics];
|
||||
}
|
||||
|
||||
class MetricsUnsupported extends MetricsState {
|
||||
const MetricsUnsupported(this.period);
|
||||
@override
|
||||
final Period period;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [period];
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:selfprivacy/config/get_it_config.dart';
|
|||
import 'package:selfprivacy/logic/cubit/server_connection_dependent/server_connection_dependent_cubit.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server.dart';
|
||||
import 'package:selfprivacy/logic/models/server_metadata.dart';
|
||||
import 'package:selfprivacy/logic/models/ssh_settings.dart';
|
||||
import 'package:selfprivacy/logic/models/system_settings.dart';
|
||||
|
@ -36,47 +37,63 @@ class ServerDetailsCubit
|
|||
sshSettings: settings.sshSettings,
|
||||
),
|
||||
);
|
||||
if (state.metadata.isEmpty) {
|
||||
check();
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<ServerMetadataEntity>> get _metadata async {
|
||||
List<ServerMetadataEntity> data = [];
|
||||
final List<ServerMetadataEntity> data = [];
|
||||
|
||||
final serverProviderApi = ProvidersController.currentServerProvider;
|
||||
final dnsProviderApi = ProvidersController.currentDnsProvider;
|
||||
if (serverProviderApi != null && dnsProviderApi != null) {
|
||||
if (serverProviderApi?.isAuthorized ?? false) {
|
||||
final serverId = getIt<ResourcesModel>().serverDetails?.id ?? 0;
|
||||
final metadataResult = await serverProviderApi.getMetadata(serverId);
|
||||
metadataResult.data.add(
|
||||
final metadataResult = await serverProviderApi?.getMetadata(serverId);
|
||||
|
||||
data.addAll(metadataResult?.data ?? []);
|
||||
}
|
||||
|
||||
if (serverProviderApi == null || !serverProviderApi.isAuthorized) {
|
||||
final Server server = getIt<ResourcesModel>().servers.first;
|
||||
data.add(
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.other,
|
||||
trId: 'server.server_provider',
|
||||
value: server.hostingDetails.provider.displayName,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (dnsProviderApi != null && dnsProviderApi.isAuthorized) {
|
||||
data.add(
|
||||
ServerMetadataEntity(
|
||||
trId: 'server.dns_provider',
|
||||
value: dnsProviderApi.type.displayName,
|
||||
type: MetadataType.other,
|
||||
),
|
||||
);
|
||||
|
||||
data = metadataResult.data;
|
||||
} else {
|
||||
final Server server = getIt<ResourcesModel>().servers.first;
|
||||
data.add(
|
||||
ServerMetadataEntity(
|
||||
trId: 'server.dns_provider',
|
||||
value: server.domain.provider.displayName,
|
||||
type: MetadataType.other,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void check() async {
|
||||
final bool isReadyToCheck = getIt<ResourcesModel>().serverDetails != null;
|
||||
try {
|
||||
if (isReadyToCheck) {
|
||||
emit(const ServerDetailsLoading());
|
||||
final List<ServerMetadataEntity> metadata = await _metadata;
|
||||
emit(
|
||||
state.copyWith(
|
||||
metadata: metadata,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
emit(const ServerDetailsNotReady());
|
||||
}
|
||||
} on StateError {
|
||||
print('Tried to emit server info state when cubit is closed');
|
||||
}
|
||||
final List<ServerMetadataEntity> metadata = await _metadata;
|
||||
emit(
|
||||
state.copyWith(
|
||||
metadata: metadata,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -85,9 +102,7 @@ class ServerDetailsCubit
|
|||
}
|
||||
|
||||
@override
|
||||
void load() async {
|
||||
check();
|
||||
}
|
||||
void load() async {}
|
||||
|
||||
@override
|
||||
Future<void> close() {
|
||||
|
|
|
@ -552,6 +552,34 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
);
|
||||
}
|
||||
|
||||
void selectRecoveryMethod(final ServerRecoveryMethods method) {
|
||||
final ServerInstallationRecovery dataState =
|
||||
state as ServerInstallationRecovery;
|
||||
switch (method) {
|
||||
case ServerRecoveryMethods.newDeviceKey:
|
||||
emit(
|
||||
dataState.copyWith(
|
||||
currentStep: RecoveryStep.newDeviceKey,
|
||||
),
|
||||
);
|
||||
break;
|
||||
case ServerRecoveryMethods.recoveryKey:
|
||||
emit(
|
||||
dataState.copyWith(
|
||||
currentStep: RecoveryStep.recoveryKey,
|
||||
),
|
||||
);
|
||||
break;
|
||||
case ServerRecoveryMethods.oldToken:
|
||||
emit(
|
||||
dataState.copyWith(
|
||||
currentStep: RecoveryStep.oldToken,
|
||||
),
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void tryToRecover(
|
||||
final String token,
|
||||
final ServerRecoveryMethods method,
|
||||
|
@ -596,8 +624,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
isWithToken: true,
|
||||
overrideDomain: serverDomain.domainName,
|
||||
).getDnsProviderType();
|
||||
if (serverProvider == ServerProviderType.unknown ||
|
||||
dnsProvider == DnsProviderType.unknown) {
|
||||
if (dnsProvider == DnsProviderType.unknown) {
|
||||
getIt<NavigationService>()
|
||||
.showSnackBar('recovering.generic_error'.tr());
|
||||
return;
|
||||
|
@ -672,32 +699,13 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
}
|
||||
}
|
||||
|
||||
void selectRecoveryMethod(final ServerRecoveryMethods method) {
|
||||
final ServerInstallationRecovery dataState =
|
||||
state as ServerInstallationRecovery;
|
||||
switch (method) {
|
||||
case ServerRecoveryMethods.newDeviceKey:
|
||||
emit(
|
||||
dataState.copyWith(
|
||||
currentStep: RecoveryStep.newDeviceKey,
|
||||
),
|
||||
);
|
||||
break;
|
||||
case ServerRecoveryMethods.recoveryKey:
|
||||
emit(
|
||||
dataState.copyWith(
|
||||
currentStep: RecoveryStep.recoveryKey,
|
||||
),
|
||||
);
|
||||
break;
|
||||
case ServerRecoveryMethods.oldToken:
|
||||
emit(
|
||||
dataState.copyWith(
|
||||
currentStep: RecoveryStep.oldToken,
|
||||
),
|
||||
);
|
||||
break;
|
||||
}
|
||||
Future<void> skipSettingServerProviderKey() async {
|
||||
emit(
|
||||
(state as ServerInstallationRecovery).copyWith(
|
||||
providerApiToken: null,
|
||||
currentStep: RecoveryStep.dnsProviderToken,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<ServerBasicInfoWithValidators>> getAvailableServers() async {
|
||||
|
@ -747,7 +755,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
linuxDevice: '',
|
||||
),
|
||||
apiToken: dataState.serverDetails!.apiToken,
|
||||
provider: ServerProviderType.hetzner,
|
||||
provider: dataState.serverDetails!.provider,
|
||||
);
|
||||
await repository.saveDomain(serverDomain);
|
||||
await repository.saveServerDetails(serverDetails);
|
||||
|
@ -804,16 +812,23 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
await repository.saveIsServerRebootedFirstTime(true);
|
||||
await repository.saveIsServerRebootedSecondTime(true);
|
||||
await repository.saveIsRecoveringServer(false);
|
||||
final serverType = await ProvidersController.currentServerProvider!
|
||||
.getServerType(state.serverDetails!.id);
|
||||
await repository.saveServerType(serverType.data!);
|
||||
await ProvidersController.currentServerProvider!
|
||||
.trySetServerLocation(serverType.data!.location.identifier);
|
||||
late final GenericResult<ServerType?>? serverType;
|
||||
if (ProvidersController.currentServerProvider?.isAuthorized ?? false) {
|
||||
serverType = await ProvidersController.currentServerProvider
|
||||
?.getServerType(state.serverDetails!.id);
|
||||
if (serverType != null) {
|
||||
await repository.saveServerType(serverType.data!);
|
||||
await ProvidersController.currentServerProvider!
|
||||
.trySetServerLocation(serverType.data!.location.identifier);
|
||||
}
|
||||
} else {
|
||||
serverType = null;
|
||||
}
|
||||
await repository.saveHasFinalChecked(true);
|
||||
final ServerInstallationRecovery updatedState =
|
||||
(state as ServerInstallationRecovery).copyWith(
|
||||
backblazeCredential: backblazeCredential,
|
||||
serverTypeIdentificator: serverType.data!.identifier,
|
||||
serverTypeIdentificator: serverType?.data?.identifier,
|
||||
);
|
||||
emit(updatedState.finish());
|
||||
getIt<ApiConnectionRepository>().init();
|
||||
|
|
|
@ -95,8 +95,8 @@ class ServerInstallationRepository {
|
|||
// We have a server set up, so we load it
|
||||
TlsOptions.verifyCertificate = true;
|
||||
return ServerInstallationFinished(
|
||||
providerApiToken: providerApiToken!,
|
||||
serverTypeIdentificator: serverTypeIdentificator!,
|
||||
providerApiToken: providerApiToken,
|
||||
serverTypeIdentificator: serverTypeIdentificator,
|
||||
dnsApiToken: dnsApiToken!,
|
||||
serverDomain: serverDomain!,
|
||||
backblazeCredential: backblazeCredential!,
|
||||
|
@ -105,6 +105,30 @@ class ServerInstallationRepository {
|
|||
}
|
||||
}
|
||||
|
||||
// If wizard data has info on the providers, init them
|
||||
if (wizardData.serverProviderType != null &&
|
||||
wizardData.serverProviderType != ServerProviderType.unknown) {
|
||||
ProvidersController.initServerProvider(
|
||||
ServerProviderSettings(
|
||||
provider: wizardData.serverProviderType!,
|
||||
isAuthorized: wizardData.serverProviderKey != null,
|
||||
location: wizardData.serverLocation,
|
||||
token: wizardData.serverProviderKey,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (wizardData.dnsProviderType != null &&
|
||||
wizardData.dnsProviderType != DnsProviderType.unknown) {
|
||||
ProvidersController.initDnsProvider(
|
||||
DnsProviderSettings(
|
||||
provider: wizardData.dnsProviderType!,
|
||||
isAuthorized: wizardData.dnsProviderKey != null,
|
||||
token: wizardData.dnsProviderKey,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (wizardData.isRecoveringServer && wizardData.serverDomain != null) {
|
||||
return ServerInstallationRecovery(
|
||||
providerApiToken: wizardData.serverProviderKey,
|
||||
|
@ -548,17 +572,23 @@ class ServerInstallationRepository {
|
|||
domain: wizardData.serverDomain!,
|
||||
),
|
||||
);
|
||||
await getIt<ResourcesModel>().associateServerWithToken(
|
||||
wizardData.serverDetails!.id,
|
||||
wizardData.serverProviderKey!,
|
||||
);
|
||||
await getIt<ResourcesModel>().associateDomainWithToken(
|
||||
wizardData.serverDomain!.domainName,
|
||||
wizardData.dnsProviderKey!,
|
||||
);
|
||||
await getIt<ResourcesModel>().addBackupsCredential(
|
||||
wizardData.backupsCredential!,
|
||||
);
|
||||
if (wizardData.serverProviderKey != null) {
|
||||
await getIt<ResourcesModel>().associateServerWithToken(
|
||||
wizardData.serverDetails!.id,
|
||||
wizardData.serverProviderKey!,
|
||||
);
|
||||
}
|
||||
if (wizardData.dnsProviderKey != null) {
|
||||
await getIt<ResourcesModel>().associateDomainWithToken(
|
||||
wizardData.serverDomain!.domainName,
|
||||
wizardData.dnsProviderKey!,
|
||||
);
|
||||
}
|
||||
if (wizardData.backupsCredential != null) {
|
||||
await getIt<ResourcesModel>().addBackupsCredential(
|
||||
wizardData.backupsCredential!,
|
||||
);
|
||||
}
|
||||
await getIt<WizardDataModel>().clearServerInstallation();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -226,8 +226,8 @@ class ServerInstallationNotFinished extends ServerInstallationState {
|
|||
);
|
||||
|
||||
ServerInstallationFinished finish() => ServerInstallationFinished(
|
||||
providerApiToken: providerApiToken!,
|
||||
serverTypeIdentificator: serverTypeIdentificator!,
|
||||
providerApiToken: providerApiToken,
|
||||
serverTypeIdentificator: serverTypeIdentificator,
|
||||
dnsApiToken: dnsApiToken!,
|
||||
backblazeCredential: backblazeCredential!,
|
||||
serverDomain: serverDomain!,
|
||||
|
@ -257,12 +257,12 @@ class ServerInstallationEmpty extends ServerInstallationNotFinished {
|
|||
|
||||
class ServerInstallationFinished extends ServerInstallationState {
|
||||
const ServerInstallationFinished({
|
||||
required String super.providerApiToken,
|
||||
required String super.serverTypeIdentificator,
|
||||
required String super.dnsApiToken,
|
||||
required BackupsCredential super.backblazeCredential,
|
||||
required ServerDomain super.serverDomain,
|
||||
required ServerHostingDetails super.serverDetails,
|
||||
super.providerApiToken,
|
||||
super.serverTypeIdentificator,
|
||||
}) : super(
|
||||
rootUser: null,
|
||||
isServerStarted: true,
|
||||
|
@ -367,8 +367,8 @@ class ServerInstallationRecovery extends ServerInstallationState {
|
|||
);
|
||||
|
||||
ServerInstallationFinished finish() => ServerInstallationFinished(
|
||||
providerApiToken: providerApiToken!,
|
||||
serverTypeIdentificator: serverTypeIdentificator!,
|
||||
providerApiToken: providerApiToken,
|
||||
serverTypeIdentificator: serverTypeIdentificator,
|
||||
dnsApiToken: dnsApiToken!,
|
||||
backblazeCredential: backblazeCredential!,
|
||||
serverDomain: serverDomain!,
|
||||
|
|
|
@ -320,20 +320,20 @@ class ApiConnectionRepository {
|
|||
await _apiData.serverJobs
|
||||
.refetchData(version, () => _dataStream.add(_apiData));
|
||||
}
|
||||
await _apiData.backups
|
||||
.refetchData(version, () => _dataStream.add(_apiData));
|
||||
await _apiData.backupConfig
|
||||
.refetchData(version, () => _dataStream.add(_apiData));
|
||||
await _apiData.services
|
||||
.refetchData(version, () => _dataStream.add(_apiData));
|
||||
await _apiData.users.refetchData(version, () => _dataStream.add(_apiData));
|
||||
await _apiData.volumes
|
||||
.refetchData(version, () => _dataStream.add(_apiData));
|
||||
await _apiData.settings
|
||||
.refetchData(version, () => _dataStream.add(_apiData));
|
||||
await _apiData.recoveryKeyStatus
|
||||
.refetchData(version, () => _dataStream.add(_apiData));
|
||||
await _apiData.devices
|
||||
.refetchData(version, () => _dataStream.add(_apiData));
|
||||
await _apiData.users.refetchData(version, () => _dataStream.add(_apiData));
|
||||
await _apiData.settings
|
||||
await _apiData.backupConfig
|
||||
.refetchData(version, () => _dataStream.add(_apiData));
|
||||
await _apiData.backups
|
||||
.refetchData(version, () => _dataStream.add(_apiData));
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ class DiskVolume {
|
|||
this.providerVolume,
|
||||
});
|
||||
|
||||
DiskVolume.fromServerDiscVolume(
|
||||
DiskVolume.fromServerAndDiskVolume(
|
||||
final ServerDiskVolume volume,
|
||||
final ServerProviderVolume? providerVolume,
|
||||
) : this(
|
||||
|
@ -104,7 +104,7 @@ class DiskStatus {
|
|||
}
|
||||
|
||||
final DiskVolume diskVolume =
|
||||
DiskVolume.fromServerDiscVolume(volume, providerVolume);
|
||||
DiskVolume.fromServerAndDiskVolume(volume, providerVolume);
|
||||
|
||||
return diskVolume;
|
||||
}).toList();
|
||||
|
|
|
@ -36,6 +36,9 @@ class BackblazeBackupsProvider extends BackupsProvider {
|
|||
|
||||
final ApiAdapter _adapter;
|
||||
|
||||
@override
|
||||
bool get isAuthorized => _adapter.api().isWithToken;
|
||||
|
||||
@override
|
||||
BackupsProviderType get type => BackupsProviderType.backblaze;
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ abstract class BackupsProvider {
|
|||
/// provider implements [BackupsProvider] interface.
|
||||
BackupsProviderType get type;
|
||||
|
||||
bool get isAuthorized;
|
||||
|
||||
/// Returns a full url to a guide on how to setup
|
||||
/// backups provider
|
||||
String get howToRegister;
|
||||
|
|
|
@ -27,7 +27,7 @@ class ApiAdapter {
|
|||
}
|
||||
|
||||
class CloudflareDnsProvider extends DnsProvider {
|
||||
CloudflareDnsProvider() : _adapter = ApiAdapter();
|
||||
CloudflareDnsProvider() : _adapter = ApiAdapter(isWithToken: false);
|
||||
CloudflareDnsProvider.load(
|
||||
final bool isAuthorized,
|
||||
final String? token,
|
||||
|
@ -38,6 +38,9 @@ class CloudflareDnsProvider extends DnsProvider {
|
|||
|
||||
ApiAdapter _adapter;
|
||||
|
||||
@override
|
||||
bool get isAuthorized => _adapter.api().isWithToken;
|
||||
|
||||
@override
|
||||
DnsProviderType get type => DnsProviderType.cloudflare;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class ApiAdapter {
|
|||
}
|
||||
|
||||
class DesecDnsProvider extends DnsProvider {
|
||||
DesecDnsProvider() : _adapter = ApiAdapter();
|
||||
DesecDnsProvider() : _adapter = ApiAdapter(isWithToken: false);
|
||||
DesecDnsProvider.load(
|
||||
final bool isAuthorized,
|
||||
final String? token,
|
||||
|
@ -32,6 +32,9 @@ class DesecDnsProvider extends DnsProvider {
|
|||
|
||||
final ApiAdapter _adapter;
|
||||
|
||||
@override
|
||||
bool get isAuthorized => _adapter.api().isWithToken;
|
||||
|
||||
@override
|
||||
DnsProviderType get type => DnsProviderType.desec;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class ApiAdapter {
|
|||
}
|
||||
|
||||
class DigitalOceanDnsProvider extends DnsProvider {
|
||||
DigitalOceanDnsProvider() : _adapter = ApiAdapter();
|
||||
DigitalOceanDnsProvider() : _adapter = ApiAdapter(isWithToken: false);
|
||||
DigitalOceanDnsProvider.load(
|
||||
final bool isAuthorized,
|
||||
final String? token,
|
||||
|
@ -32,6 +32,9 @@ class DigitalOceanDnsProvider extends DnsProvider {
|
|||
|
||||
final ApiAdapter _adapter;
|
||||
|
||||
@override
|
||||
bool get isAuthorized => _adapter.api().isWithToken;
|
||||
|
||||
@override
|
||||
DnsProviderType get type => DnsProviderType.digitalOcean;
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ abstract class DnsProvider {
|
|||
/// provider implements [DnsProvider] interface.
|
||||
DnsProviderType get type;
|
||||
|
||||
bool get isAuthorized;
|
||||
|
||||
/// Returns a full url to a guide on how to setup
|
||||
/// DNS provider nameservers
|
||||
String get howToRegister;
|
||||
|
|
|
@ -39,7 +39,7 @@ class ApiAdapter {
|
|||
}
|
||||
|
||||
class DigitalOceanServerProvider extends ServerProvider {
|
||||
DigitalOceanServerProvider() : _adapter = ApiAdapter();
|
||||
DigitalOceanServerProvider() : _adapter = ApiAdapter(isWithToken: false);
|
||||
DigitalOceanServerProvider.load(
|
||||
final String? location,
|
||||
final bool isAuthorized,
|
||||
|
@ -53,6 +53,9 @@ class DigitalOceanServerProvider extends ServerProvider {
|
|||
ApiAdapter _adapter;
|
||||
final Currency currency = Currency.fromType(CurrencyType.usd);
|
||||
|
||||
@override
|
||||
bool get isAuthorized => _adapter.api().isWithToken;
|
||||
|
||||
@override
|
||||
ServerProviderType get type => ServerProviderType.digitalOcean;
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ class ApiAdapter {
|
|||
}
|
||||
|
||||
class HetznerServerProvider extends ServerProvider {
|
||||
HetznerServerProvider() : _adapter = ApiAdapter();
|
||||
HetznerServerProvider() : _adapter = ApiAdapter(isWithToken: false);
|
||||
HetznerServerProvider.load(
|
||||
final String? location,
|
||||
final bool isAuthorized,
|
||||
|
@ -54,6 +54,9 @@ class HetznerServerProvider extends ServerProvider {
|
|||
final Currency currency = Currency.fromType(CurrencyType.eur);
|
||||
int? cachedCoreAmount;
|
||||
|
||||
@override
|
||||
bool get isAuthorized => _adapter.api().isWithToken;
|
||||
|
||||
@override
|
||||
ServerProviderType get type => ServerProviderType.hetzner;
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ abstract class ServerProvider {
|
|||
/// provider implements [ServerProvider] interface.
|
||||
ServerProviderType get type;
|
||||
|
||||
bool get isAuthorized;
|
||||
|
||||
/// Returns [ServerBasicInfo] of all available machines
|
||||
/// assigned to the authorized user.
|
||||
///
|
||||
|
|
|
@ -100,37 +100,58 @@ class _Chart extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
];
|
||||
} else if (state is MetricsUnsupported) {
|
||||
charts = [
|
||||
FilledCard(
|
||||
clipped: false,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'resource_chart.unsupported'.tr(),
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
];
|
||||
} else {
|
||||
throw 'wrong state';
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
SegmentedButtons(
|
||||
isSelected: [
|
||||
period == Period.month,
|
||||
period == Period.day,
|
||||
period == Period.hour,
|
||||
],
|
||||
onPressed: (final index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
cubit.changePeriod(Period.month);
|
||||
break;
|
||||
case 1:
|
||||
cubit.changePeriod(Period.day);
|
||||
break;
|
||||
case 2:
|
||||
cubit.changePeriod(Period.hour);
|
||||
break;
|
||||
}
|
||||
},
|
||||
titles: [
|
||||
'resource_chart.month'.tr(),
|
||||
'resource_chart.day'.tr(),
|
||||
'resource_chart.hour'.tr(),
|
||||
],
|
||||
),
|
||||
if (state is! MetricsUnsupported)
|
||||
SegmentedButtons(
|
||||
isSelected: [
|
||||
period == Period.month,
|
||||
period == Period.day,
|
||||
period == Period.hour,
|
||||
],
|
||||
onPressed: (final index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
cubit.changePeriod(Period.month);
|
||||
break;
|
||||
case 1:
|
||||
cubit.changePeriod(Period.day);
|
||||
break;
|
||||
case 2:
|
||||
cubit.changePeriod(Period.hour);
|
||||
break;
|
||||
}
|
||||
},
|
||||
titles: [
|
||||
'resource_chart.month'.tr(),
|
||||
'resource_chart.day'.tr(),
|
||||
'resource_chart.hour'.tr(),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
...charts,
|
||||
],
|
||||
|
|
|
@ -84,7 +84,11 @@ class _ServerLogsScreenState extends State<ServerLogsScreen> {
|
|||
const Key centerKey = ValueKey<String>('server-logs-center-key');
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(widget.serviceId == null ? 'server.logs'.tr() : 'service_page.logs'.tr()),
|
||||
title: Text(
|
||||
widget.serviceId == null
|
||||
? 'server.logs'.tr()
|
||||
: 'service_page.logs'.tr(),
|
||||
),
|
||||
),
|
||||
endDrawer: BlocBuilder<ServerLogsBloc, ServerLogsState>(
|
||||
builder: (final context, final state) {
|
||||
|
@ -160,10 +164,12 @@ class _ServerLogsScreenState extends State<ServerLogsScreen> {
|
|||
],
|
||||
);
|
||||
} else if (state is ServerLogsError) {
|
||||
return EmptyPagePlaceholder(
|
||||
title: 'basis.error'.tr(),
|
||||
iconData: Icons.error_outline,
|
||||
description: state.error.toString(),
|
||||
return Center(
|
||||
child: EmptyPagePlaceholder(
|
||||
title: 'basis.error'.tr(),
|
||||
iconData: Icons.error_outline,
|
||||
description: state.error.toString(),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Center(child: Text('server.no_logs'.tr()));
|
||||
|
|
|
@ -63,42 +63,39 @@ class _ServerDetailsScreenState extends State<ServerDetailsScreen>
|
|||
);
|
||||
}
|
||||
|
||||
return BlocProvider(
|
||||
create: (final context) => context.read<ServerDetailsCubit>()..check(),
|
||||
child: BrandHeroScreen(
|
||||
hasFlashButton: true,
|
||||
heroIcon: BrandIcons.server,
|
||||
heroTitle: 'server.card_title'.tr(),
|
||||
heroSubtitle: 'server.description'.tr(),
|
||||
children: [
|
||||
StorageCard(
|
||||
diskStatus: context.watch<VolumesBloc>().state.diskStatus,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ListTile(
|
||||
title: Text('server.settings'.tr()),
|
||||
leading: const Icon(BrandIcons.settings),
|
||||
onTap: () => context.pushRoute(const ServerSettingsRoute()),
|
||||
),
|
||||
ListTile(
|
||||
title: Text('server.logs'.tr()),
|
||||
leading: const Icon(Icons.manage_search_outlined),
|
||||
onTap: () => context.pushRoute(ServerLogsRoute()),
|
||||
),
|
||||
const Divider(height: 32),
|
||||
Text(
|
||||
'server.resource_usage'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
BlocProvider(
|
||||
create: (final context) => MetricsCubit()..restart(),
|
||||
child: _Chart(),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_TextDetails(),
|
||||
],
|
||||
),
|
||||
return BrandHeroScreen(
|
||||
hasFlashButton: true,
|
||||
heroIcon: BrandIcons.server,
|
||||
heroTitle: 'server.card_title'.tr(),
|
||||
heroSubtitle: 'server.description'.tr(),
|
||||
children: [
|
||||
StorageCard(
|
||||
diskStatus: context.watch<VolumesBloc>().state.diskStatus,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ListTile(
|
||||
title: Text('server.settings'.tr()),
|
||||
leading: const Icon(BrandIcons.settings),
|
||||
onTap: () => context.pushRoute(const ServerSettingsRoute()),
|
||||
),
|
||||
ListTile(
|
||||
title: Text('server.logs'.tr()),
|
||||
leading: const Icon(Icons.manage_search_outlined),
|
||||
onTap: () => context.pushRoute(ServerLogsRoute()),
|
||||
),
|
||||
const Divider(height: 32),
|
||||
Text(
|
||||
'server.resource_usage'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
BlocProvider(
|
||||
create: (final context) => MetricsCubit()..restart(),
|
||||
child: _Chart(),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_TextDetails(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ class _TempMessage extends StatelessWidget {
|
|||
final String message;
|
||||
@override
|
||||
Widget build(final BuildContext context) => SizedBox(
|
||||
height: MediaQuery.of(context).size.height - 100,
|
||||
height: 200,
|
||||
child: Center(
|
||||
child: Text(
|
||||
message,
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/server_provider_form_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||
|
||||
|
@ -15,6 +17,27 @@ class RecoveryServerProviderConnected extends StatelessWidget {
|
|||
final ServerInstallationCubit appConfig =
|
||||
context.watch<ServerInstallationCubit>();
|
||||
|
||||
if (appConfig.state.serverDetails?.provider == ServerProviderType.unknown) {
|
||||
return BrandHeroScreen(
|
||||
heroTitle: 'recovering.server_provider_unknown'.tr(),
|
||||
heroSubtitle: 'recovering.server_provider_unknown_description'.tr(),
|
||||
hasBackButton: true,
|
||||
hasFlashButton: false,
|
||||
ignoreBreakpoints: true,
|
||||
onBackButtonPressed: () {
|
||||
Navigator.of(context).popUntil((final route) => route.isFirst);
|
||||
},
|
||||
children: [
|
||||
BrandButton.filled(
|
||||
text: 'basis.continue'.tr(),
|
||||
onPressed: () => context
|
||||
.read<ServerInstallationCubit>()
|
||||
.skipSettingServerProviderKey(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return BlocProvider(
|
||||
create: (final BuildContext context) =>
|
||||
ServerProviderFormCubit(appConfig),
|
||||
|
@ -50,13 +73,13 @@ class RecoveryServerProviderConnected extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Gap(16),
|
||||
BrandButton.filled(
|
||||
onPressed: () =>
|
||||
context.read<ServerProviderFormCubit>().trySubmit(),
|
||||
child: Text('basis.continue'.tr()),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Gap(16),
|
||||
Builder(
|
||||
builder: (final context) => BrandButton.text(
|
||||
title: 'initializing.how'.tr(),
|
||||
|
@ -66,6 +89,13 @@ class RecoveryServerProviderConnected extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
const Gap(16),
|
||||
BrandButton.text(
|
||||
title: 'recovering.login_later'.tr(),
|
||||
onPressed: () => context
|
||||
.read<ServerInstallationCubit>()
|
||||
.skipSettingServerProviderKey(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
Loading…
Reference in a new issue