core.notification.NotificationItem.on_get()   F
last analyzed

Complexity

Conditions 17

Size

Total Lines 84
Code Lines 63

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 63
nop 3
dl 0
loc 84
rs 1.8
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like core.notification.NotificationItem.on_get() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import falcon
2
import json
3
import mysql.connector
4
import config
5
from datetime import datetime, timedelta, timezone
6
7
8
class NotificationCollection:
9
    @staticmethod
10
    def __init__():
11
        pass
12
13
    @staticmethod
14
    def on_options(req, resp):
15
        resp.status = falcon.HTTP_200
16
17
    @staticmethod
18
    def on_get(req, resp):
19
        status = req.params.get('status')
20
        start_datetime_local = req.params.get('startdatetime')
21
        end_datetime_local = req.params.get('enddatetime')
22
        if status is not None:
23
            status = str.strip(status)
24
            if status not in ['unread', 'read', 'archived']:
25
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_STATUS')
26
27
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
28
        if config.utc_offset[0] == '-':
29
            timezone_offset = -timezone_offset
30
        start_datetime_utc = None
31
        if start_datetime_local is not None and len(str.strip(start_datetime_local)) > 0:
32
            start_datetime_local = str.strip(start_datetime_local)
33
            try:
34
                start_datetime_utc = datetime.strptime(start_datetime_local,
35
                                                       '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
36
                                     timedelta(minutes=timezone_offset)
37
            except ValueError:
38
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
39
                                       description="API.INVALID_START_DATETIME")
40
41
        end_datetime_utc = None
42
        if end_datetime_local is not None and len(str.strip(end_datetime_local)) > 0:
43
            end_datetime_local = str.strip(end_datetime_local)
44
            try:
45
                end_datetime_utc = datetime.strptime(end_datetime_local,
46
                                                     '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
47
                                        timedelta(minutes=timezone_offset)
48
            except ValueError:
49
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
50
                                       description="API.INVALID_END_DATETIME")
51
52
        if start_datetime_utc is not None and end_datetime_utc is not None and \
53
                start_datetime_utc >= end_datetime_utc:
54
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
55
                                   description='API.INVALID_END_DATETIME')
56
57
        # Verify User Session
58
        token = req.headers.get('TOKEN')
59
        user_uuid = req.headers.get('USER-UUID')
60
        if token is None:
61
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
62
                                   description='API.TOKEN_NOT_FOUND_IN_HEADERS_PLEASE_LOGIN')
63
        if user_uuid is None:
64
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
65
                                   description='API.USER_UUID_NOT_FOUND_IN_HEADERS_PLEASE_LOGIN')
66
67
        cnx = mysql.connector.connect(**config.myems_user_db)
68
        cursor = cnx.cursor()
69
70
        query = (" SELECT utc_expires "
71
                 " FROM tbl_sessions "
72
                 " WHERE user_uuid = %s AND token = %s")
73
        cursor.execute(query, (user_uuid, token,))
74
        row = cursor.fetchone()
75
76
        if row is None:
77
            if cursor:
78
                cursor.close()
79
            if cnx:
80
                cnx.disconnect()
81
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
82
                                   description='API.INVALID_SESSION_PLEASE_RE_LOGIN')
83
        else:
84
            utc_expires = row[0]
85
            if datetime.utcnow() > utc_expires:
86
                if cursor:
87
                    cursor.close()
88
                if cnx:
89
                    cnx.disconnect()
90
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
91
                                       description='API.USER_SESSION_TIMEOUT')
92
93
        cursor.execute(" SELECT id "
94
                       " FROM tbl_users "
95
                       " WHERE uuid = %s ",
96
                       (user_uuid,))
97
        row = cursor.fetchone()
98
        if row is None:
99
            if cursor:
100
                cursor.close()
101
            if cnx:
102
                cnx.disconnect()
103
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
104
                                   description='API.INVALID_USER_PLEASE_RE_LOGIN')
105
        else:
106
            user_id = row[0]
107
108
        # get notifications
109
        if status is None:
110
            query = (" SELECT id, created_datetime_utc, status, subject, message, url "
111
                     " FROM tbl_notifications "
112
                     " WHERE user_id = %s AND "
113
                     "       created_datetime_utc >= %s AND created_datetime_utc < %s AND"
114
                     "       status != 'archived' "
115
                     " ORDER BY created_datetime_utc DESC ")
116
            cursor.execute(query, (user_id, start_datetime_utc, end_datetime_utc))
117
        else:
118
            query = (" SELECT id, created_datetime_utc, status, subject, message, url "
119
                     " FROM tbl_notifications "
120
                     " WHERE user_id = %s AND "
121
                     "       created_datetime_utc >= %s AND created_datetime_utc < %s AND "
122
                     "       status = %s "
123
                     " ORDER BY created_datetime_utc DESC ")
124
            cursor.execute(query, (user_id, start_datetime_utc, end_datetime_utc, status))
125
        rows = cursor.fetchall()
126
127
        if cursor:
128
            cursor.close()
129
        if cnx:
130
            cnx.disconnect()
131
132
        result = list()
133
        if rows is not None and len(rows) > 0:
134
            for row in rows:
135
                meta_result = {"id": row[0],
136
                               "created_datetime":
137
                                   (row[1] +
138
                                    timedelta(hours=int(config.utc_offset[1:3]))).strftime('%Y-%m-%dT%H:%M:%S'),
139
                               "status": row[2],
140
                               "subject": row[3],
141
                               "message": row[4],
142
                               "url": row[5]}
143
                result.append(meta_result)
144
145
        resp.body = json.dumps(result)
146
147
148
class NotificationItem:
149
    @staticmethod
150
    def __init__():
151
        pass
152
153
    @staticmethod
154
    def on_options(req, resp, id_):
155
        resp.status = falcon.HTTP_200
156
157
    @staticmethod
158
    def on_get(req, resp, id_):
159
        """Handles GET requests"""
160
        if not id_.isdigit() or int(id_) <= 0:
161
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
162
                                   description='API.INVALID_NOTIFICATION_ID')
163
164
        # Verify User Session
165
        token = req.headers.get('TOKEN')
166
        user_uuid = req.headers.get('USER-UUID')
167
        if token is None:
168
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
169
                                   description='API.TOKEN_NOT_FOUND_IN_HEADERS_PLEASE_LOGIN')
170
        if user_uuid is None:
171
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
172
                                   description='API.USER_UUID_NOT_FOUND_IN_HEADERS_PLEASE_LOGIN')
173
174
        cnx = mysql.connector.connect(**config.myems_user_db)
175
        cursor = cnx.cursor()
176
177
        query = (" SELECT utc_expires "
178
                 " FROM tbl_sessions "
179
                 " WHERE user_uuid = %s AND token = %s")
180
        cursor.execute(query, (user_uuid, token,))
181
        row = cursor.fetchone()
182
183
        if row is None:
184
            if cursor:
185
                cursor.close()
186
            if cnx:
187
                cnx.disconnect()
188
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
189
                                   description='API.INVALID_SESSION_PLEASE_RE_LOGIN')
190
        else:
191
            utc_expires = row[0]
192
            if datetime.utcnow() > utc_expires:
193
                if cursor:
194
                    cursor.close()
195
                if cnx:
196
                    cnx.disconnect()
197
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
198
                                       description='API.USER_SESSION_TIMEOUT')
199
200
        cursor.execute(" SELECT id "
201
                       " FROM tbl_users "
202
                       " WHERE uuid = %s ",
203
                       (user_uuid,))
204
        row = cursor.fetchone()
205
        if row is None:
206
            if cursor:
207
                cursor.close()
208
            if cnx:
209
                cnx.disconnect()
210
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
211
                                   description='API.INVALID_USER_PLEASE_RE_LOGIN')
212
        else:
213
            user_id = row[0]
214
215
        # get notification
216
        query = (" SELECT id, created_datetime_utc, status, subject, message, url "
217
                 " FROM tbl_notifications "
218
                 " WHERE id = %s AND user_id = %s ")
219
        cursor.execute(query, (id_, user_id))
220
        row = cursor.fetchone()
221
222
        if cursor:
223
            cursor.close()
224
        if cnx:
225
            cnx.disconnect()
226
227
        if row is None:
228
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
229
                                   description='API.NOTIFICATION_NOT_FOUND')
230
231
        meta_result = {"id": row[0],
232
                       "created_datetime":
233
                           (row[1] +
234
                            timedelta(hours=int(config.utc_offset[1:3]))).strftime('%Y-%m-%dT%H:%M:%S'),
235
                       "status": row[2],
236
                       "subject": row[3],
237
                       "message": row[4],
238
                       "url": row[5]}
239
240
        resp.body = json.dumps(meta_result)
241
242
    @staticmethod
243
    def on_put(req, resp, id_):
244
        """Handles PUT requests"""
245
        try:
246
            raw_json = req.stream.read().decode('utf-8')
247
        except Exception as ex:
248
            raise falcon.HTTPError(falcon.HTTP_400, title='API.EXCEPTION', description=ex)
249
250
        if not id_.isdigit() or int(id_) <= 0:
251
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
252
                                   description='API.INVALID_NOTIFICATION_ID')
253
254
        new_values = json.loads(raw_json)
255
256
        if 'status' not in new_values['data'].keys() or \
257
                not isinstance(new_values['data']['status'], str) or \
258
                len(str.strip(new_values['data']['status'])) == 0 or \
259
                str.strip(new_values['data']['status']) not in ('unread', 'read', 'archived'):
260
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
261
                                   description='API.INVALID_STATUS')
262
        status = str.strip(new_values['data']['status'])
263
264
        # Verify User Session
265
        token = req.headers.get('TOKEN')
266
        user_uuid = req.headers.get('USER-UUID')
267
        if token is None:
268
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
269
                                   description='API.TOKEN_NOT_FOUND_IN_HEADERS_PLEASE_LOGIN')
270
        if user_uuid is None:
271
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
272
                                   description='API.USER_UUID_NOT_FOUND_IN_HEADERS_PLEASE_LOGIN')
273
274
        cnx = mysql.connector.connect(**config.myems_user_db)
275
        cursor = cnx.cursor()
276
277
        query = (" SELECT utc_expires "
278
                 " FROM tbl_sessions "
279
                 " WHERE user_uuid = %s AND token = %s")
280
        cursor.execute(query, (user_uuid, token,))
281
        row = cursor.fetchone()
282
283
        if row is None:
284
            if cursor:
285
                cursor.close()
286
            if cnx:
287
                cnx.disconnect()
288
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
289
                                   description='API.INVALID_SESSION_PLEASE_RE_LOGIN')
290
        else:
291
            utc_expires = row[0]
292
            if datetime.utcnow() > utc_expires:
293
                if cursor:
294
                    cursor.close()
295
                if cnx:
296
                    cnx.disconnect()
297
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
298
                                       description='API.USER_SESSION_TIMEOUT')
299
300
        cursor.execute(" SELECT id "
301
                       " FROM tbl_users "
302
                       " WHERE uuid = %s ",
303
                       (user_uuid,))
304
        row = cursor.fetchone()
305
        if row is None:
306
            if cursor:
307
                cursor.close()
308
            if cnx:
309
                cnx.disconnect()
310
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
311
                                   description='API.INVALID_USER_PLEASE_RE_LOGIN')
312
        else:
313
            user_id = row[0]
314
315
        cursor.execute(" SELECT id "
316
                       " FROM tbl_notifications "
317
                       " WHERE id = %s AND user_id = %s ", (id_, user_id))
318
        if cursor.fetchone() is None:
319
            if cursor:
320
                cursor.close()
321
            if cnx:
322
                cnx.disconnect()
323
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
324
                                   description='API.NOTIFICATION_NOT_FOUND')
325
326
        update_row = (" UPDATE tbl_notifications "
327
                      " SET status = %s "
328
                      " WHERE id = %s ")
329
        cursor.execute(update_row, (status,
330
                                    id_,))
331
        cnx.commit()
332
        if cursor:
333
            cursor.close()
334
        if cnx:
335
            cnx.disconnect()
336
337
        resp.status = falcon.HTTP_200
338
339
    @staticmethod
340
    def on_delete(req, resp, id_):
341
        if not id_.isdigit() or int(id_) <= 0:
342
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
343
                                   description='API.INVALID_NOTIFICATION_ID')
344
345
        # Verify User Session
346
        token = req.headers.get('TOKEN')
347
        user_uuid = req.headers.get('USER-UUID')
348
        if token is None:
349
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
350
                                   description='API.TOKEN_NOT_FOUND_IN_HEADERS_PLEASE_LOGIN')
351
        if user_uuid is None:
352
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
353
                                   description='API.USER_UUID_NOT_FOUND_IN_HEADERS_PLEASE_LOGIN')
354
355
        cnx = mysql.connector.connect(**config.myems_user_db)
356
        cursor = cnx.cursor()
357
358
        query = (" SELECT utc_expires "
359
                 " FROM tbl_sessions "
360
                 " WHERE user_uuid = %s AND token = %s")
361
        cursor.execute(query, (user_uuid, token,))
362
        row = cursor.fetchone()
363
364
        if row is None:
365
            if cursor:
366
                cursor.close()
367
            if cnx:
368
                cnx.disconnect()
369
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
370
                                   description='API.INVALID_SESSION_PLEASE_RE_LOGIN')
371
        else:
372
            utc_expires = row[0]
373
            if datetime.utcnow() > utc_expires:
374
                if cursor:
375
                    cursor.close()
376
                if cnx:
377
                    cnx.disconnect()
378
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
379
                                       description='API.USER_SESSION_TIMEOUT')
380
381
        cursor.execute(" SELECT id "
382
                       " FROM tbl_users "
383
                       " WHERE uuid = %s ",
384
                       (user_uuid,))
385
        row = cursor.fetchone()
386
        if row is None:
387
            if cursor:
388
                cursor.close()
389
            if cnx:
390
                cnx.disconnect()
391
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
392
                                   description='API.INVALID_USER_PLEASE_RE_LOGIN')
393
        else:
394
            user_id = row[0]
395
396
        cursor.execute(" SELECT id "
397
                       " FROM tbl_notifications "
398
                       " WHERE id = %s AND user_id = %s ", (id_, user_id))
399
        row = cursor.fetchone()
400
401
        if row is None:
402
            if cursor:
403
                cursor.close()
404
            if cnx:
405
                cnx.disconnect()
406
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND',
407
                                   description='API.NOTIFICATION_NOT_FOUND')
408
409
        cursor.execute(" DELETE FROM tbl_notifications WHERE id = %s ", (id_,))
410
        cnx.commit()
411
        if cursor:
412
            cursor.close()
413
        if cnx:
414
            cnx.disconnect()
415
416
        resp.status = falcon.HTTP_204
417