mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
fixins
This commit is contained in:
@@ -7,7 +7,7 @@ const logger = require('../../globals/logger').child('liftService');
|
||||
const { loadConfig } = require('../../helpers/configLoader');
|
||||
const { isFeatureEnabled } = require('../../helpers/features');
|
||||
const { getMode, MODES } = require('../modeManager');
|
||||
const { isLockdownAdmin } = require('../roleService');
|
||||
const { isAdmin, isLockdownAdmin } = require('../roleService');
|
||||
const {
|
||||
homeAssistantEvents,
|
||||
getRawEntitySnapshot,
|
||||
@@ -186,13 +186,20 @@ if (featureEnabled) {
|
||||
homeAssistantEvents.on('status', emitUpdate);
|
||||
|
||||
io.on('connection', (socket) => {
|
||||
function assertFeatureAccess() {
|
||||
const mode = getMode();
|
||||
// Lift is a public activity feature in open and turns modes. Restricted
|
||||
// access modes mirror the rest of the server: admin mode admits normal
|
||||
// admins, while lockdown admits only the explicitly stronger lockdown
|
||||
// role. Enforcing this in the owning service keeps UI buttons and text
|
||||
// command behavior aligned instead of trusting individual callers.
|
||||
if (mode === MODES.ADMIN && !isAdmin(socket)) throw new Error('Admin mode: admins only');
|
||||
if (mode === MODES.LOCKDOWN && !isLockdownAdmin(socket)) throw new Error('Server in lockdown');
|
||||
}
|
||||
|
||||
socket.on('lift:up', async (_, cb = () => {}) => {
|
||||
try {
|
||||
if (getMode() === MODES.LOCKDOWN && !isLockdownAdmin(socket)) {
|
||||
throw new Error('Server in lockdown');
|
||||
}
|
||||
// Lift movement is now a public activity feature. Lockdown still wins
|
||||
// above because that mode is the global safety/admin gate for the room.
|
||||
assertFeatureAccess();
|
||||
const resp = await moveUp(socket.id || 'socket');
|
||||
cb({ success: true, ...resp });
|
||||
} catch (err) {
|
||||
@@ -202,11 +209,7 @@ if (featureEnabled) {
|
||||
|
||||
socket.on('lift:down', async (_, cb = () => {}) => {
|
||||
try {
|
||||
if (getMode() === MODES.LOCKDOWN && !isLockdownAdmin(socket)) {
|
||||
throw new Error('Server in lockdown');
|
||||
}
|
||||
// Public access intentionally mirrors lift:up so both directions share
|
||||
// the same policy and cannot drift into different permission behavior.
|
||||
assertFeatureAccess();
|
||||
const resp = await moveDown(socket.id || 'socket');
|
||||
cb({ success: true, ...resp });
|
||||
} catch (err) {
|
||||
|
||||
@@ -8,7 +8,7 @@ const { loadConfig } = require('../../helpers/configLoader');
|
||||
const { isFeatureEnabled } = require('../../helpers/features');
|
||||
const { isVerified } = require('../verificationService');
|
||||
const { getMode, MODES } = require('../modeManager');
|
||||
const { isLockdownAdmin } = require('../roleService');
|
||||
const { isAdmin, isLockdownAdmin } = require('../roleService');
|
||||
const {
|
||||
homeAssistantEvents,
|
||||
getRawEntitySnapshot,
|
||||
@@ -269,17 +269,19 @@ function hasVerifiedSockets() {
|
||||
|
||||
if (featureEnabled) {
|
||||
io.on('connection', (socket) => {
|
||||
function assertLockdownAccess() {
|
||||
if (getMode() === MODES.LOCKDOWN && !isLockdownAdmin(socket)) {
|
||||
throw new Error('Server in lockdown');
|
||||
}
|
||||
function assertFeatureAccess() {
|
||||
const mode = getMode();
|
||||
// Neato shares the same public-activity policy as lift: everyone may use
|
||||
// it in open/turns modes, admin mode requires an admin, and lockdown
|
||||
// requires a lockdown admin. This service-level gate protects every socket
|
||||
// action even if a future client bypasses the current UI presentation.
|
||||
if (mode === MODES.ADMIN && !isAdmin(socket)) throw new Error('Admin mode: admins only');
|
||||
if (mode === MODES.LOCKDOWN && !isLockdownAdmin(socket)) throw new Error('Server in lockdown');
|
||||
}
|
||||
|
||||
socket.on('neato:start', async (_, cb = () => {}) => {
|
||||
try {
|
||||
assertLockdownAccess();
|
||||
// Neato commands are public activity features. The lockdown check above
|
||||
// remains the room-wide safety/admin gate when the server is restricted.
|
||||
assertFeatureAccess();
|
||||
await startCleaning();
|
||||
cb({ success: true });
|
||||
} catch (err) {
|
||||
@@ -289,8 +291,7 @@ if (featureEnabled) {
|
||||
|
||||
socket.on('neato:sendHome', async (_, cb = () => {}) => {
|
||||
try {
|
||||
assertLockdownAccess();
|
||||
// Keep send-home public for consistency with the rest of the Neato card.
|
||||
assertFeatureAccess();
|
||||
await sendHome();
|
||||
cb({ success: true });
|
||||
} catch (err) {
|
||||
@@ -300,8 +301,7 @@ if (featureEnabled) {
|
||||
|
||||
socket.on('neato:locate', async (_, cb = () => {}) => {
|
||||
try {
|
||||
assertLockdownAccess();
|
||||
// Locate is a public activity action; lockdown still blocks it above.
|
||||
assertFeatureAccess();
|
||||
await locateRobot();
|
||||
cb({ success: true });
|
||||
} catch (err) {
|
||||
@@ -311,9 +311,7 @@ if (featureEnabled) {
|
||||
|
||||
socket.on('neato:clearErrors', async (_, cb = () => {}) => {
|
||||
try {
|
||||
assertLockdownAccess();
|
||||
// Error clearing is grouped with the public Neato controls so the UI does
|
||||
// not show a button that only some public users can actually run.
|
||||
assertFeatureAccess();
|
||||
await clearErrors();
|
||||
cb({ success: true });
|
||||
} catch (err) {
|
||||
@@ -323,9 +321,7 @@ if (featureEnabled) {
|
||||
|
||||
socket.on('neato:powerCycle', async (_, cb = () => {}) => {
|
||||
try {
|
||||
assertLockdownAccess();
|
||||
// Power cycle follows the same public policy as the rest of the card;
|
||||
// operational safety remains controlled by lockdown mode.
|
||||
assertFeatureAccess();
|
||||
await powerCycle();
|
||||
cb({ success: true });
|
||||
} catch (err) {
|
||||
|
||||
@@ -97,8 +97,19 @@ function createCommandHandlers(deps) {
|
||||
// light locking belongs here because it can force the physical room lights
|
||||
// on and disables ordinary Home Assistant room controls for everyone else.
|
||||
const moderationActions = new Set(['lock', 'unlock', 'mode', 'goal', 'reason', 'verify', 'deter', 'lights', 'kick', 'lift', 'neato']);
|
||||
const isAccessModeCommand = commandDefinition?.permission === 'access-mode';
|
||||
|
||||
if (!isAdmin && action !== '' && action !== 'status' && action !== 'help' && action !== 'replay' && action !== 'bridge' && action !== 'goal' && action !== 'reason' && action !== 'verify' && action !== 'deter') {
|
||||
// Feature commands are public activities while access is open or managed
|
||||
// by turns. In admin mode they follow the same admin-only boundary as rover
|
||||
// access, and lockdown continues to require the stricter lockdown role.
|
||||
// Keeping this policy in the shared dispatcher makes web chat and Discord
|
||||
// behave identically instead of each transport interpreting modes itself.
|
||||
if (isAccessModeCommand && mode === MODES.ADMIN && !isAdmin) {
|
||||
await request.reply({ content: 'Admin mode: only admins can run feature commands.', allowedMentions: { parse: [], repliedUser: false } });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAccessModeCommand && !isAdmin && action !== '' && action !== 'status' && action !== 'help' && action !== 'replay' && action !== 'bridge' && action !== 'goal' && action !== 'reason' && action !== 'verify' && action !== 'deter') {
|
||||
await request.reply({ content: 'Only admins can run that command.', allowedMentions: { parse: [], repliedUser: false } });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ function buildCommandRegistry(prefix, timeCommand) {
|
||||
kick: { category: 'admin', summary: 'Remove a user from their current rover.', usage: [`${prefix} kick <user> [reason]`], access: 'Admin', permission: 'admin' },
|
||||
verify: { category: 'admin', summary: 'List or remove verified identities.', usage: [`${prefix} verify list`, `${prefix} verify remove <identity>`], access: 'Lockdown admin', permission: 'lockdown-admin' },
|
||||
deter: { category: 'admin', summary: 'List, add, or remove identity deterrence.', usage: [`${prefix} deter list`, `${prefix} deter ban <identity>`, `${prefix} deter unban <identity>`], access: 'Lockdown admin', permission: 'lockdown-admin' },
|
||||
lift: { category: 'features', summary: 'Show or move the lift.', usage: [`${prefix} lift <status|up|down>`], access: 'Admin', permission: 'admin', requiredFeature: 'lift', unavailableLabel: 'Lift' },
|
||||
neato: { category: 'features', summary: 'Show or control Neato.', usage: [`${prefix} neato <status|start|home|locate|clear-errors>`], access: 'Admin', permission: 'admin', requiredFeature: 'neato', unavailableLabel: 'Neato' },
|
||||
lift: { category: 'features', summary: 'Show or move the lift.', usage: [`${prefix} lift <status|up|down>`], access: 'Public unless server access is restricted', permission: 'access-mode', requiredFeature: 'lift', unavailableLabel: 'Lift' },
|
||||
neato: { category: 'features', summary: 'Show or control Neato.', usage: [`${prefix} neato <status|start|home|locate|clear-errors>`], access: 'Public unless server access is restricted', permission: 'access-mode', requiredFeature: 'neato', unavailableLabel: 'Neato' },
|
||||
bridge: { category: 'discord', summary: 'Configure this Discord server chat bridge.', usage: [`${prefix} bridge`, `${prefix} bridge here <global|private>`, `${prefix} bridge mode <global|private>`, `${prefix} bridge off`], access: 'Discord server manager' },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
1. assign rovers based on battery percentage, give people highest one
|
||||
2. add admin ui for VIP and private requests instead of only through discord
|
||||
3. make overcurrent limiter speed sensitive, slower fill at lower speeds
|
||||
4. add feature chat commands, like /neato start, /lift up, etc
|
||||
5. add more background gap themes
|
||||
6. fix this:
|
||||
4. add more background gap themes
|
||||
5. fix this:
|
||||
`Jun 18 15:14:18 roombaserver.local node[216731]: /home/daniel/MultiRoombaRover/server/src/services/roverManager/socketHandlers.js:92
|
||||
Jun 18 15:14:18 roombaserver.local node[216731]: cb({ error: err.message });
|
||||
Jun 18 15:14:18 roombaserver.local node[216731]: ^
|
||||
|
||||
Reference in New Issue
Block a user