diff --git a/doc/API/DeviceGroups.md b/doc/API/DeviceGroups.md index 99fca0f92d..8dbdd389e8 100644 --- a/doc/API/DeviceGroups.md +++ b/doc/API/DeviceGroups.md @@ -97,6 +97,72 @@ Output: } ``` +### `update_devicegroup` + +Updates a device group. + +Route: `/api/v0/devicegroups/:name` + +- name Is the name of the device group which can be obtained using + [`get_devicegroups`](#function-get_devicegroups). Please ensure that + the name is urlencoded if it needs to be (i.e Linux Servers would + need to be urlencoded. + +Input (JSON): + +- `name`: *optional* - The name of the device group +- `type`: *optional* - should be `static` or `dynamic`. Setting this to static + requires that the devices input be provided +- `desc`: *optional* - Description of the device group +- `rules`: *required if type == dynamic* - A set of rules to determine which + devices should be included in this device group +- `devices`: *required if type == static* - A list of devices that should be + included in this group. This is a static list of devices + +Examples: + +```curl +curl -X PATCH -d '{"name": "NewLinuxServers"}' -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/LinuxServers +``` + +Output: + +```json +{ + "status": "ok", + "message": "Device group LinuxServers updated" +} +``` + +### `delete_devicegroup` + +Deletes a device group. + +Route: `/api/v0/devicegroups/:name` + +- name Is the name of the device group which can be obtained using + [`get_devicegroups`](#function-get_devicegroups). Please ensure that + the name is urlencoded if it needs to be (i.e Linux Servers would + need to be urlencoded. + +Input: + +- + +Examples: + +```curl +curl -X DELETE -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices/LinuxServers +``` + +Output: + +```json +{ + "status": "ok", + "message": "Device group LinuxServers deleted" +} +``` ### `get_devices_by_group` diff --git a/includes/html/api_functions.inc.php b/includes/html/api_functions.inc.php index b3552d54e3..4f8beaef34 100644 --- a/includes/html/api_functions.inc.php +++ b/includes/html/api_functions.inc.php @@ -2233,6 +2233,88 @@ function add_device_group(Illuminate\Http\Request $request) return api_success($deviceGroup->id, 'id', 'Device group ' . $deviceGroup->name . ' created', 201); } +function update_device_group(Illuminate\Http\Request $request) +{ + $data = json_decode($request->getContent(), true); + if (json_last_error() || ! is_array($data)) { + return api_error(400, "We couldn't parse the provided json. " . json_last_error_msg()); + } + + $name = $request->route('name'); + if (! $name) { + return api_error(400, 'No device group name provided'); + } + + $deviceGroup = ctype_digit($name) ? DeviceGroup::find($name) : DeviceGroup::where('name', $name)->first(); + + if (! $deviceGroup) { + return api_error(404, "Device group $name not found"); + } + + $rules = [ + 'name' => 'sometimes|string|unique:device_groups', + 'desc' => 'sometimes|string', + 'type' => 'sometimes|in:dynamic,static', + 'devices' => 'array|required_if:type,static', + 'devices.*' => 'integer', + 'rules' => 'json|required_if:type,dynamic', + ]; + + $v = Validator::make($data, $rules); + if ($v->fails()) { + return api_error(422, $v->messages()); + } + + if (! empty($data['rules'])) { + // Only use the rules if they are able to be parsed by the QueryBuilder + $query = QueryBuilderParser::fromJson($data['rules'])->toSql(); + if (empty($query)) { + return api_error(500, "We couldn't parse your rule"); + } + } + + $validatedData = $v->safe()->only(['name', 'desc', 'type']); + $deviceGroup->fill($validatedData); + + if ($deviceGroup->type == 'static' && array_key_exists('devices', $data)) { + $deviceGroup->devices()->sync($data['devices']); + } + + if ($deviceGroup->type == 'dynamic' && ! empty($data['rules'])) { + $deviceGroup->rules = json_decode($data['rules']); + } + + try { + $deviceGroup->save(); + } catch (\Illuminate\Database\QueryException $e) { + return api_error(500, 'Failed to save changes device group'); + } + + return api_success_noresult(200, "Device group $name updated"); +} + +function delete_device_group(Illuminate\Http\Request $request) +{ + $name = $request->route('name'); + if (! $name) { + return api_error(400, 'No device group name provided'); + } + + $deviceGroup = ctype_digit($name) ? DeviceGroup::find($name) : DeviceGroup::where('name', $name)->first(); + + if (! $deviceGroup) { + return api_error(404, "Device group $name not found"); + } + + $deleted = $deviceGroup->delete(); + + if (! $deleted) { + return api_error(500, "Device group $name could not be removed"); + } + + return api_success_noresult(200, "Device group $name deleted"); +} + function update_device_group_add_devices(Illuminate\Http\Request $request) { $data = json_decode($request->getContent(), true); diff --git a/routes/api.php b/routes/api.php index 48e1f2aece..90e8769b42 100644 --- a/routes/api.php +++ b/routes/api.php @@ -68,6 +68,8 @@ Route::prefix('v0')->namespace('\App\Api\Controllers')->group(function () { }); Route::prefix('devicegroups')->group(function () { + Route::patch('{name}', 'LegacyApiController@update_device_group')->name('update_device_group'); + Route::delete('{name}', 'LegacyApiController@delete_device_group')->name('delete_device_group'); Route::post('{name}/devices', 'LegacyApiController@update_device_group_add_devices')->name('update_device_group_add_devices'); Route::delete('{name}/devices', 'LegacyApiController@update_device_group_remove_devices')->name('update_device_group_remove_devices'); Route::post('{name}/maintenance', 'LegacyApiController@maintenance_devicegroup')->name('maintenance_devicegroup');