feat: Add ssh settings
continuous-integration/drone/push Build is passing Details

pull/477/head
Inex Code 2024-03-09 19:30:43 +03:00
parent b2384a5635
commit bba29caeba
12 changed files with 1094 additions and 90 deletions

View File

@ -95,7 +95,8 @@
"no_key_name": "Unnamed key",
"root_title": "These are superuser keys",
"root_subtitle": "Owners of these keys get full access to the server and can do anything on it. Only add your own keys to the server.",
"input_label": "Public ED25519, ECDSA or RSA key"
"input_label": "Public ED25519, ECDSA or RSA key",
"ssh_disabled_warning": "SSH is disabled. You can enable it in the server settings."
},
"onboarding": {
"page1_title": "Digital independence, available to all of us",
@ -130,6 +131,10 @@
"reboot_after_upgrade_hint": "Reboot without prompt after applying changes on server",
"server_timezone": "Server timezone",
"select_timezone": "Select timezone",
"enable_ssh": "Enable SSH",
"enable_ssh_hint": "Allow SSH access to the server",
"allow_password_authentication": "Allow password authentication for SSH",
"allow_password_authentication_hint": "Allow users to log into your server's shell with a password (does not apply to root user)",
"timezone_search_bar": "Timezone name or time shift value",
"server_id": "Server ID",
"status": "Status",
@ -626,7 +631,8 @@
"rebuild_system": "Rebuild system",
"start_server_upgrade": "Start the server upgrade",
"change_auto_upgrade_settings": "Change auto-upgrade settings",
"change_server_timezone": "Change server timezone"
"change_server_timezone": "Change server timezone",
"change_ssh_settings": "Change SSH settings"
},
"validations": {
"required": "Required",

View File

@ -62,3 +62,13 @@ mutation ChangeAutoUpgradeSettings($settings: AutoUpgradeSettingsInput!) {
}
}
}
mutation ChangeSshSettings($settings: SSHSettingsInput!) {
system {
changeSshSettings(settings: $settings) {
...basicMutationReturnFields
enable
passwordAuthentication
}
}
}

View File

@ -4123,3 +4123,783 @@ class _CopyWithStubImpl$Mutation$ChangeAutoUpgradeSettings$system$changeAutoUpgr
}) =>
_res;
}
class Variables$Mutation$ChangeSshSettings {
factory Variables$Mutation$ChangeSshSettings(
{required Input$SSHSettingsInput settings}) =>
Variables$Mutation$ChangeSshSettings._({
r'settings': settings,
});
Variables$Mutation$ChangeSshSettings._(this._$data);
factory Variables$Mutation$ChangeSshSettings.fromJson(
Map<String, dynamic> data) {
final result$data = <String, dynamic>{};
final l$settings = data['settings'];
result$data['settings'] =
Input$SSHSettingsInput.fromJson((l$settings as Map<String, dynamic>));
return Variables$Mutation$ChangeSshSettings._(result$data);
}
Map<String, dynamic> _$data;
Input$SSHSettingsInput get settings =>
(_$data['settings'] as Input$SSHSettingsInput);
Map<String, dynamic> toJson() {
final result$data = <String, dynamic>{};
final l$settings = settings;
result$data['settings'] = l$settings.toJson();
return result$data;
}
CopyWith$Variables$Mutation$ChangeSshSettings<
Variables$Mutation$ChangeSshSettings>
get copyWith => CopyWith$Variables$Mutation$ChangeSshSettings(
this,
(i) => i,
);
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (!(other is Variables$Mutation$ChangeSshSettings) ||
runtimeType != other.runtimeType) {
return false;
}
final l$settings = settings;
final lOther$settings = other.settings;
if (l$settings != lOther$settings) {
return false;
}
return true;
}
@override
int get hashCode {
final l$settings = settings;
return Object.hashAll([l$settings]);
}
}
abstract class CopyWith$Variables$Mutation$ChangeSshSettings<TRes> {
factory CopyWith$Variables$Mutation$ChangeSshSettings(
Variables$Mutation$ChangeSshSettings instance,
TRes Function(Variables$Mutation$ChangeSshSettings) then,
) = _CopyWithImpl$Variables$Mutation$ChangeSshSettings;
factory CopyWith$Variables$Mutation$ChangeSshSettings.stub(TRes res) =
_CopyWithStubImpl$Variables$Mutation$ChangeSshSettings;
TRes call({Input$SSHSettingsInput? settings});
}
class _CopyWithImpl$Variables$Mutation$ChangeSshSettings<TRes>
implements CopyWith$Variables$Mutation$ChangeSshSettings<TRes> {
_CopyWithImpl$Variables$Mutation$ChangeSshSettings(
this._instance,
this._then,
);
final Variables$Mutation$ChangeSshSettings _instance;
final TRes Function(Variables$Mutation$ChangeSshSettings) _then;
static const _undefined = <dynamic, dynamic>{};
TRes call({Object? settings = _undefined}) =>
_then(Variables$Mutation$ChangeSshSettings._({
..._instance._$data,
if (settings != _undefined && settings != null)
'settings': (settings as Input$SSHSettingsInput),
}));
}
class _CopyWithStubImpl$Variables$Mutation$ChangeSshSettings<TRes>
implements CopyWith$Variables$Mutation$ChangeSshSettings<TRes> {
_CopyWithStubImpl$Variables$Mutation$ChangeSshSettings(this._res);
TRes _res;
call({Input$SSHSettingsInput? settings}) => _res;
}
class Mutation$ChangeSshSettings {
Mutation$ChangeSshSettings({
required this.system,
this.$__typename = 'Mutation',
});
factory Mutation$ChangeSshSettings.fromJson(Map<String, dynamic> json) {
final l$system = json['system'];
final l$$__typename = json['__typename'];
return Mutation$ChangeSshSettings(
system: Mutation$ChangeSshSettings$system.fromJson(
(l$system as Map<String, dynamic>)),
$__typename: (l$$__typename as String),
);
}
final Mutation$ChangeSshSettings$system system;
final String $__typename;
Map<String, dynamic> toJson() {
final _resultData = <String, dynamic>{};
final l$system = system;
_resultData['system'] = l$system.toJson();
final l$$__typename = $__typename;
_resultData['__typename'] = l$$__typename;
return _resultData;
}
@override
int get hashCode {
final l$system = system;
final l$$__typename = $__typename;
return Object.hashAll([
l$system,
l$$__typename,
]);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (!(other is Mutation$ChangeSshSettings) ||
runtimeType != other.runtimeType) {
return false;
}
final l$system = system;
final lOther$system = other.system;
if (l$system != lOther$system) {
return false;
}
final l$$__typename = $__typename;
final lOther$$__typename = other.$__typename;
if (l$$__typename != lOther$$__typename) {
return false;
}
return true;
}
}
extension UtilityExtension$Mutation$ChangeSshSettings
on Mutation$ChangeSshSettings {
CopyWith$Mutation$ChangeSshSettings<Mutation$ChangeSshSettings>
get copyWith => CopyWith$Mutation$ChangeSshSettings(
this,
(i) => i,
);
}
abstract class CopyWith$Mutation$ChangeSshSettings<TRes> {
factory CopyWith$Mutation$ChangeSshSettings(
Mutation$ChangeSshSettings instance,
TRes Function(Mutation$ChangeSshSettings) then,
) = _CopyWithImpl$Mutation$ChangeSshSettings;
factory CopyWith$Mutation$ChangeSshSettings.stub(TRes res) =
_CopyWithStubImpl$Mutation$ChangeSshSettings;
TRes call({
Mutation$ChangeSshSettings$system? system,
String? $__typename,
});
CopyWith$Mutation$ChangeSshSettings$system<TRes> get system;
}
class _CopyWithImpl$Mutation$ChangeSshSettings<TRes>
implements CopyWith$Mutation$ChangeSshSettings<TRes> {
_CopyWithImpl$Mutation$ChangeSshSettings(
this._instance,
this._then,
);
final Mutation$ChangeSshSettings _instance;
final TRes Function(Mutation$ChangeSshSettings) _then;
static const _undefined = <dynamic, dynamic>{};
TRes call({
Object? system = _undefined,
Object? $__typename = _undefined,
}) =>
_then(Mutation$ChangeSshSettings(
system: system == _undefined || system == null
? _instance.system
: (system as Mutation$ChangeSshSettings$system),
$__typename: $__typename == _undefined || $__typename == null
? _instance.$__typename
: ($__typename as String),
));
CopyWith$Mutation$ChangeSshSettings$system<TRes> get system {
final local$system = _instance.system;
return CopyWith$Mutation$ChangeSshSettings$system(
local$system, (e) => call(system: e));
}
}
class _CopyWithStubImpl$Mutation$ChangeSshSettings<TRes>
implements CopyWith$Mutation$ChangeSshSettings<TRes> {
_CopyWithStubImpl$Mutation$ChangeSshSettings(this._res);
TRes _res;
call({
Mutation$ChangeSshSettings$system? system,
String? $__typename,
}) =>
_res;
CopyWith$Mutation$ChangeSshSettings$system<TRes> get system =>
CopyWith$Mutation$ChangeSshSettings$system.stub(_res);
}
const documentNodeMutationChangeSshSettings = DocumentNode(definitions: [
OperationDefinitionNode(
type: OperationType.mutation,
name: NameNode(value: 'ChangeSshSettings'),
variableDefinitions: [
VariableDefinitionNode(
variable: VariableNode(name: NameNode(value: 'settings')),
type: NamedTypeNode(
name: NameNode(value: 'SSHSettingsInput'),
isNonNull: true,
),
defaultValue: DefaultValueNode(value: null),
directives: [],
)
],
directives: [],
selectionSet: SelectionSetNode(selections: [
FieldNode(
name: NameNode(value: 'system'),
alias: null,
arguments: [],
directives: [],
selectionSet: SelectionSetNode(selections: [
FieldNode(
name: NameNode(value: 'changeSshSettings'),
alias: null,
arguments: [
ArgumentNode(
name: NameNode(value: 'settings'),
value: VariableNode(name: NameNode(value: 'settings')),
)
],
directives: [],
selectionSet: SelectionSetNode(selections: [
FragmentSpreadNode(
name: NameNode(value: 'basicMutationReturnFields'),
directives: [],
),
FieldNode(
name: NameNode(value: 'enable'),
alias: null,
arguments: [],
directives: [],
selectionSet: null,
),
FieldNode(
name: NameNode(value: 'passwordAuthentication'),
alias: null,
arguments: [],
directives: [],
selectionSet: null,
),
FieldNode(
name: NameNode(value: '__typename'),
alias: null,
arguments: [],
directives: [],
selectionSet: null,
),
]),
),
FieldNode(
name: NameNode(value: '__typename'),
alias: null,
arguments: [],
directives: [],
selectionSet: null,
),
]),
),
FieldNode(
name: NameNode(value: '__typename'),
alias: null,
arguments: [],
directives: [],
selectionSet: null,
),
]),
),
fragmentDefinitionbasicMutationReturnFields,
]);
Mutation$ChangeSshSettings _parserFn$Mutation$ChangeSshSettings(
Map<String, dynamic> data) =>
Mutation$ChangeSshSettings.fromJson(data);
typedef OnMutationCompleted$Mutation$ChangeSshSettings = FutureOr<void>
Function(
Map<String, dynamic>?,
Mutation$ChangeSshSettings?,
);
class Options$Mutation$ChangeSshSettings
extends graphql.MutationOptions<Mutation$ChangeSshSettings> {
Options$Mutation$ChangeSshSettings({
String? operationName,
required Variables$Mutation$ChangeSshSettings variables,
graphql.FetchPolicy? fetchPolicy,
graphql.ErrorPolicy? errorPolicy,
graphql.CacheRereadPolicy? cacheRereadPolicy,
Object? optimisticResult,
Mutation$ChangeSshSettings? typedOptimisticResult,
graphql.Context? context,
OnMutationCompleted$Mutation$ChangeSshSettings? onCompleted,
graphql.OnMutationUpdate<Mutation$ChangeSshSettings>? update,
graphql.OnError? onError,
}) : onCompletedWithParsed = onCompleted,
super(
variables: variables.toJson(),
operationName: operationName,
fetchPolicy: fetchPolicy,
errorPolicy: errorPolicy,
cacheRereadPolicy: cacheRereadPolicy,
optimisticResult: optimisticResult ?? typedOptimisticResult?.toJson(),
context: context,
onCompleted: onCompleted == null
? null
: (data) => onCompleted(
data,
data == null
? null
: _parserFn$Mutation$ChangeSshSettings(data),
),
update: update,
onError: onError,
document: documentNodeMutationChangeSshSettings,
parserFn: _parserFn$Mutation$ChangeSshSettings,
);
final OnMutationCompleted$Mutation$ChangeSshSettings? onCompletedWithParsed;
@override
List<Object?> get properties => [
...super.onCompleted == null
? super.properties
: super.properties.where((property) => property != onCompleted),
onCompletedWithParsed,
];
}
class WatchOptions$Mutation$ChangeSshSettings
extends graphql.WatchQueryOptions<Mutation$ChangeSshSettings> {
WatchOptions$Mutation$ChangeSshSettings({
String? operationName,
required Variables$Mutation$ChangeSshSettings variables,
graphql.FetchPolicy? fetchPolicy,
graphql.ErrorPolicy? errorPolicy,
graphql.CacheRereadPolicy? cacheRereadPolicy,
Object? optimisticResult,
Mutation$ChangeSshSettings? typedOptimisticResult,
graphql.Context? context,
Duration? pollInterval,
bool? eagerlyFetchResults,
bool carryForwardDataOnException = true,
bool fetchResults = false,
}) : super(
variables: variables.toJson(),
operationName: operationName,
fetchPolicy: fetchPolicy,
errorPolicy: errorPolicy,
cacheRereadPolicy: cacheRereadPolicy,
optimisticResult: optimisticResult ?? typedOptimisticResult?.toJson(),
context: context,
document: documentNodeMutationChangeSshSettings,
pollInterval: pollInterval,
eagerlyFetchResults: eagerlyFetchResults,
carryForwardDataOnException: carryForwardDataOnException,
fetchResults: fetchResults,
parserFn: _parserFn$Mutation$ChangeSshSettings,
);
}
extension ClientExtension$Mutation$ChangeSshSettings on graphql.GraphQLClient {
Future<graphql.QueryResult<Mutation$ChangeSshSettings>>
mutate$ChangeSshSettings(
Options$Mutation$ChangeSshSettings options) async =>
await this.mutate(options);
graphql.ObservableQuery<Mutation$ChangeSshSettings>
watchMutation$ChangeSshSettings(
WatchOptions$Mutation$ChangeSshSettings options) =>
this.watchMutation(options);
}
class Mutation$ChangeSshSettings$system {
Mutation$ChangeSshSettings$system({
required this.changeSshSettings,
this.$__typename = 'SystemMutations',
});
factory Mutation$ChangeSshSettings$system.fromJson(
Map<String, dynamic> json) {
final l$changeSshSettings = json['changeSshSettings'];
final l$$__typename = json['__typename'];
return Mutation$ChangeSshSettings$system(
changeSshSettings:
Mutation$ChangeSshSettings$system$changeSshSettings.fromJson(
(l$changeSshSettings as Map<String, dynamic>)),
$__typename: (l$$__typename as String),
);
}
final Mutation$ChangeSshSettings$system$changeSshSettings changeSshSettings;
final String $__typename;
Map<String, dynamic> toJson() {
final _resultData = <String, dynamic>{};
final l$changeSshSettings = changeSshSettings;
_resultData['changeSshSettings'] = l$changeSshSettings.toJson();
final l$$__typename = $__typename;
_resultData['__typename'] = l$$__typename;
return _resultData;
}
@override
int get hashCode {
final l$changeSshSettings = changeSshSettings;
final l$$__typename = $__typename;
return Object.hashAll([
l$changeSshSettings,
l$$__typename,
]);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (!(other is Mutation$ChangeSshSettings$system) ||
runtimeType != other.runtimeType) {
return false;
}
final l$changeSshSettings = changeSshSettings;
final lOther$changeSshSettings = other.changeSshSettings;
if (l$changeSshSettings != lOther$changeSshSettings) {
return false;
}
final l$$__typename = $__typename;
final lOther$$__typename = other.$__typename;
if (l$$__typename != lOther$$__typename) {
return false;
}
return true;
}
}
extension UtilityExtension$Mutation$ChangeSshSettings$system
on Mutation$ChangeSshSettings$system {
CopyWith$Mutation$ChangeSshSettings$system<Mutation$ChangeSshSettings$system>
get copyWith => CopyWith$Mutation$ChangeSshSettings$system(
this,
(i) => i,
);
}
abstract class CopyWith$Mutation$ChangeSshSettings$system<TRes> {
factory CopyWith$Mutation$ChangeSshSettings$system(
Mutation$ChangeSshSettings$system instance,
TRes Function(Mutation$ChangeSshSettings$system) then,
) = _CopyWithImpl$Mutation$ChangeSshSettings$system;
factory CopyWith$Mutation$ChangeSshSettings$system.stub(TRes res) =
_CopyWithStubImpl$Mutation$ChangeSshSettings$system;
TRes call({
Mutation$ChangeSshSettings$system$changeSshSettings? changeSshSettings,
String? $__typename,
});
CopyWith$Mutation$ChangeSshSettings$system$changeSshSettings<TRes>
get changeSshSettings;
}
class _CopyWithImpl$Mutation$ChangeSshSettings$system<TRes>
implements CopyWith$Mutation$ChangeSshSettings$system<TRes> {
_CopyWithImpl$Mutation$ChangeSshSettings$system(
this._instance,
this._then,
);
final Mutation$ChangeSshSettings$system _instance;
final TRes Function(Mutation$ChangeSshSettings$system) _then;
static const _undefined = <dynamic, dynamic>{};
TRes call({
Object? changeSshSettings = _undefined,
Object? $__typename = _undefined,
}) =>
_then(Mutation$ChangeSshSettings$system(
changeSshSettings:
changeSshSettings == _undefined || changeSshSettings == null
? _instance.changeSshSettings
: (changeSshSettings
as Mutation$ChangeSshSettings$system$changeSshSettings),
$__typename: $__typename == _undefined || $__typename == null
? _instance.$__typename
: ($__typename as String),
));
CopyWith$Mutation$ChangeSshSettings$system$changeSshSettings<TRes>
get changeSshSettings {
final local$changeSshSettings = _instance.changeSshSettings;
return CopyWith$Mutation$ChangeSshSettings$system$changeSshSettings(
local$changeSshSettings, (e) => call(changeSshSettings: e));
}
}
class _CopyWithStubImpl$Mutation$ChangeSshSettings$system<TRes>
implements CopyWith$Mutation$ChangeSshSettings$system<TRes> {
_CopyWithStubImpl$Mutation$ChangeSshSettings$system(this._res);
TRes _res;
call({
Mutation$ChangeSshSettings$system$changeSshSettings? changeSshSettings,
String? $__typename,
}) =>
_res;
CopyWith$Mutation$ChangeSshSettings$system$changeSshSettings<TRes>
get changeSshSettings =>
CopyWith$Mutation$ChangeSshSettings$system$changeSshSettings.stub(
_res);
}
class Mutation$ChangeSshSettings$system$changeSshSettings
implements Fragment$basicMutationReturnFields$$SSHSettingsMutationReturn {
Mutation$ChangeSshSettings$system$changeSshSettings({
required this.code,
required this.message,
required this.success,
this.$__typename = 'SSHSettingsMutationReturn',
required this.enable,
required this.passwordAuthentication,
});
factory Mutation$ChangeSshSettings$system$changeSshSettings.fromJson(
Map<String, dynamic> json) {
final l$code = json['code'];
final l$message = json['message'];
final l$success = json['success'];
final l$$__typename = json['__typename'];
final l$enable = json['enable'];
final l$passwordAuthentication = json['passwordAuthentication'];
return Mutation$ChangeSshSettings$system$changeSshSettings(
code: (l$code as int),
message: (l$message as String),
success: (l$success as bool),
$__typename: (l$$__typename as String),
enable: (l$enable as bool),
passwordAuthentication: (l$passwordAuthentication as bool),
);
}
final int code;
final String message;
final bool success;
final String $__typename;
final bool enable;
final bool passwordAuthentication;
Map<String, dynamic> toJson() {
final _resultData = <String, dynamic>{};
final l$code = code;
_resultData['code'] = l$code;
final l$message = message;
_resultData['message'] = l$message;
final l$success = success;
_resultData['success'] = l$success;
final l$$__typename = $__typename;
_resultData['__typename'] = l$$__typename;
final l$enable = enable;
_resultData['enable'] = l$enable;
final l$passwordAuthentication = passwordAuthentication;
_resultData['passwordAuthentication'] = l$passwordAuthentication;
return _resultData;
}
@override
int get hashCode {
final l$code = code;
final l$message = message;
final l$success = success;
final l$$__typename = $__typename;
final l$enable = enable;
final l$passwordAuthentication = passwordAuthentication;
return Object.hashAll([
l$code,
l$message,
l$success,
l$$__typename,
l$enable,
l$passwordAuthentication,
]);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (!(other is Mutation$ChangeSshSettings$system$changeSshSettings) ||
runtimeType != other.runtimeType) {
return false;
}
final l$code = code;
final lOther$code = other.code;
if (l$code != lOther$code) {
return false;
}
final l$message = message;
final lOther$message = other.message;
if (l$message != lOther$message) {
return false;
}
final l$success = success;
final lOther$success = other.success;
if (l$success != lOther$success) {
return false;
}
final l$$__typename = $__typename;
final lOther$$__typename = other.$__typename;
if (l$$__typename != lOther$$__typename) {
return false;
}
final l$enable = enable;
final lOther$enable = other.enable;
if (l$enable != lOther$enable) {
return false;
}
final l$passwordAuthentication = passwordAuthentication;
final lOther$passwordAuthentication = other.passwordAuthentication;
if (l$passwordAuthentication != lOther$passwordAuthentication) {
return false;
}
return true;
}
}
extension UtilityExtension$Mutation$ChangeSshSettings$system$changeSshSettings
on Mutation$ChangeSshSettings$system$changeSshSettings {
CopyWith$Mutation$ChangeSshSettings$system$changeSshSettings<
Mutation$ChangeSshSettings$system$changeSshSettings>
get copyWith =>
CopyWith$Mutation$ChangeSshSettings$system$changeSshSettings(
this,
(i) => i,
);
}
abstract class CopyWith$Mutation$ChangeSshSettings$system$changeSshSettings<
TRes> {
factory CopyWith$Mutation$ChangeSshSettings$system$changeSshSettings(
Mutation$ChangeSshSettings$system$changeSshSettings instance,
TRes Function(Mutation$ChangeSshSettings$system$changeSshSettings) then,
) = _CopyWithImpl$Mutation$ChangeSshSettings$system$changeSshSettings;
factory CopyWith$Mutation$ChangeSshSettings$system$changeSshSettings.stub(
TRes res) =
_CopyWithStubImpl$Mutation$ChangeSshSettings$system$changeSshSettings;
TRes call({
int? code,
String? message,
bool? success,
String? $__typename,
bool? enable,
bool? passwordAuthentication,
});
}
class _CopyWithImpl$Mutation$ChangeSshSettings$system$changeSshSettings<TRes>
implements
CopyWith$Mutation$ChangeSshSettings$system$changeSshSettings<TRes> {
_CopyWithImpl$Mutation$ChangeSshSettings$system$changeSshSettings(
this._instance,
this._then,
);
final Mutation$ChangeSshSettings$system$changeSshSettings _instance;
final TRes Function(Mutation$ChangeSshSettings$system$changeSshSettings)
_then;
static const _undefined = <dynamic, dynamic>{};
TRes call({
Object? code = _undefined,
Object? message = _undefined,
Object? success = _undefined,
Object? $__typename = _undefined,
Object? enable = _undefined,
Object? passwordAuthentication = _undefined,
}) =>
_then(Mutation$ChangeSshSettings$system$changeSshSettings(
code:
code == _undefined || code == null ? _instance.code : (code as int),
message: message == _undefined || message == null
? _instance.message
: (message as String),
success: success == _undefined || success == null
? _instance.success
: (success as bool),
$__typename: $__typename == _undefined || $__typename == null
? _instance.$__typename
: ($__typename as String),
enable: enable == _undefined || enable == null
? _instance.enable
: (enable as bool),
passwordAuthentication: passwordAuthentication == _undefined ||
passwordAuthentication == null
? _instance.passwordAuthentication
: (passwordAuthentication as bool),
));
}
class _CopyWithStubImpl$Mutation$ChangeSshSettings$system$changeSshSettings<
TRes>
implements
CopyWith$Mutation$ChangeSshSettings$system$changeSshSettings<TRes> {
_CopyWithStubImpl$Mutation$ChangeSshSettings$system$changeSshSettings(
this._res);
TRes _res;
call({
int? code,
String? message,
bool? success,
String? $__typename,
bool? enable,
bool? passwordAuthentication,
}) =>
_res;
}

View File

@ -258,6 +258,50 @@ class ServerApi extends GraphQLApiMap
}
}
Future<GenericResult<SshSettings?>> setSshSettings(
final SshSettings settings,
) async {
try {
final GraphQLClient client = await getClient();
final input = Input$SSHSettingsInput(
enable: settings.enable,
passwordAuthentication: settings.passwordAuthentication,
);
final variables = Variables$Mutation$ChangeSshSettings(
settings: input,
);
final mutation = Options$Mutation$ChangeSshSettings(
variables: variables,
);
final result = await client.mutate$ChangeSshSettings(mutation);
if (result.hasException) {
return GenericResult<SshSettings?>(
success: false,
message: result.exception.toString(),
data: null,
);
}
return GenericResult<SshSettings?>(
success: result.parsedData?.system.changeSshSettings.success ?? false,
message: result.parsedData?.system.changeSshSettings.message,
data: result.parsedData == null
? null
: SshSettings(
enable: result.parsedData!.system.changeSshSettings.enable,
passwordAuthentication: result.parsedData!.system
.changeSshSettings.passwordAuthentication,
),
);
} catch (e) {
print(e);
return GenericResult<SshSettings?>(
success: false,
message: e.toString(),
data: null,
);
}
}
Future<SystemSettings> getSystemSettings() async {
QueryResult<Query$SystemSettings> response;
SystemSettings settings = SystemSettings(

View File

@ -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/models/auto_upgrade_settings.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';
import 'package:selfprivacy/logic/models/timezone_settings.dart';
import 'package:selfprivacy/logic/providers/providers_controller.dart';
@ -31,6 +32,7 @@ class ServerDetailsCubit
metadata: state.metadata,
serverTimezone: TimeZoneSettings.fromString(settings.timezone),
autoUpgradeSettings: settings.autoUpgradeSettings,
sshSettings: settings.sshSettings,
),
);
}

View File

@ -52,15 +52,18 @@ class Loaded extends ServerDetailsState {
required super.metadata,
required this.serverTimezone,
required this.autoUpgradeSettings,
required this.sshSettings,
});
final TimeZoneSettings serverTimezone;
final AutoUpgradeSettings autoUpgradeSettings;
final SshSettings sshSettings;
@override
List<Object> get props => [
metadata,
serverTimezone,
autoUpgradeSettings,
sshSettings,
];
@override
@ -68,11 +71,12 @@ class Loaded extends ServerDetailsState {
final List<ServerMetadataEntity>? metadata,
final TimeZoneSettings? serverTimezone,
final AutoUpgradeSettings? autoUpgradeSettings,
final DateTime? checkTime,
final SshSettings? sshSettings,
}) =>
Loaded(
metadata: metadata ?? this.metadata,
serverTimezone: serverTimezone ?? this.serverTimezone,
autoUpgradeSettings: autoUpgradeSettings ?? this.autoUpgradeSettings,
sshSettings: sshSettings ?? this.sshSettings,
);
}

View File

@ -16,6 +16,7 @@ import 'package:selfprivacy/logic/models/json/recovery_token_status.dart';
import 'package:selfprivacy/logic/models/json/server_disk_volume.dart';
import 'package:selfprivacy/logic/models/json/server_job.dart';
import 'package:selfprivacy/logic/models/service.dart';
import 'package:selfprivacy/logic/models/ssh_settings.dart';
import 'package:selfprivacy/logic/models/system_settings.dart';
/// Repository for all API calls
@ -220,6 +221,24 @@ class ApiConnectionRepository {
}
}
Future<(bool, String)> setSshSettings(
final bool enable,
final bool passwordAuthentication,
) async {
final GenericResult<SshSettings?> result = await api.setSshSettings(
SshSettings(
enable: enable,
passwordAuthentication: passwordAuthentication,
),
);
_apiData.settings.invalidate();
if (result.data != null) {
return (true, result.message ?? 'basis.done'.tr());
} else {
return (false, result.message ?? 'jobs.generic_error'.tr());
}
}
void dispose() {
_dataStream.close();
_connectionStatusStream.close();

View File

@ -399,3 +399,47 @@ class ChangeServerTimezoneJob extends ReplaceableJob {
id: id,
);
}
class ChangeSshSettingsJob extends ReplaceableJob {
ChangeSshSettingsJob({
required this.enable,
required this.passwordAuthentication,
super.status,
super.message,
super.id,
}) : super(title: 'jobs.change_ssh_settings'.tr());
final bool enable;
final bool passwordAuthentication;
@override
Future<(bool, String)> execute() async => getIt<ApiConnectionRepository>()
.setSshSettings(enable, passwordAuthentication);
@override
bool shouldRemoveInsteadOfAdd(final List<ClientJob> jobs) {
final currentSettings =
getIt<ApiConnectionRepository>().apiData.settings.data?.sshSettings;
if (currentSettings == null) {
return false;
}
return currentSettings.enable == enable &&
currentSettings.passwordAuthentication == passwordAuthentication;
}
@override
List<Object> get props => [...super.props, enable, passwordAuthentication];
@override
ChangeSshSettingsJob copyWithNewStatus({
required final JobStatusEnum status,
final String? message,
}) =>
ChangeSshSettingsJob(
enable: enable,
passwordAuthentication: passwordAuthentication,
status: status,
message: message,
id: id,
);
}

View File

@ -10,6 +10,8 @@ class _ServerSettings extends StatefulWidget {
class _ServerSettingsState extends State<_ServerSettings> {
bool? allowAutoUpgrade;
bool? rebootAfterUpgrade;
bool? enableSsh;
bool? allowPasswordAuthentication;
@override
Widget build(final BuildContext context) {
@ -24,6 +26,12 @@ class _ServerSettingsState extends State<_ServerSettings> {
rebootAfterUpgrade = serverDetailsState.autoUpgradeSettings.allowReboot;
}
if (enableSsh == null || allowPasswordAuthentication == null) {
enableSsh = serverDetailsState.sshSettings.enable;
allowPasswordAuthentication =
serverDetailsState.sshSettings.passwordAuthentication;
}
return Column(
children: [
SwitchListTile(
@ -105,6 +113,71 @@ class _ServerSettingsState extends State<_ServerSettings> {
);
},
),
SwitchListTile(
value: enableSsh ?? true,
onChanged: (final switched) {
context.read<JobsCubit>().addJob(
ChangeSshSettingsJob(
enable: switched,
passwordAuthentication:
allowPasswordAuthentication ?? false,
),
);
setState(() {
enableSsh = switched;
});
},
title: Text(
'server.enable_ssh'.tr(),
style: TextStyle(
fontStyle: enableSsh != serverDetailsState.sshSettings.enable
? FontStyle.italic
: FontStyle.normal,
),
),
subtitle: Text(
'server.enable_ssh_hint'.tr(),
style: TextStyle(
fontStyle: enableSsh != serverDetailsState.sshSettings.enable
? FontStyle.italic
: FontStyle.normal,
),
),
activeColor: Theme.of(context).colorScheme.primary,
),
SwitchListTile(
value: allowPasswordAuthentication ?? false,
onChanged: (final switched) {
context.read<JobsCubit>().addJob(
ChangeSshSettingsJob(
enable: enableSsh ?? true,
passwordAuthentication: switched,
),
);
setState(() {
allowPasswordAuthentication = switched;
});
},
title: Text(
'server.allow_password_authentication'.tr(),
style: TextStyle(
fontStyle: allowPasswordAuthentication !=
serverDetailsState.sshSettings.passwordAuthentication
? FontStyle.italic
: FontStyle.normal,
),
),
subtitle: Text(
'server.allow_password_authentication_hint'.tr(),
style: TextStyle(
fontStyle: allowPasswordAuthentication !=
serverDetailsState.sshSettings.passwordAuthentication
? FontStyle.italic
: FontStyle.normal,
),
),
activeColor: Theme.of(context).colorScheme.primary,
),
],
);
}

View File

@ -25,11 +25,11 @@ class ServerSettingsScreen extends StatefulWidget {
class _ServerSettingsScreenState extends State<ServerSettingsScreen> {
@override
Widget build(final BuildContext context) => BrandHeroScreen(
hasFlashButton: true,
heroIcon: Icons.settings_outlined,
heroTitle: 'server.settings'.tr(),
children: const [
_ServerSettings(),
],
);
hasFlashButton: true,
heroIcon: Icons.settings_outlined,
heroTitle: 'server.settings'.tr(),
children: const [
_ServerSettings(),
],
);
}

View File

@ -169,89 +169,110 @@ class _SshKeysCard extends StatelessWidget {
final User user;
@override
Widget build(final BuildContext context) => FilledCard(
child: Column(
children: [
ListTileOnSurfaceVariant(
title: 'ssh.title'.tr(),
),
const Divider(height: 0),
ListTileOnSurfaceVariant(
title: 'ssh.create'.tr(),
leadingIcon: Icons.add_circle_outline,
onTap: () {
showModalBottomSheet<void>(
context: context,
isScrollControlled: true,
useRootNavigator: true,
builder: (final BuildContext context) => Padding(
padding: MediaQuery.of(context).viewInsets,
child: NewSshKey(user),
),
);
},
),
Column(
children: user.sshKeys.map((final String key) {
final publicKey =
key.split(' ').length > 1 ? key.split(' ')[1] : key;
final keyType = key.split(' ')[0];
final keyName = key.split(' ').length > 2
? key.split(' ')[2]
: 'ssh.no_key_name'.tr();
return ListTileOnSurfaceVariant(
title: '$keyName ($keyType)',
disableSubtitleOverflow: true,
// do not overflow text
subtitle: publicKey,
onTap: () {
showDialog(
context: context,
builder: (final BuildContext context) => AlertDialog(
title: Text('ssh.delete'.tr()),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('ssh.delete_confirm_question'.tr()),
Text('$keyName ($keyType)'),
Text(publicKey),
],
),
Widget build(final BuildContext context) {
final serverDetailsState = context.watch<ServerDetailsCubit>().state;
final bool sshDisabled =
serverDetailsState is Loaded && !serverDetailsState.sshSettings.enable;
return FilledCard(
child: Column(
children: [
ListTileOnSurfaceVariant(
title: 'ssh.title'.tr(),
),
const Divider(height: 0),
ListTileOnSurfaceVariant(
title: 'ssh.create'.tr(),
leadingIcon: Icons.add_circle_outline,
onTap: () {
showModalBottomSheet<void>(
context: context,
isScrollControlled: true,
useRootNavigator: true,
builder: (final BuildContext context) => Padding(
padding: MediaQuery.of(context).viewInsets,
child: NewSshKey(user),
),
);
},
),
Column(
children: user.sshKeys.map((final String key) {
final publicKey =
key.split(' ').length > 1 ? key.split(' ')[1] : key;
final keyType = key.split(' ')[0];
final keyName = key.split(' ').length > 2
? key.split(' ')[2]
: 'ssh.no_key_name'.tr();
return ListTileOnSurfaceVariant(
title: '$keyName ($keyType)',
disableSubtitleOverflow: true,
// do not overflow text
subtitle: publicKey,
onTap: () {
showDialog(
context: context,
builder: (final BuildContext context) => AlertDialog(
title: Text('ssh.delete'.tr()),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('ssh.delete_confirm_question'.tr()),
Text('$keyName ($keyType)'),
Text(publicKey),
],
),
actions: <Widget>[
TextButton(
child: Text('basis.cancel'.tr()),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: Text(
'basis.delete'.tr(),
style: TextStyle(
color: Theme.of(context).colorScheme.error,
),
),
onPressed: () {
context.read<JobsCubit>().addJob(
DeleteSSHKeyJob(
user: user,
publicKey: key,
),
);
context.popRoute();
},
),
],
),
);
},
);
}).toList(),
actions: <Widget>[
TextButton(
child: Text('basis.cancel'.tr()),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: Text(
'basis.delete'.tr(),
style: TextStyle(
color: Theme.of(context).colorScheme.error,
),
),
onPressed: () {
context.read<JobsCubit>().addJob(
DeleteSSHKeyJob(
user: user,
publicKey: key,
),
);
context.popRoute();
},
),
],
),
);
},
);
}).toList(),
),
if (sshDisabled)
Column(
children: [
const Divider(height: 0),
Padding(
padding: const EdgeInsets.all(8.0),
child: Expanded(
child: InfoBox(
text: 'ssh.ssh_disabled_warning'.tr(),
isWarning: true,
),
),
),
],
),
],
),
);
],
),
);
}
}
class NewSshKey extends StatelessWidget {

View File

@ -9,6 +9,7 @@ import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
import 'package:selfprivacy/logic/cubit/forms/user/ssh_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/user/user_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_detailed_info/server_detailed_info_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/models/hive/user.dart';
import 'package:selfprivacy/logic/models/job.dart';