Passed
Push — master ( 844492...7c39ee )
by
unknown
09:45 queued 11s
created

core.gateway.GatewayCollection.on_get()   C

Complexity

Conditions 9

Size

Total Lines 46
Code Lines 38

Duplication

Lines 16
Ratio 34.78 %

Importance

Changes 0
Metric Value
eloc 38
dl 16
loc 46
rs 6.6346
c 0
b 0
f 0
cc 9
nop 2
1
import uuid
2
from datetime import datetime, timezone, timedelta
3
import falcon
4
import mysql.connector
5
import simplejson as json
6
from core.useractivity import user_logger, admin_control
7
import config
8
9
10
class GatewayCollection:
11
    """
12
    Gateway Collection Resource
13
14
    This class handles CRUD operations for gateway collection.
15
    It provides endpoints for listing all gateways and creating new gateways.
16
    Gateways represent communication interfaces for data collection in the energy management system.
17
    """
18
    def __init__(self):
19
        """Initialize GatewayCollection"""
20
        pass
21
22
    @staticmethod
23
    def on_options(req, resp):
24
        """Handle OPTIONS requests for CORS preflight"""
25
        _ = req
26
        resp.status = falcon.HTTP_200
27
28
    @staticmethod
29
    def on_get(req, resp):
30
        admin_control(req)
31
        search_query = req.get_param('q', default=None)
32
        if search_query is not None and len(search_query.strip()) > 0:
33
            search_query = search_query.strip()
34
        else:
35
            search_query = ''
36
37
        cnx = mysql.connector.connect(**config.myems_system_db)
38
        cursor = cnx.cursor()
39
        query = (" SELECT id, name, uuid, token, last_seen_datetime_utc, description "
40
                 " FROM tbl_gateways ")
41
        params = []
42
        if search_query:
43
            query += " WHERE name LIKE %s OR description LIKE %s "
44
            params = [f'%{search_query}%', f'%{search_query}%']
45
        query += " ORDER BY id "
46
        cursor.execute(query, params)
47
        rows = cursor.fetchall()
48
        cursor.close()
49
        cnx.close()
50
51
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
52
        if config.utc_offset[0] == '-':
53
            timezone_offset = -timezone_offset
54
55
        result = list()
56 View Code Duplication
        if rows is not None and len(rows) > 0:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
57
            for row in rows:
58
                if isinstance(row[4], datetime):
59
                    last_seen_datetime_local = row[4].replace(tzinfo=timezone.utc) + \
60
                                               timedelta(minutes=timezone_offset)
61
                    last_seen_datetime = last_seen_datetime_local.isoformat()[0:19]
62
                else:
63
                    last_seen_datetime = None
64
                meta_result = {"id": row[0],
65
                               "name": row[1],
66
                               "uuid": row[2],
67
                               "token": row[3],
68
                               "last_seen_datetime": last_seen_datetime,
69
                               "description": row[5]
70
                               }
71
                result.append(meta_result)
72
73
        resp.text = json.dumps(result)
74
75 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
76
    @user_logger
77
    def on_post(req, resp):
78
        """Handles POST requests"""
79
        admin_control(req)
80
        try:
81
            raw_json = req.stream.read().decode('utf-8')
82
        except Exception as ex:
83
            print(str(ex))
84
            raise falcon.HTTPError(status=falcon.HTTP_400,
85
                                   title='API.BAD_REQUEST',
86
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
87
88
        new_values = json.loads(raw_json)
89
90
        if 'name' not in new_values['data'].keys() or \
91
                not isinstance(new_values['data']['name'], str) or \
92
                len(str.strip(new_values['data']['name'])) == 0:
93
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
94
                                   description='API.INVALID_GATEWAY_NAME')
95
        name = str.strip(new_values['data']['name'])
96
97
        if 'description' in new_values['data'].keys() and \
98
                new_values['data']['description'] is not None and \
99
                len(str(new_values['data']['description'])) > 0:
100
            description = str.strip(new_values['data']['description'])
101
        else:
102
            description = None
103
104
        cnx = mysql.connector.connect(**config.myems_system_db)
105
        cursor = cnx.cursor()
106
107
        cursor.execute(" SELECT name "
108
                       " FROM tbl_gateways "
109
                       " WHERE name = %s ", (name,))
110
        if cursor.fetchone() is not None:
111
            cursor.close()
112
            cnx.close()
113
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
114
                                   description='API.GATEWAY_NAME_IS_ALREADY_IN_USE')
115
116
        add_values = (" INSERT INTO tbl_gateways (name, uuid, token, description) "
117
                      " VALUES (%s, %s, %s, %s) ")
118
        cursor.execute(add_values, (name,
119
                                    str(uuid.uuid4()),
120
                                    str(uuid.uuid4()),
121
                                    description))
122
        new_id = cursor.lastrowid
123
        cnx.commit()
124
        cursor.close()
125
        cnx.close()
126
127
        resp.status = falcon.HTTP_201
128
        resp.location = '/gateways/' + str(new_id)
129
130
131
class GatewayItem:
132
    def __init__(self):
133
        pass
134
135
    @staticmethod
136
    def on_options(req, resp, id_):
137
        _ = req
138
        resp.status = falcon.HTTP_200
139
        _ = id_
140
141 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
142
    def on_get(req, resp, id_):
143
        admin_control(req)
144
        if not id_.isdigit() or int(id_) <= 0:
145
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
146
                                   description='API.INVALID_GATEWAY_ID')
147
148
        cnx = mysql.connector.connect(**config.myems_system_db)
149
        cursor = cnx.cursor()
150
151
        query = (" SELECT id, name, uuid, token, last_seen_datetime_utc, description "
152
                 " FROM tbl_gateways "
153
                 " WHERE id = %s ")
154
        cursor.execute(query, (id_,))
155
        row = cursor.fetchone()
156
        cursor.close()
157
        cnx.close()
158
        if row is None:
159
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
160
                                   description='API.GATEWAY_NOT_FOUND')
161
162
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
163
        if config.utc_offset[0] == '-':
164
            timezone_offset = -timezone_offset
165
166
        if isinstance(row[4], datetime):
167
            last_seen_datetime_local = row[4].replace(tzinfo=timezone.utc) + \
168
                                       timedelta(minutes=timezone_offset)
169
            last_seen_datetime = last_seen_datetime_local.isoformat()[0:19]
170
        else:
171
            last_seen_datetime = None
172
173
        result = {"id": row[0],
174
                  "name": row[1],
175
                  "uuid": row[2],
176
                  "token": row[3],
177
                  "last_seen_datetime": last_seen_datetime,
178
                  "description": row[5]}
179
180
        resp.text = json.dumps(result)
181
182
    @staticmethod
183
    @user_logger
184
    def on_delete(req, resp, id_):
185
        admin_control(req)
186
        if not id_.isdigit() or int(id_) <= 0:
187
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
188
                                   description='API.INVALID_GATEWAY_ID')
189
190
        cnx = mysql.connector.connect(**config.myems_system_db)
191
        cursor = cnx.cursor()
192
193
        cursor.execute(" SELECT name "
194
                       " FROM tbl_gateways "
195
                       " WHERE id = %s ", (id_,))
196
        if cursor.fetchone() is None:
197
            cursor.close()
198
            cnx.close()
199
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
200
                                   description='API.GATEWAY_NOT_FOUND')
201
202
        # check if this gateway is being used by any data sources
203
        cursor.execute(" SELECT name "
204
                       " FROM tbl_data_sources "
205
                       " WHERE gateway_id = %s "
206
                       " LIMIT 1 ",
207
                       (id_,))
208
        if cursor.fetchone() is not None:
209
            cursor.close()
210
            cnx.close()
211
            raise falcon.HTTPError(status=falcon.HTTP_400,
212
                                   title='API.BAD_REQUEST',
213
                                   description='API.THERE_IS_RELATION_WITH_DATA_SOURCES')
214
215
        cursor.execute(" DELETE FROM tbl_gateways WHERE id = %s ", (id_,))
216
        cnx.commit()
217
218
        cursor.close()
219
        cnx.close()
220
        resp.status = falcon.HTTP_204
221
222 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
223
    @user_logger
224
    def on_put(req, resp, id_):
225
        """Handles PUT requests"""
226
        admin_control(req)
227
        try:
228
            raw_json = req.stream.read().decode('utf-8')
229
        except Exception as ex:
230
            print(str(ex))
231
            raise falcon.HTTPError(status=falcon.HTTP_400,
232
                                   title='API.BAD_REQUEST',
233
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
234
235
        if not id_.isdigit() or int(id_) <= 0:
236
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
237
                                   description='API.INVALID_GATEWAY_ID')
238
239
        new_values = json.loads(raw_json)
240
241
        if 'name' not in new_values['data'].keys() or \
242
                not isinstance(new_values['data']['name'], str) or \
243
                len(str.strip(new_values['data']['name'])) == 0:
244
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
245
                                   description='API.INVALID_GATEWAY_NAME')
246
        name = str.strip(new_values['data']['name'])
247
248
        if 'description' in new_values['data'].keys() and \
249
                new_values['data']['description'] is not None and \
250
                len(str(new_values['data']['description'])) > 0:
251
            description = str.strip(new_values['data']['description'])
252
        else:
253
            description = None
254
255
        cnx = mysql.connector.connect(**config.myems_system_db)
256
        cursor = cnx.cursor()
257
258
        cursor.execute(" SELECT name "
259
                       " FROM tbl_gateways "
260
                       " WHERE id = %s ", (id_,))
261
        if cursor.fetchone() is None:
262
            cursor.close()
263
            cnx.close()
264
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
265
                                   description='API.GATEWAY_NOT_FOUND')
266
267
        cursor.execute(" SELECT name "
268
                       " FROM tbl_gateways "
269
                       " WHERE name = %s AND id != %s ", (name, id_))
270
        if cursor.fetchone() is not None:
271
            cursor.close()
272
            cnx.close()
273
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
274
                                   description='API.GATEWAY_NAME_IS_ALREADY_IN_USE')
275
276
        update_row = (" UPDATE tbl_gateways "
277
                      " SET name = %s, description = %s "
278
                      " WHERE id = %s ")
279
        cursor.execute(update_row, (name,
280
                                    description,
281
                                    id_,))
282
        cnx.commit()
283
284
        cursor.close()
285
        cnx.close()
286
287
        resp.status = falcon.HTTP_200
288
289
290
class GatewayDataSourceCollection:
291
    def __init__(self):
292
        pass
293
294
    @staticmethod
295
    def on_options(req, resp, id_):
296
        _ = req
297
        resp.status = falcon.HTTP_200
298
        _ = id_
299
300
    @staticmethod
301
    def on_get(req, resp, id_):
302
        admin_control(req)
303
        if not id_.isdigit() or int(id_) <= 0:
304
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
305
                                   description='API.INVALID_GATEWAY_ID')
306
307
        cnx = mysql.connector.connect(**config.myems_system_db)
308
        cursor = cnx.cursor()
309
310
        cursor.execute(" SELECT name "
311
                       " FROM tbl_gateways "
312
                       " WHERE id = %s ", (id_,))
313
        if cursor.fetchone() is None:
314
            cursor.close()
315
            cnx.close()
316
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
317
                                   description='API.GATEWAY_NOT_FOUND')
318
319
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
320
        if config.utc_offset[0] == '-':
321
            timezone_offset = -timezone_offset
322
323
        result = list()
324
        query_data_source = (" SELECT id, name, uuid, "
325
                             "         protocol, connection, last_seen_datetime_utc, description "
326
                             " FROM tbl_data_sources "
327
                             " WHERE gateway_id = %s "
328
                             " ORDER BY name ")
329
        cursor.execute(query_data_source, (id_,))
330
        rows_data_source = cursor.fetchall()
331 View Code Duplication
        if rows_data_source is not None and len(rows_data_source) > 0:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
332
            for row in rows_data_source:
333
                if isinstance(row[5], datetime):
334
                    last_seen_datetime_local = row[5].replace(tzinfo=timezone.utc) + \
335
                                               timedelta(minutes=timezone_offset)
336
                    last_seen_datetime = last_seen_datetime_local.isoformat()[0:19]
337
                else:
338
                    last_seen_datetime = None
339
                meta_result = {"id": row[0],
340
                               "name": row[1],
341
                               "uuid": row[2],
342
                               "protocol": row[3],
343
                               "connection": row[4],
344
                               "last_seen_datetime": last_seen_datetime,
345
                               "description": row[6]
346
                               }
347
                result.append(meta_result)
348
349
        cursor.close()
350
        cnx.close()
351
        resp.text = json.dumps(result)
352
353
354
class GatewayExport:
355
356
    def __init__(self):
357
        pass
358
359
    @staticmethod
360
    def on_options(req, resp, id_):
361
        _ = req
362
        resp.status = falcon.HTTP_200
363
        _ = id_
364
365 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
366
    def on_get(req, resp, id_):
367
        admin_control(req)
368
        if not id_.isdigit() or int(id_) <= 0:
369
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
370
                                   description='API.INVALID_GATEWAY_ID')
371
372
        cnx = mysql.connector.connect(**config.myems_system_db)
373
        cursor = cnx.cursor()
374
375
        query = (" SELECT id, name, uuid, token, last_seen_datetime_utc, description "
376
                 " FROM tbl_gateways "
377
                 " WHERE id = %s ")
378
        cursor.execute(query, (id_,))
379
        row = cursor.fetchone()
380
        cursor.close()
381
        cnx.close()
382
        if row is None:
383
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
384
                                   description='API.GATEWAY_NOT_FOUND')
385
386
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
387
        if config.utc_offset[0] == '-':
388
            timezone_offset = -timezone_offset
389
390
        if isinstance(row[4], datetime):
391
            last_seen_datetime_local = row[4].replace(tzinfo=timezone.utc) + \
392
                                       timedelta(minutes=timezone_offset)
393
            last_seen_datetime = last_seen_datetime_local.isoformat()[0:19]
394
        else:
395
            last_seen_datetime = None
396
397
        result = {"id": row[0],
398
                  "name": row[1],
399
                  "uuid": row[2],
400
                  "token": row[3],
401
                  "last_seen_datetime": last_seen_datetime,
402
                  "description": row[5]}
403
404
        resp.text = json.dumps(result)
405
406
407
class GatewayImport:
408
    def __init__(self):
409
        pass
410
411
    @staticmethod
412
    def on_options(req, resp):
413
        _ = req
414
        resp.status = falcon.HTTP_200
415
416
    @staticmethod
417
    @user_logger
418
    def on_post(req, resp):
419
        """Handles POST requests"""
420
        admin_control(req)
421
        try:
422
            raw_json = req.stream.read().decode('utf-8')
423
        except Exception as ex:
424
            print(str(ex))
425
            raise falcon.HTTPError(status=falcon.HTTP_400,
426
                                   title='API.BAD_REQUEST',
427
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
428
429
        new_values = json.loads(raw_json)
430
431
        if 'name' not in new_values.keys() or \
432
                not isinstance(new_values['name'], str) or \
433
                len(str.strip(new_values['name'])) == 0:
434
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
435
                                   description='API.INVALID_GATEWAY_NAME')
436
        name = str.strip(new_values['name'])
437
438
        if 'description' in new_values.keys() and \
439
                new_values['description'] is not None and \
440
                len(str(new_values['description'])) > 0:
441
            description = str.strip(new_values['description'])
442
        else:
443
            description = None
444
445
        cnx = mysql.connector.connect(**config.myems_system_db)
446
        cursor = cnx.cursor()
447
448
        cursor.execute(" SELECT name "
449
                       " FROM tbl_gateways "
450
                       " WHERE name = %s ", (name,))
451
        if cursor.fetchone() is not None:
452
            cursor.close()
453
            cnx.close()
454
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
455
                                   description='API.GATEWAY_NAME_IS_ALREADY_IN_USE')
456
457
        add_values = (" INSERT INTO tbl_gateways (name, uuid, token, description) "
458
                      " VALUES (%s, %s, %s, %s) ")
459
        cursor.execute(add_values, (name,
460
                                    str(uuid.uuid4()),
461
                                    str(uuid.uuid4()),
462
                                    description))
463
        new_id = cursor.lastrowid
464
        cnx.commit()
465
        cursor.close()
466
        cnx.close()
467
468
        resp.status = falcon.HTTP_201
469
        resp.location = '/gateways/' + str(new_id)
470
471
472
class GatewayClone:
473
    def __init__(self):
474
        pass
475
476
    @staticmethod
477
    def on_options(req, resp, id_):
478
        _ = req
479
        resp.status = falcon.HTTP_200
480
        _ = id_
481
482
    @staticmethod
483
    @user_logger
484
    def on_post(req, resp, id_):
485
        admin_control(req)
486
        if not id_.isdigit() or int(id_) <= 0:
487
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
488
                                   description='API.INVALID_GATEWAY_ID')
489
490
        cnx = mysql.connector.connect(**config.myems_system_db)
491
        cursor = cnx.cursor()
492
493
        query = (" SELECT id, name, uuid, token, last_seen_datetime_utc, description "
494
                 " FROM tbl_gateways "
495
                 " WHERE id = %s ")
496
        cursor.execute(query, (id_,))
497
        row = cursor.fetchone()
498
        if row is None:
499
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
500
                                   description='API.GATEWAY_NOT_FOUND')
501
502
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
503
        if config.utc_offset[0] == '-':
504
            timezone_offset = -timezone_offset
505
506
        if isinstance(row[4], datetime):
507
            last_seen_datetime_local = row[4].replace(tzinfo=timezone.utc) + \
508
                                       timedelta(minutes=timezone_offset)
509
            last_seen_datetime = last_seen_datetime_local.isoformat()[0:19]
510
        else:
511
            last_seen_datetime = None
512
513
        result = {"id": row[0],
514
                  "name": row[1],
515
                  "uuid": row[2],
516
                  "token": row[3],
517
                  "last_seen_datetime": last_seen_datetime,
518
                  "description": row[5]}
519
        new_name = (str.strip(result['name']) +
520
                    (datetime.utcnow() + timedelta(minutes=timezone_offset)).isoformat(sep='-', timespec='seconds'))
521
        add_values = (" INSERT INTO tbl_gateways (name, uuid, token, description) "
522
                      " VALUES (%s, %s, %s, %s) ")
523
        cursor.execute(add_values, (new_name,
524
                                    str(uuid.uuid4()),
525
                                    str(uuid.uuid4()),
526
                                    result['description']))
527
        new_id = cursor.lastrowid
528
        cnx.commit()
529
        cursor.close()
530
        cnx.close()
531
532
        resp.status = falcon.HTTP_201
533
        resp.location = '/gateways/' + str(new_id)
534