mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-11 10:29:39 +00:00
refactor(server-api): Make general server info polymorphic
Removing Hetzner type hardcode from server page and replacing it with generic String-based metadata container
This commit is contained in:
parent
b3395915da
commit
10bdd4c800
|
@ -110,6 +110,7 @@
|
|||
"disk": "Disk local",
|
||||
"monthly_cost": "Monthly cost",
|
||||
"location": "Location",
|
||||
"provider": "Provider",
|
||||
"core_count": {
|
||||
"one": "{} core",
|
||||
"two": "{} cores",
|
||||
|
|
|
@ -110,6 +110,7 @@
|
|||
"disk": "Диск",
|
||||
"monthly_cost": "Ежемесячная стоимость",
|
||||
"location": "Размещение",
|
||||
"provider": "Провайдер",
|
||||
"core_count": {
|
||||
"one": "{} ядро",
|
||||
"two": "{} ядра",
|
||||
|
|
|
@ -2,18 +2,20 @@ import 'dart:convert';
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/volume_provider.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
import 'package:selfprivacy/logic/models/json/hetzner_server_info.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
import 'package:selfprivacy/logic/models/price.dart';
|
||||
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
||||
import 'package:selfprivacy/logic/models/server_metadata.dart';
|
||||
import 'package:selfprivacy/logic/models/server_provider_location.dart';
|
||||
import 'package:selfprivacy/logic/models/server_type.dart';
|
||||
import 'package:selfprivacy/utils/extensions/string_extensions.dart';
|
||||
import 'package:selfprivacy/utils/password_generator.dart';
|
||||
|
||||
class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
||||
|
@ -313,8 +315,6 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
|||
base64.encode(utf8.encode(rootUser.password ?? 'PASS'));
|
||||
|
||||
final String formattedHostname = getHostnameFromDomain(domainName);
|
||||
|
||||
// TODO: change to 'master' change to 'master' change to 'master'
|
||||
const String infectBranch = 'providers/digital-ocean';
|
||||
|
||||
final String userdataString =
|
||||
|
@ -474,14 +474,59 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
|||
return metrics;
|
||||
}
|
||||
|
||||
Future<HetznerServerInfo> getInfo() async {
|
||||
final ServerHostingDetails? hetznerServer =
|
||||
getIt<ApiConfigModel>().serverDetails;
|
||||
final Dio client = await getClient();
|
||||
final Response response = await client.get('/servers/${hetznerServer!.id}');
|
||||
close(client);
|
||||
@override
|
||||
Future<List<ServerMetadataEntity>> getMetadata(final int serverId) async {
|
||||
List<ServerMetadataEntity> metadata = [];
|
||||
|
||||
return HetznerServerInfo.fromJson(response.data!['server']);
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
final Response response = await client.get('/droplets/$serverId');
|
||||
final droplet = response.data!['droplet'];
|
||||
metadata = [
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.id,
|
||||
name: 'server.server_id'.tr(),
|
||||
value: droplet['id'].toString(),
|
||||
),
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.status,
|
||||
name: 'server.status'.tr(),
|
||||
value: droplet['status'].toString().capitalize(),
|
||||
),
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.cpu,
|
||||
name: 'server.cpu'.tr(),
|
||||
value: 'server.core_count'.plural(droplet['vcpus']),
|
||||
),
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.ram,
|
||||
name: 'server.ram'.tr(),
|
||||
value: "${droplet['memory'].toString()} MB",
|
||||
),
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.cost,
|
||||
name: 'server.monthly_cost'.tr(),
|
||||
value: droplet['size']['price_monthly'].toString(),
|
||||
),
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.location,
|
||||
name: 'server.location'.tr(),
|
||||
value:
|
||||
'${droplet['region']['name']} ${getEmojiFlag(droplet['region']['slug'].toString()) ?? ''}',
|
||||
),
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.other,
|
||||
name: 'server.provider'.tr(),
|
||||
value: 'Digital Ocean',
|
||||
),
|
||||
];
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
close(client);
|
||||
}
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/volume_provider.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider.dart';
|
||||
|
@ -12,8 +13,10 @@ import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
|||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
import 'package:selfprivacy/logic/models/price.dart';
|
||||
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
||||
import 'package:selfprivacy/logic/models/server_metadata.dart';
|
||||
import 'package:selfprivacy/logic/models/server_provider_location.dart';
|
||||
import 'package:selfprivacy/logic/models/server_type.dart';
|
||||
import 'package:selfprivacy/utils/extensions/string_extensions.dart';
|
||||
import 'package:selfprivacy/utils/password_generator.dart';
|
||||
|
||||
class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||
|
@ -513,14 +516,59 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
|||
return metrics;
|
||||
}
|
||||
|
||||
Future<HetznerServerInfo> getInfo() async {
|
||||
final ServerHostingDetails? hetznerServer =
|
||||
getIt<ApiConfigModel>().serverDetails;
|
||||
final Dio client = await getClient();
|
||||
final Response response = await client.get('/servers/${hetznerServer!.id}');
|
||||
close(client);
|
||||
@override
|
||||
Future<List<ServerMetadataEntity>> getMetadata(final int serverId) async {
|
||||
List<ServerMetadataEntity> metadata = [];
|
||||
|
||||
return HetznerServerInfo.fromJson(response.data!['server']);
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
final Response response = await client.get('/servers/$serverId');
|
||||
final hetznerInfo = HetznerServerInfo.fromJson(response.data!['server']);
|
||||
metadata = [
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.id,
|
||||
name: 'server.server_id'.tr(),
|
||||
value: hetznerInfo.id.toString(),
|
||||
),
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.status,
|
||||
name: 'server.status'.tr(),
|
||||
value: hetznerInfo.status.toString().split('.')[1].capitalize(),
|
||||
),
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.cpu,
|
||||
name: 'server.cpu'.tr(),
|
||||
value: 'server.core_count'.plural(hetznerInfo.serverType.cores),
|
||||
),
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.ram,
|
||||
name: 'server.ram'.tr(),
|
||||
value: '${hetznerInfo.serverType.memory.toString()} GB',
|
||||
),
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.cost,
|
||||
name: 'server.monthly_cost'.tr(),
|
||||
value: hetznerInfo.serverType.prices[1].monthly.toStringAsFixed(2),
|
||||
),
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.location,
|
||||
name: 'server.location'.tr(),
|
||||
value:
|
||||
'${hetznerInfo.location.city}, ${hetznerInfo.location.country}',
|
||||
),
|
||||
ServerMetadataEntity(
|
||||
type: MetadataType.other,
|
||||
name: 'server.provider'.tr(),
|
||||
value: 'Hetzner',
|
||||
),
|
||||
];
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
close(client);
|
||||
}
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
|||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
||||
import 'package:selfprivacy/logic/models/server_metadata.dart';
|
||||
import 'package:selfprivacy/logic/models/server_provider_location.dart';
|
||||
import 'package:selfprivacy/logic/models/server_type.dart';
|
||||
|
||||
|
@ -39,6 +40,7 @@ abstract class ServerProviderApi extends ApiMap {
|
|||
|
||||
Future<bool> isApiTokenValid(final String token);
|
||||
ProviderApiTokenValidation getApiTokenValidation();
|
||||
Future<List<ServerMetadataEntity>> getMetadata(final int serverId);
|
||||
|
||||
abstract final String infectProviderName;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'package:selfprivacy/config/get_it_config.dart';
|
|||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_detailed_info/server_detailed_info_repository.dart';
|
||||
import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart';
|
||||
import 'package:selfprivacy/logic/models/json/hetzner_server_info.dart';
|
||||
import 'package:selfprivacy/logic/models/server_metadata.dart';
|
||||
import 'package:selfprivacy/logic/models/timezone_settings.dart';
|
||||
|
||||
part 'server_detailed_info_state.dart';
|
||||
|
@ -22,7 +22,7 @@ class ServerDetailsCubit
|
|||
final ServerDetailsRepositoryDto data = await repository.load();
|
||||
emit(
|
||||
Loaded(
|
||||
serverInfo: data.hetznerServerInfo,
|
||||
metadata: data.metadata,
|
||||
autoUpgradeSettings: data.autoUpgradeSettings,
|
||||
serverTimezone: data.serverTimezone,
|
||||
checkTime: DateTime.now(),
|
||||
|
|
|
@ -1,22 +1,42 @@
|
|||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/hetzner/hetzner.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_factory_creator.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_factory_settings.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider_factory.dart';
|
||||
import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart';
|
||||
import 'package:selfprivacy/logic/models/json/hetzner_server_info.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/server_metadata.dart';
|
||||
import 'package:selfprivacy/logic/models/timezone_settings.dart';
|
||||
|
||||
class ServerDetailsRepository {
|
||||
HetznerApi hetzner = HetznerApi(
|
||||
/// TODO: Hetzner hardcode (???)
|
||||
region: getIt<ApiConfigModel>().serverLocation,
|
||||
);
|
||||
ServerApi server = ServerApi();
|
||||
ServerProviderApiFactory? serverProviderApiFactory;
|
||||
|
||||
void _buildServerProviderFactory() {
|
||||
final ServerProvider? providerType = getIt<ApiConfigModel>().serverProvider;
|
||||
final String? location = getIt<ApiConfigModel>().serverLocation;
|
||||
serverProviderApiFactory = ApiFactoryCreator.createServerProviderApiFactory(
|
||||
ServerProviderApiFactorySettings(
|
||||
provider: providerType ?? ServerProvider.unknown,
|
||||
location: location,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<ServerDetailsRepositoryDto> load() async {
|
||||
if (serverProviderApiFactory == null) {
|
||||
_buildServerProviderFactory();
|
||||
}
|
||||
|
||||
final settings = await server.getSystemSettings();
|
||||
final serverId = getIt<ApiConfigModel>().serverDetails!.id;
|
||||
final metadata = await serverProviderApiFactory!
|
||||
.getServerProvider()
|
||||
.getMetadata(serverId);
|
||||
|
||||
return ServerDetailsRepositoryDto(
|
||||
autoUpgradeSettings: settings.autoUpgradeSettings,
|
||||
hetznerServerInfo: await hetzner.getInfo(),
|
||||
metadata: metadata,
|
||||
serverTimezone: TimeZoneSettings.fromString(
|
||||
settings.timezone,
|
||||
),
|
||||
|
@ -40,13 +60,11 @@ class ServerDetailsRepository {
|
|||
|
||||
class ServerDetailsRepositoryDto {
|
||||
ServerDetailsRepositoryDto({
|
||||
required this.hetznerServerInfo,
|
||||
required this.metadata,
|
||||
required this.serverTimezone,
|
||||
required this.autoUpgradeSettings,
|
||||
});
|
||||
final HetznerServerInfo hetznerServerInfo;
|
||||
|
||||
final List<ServerMetadataEntity> metadata;
|
||||
final TimeZoneSettings serverTimezone;
|
||||
|
||||
final AutoUpgradeSettings autoUpgradeSettings;
|
||||
}
|
||||
|
|
|
@ -17,21 +17,19 @@ class Loading extends ServerDetailsState {}
|
|||
|
||||
class Loaded extends ServerDetailsState {
|
||||
const Loaded({
|
||||
required this.serverInfo,
|
||||
required this.metadata,
|
||||
required this.serverTimezone,
|
||||
required this.autoUpgradeSettings,
|
||||
required this.checkTime,
|
||||
});
|
||||
final HetznerServerInfo serverInfo;
|
||||
|
||||
final List<ServerMetadataEntity> metadata;
|
||||
final TimeZoneSettings serverTimezone;
|
||||
|
||||
final AutoUpgradeSettings autoUpgradeSettings;
|
||||
final DateTime checkTime;
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
serverInfo,
|
||||
metadata,
|
||||
serverTimezone,
|
||||
autoUpgradeSettings,
|
||||
checkTime,
|
||||
|
|
21
lib/logic/models/server_metadata.dart
Normal file
21
lib/logic/models/server_metadata.dart
Normal file
|
@ -0,0 +1,21 @@
|
|||
enum MetadataType {
|
||||
id,
|
||||
status,
|
||||
cpu,
|
||||
ram,
|
||||
cost,
|
||||
location,
|
||||
|
||||
other,
|
||||
}
|
||||
|
||||
class ServerMetadataEntity {
|
||||
ServerMetadataEntity({
|
||||
required this.name,
|
||||
required this.value,
|
||||
this.type = MetadataType.other,
|
||||
});
|
||||
final MetadataType type;
|
||||
final String name;
|
||||
final String value;
|
||||
}
|
|
@ -10,6 +10,7 @@ import 'package:selfprivacy/logic/cubit/server_installation/server_installation_
|
|||
import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart';
|
||||
import 'package:selfprivacy/logic/models/job.dart';
|
||||
import 'package:selfprivacy/logic/models/server_metadata.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_button/segmented_buttons.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
part of 'server_details_screen.dart';
|
||||
|
||||
class _TextDetails extends StatelessWidget {
|
||||
final Map<MetadataType, IconData> metadataToIcon = const {
|
||||
MetadataType.id: Icons.numbers_outlined,
|
||||
MetadataType.status: Icons.mode_standby_outlined,
|
||||
MetadataType.cpu: Icons.memory_outlined,
|
||||
MetadataType.ram: Icons.memory_outlined,
|
||||
MetadataType.cost: Icons.euro_outlined,
|
||||
MetadataType.location: Icons.location_on_outlined,
|
||||
MetadataType.other: Icons.info_outlined,
|
||||
};
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) {
|
||||
final details = context.watch<ServerDetailsCubit>().state;
|
||||
|
@ -10,7 +20,6 @@ class _TextDetails extends StatelessWidget {
|
|||
} else if (details is ServerDetailsNotReady) {
|
||||
return _TempMessage(message: 'basis.no_data'.tr());
|
||||
} else if (details is Loaded) {
|
||||
final data = details.serverInfo;
|
||||
return FilledCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
@ -24,37 +33,15 @@ class _TextDetails extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
ListTileOnSurfaceVariant(
|
||||
leadingIcon: Icons.numbers_outlined,
|
||||
title: data.id.toString(),
|
||||
subtitle: 'server.server_id'.tr(),
|
||||
),
|
||||
ListTileOnSurfaceVariant(
|
||||
leadingIcon: Icons.mode_standby_outlined,
|
||||
title: data.status.toString().split('.')[1].capitalize(),
|
||||
subtitle: 'server.status'.tr(),
|
||||
),
|
||||
ListTileOnSurfaceVariant(
|
||||
leadingIcon: Icons.memory_outlined,
|
||||
title: 'server.core_count'.plural(data.serverType.cores),
|
||||
subtitle: 'server.cpu'.tr(),
|
||||
),
|
||||
ListTileOnSurfaceVariant(
|
||||
leadingIcon: Icons.memory_outlined,
|
||||
title: '${data.serverType.memory.toString()} GB',
|
||||
subtitle: 'server.ram'.tr(),
|
||||
),
|
||||
ListTileOnSurfaceVariant(
|
||||
leadingIcon: Icons.euro_outlined,
|
||||
title: data.serverType.prices[1].monthly.toStringAsFixed(2),
|
||||
subtitle: 'server.monthly_cost'.tr(),
|
||||
),
|
||||
// Server location
|
||||
ListTileOnSurfaceVariant(
|
||||
leadingIcon: Icons.location_on_outlined,
|
||||
title: '${data.location.city}, ${data.location.country}',
|
||||
subtitle: 'server.location'.tr(),
|
||||
),
|
||||
...details.metadata
|
||||
.map(
|
||||
(final metadata) => ListTileOnSurfaceVariant(
|
||||
leadingIcon: metadataToIcon[metadata.type],
|
||||
title: metadata.name,
|
||||
subtitle: metadata.value,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue