Skip to content

Commit

Permalink
feat: settings: removing prefs undoes sudoers patch
Browse files Browse the repository at this point in the history
  • Loading branch information
alexVinarskis committed Feb 23, 2024
1 parent 81ebf89 commit 3b85be7
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 16 deletions.
17 changes: 17 additions & 0 deletions lib/classes/sudoers_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,19 @@ import '../configs/environment.dart';
class SudoersManager {
static final _shell = Shell(verbose: Environment.runningDebug, throwOnError: false);
static const sudoersPatchCmd = 'export PATH="${Constants.apiPathLinux}:\$PATH" && echo "ALL ALL=(ALL) NOPASSWD: \$(which cctk)" | sudo tee /etc/sudoers.d/${Constants.applicationPackageName}';
static const sudoersUnpatchCmd = 'sudo rm -f /etc/sudoers.d/${Constants.applicationPackageName}';
static bool? runningSudo;

static final List<Function()> _callbacksSudoersChanged = [];
static void addCallbacksSudoersChanged(var callback) { _callbacksSudoersChanged.add(callback); }
static void removeCallbacksSudoersChanged(var callback) { _callbacksSudoersChanged.remove(callback); }
static void _callSudoersChanged() {
var dubList = List.from(_callbacksSudoersChanged);
for (var callback in dubList) {
callback();
}
}

static Future<bool> verifySudo() async {
ProcessResult pr;
if (Platform.isLinux) {
Expand All @@ -26,6 +37,12 @@ class SudoersManager {

static Future<bool> patchSudoers() async {
ProcessResult pr = (await _shell.run('''pkexec bash -c '$sudoersPatchCmd' '''))[0];
_callSudoersChanged();
return pr.exitCode == 0;
}
static Future<bool> unpatchSudoers() async {
ProcessResult pr = (await _shell.run('''pkexec bash -c '$sudoersUnpatchCmd' '''))[0];
_callSudoersChanged();
return pr.exitCode == 0;
}
}
49 changes: 33 additions & 16 deletions lib/components/notification_sudoers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,53 +41,70 @@ class NotificationSudoersState extends State<NotificationSudoers> {
void initState() {
super.initState();
ApiCCTK.addCallbacksDepsChanged(_handleApiStateUpdate);
SudoersManager.addCallbacksSudoersChanged(_handleSudoersChanged);
}

@override
void dispose() {
ApiCCTK.removeCallbacksDepsChanged(_handleApiStateUpdate);
SudoersManager.removeCallbacksSudoersChanged(_handleSudoersChanged);
super.dispose();
}

void _handleSudoersChanged() {
SudoersManager.verifySudo().then((runningSudo) => _handleSudoersState(runningSudo));
}
void _handleApiStateUpdate(bool apiReady) {
if (!apiReady) {
return;
}
SudoersManager.verifySudo().then((runningSudo) => _handleSudoersState(runningSudo));
ApiCCTK.removeCallbacksDepsChanged(_handleApiStateUpdate);
_handleSudoersChanged();
}

void _handleSudoersState(bool runningSudo) {
/* Was hidden already, ignore */
if (runningSudo && _sudoersState == SudoersState.hidden) {
return;
}
/* Freshly successfully patched, but not running sudo */
if (!runningSudo && _sudoersState == SudoersState.patchingSucceededNoRestart) {
setState(() {
_sudoersState = SudoersState.patchingSucceededRestart;
});
return;
}
/* Succeeded, and it was not hidden yet */
if (runningSudo) {
ApiCCTK.requestUpdate();
Timer(const Duration(seconds: 3), () {
if (mounted) {
setState(() {
_sudoersState = SudoersState.hidden;
});
}
});
return;
}
/* Did not succeed, but reason is known, ignore */
if (_sudoersState == SudoersState.patchingSucceededRestart || _sudoersState == SudoersState.patchingFailed) {
return;
}
/* Did not succeed, reason is unknown */
setState(() {
_sudoersState = SudoersState.awaiting;
});
ApiCCTK.removeCallbacksDepsChanged(_handleApiStateUpdate);
}

void _patchSudoers() async {
setState(() {
_sudoersState = SudoersState.patching;
});
bool patched = await SudoersManager.patchSudoers();
final bool patched = await SudoersManager.patchSudoers();
if (patched) {
setState(() {
_sudoersState = SudoersState.patchingSucceededNoRestart;
});
bool runningSudo = await SudoersManager.verifySudo();
if (runningSudo) {
ApiCCTK.requestUpdate();
Timer(const Duration(seconds: 3), () {
setState(() {
_sudoersState = SudoersState.hidden;
});
});
} else {
setState(() {
_sudoersState = SudoersState.patchingSucceededRestart;
});
}
} else {
setState(() {
_sudoersState = SudoersState.patchingFailed;
Expand Down
6 changes: 6 additions & 0 deletions lib/components/settings_modal.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
Expand All @@ -8,6 +9,7 @@ import 'package:url_launcher/url_launcher.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import '../classes/bios_protection_manager.dart';
import '../classes/ota_manager.dart';
import '../classes/sudoers_manager.dart';
import '../configs/constants.dart';


Expand Down Expand Up @@ -288,6 +290,10 @@ class SettingsModal {
/* Erase saved preferences and cached variables */
SharedPreferences preferences = await SharedPreferences.getInstance();
await preferences.clear();
/* Undo sudoers patch, if applied, do NOT await */
if (Platform.isLinux) {
SudoersManager.unpatchSudoers();
}
/* Re-initialize settings modal, to reflect changes */
setState(() {
settingIntanceKey = UniqueKey();
Expand Down

0 comments on commit 3b85be7

Please sign in to comment.