$group) { Database::exec("UPDATE remoteaccess_group SET groupname = :name, wolcount = :wol, passwd = :passwd, active = :active WHERE groupid = :id", [ 'id' => $id, 'name' => $group['groupname'] ?? $id, 'wol' => $group['wolcount'] ?? 0, 'passwd' => $group['passwd'] ?? 0, 'active' => (int)($group['active'] ?? 0), ]); } Message::addSuccess('settings-saved'); } elseif ($action === 'save-settings') { User::assertPermission('set-proxy-ip'); Property::set(RemoteAccess::PROP_ALLOWED_VNC_NET, Request::post('allowed-source', '', 'string')); Property::set(RemoteAccess::PROP_TRY_VIRT_HANDOVER, Request::post('virt-handover', false, 'int')); Property::set(RemoteAccess::PROP_VNC_PORT, Request::post('vncport', 5900, 'int')); Message::addSuccess('settings-saved'); } elseif ($action === 'delete-group') { User::assertPermission('group.edit'); $groupid = Request::post('groupid', Request::REQUIRED, 'int'); $group = $this->groupNameOrFail($groupid); if (!$this->checkGroupLocations($groupid)) { Message::addError('locations-not-allowed', $group); } else { Database::exec("DELETE FROM remoteaccess_group WHERE groupid = :id", ['id' => $groupid]); Message::addSuccess('group-deleted', $group); } } elseif ($action === 'set-locations') { User::assertPermission('group.locations'); $groupid = Request::post('groupid', Request::REQUIRED, 'int'); $group = $this->groupNameOrFail($groupid); $locations = array_values(Request::post('location', [], 'array')); // Merge what's already set where we don't have permission $locations = Permission::mergeWithDisallowed($locations, 'group.locations', "SELECT locationid FROM remoteaccess_x_location WHERE groupid = :id", ['id' => $groupid]); if (empty($locations)) { Database::exec("DELETE FROM remoteaccess_x_location WHERE groupid = :id", ['id' => $groupid]); } else { Database::exec("INSERT IGNORE INTO remoteaccess_x_location (groupid, locationid) VALUES :values", ['values' => array_map(function($item) use ($groupid) { return [$groupid, $item]; }, $locations)]); Database::exec("DELETE FROM remoteaccess_x_location WHERE groupid = :id AND locationid NOT IN (:locations)", ['id' => $groupid, 'locations' => $locations]); } Message::addSuccess('group-updated', $group); } if (Request::isPost()) { Util::redirect('?do=remoteaccess'); } } private function groupNameOrFail($groupid) { $group = Database::queryFirst("SELECT groupname FROM remoteaccess_group WHERE groupid = :id", ['id' => $groupid]); if ($group === false) { Message::addError('group-not-found', $groupid); Util::redirect('?do=remoteaccess'); } return $group['groupname']; } protected function doRender() { $groupid = Request::get('groupid', false, 'int'); if ($groupid === false) { // Edit list of groups and their settings $groups = Database::queryAll("SELECT g.groupid, g.groupname, g.wolcount, g.passwd, Count(l.locationid) AS locs, If(g.active, 'checked', '') AS checked, unwoken FROM remoteaccess_group g LEFT JOIN remoteaccess_x_location l USING (groupid) GROUP BY g.groupid, g.groupname ORDER BY g.groupname ASC"); $data = [ 'allowed-source' => Property::get(RemoteAccess::PROP_ALLOWED_VNC_NET), 'virt-handover_checked' => Property::get(RemoteAccess::PROP_TRY_VIRT_HANDOVER) ? 'checked' : '', 'vncport' => Property::get(RemoteAccess::PROP_VNC_PORT, 5900), 'groups' => $groups, ]; $data['plugin_version'] = Property::get(RemoteAccess::PROP_PLUGIN_VERSION); Permission::addGlobalTags($data['perms'], null, ['group.locations', 'group.add', 'group.edit', 'set-proxy-ip']); // List of locations used in at least one group $res = Database::simpleQuery("SELECT l.locationid, l.locationname, g.groupid, g.groupname, g.active FROM location l INNER JOIN remoteaccess_x_location rxl USING (locationid) INNER JOIN remoteaccess_group g USING (groupid) ORDER BY locationname, locationid"); $data['locations'] = []; $last = null; foreach ($res as $row) { if ($last === null || $last['locationid'] !== $row['locationid']) { unset($last); $last = [ 'locationid' => $row['locationid'], 'locationname' => $row['locationname'], 'lclass' => 'slx-strike', 'groups' => [], ]; $data['locations'][] =& $last; } $last['groups'][] = [ 'groupid' => $row['groupid'], 'groupname' => $row['groupname'], 'gclass' => $row['active'] ? '' : 'slx-strike', ]; if ($row['active']) { $last['lclass'] = ''; } } unset($last); $this->addSchedulerTags($data['locations']); Render::addTemplate('edit-settings', $data); } else { // Edit locations for group $group = $this->groupNameOrFail($groupid); $locationList = Location::getLocationsAssoc(); $enabled = RemoteAccess::getEnabledLocations($groupid, false); $allowed = User::getAllowedLocations('group.locations'); foreach ($enabled as $lid) { if (isset($locationList[$lid])) { $locationList[$lid]['checked'] = 'checked'; } } $this->addSchedulerTags($locationList); foreach ($locationList as $lid => &$loc) { if (!in_array($lid, $allowed)) { $loc['disabled'] = 'disabled'; } } $data = [ 'groupid' => $groupid, 'groupname' => $group, 'locations' => array_values($locationList), 'disabled' => empty($allowed) ? 'disabled' : '', ]; Permission::addGlobalTags($data['perms'], null, ['group.locations', 'group.edit']); Render::addTemplate('edit-group', $data); } } /** * @param int $groupid group to check * @return bool if we have permission for all the locations assigned to group */ private function checkGroupLocations(int $groupid): bool { $allowed = User::getAllowedLocations('group.locations'); if (in_array(0, $allowed)) return true; $hasLocs = Database::queryColumnArray("SELECT locationid FROM remoteaccess_x_location WHERE groupid = :id", ['id' => $groupid]); $diff = array_diff($hasLocs, $allowed); return empty($diff); } private function addSchedulerTags(array &$locationList) { if (!Module::isAvailable('rebootcontrol')) return; foreach ($locationList as $lid => &$loc) { $options = Scheduler::getLocationOptions($loc['locationid'] ?? $lid); if ($options['ra-mode'] === Scheduler::RA_SELECTIVE) { $loc['ra_selective'] = true; } elseif ($options['ra-mode'] === Scheduler::RA_NEVER) { $loc['ra_never'] = true; } } } }