Skip to content

Commit c4d1a53

Browse files
PhotoboothPhotobooth
authored andcommitted
feat(usb-sync): sudoers, Move2USB verification, manual copy
- Installer/setup: sudoers.d 021 for www-data mount/umount; polkit and sudoers decoupled; remove legacy 020 rule. - remotebuzzer Move2USB: expect copy.chk at USB root after rsync; check spawn errors. - en.json: synctodrive and Move2USB manual strings; fix Automated typo. Made-with: Cursor
1 parent 61b24b0 commit c4d1a53

File tree

5 files changed

+40
-154
lines changed

5 files changed

+40
-154
lines changed

assets/js/remotebuzzer-server.js

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,7 @@ function move2usbAction() {
592592
log('ERROR: Could not parse config, aborting move2usb');
593593
return;
594594
}
595+
copySuccess = false;
595596
log('USB target ', parsedConfig.drive);
596597

597598
const getDriveInfo = ({ drive }) => {
@@ -909,12 +910,10 @@ function move2usbAction() {
909910

910911
fs.writeFileSync(path.join(dataAbsPath, 'copy.chk'), '', { flag: 'w' });
911912

912-
if (fs.existsSync(path.join(drive.mountpoint, 'data/copy.chk'))) {
913+
const usbCheckfile = path.join(drive.mountpoint, 'copy.chk');
914+
if (fs.existsSync(usbCheckfile)) {
913915
log(' ');
914-
log(
915-
'[WARNING] Last sync might not completed, Checkfile exists:',
916-
path.join(drive.mountpoint, 'data/copy.chk')
917-
);
916+
log('[WARNING] Move2USB: stale copy.chk already on USB before rsync:', usbCheckfile);
918917
log(' ');
919918
}
920919

@@ -951,26 +950,30 @@ function move2usbAction() {
951950

952951
log('Executing command: <', cmd, '>');
953952

954-
try {
955-
spawnSync(cmd, {
956-
shell: '/bin/bash',
957-
stdio: 'ignore'
958-
});
959-
} catch (err) {
960-
log('ERROR: Could not start rsync:', err.toString());
953+
const rsyncResult = spawnSync(cmd, {
954+
shell: '/bin/bash',
955+
stdio: 'ignore'
956+
});
957+
if (rsyncResult.error) {
958+
log('ERROR: Could not start rsync:', rsyncResult.error.toString());
959+
960+
return;
961+
}
962+
if (rsyncResult.status !== 0) {
963+
log('ERROR: rsync exited with code ' + rsyncResult.status);
961964

962965
return;
963966
}
964967

965968
log('Sync completed');
966969

967-
if (fs.existsSync(path.join(drive.mountpoint, 'data/copy.chk'))) {
970+
if (fs.existsSync(usbCheckfile)) {
968971
copySuccess = true;
969972
} else {
970973
log(' ');
971974
log(
972-
'[ERROR] Sync error, sync might be not successfull. Checkfile does not exist:',
973-
path.join(drive.mountpoint, 'data/copy.chk')
975+
'[ERROR] Move2USB: sync verification failed (copy.chk missing on USB after rsync, expected at):',
976+
usbCheckfile
974977
);
975978
log(' ');
976979
copySuccess = false;
@@ -979,7 +982,7 @@ function move2usbAction() {
979982
}
980983

981984
try {
982-
fs.unlinkSync(path.join(drive.mountpoint, 'data/copy.chk'));
985+
fs.unlinkSync(usbCheckfile);
983986
} catch (err) {
984987
log('Warning: Could not remove checkfile from USB: ' + err.message);
985988
}

assets/js/sync-to-drive.js

100644100755
File mode changed.

install-photobooth.sh

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,17 +1269,20 @@ EOF
12691269
}
12701270

12711271
function install_usb_sudoers() {
1272-
local sudoers_file="/etc/sudoers.d/020_www-data-usb"
1273-
1272+
local sudoers_file="/etc/sudoers.d/021_www-data-usb-sync"
1273+
# Match manual helper scripts/setup-usb-sync.sh (portable paths; some distros use /bin vs /usr/bin).
12741274
cat >"$sudoers_file" <<'EOF'
1275-
# Photobooth USB sync: allow www-data to mount, unmount and create mountpoints
1276-
www-data ALL=(ALL) NOPASSWD: /usr/bin/mount, /usr/bin/umount, /usr/bin/mkdir -p /media/*
1275+
# Photobooth USB Sync — passwordless mount/umount/mkdir for www-data (sync-to-drive.js, move2usb).
1276+
# Use together with Polkit rules for udisksctl; this covers sudo fallbacks in the Node scripts.
1277+
Cmnd_Alias PHOTOBOOTH_USB_SYNC = /bin/mount, /usr/bin/mount, /bin/umount, /usr/bin/umount, /bin/mkdir -p /media/*, /usr/bin/mkdir -p /media/*
1278+
www-data ALL=(root) NOPASSWD: PHOTOBOOTH_USB_SYNC
12771279
EOF
12781280

12791281
chmod 440 "$sudoers_file"
12801282

12811283
if visudo -cf "$sudoers_file" >/dev/null 2>&1; then
12821284
info "Setup" "Installed USB sudoers rule for www-data at $sudoers_file"
1285+
rm -f /etc/sudoers.d/020_www-data-usb 2>/dev/null || true
12831286
return 0
12841287
else
12851288
error "Invalid sudoers file created at $sudoers_file. Please check manually."
@@ -1324,12 +1327,14 @@ function remove_polkit_usb_rule() {
13241327
local PKLA_FILE="/etc/polkit-1/localauthority/50-local.d/photobooth.pkla"
13251328
local RULES_FILE="/etc/polkit-1/rules.d/photobooth.rules"
13261329
local LEGACY_RULES_FILE="/etc/polkit-1/rules.d/50-photobooth-udisks.rules"
1327-
local SUDOERS_FILE="/etc/sudoers.d/020_www-data-usb"
1330+
local SUDOERS_FILE_LEGACY="/etc/sudoers.d/020_www-data-usb"
1331+
local SUDOERS_FILE="/etc/sudoers.d/021_www-data-usb-sync"
13281332
local REMOVED=false
13291333

13301334
[[ -f "$PKLA_FILE" ]] && rm -f "$PKLA_FILE" && REMOVED=true
13311335
[[ -f "$RULES_FILE" ]] && rm -f "$RULES_FILE" && REMOVED=true
13321336
[[ -f "$LEGACY_RULES_FILE" ]] && rm -f "$LEGACY_RULES_FILE" && REMOVED=true
1337+
[[ -f "$SUDOERS_FILE_LEGACY" ]] && rm -f "$SUDOERS_FILE_LEGACY" && REMOVED=true
13331338
[[ -f "$SUDOERS_FILE" ]] && rm -f "$SUDOERS_FILE" && REMOVED=true
13341339

13351340
$REMOVED && return 0 || return 1
@@ -1404,18 +1409,15 @@ function disable_automount() {
14041409

14051410
function set_usb_sync() {
14061411
if whiptail --title "USB Sync" \
1407-
--yesno "Setup USB Sync policy?\n\nThis is needed to use the USB Sync feature of Photobooth.\nUSB Sync can be activated via Adminpanel." \
1412+
--yesno "Setup USB Sync policy?\n\nInstalls Polkit rules for udisksctl and sudoers for mount/umount/mkdir as www-data.\nAlso tries to disable desktop auto-mount to avoid permission conflicts.\nUSB Sync is enabled in the Admin panel." \
14081413
12 60; then
14091414

1410-
if create_polkit_usb_rule; then
1411-
install_usb_sudoers
1412-
if disable_automount; then
1413-
confirm "USB Sync" "USB Sync policy created and auto mount settings updated successfully."
1414-
else
1415-
confirm "USB Sync" "USB Sync policy created, but no configuration file was found to adjust auto mount."
1416-
fi
1415+
create_polkit_usb_rule || warn "Polkit USB rule could not be created; udisksctl may still need manual policy."
1416+
install_usb_sudoers || warn "USB sudoers rule could not be installed; sudo mount fallbacks may fail."
1417+
if disable_automount; then
1418+
confirm "USB Sync" "USB Sync policy and auto-mount adjustments applied."
14171419
else
1418-
confirm "USB Sync" "Failed to create USB Sync policy!"
1420+
confirm "USB Sync" "USB Sync Polkit/sudoers applied; no pcmanfm volume config found to adjust auto-mount."
14191421
fi
14201422

14211423
else

resources/lang/en.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,7 @@
718718
"manual:remotebuzzer:remotebuzzer_custombutton": "If enabled, custom button action can be triggered via HTTP request.",
719719
"manual:remotebuzzer:remotebuzzer_enable_standalonegallery": "Controls whether the rotary encoder HTTP endpoints are active on the standalone gallery view.",
720720
"manual:remotebuzzer:remotebuzzer_input_device": "Linux input device for hardware triggers (e.g. /dev/input/by-id/...). Uses the per-action key codes (picture/collage/custom/print/video) to map incoming key events.",
721-
"manual:remotebuzzer:remotebuzzer_move2usbbutton": "If enabled, Move2USB can be triggered via HTTP request.",
721+
"manual:remotebuzzer:remotebuzzer_move2usbbutton": "If enabled, Move2USB can be triggered via HTTP request. Uses the same USB device identifier as USB Sync (<code>synctodrive</code> target in the admin panel). Requires the same Linux mount permissions as USB Sync (Polkit/sudoers for <code>www-data</code>; see USB Sync manual).",
722722
"manual:remotebuzzer:remotebuzzer_picturebutton": "If enabled, picrure can be triggered via HTTP request.",
723723
"manual:remotebuzzer:remotebuzzer_port": "Server TCP Port - example 14711.",
724724
"manual:remotebuzzer:remotebuzzer_printbutton": "If enabled, print can be triggered via HTTP request.",
@@ -758,9 +758,9 @@
758758
"manual:sound:sound_fallback_enabled": "Use EN sounds as fallback if the current language is not supported yet",
759759
"manual:sound:sound_test": "Play a random test sound",
760760
"manual:sound:sound_voice": "Which voice to use for sounds",
761-
"manual:synctodrive:synctodrive_enabled": "Enable automatic syncing of new pictures to USB device using rsync",
762-
"manual:synctodrive:synctodrive_interval": "Seconds to trigger syncing as interval",
763-
"manual:synctodrive:synctodrive_target": "Pattern to identify USB device either by USB stick name (e.g. <code>photobooth</code>), device full path (e.g <code>/dev/sda1</code>) or device subsystem (e.g. <code>sda</code>).",
761+
"manual:synctodrive:synctodrive_enabled": "Enable automatic syncing of new pictures to a USB device using rsync. On Linux the web server user (<code>www-data</code>) must be allowed to mount the stick: the Photobooth install wizard can install Polkit rules and passwordless sudo for <code>mount</code>/<code>umount</code> (Permissions → USB Sync policy, or during install via general permissions). You can also run <code>scripts/setup-usb-sync.sh</code> as root after updates. Use a labelled FAT32 or exFAT volume where the label matches the identifier below.",
762+
"manual:synctodrive:synctodrive_interval": "Seconds between automatic sync attempts (interval while the USB Sync process is running).",
763+
"manual:synctodrive:synctodrive_target": "Pattern to identify the USB device: usually the volume label of the stick (e.g. <code>photobooth</code>), or the block device path (e.g. <code>/dev/sda1</code>) or short name (e.g. <code>sda1</code>). Must match a removable USB device.",
764764
"manual:theme_title": "Use the Themes box to save current theme fields, load another, export a ZIP (config + referenced images), or import that ZIP to install a theme. Import or save will overwrite an existing theme with the same name.",
765765
"manual:userinterface:background_admin": "Enter the path to the admin panel background image.",
766766
"manual:userinterface:background_chroma": "Enter the path to the chroma keying background image.",
@@ -1068,7 +1068,7 @@
10681068
"success": "Successful!",
10691069
"synctodrive": "USB Sync",
10701070
"synctodrive:synctodrive_enabled": "Enable",
1071-
"synctodrive:synctodrive_interval": "Autmated syncing interval",
1071+
"synctodrive:synctodrive_interval": "Automated syncing interval",
10721072
"synctodrive:synctodrive_target": "USB device identifier",
10731073
"takeCollage": "Collage",
10741074
"takePhoto": "Picture",

scripts/setup-usb-sync.sh

Lines changed: 0 additions & 119 deletions
This file was deleted.

0 commit comments

Comments
 (0)