197 lines
7.1 KiB
Dart
197 lines
7.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
|
|
import '../../../../core/constants/route_constants.dart';
|
|
import '../../../../shared/widgets/app_button.dart';
|
|
import '../../../../shared/widgets/app_text_field.dart';
|
|
import '../../domain/entities/app_settings.dart';
|
|
import '../providers/settings_provider.dart';
|
|
import '../widgets/settings_widgets.dart';
|
|
import '../../../../shared/widgets/app_toast.dart';
|
|
|
|
class SecuritySettingsScreen extends ConsumerStatefulWidget {
|
|
const SecuritySettingsScreen({super.key});
|
|
|
|
@override
|
|
ConsumerState<SecuritySettingsScreen> createState() =>
|
|
_SecuritySettingsScreenState();
|
|
}
|
|
|
|
class _SecuritySettingsScreenState extends ConsumerState<SecuritySettingsScreen> {
|
|
final _formKey = GlobalKey<FormState>();
|
|
late final TextEditingController _minPasswordController;
|
|
late final TextEditingController _passwordExpiryController;
|
|
late final TextEditingController _sessionTimeoutController;
|
|
late final TextEditingController _loginAttemptController;
|
|
late final TextEditingController _lockDurationController;
|
|
late final TextEditingController _ipWhitelistController;
|
|
late bool _otpEnabled;
|
|
late bool _mfaEnabled;
|
|
late bool _autoLogout;
|
|
late bool _concurrentLogin;
|
|
late bool _auditLogging;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
final security = ref.read(appSettingsProvider).security;
|
|
_minPasswordController =
|
|
TextEditingController(text: '${security.minPasswordLength}');
|
|
_passwordExpiryController =
|
|
TextEditingController(text: '${security.passwordExpiryDays}');
|
|
_sessionTimeoutController =
|
|
TextEditingController(text: '${security.sessionTimeoutMinutes}');
|
|
_loginAttemptController =
|
|
TextEditingController(text: '${security.loginAttemptLimit}');
|
|
_lockDurationController =
|
|
TextEditingController(text: '${security.accountLockDurationMinutes}');
|
|
_ipWhitelistController = TextEditingController(text: security.ipWhitelist);
|
|
_otpEnabled = security.otpEnabled;
|
|
_mfaEnabled = security.mfaEnabled;
|
|
_autoLogout = security.autoLogout;
|
|
_concurrentLogin = security.concurrentLoginControl;
|
|
_auditLogging = security.auditLoggingEnabled;
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_minPasswordController.dispose();
|
|
_passwordExpiryController.dispose();
|
|
_sessionTimeoutController.dispose();
|
|
_loginAttemptController.dispose();
|
|
_lockDurationController.dispose();
|
|
_ipWhitelistController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
Future<void> _save() async {
|
|
if (!_formKey.currentState!.validate()) return;
|
|
|
|
await ref.read(appSettingsProvider.notifier).updateSecurity(
|
|
SecuritySettingsConfig(
|
|
minPasswordLength: int.parse(_minPasswordController.text.trim()),
|
|
passwordExpiryDays: int.parse(_passwordExpiryController.text.trim()),
|
|
otpEnabled: _otpEnabled,
|
|
mfaEnabled: _mfaEnabled,
|
|
sessionTimeoutMinutes:
|
|
int.parse(_sessionTimeoutController.text.trim()),
|
|
autoLogout: _autoLogout,
|
|
concurrentLoginControl: _concurrentLogin,
|
|
loginAttemptLimit: int.parse(_loginAttemptController.text.trim()),
|
|
accountLockDurationMinutes:
|
|
int.parse(_lockDurationController.text.trim()),
|
|
auditLoggingEnabled: _auditLogging,
|
|
ipWhitelist: _ipWhitelistController.text.trim(),
|
|
),
|
|
);
|
|
|
|
if (mounted) {
|
|
showAppToastFromSnackBar(context,
|
|
const SnackBar(content: Text('Security settings saved')),
|
|
);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return SettingsPageLayout(
|
|
title: 'Security Settings',
|
|
subtitle: 'Authentication, session, and audit policies',
|
|
actions: [
|
|
TextButton.icon(
|
|
onPressed: () => context.push(RouteConstants.changePassword),
|
|
icon: const Icon(Icons.password),
|
|
label: const Text('Change Password'),
|
|
),
|
|
],
|
|
child: Form(
|
|
key: _formKey,
|
|
child: Column(
|
|
children: [
|
|
SettingsFormCard(
|
|
title: 'Authentication',
|
|
children: [
|
|
AppTextField(
|
|
controller: _minPasswordController,
|
|
label: 'Minimum Password Length',
|
|
keyboardType: TextInputType.number,
|
|
),
|
|
const SizedBox(height: 16),
|
|
AppTextField(
|
|
controller: _passwordExpiryController,
|
|
label: 'Password Expiry Days',
|
|
keyboardType: TextInputType.number,
|
|
),
|
|
SettingsSwitchTile(
|
|
title: 'OTP Enable/Disable',
|
|
value: _otpEnabled,
|
|
onChanged: (v) => setState(() => _otpEnabled = v),
|
|
),
|
|
SettingsSwitchTile(
|
|
title: 'MFA Enable/Disable',
|
|
value: _mfaEnabled,
|
|
onChanged: (v) => setState(() => _mfaEnabled = v),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 16),
|
|
SettingsFormCard(
|
|
title: 'Session Settings',
|
|
children: [
|
|
AppTextField(
|
|
controller: _sessionTimeoutController,
|
|
label: 'Session Timeout (Minutes)',
|
|
keyboardType: TextInputType.number,
|
|
),
|
|
SettingsSwitchTile(
|
|
title: 'Auto Logout',
|
|
value: _autoLogout,
|
|
onChanged: (v) => setState(() => _autoLogout = v),
|
|
),
|
|
SettingsSwitchTile(
|
|
title: 'Concurrent Login Control',
|
|
value: _concurrentLogin,
|
|
onChanged: (v) => setState(() => _concurrentLogin = v),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 16),
|
|
SettingsFormCard(
|
|
title: 'Security Policies',
|
|
children: [
|
|
AppTextField(
|
|
controller: _loginAttemptController,
|
|
label: 'Login Attempt Limit',
|
|
keyboardType: TextInputType.number,
|
|
),
|
|
const SizedBox(height: 16),
|
|
AppTextField(
|
|
controller: _lockDurationController,
|
|
label: 'Account Lock Duration (Minutes)',
|
|
keyboardType: TextInputType.number,
|
|
),
|
|
const SizedBox(height: 16),
|
|
AppTextField(
|
|
controller: _ipWhitelistController,
|
|
label: 'IP Whitelist',
|
|
hint: '192.168.1.1, 10.0.0.0/24',
|
|
maxLines: 2,
|
|
),
|
|
SettingsSwitchTile(
|
|
title: 'Audit Logging',
|
|
subtitle: 'Track login, asset changes, and allocations',
|
|
value: _auditLogging,
|
|
onChanged: (v) => setState(() => _auditLogging = v),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 24),
|
|
AppButton(label: 'Save Changes', onPressed: _save),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|