1+ <?php
2+
3+ /**
4+ * phpIPAM API class to work with devices.
5+ *
6+ *
7+ */
8+ class Devices_controller extends Common_api_functions {
9+
10+ /**
11+ * _params provided.
12+ *
13+ * @var mixed
14+ */
15+ public $ _params ;
16+
17+ /**
18+ * Database object.
19+ *
20+ * @var mixed
21+ */
22+ protected $ Database ;
23+
24+ /**
25+ * Response.
26+ *
27+ * @var mixed
28+ */
29+ protected $ Response ;
30+
31+ /**
32+ * Master Tools object.
33+ *
34+ * @var mixed
35+ */
36+ protected $ Tools ;
37+
38+ /**
39+ * Main Admin class.
40+ *
41+ * @var mixed
42+ */
43+ protected $ Admin ;
44+
45+ /**
46+ * Main Subnets class.
47+ *
48+ * @var mixed
49+ */
50+ protected $ Subnets ;
51+
52+ /**
53+ * Default fields to search.
54+ *
55+ * @var mixed
56+ */
57+ protected $ default_search_fields = ['hostname ' ,'ip_addr ' ,'description ' ];
58+
59+
60+ /**
61+ * __construct function.
62+ *
63+ * @param class $Database
64+ * @param class $Tools
65+ * @param mixed $params // post/get values
66+ * @param class $Response
67+ */
68+ public function __construct ($ Database , $ Tools , $ params , $ Response ) {
69+ $ this ->Database = $ Database ;
70+ $ this ->Response = $ Response ;
71+ $ this ->Tools = $ Tools ;
72+ $ this ->_params = $ params ;
73+
74+ // init required objects
75+ $ this ->init_object ('Admin ' , $ Database );
76+ $ this ->init_object ('Subnets ' , $ Database );
77+
78+ // set valid keys
79+ $ this ->set_valid_keys ("devices " );
80+ }
81+
82+
83+
84+
85+
86+ /**
87+ * Returns json encoded options and version
88+ *
89+ * @access public
90+ * @return void
91+ */
92+ public function OPTIONS () {
93+ // validate
94+ $ this ->validate_options_request ();
95+
96+ // get api
97+ $ app = $ this ->Tools ->fetch_object ('api ' , 'app_id ' , $ this ->_params ->app_id );
98+
99+ // methods
100+ $ result = array ();
101+ $ result ['methods ' ] = array (
102+ array ("href " =>"/api/ " .$ this ->_params ->app_id ."/devices/ " , "methods " =>array (array ("rel " =>"options " , "method " =>"OPTIONS " ))),
103+ array ("href " =>"/api/ " .$ this ->_params ->app_id ."/devices/search/{search_term} " , "methods " =>array (array ("rel " =>"search " , "method " =>"GET " ))),
104+ array ("href " =>"/api/ " .$ this ->_params ->app_id ."/devices/{id}/ " , "methods " =>array (array ("rel " =>"read " , "method " =>"GET " ),
105+ array ("rel " =>"create " , "method " =>"POST " ),
106+ array ("rel " =>"update " , "method " =>"PATCH " ),
107+ array ("rel " =>"delete " , "method " =>"DELETE " ))),
108+ );
109+ # Response
110+ return array ('code ' =>200 , 'data ' =>$ result );
111+ }
112+
113+
114+
115+
116+
117+
118+ /**
119+ * GET devices functions
120+ *
121+ * ID can be:
122+ * - / // returns all devices
123+ * - /{id}/ // returns device details
124+ * - /{id}/{subnets}/ // returns all subnets attached to device
125+ * - /{id}/{addresses}/ // returns all IP addresses attached to device
126+ * - /search/{search_q}/ // searches for devices
127+ *
128+ * @access public
129+ * @return void
130+ */
131+ public function GET () {
132+ // all objects
133+ if (!isset ($ this ->_params ->id )) {
134+ // fetch all devices
135+ $ result = $ this ->Tools ->fetch_all_objects ('devices ' , 'id ' );
136+ // result
137+ if (!$ result ) { return $ this ->Response ->throw_exception (200 , "No devices configured " ); }
138+ else { return array ('code ' =>200 , 'data ' =>$ this ->prepare_result ($ result , 'devices ' , true , false )); }
139+ }
140+ // parameters are set
141+ else {
142+ // search for devices
143+ if ($ this ->_params ->id == 'search ' ) {
144+ // verify that search params are set
145+ if (isset ($ this ->_params ->id2 )) {
146+ // set query
147+ $ base_query = "SELECT * from `devices` where " ;
148+
149+ # Search all custom fields
150+ $ cfs = array_keys ($ this ->Tools ->fetch_custom_fields ('devices ' ));
151+
152+ # Merge default fields with custom fields
153+ $ search_fields = array_merge ($ cfs , $ this ->default_search_fields );
154+
155+ # Using the search fields, build a string to query parameters chained together with " or "
156+ $ search_term = $ this ->_params ->id2 ;
157+ $ extended_query = implode (' or ' , array_map (
158+ function ($ k ) {
159+ return " ` $ k` like ? " ;
160+ }, $ search_fields ));
161+
162+ # Set up an array of parameters to match the query we built
163+ $ query_params = array_fill (0 , count ($ search_fields ), "% $ search_term% " );
164+
165+ # Put together with the base query
166+ $ search_query = $ base_query . $ extended_query ;
167+
168+ # Search query
169+ $ result = $ this ->Database ->getObjectsQuery ($ search_query , $ query_params );
170+
171+ // result
172+ if (!$ result ) { return $ this ->Response ->throw_exception (200 , "No devices found " ); }
173+ else { return array ('code ' =>200 , 'data ' =>$ this ->prepare_result ($ result , 'devices ' , true , false )); }
174+ }
175+ else {
176+ $ this ->Response ->throw_exception (400 , 'No search term given ' );
177+ }
178+ }
179+ // not search
180+ else {
181+ // Id must be numeric
182+ if (!is_numeric ($ this ->_params ->id )) { $ this ->Response ->throw_exception (400 , 'ID must be numeric ' ); }
183+
184+ // additional parameter is set?
185+ if (isset ($ this ->_params ->id2 )) {
186+ // addresses
187+ if ($ this ->_params ->id2 == 'addresses ' ) {
188+ $ result = $ this ->Tools ->fetch_multiple_objects ("ipaddresses " , 'switch ' , $ this ->_params ->id , 'id ' , true );
189+ }
190+ // subnets
191+ elseif ($ this ->_params ->id2 == 'subnets ' ) {
192+ $ result = $ this ->Tools ->fetch_multiple_objects ("subnets " , 'device ' , $ this ->_params ->id , 'id ' , true );
193+ }
194+ // error
195+ else {
196+ $ this ->Response ->throw_exception (400 , 'Invalid parameters ' );
197+ }
198+ }
199+ // device details
200+ else {
201+ // fetch device
202+ $ result = $ this ->Tools ->fetch_object ('devices ' , 'id ' , $ this ->_params ->id );
203+ if (!$ result ) { $ this ->Response ->throw_exception (404 , 'Device not found ' ); }
204+ }
205+
206+ // all ok, prepare result
207+ if ($ result === false ) { return $ this ->Response ->throw_exception (200 , "No " .$ this ->_params ->id2 ." found " ); }
208+ else { return array ('code ' =>200 , 'data ' =>$ this ->prepare_result ($ result , 'devices ' , true , false )); }
209+ }
210+ }
211+ }
212+
213+
214+
215+
216+
217+ /**
218+ * HEAD, no response.
219+ */
220+ public function HEAD () {
221+ return $ this ->GET ();
222+ }
223+
224+
225+
226+
227+ /**
228+ * Creates new device
229+ *
230+ * /devices/
231+ *
232+ * @method POST
233+ */
234+ public function POST () {
235+ # Put incoming keys in order
236+ $ this ->remap_keys ();
237+
238+ # check for valid keys
239+ $ values = $ this ->validate_keys ();
240+
241+ # validations
242+ $ this ->validate_device_type ();
243+
244+ # only 1 parameter ?
245+ if (sizeof ($ values ) == 1 ) { $ this ->Response ->throw_exception (400 , 'No parameters ' ); }
246+
247+ // provide default params if they are not set
248+ if (!isset ($ this ->_params ->sections )) {
249+ $ sections_json = $ this ->get_all_sections_delimited ();
250+ if ($ sections_json !==false ) {
251+ $ values ['sections ' ] = $ sections_json ;
252+ }
253+ }
254+
255+ // execute update
256+ if (!$ this ->Admin ->object_modify ('devices ' , 'add ' , '' , $ values )) {
257+ { $ this ->Response ->throw_exception (500 , 'Device creation failed ' ); }
258+ }
259+ else {
260+ //set result
261+ return array ("code " =>201 , "message " =>"Device created " , "id " =>$ this ->Admin ->lastId , "location " =>"/api/ " .$ this ->_params ->app_id ."/devices/ " .$ this ->Admin ->lastId ."/ " );
262+ }
263+ }
264+
265+
266+
267+
268+
269+
270+ /**
271+ * Update device details
272+ *
273+ * @method PATCH
274+ */
275+ public function PATCH (){
276+ # Put incoming keys back in order
277+ $ this ->remap_keys ();
278+
279+ # validations
280+ $ this ->validate_device_type ();
281+
282+ # validate and prepare keys
283+ $ values = $ this ->validate_keys ();
284+
285+ # only 1 parameter ?
286+ if (sizeof ($ values ) == 1 ) { $ this ->Response ->throw_exception (400 , 'No parameters ' ); }
287+
288+ # execute update
289+ if (!$ this ->Admin ->object_modify ('devices ' , 'edit ' , 'id ' , $ values )) {
290+ $ this ->Response ->throw_exception (500 , 'Device edit failed ' );
291+ } else {
292+ // fetch the updated object and hand it back to the client
293+ return array ("code " =>200 , "message " =>"Device updated " , "id " =>$ this ->Admin ->lastId , "location " =>"/api/ " .$ this ->_params ->app_id ."/devices/ " .$ values ['id ' ]."/ " );
294+ }
295+ }
296+
297+
298+
299+
300+
301+
302+ /**
303+ * Delete existing device
304+ *
305+ * @method DELETE
306+ */
307+ public function DELETE () {
308+ # set variables for delete
309+ $ values = array ();
310+ $ values ['id ' ] = $ this ->_params ->id ;
311+
312+ # check that section exists
313+ if ($ this ->Admin ->fetch_object ("devices " , "id " , $ this ->_params ->id )===false )
314+ { $ this ->Response ->throw_exception (404 , "Device does not exist " ); }
315+
316+ # execute delete
317+ if (!$ this ->Admin ->object_modify ('devices ' , 'delete ' , 'id ' , $ values )) {
318+ $ this ->Response ->throw_exception (500 , 'Device delete failed ' );
319+ }
320+ else {
321+ // delete all references
322+ $ this ->Admin ->remove_object_references ('ipaddresses ' , 'switch ' , $ this ->_params ->id );
323+
324+ // set result
325+ return array ("code " =>200 , "message " =>"Device deleted " );
326+ }
327+ }
328+
329+
330+
331+
332+
333+
334+ /**
335+ * Validate device type
336+ *
337+ * @method validate_device_type
338+ * @return [type] [description]
339+ */
340+ private function validate_device_type () {
341+ if (isset ($ this ->_params ->type )) {
342+ // numeric
343+ if (!is_numeric ($ this ->_params ->type )) {
344+ $ this ->Response ->throw_exception (400 , 'Invalid devicetype identifier ' );
345+ }
346+ // check
347+ if ($ this ->Tools ->fetch_object ('deviceTypes ' , 'id ' , $ this ->_params ->type ) === false ) {
348+ $ this ->Response ->throw_exception (400 , 'Device type does not exist ' );
349+ }
350+ }
351+ }
352+
353+ /**
354+ * Create delimited string from all sections for default permissions
355+ *
356+ * @method get_all_sections_delimited
357+ * @return [type] [description]
358+ */
359+ private function get_all_sections_delimited () {
360+ $ sections = $ this ->Admin ->fetch_all_objects ("sections " );
361+ // reformat
362+ if ($ sections !==false ) {
363+ $ sections_all = array ();
364+ foreach ($ sections as $ s ) {
365+ $ sections_all [$ s ->id ] = $ s ->id ;
366+ }
367+ $ sections = implode ("; " ,$ sections_all );
368+ }
369+ // return
370+ return $ sections ;
371+ }
372+ }
0 commit comments