| Conditions | 16 |
| Total Lines | 99 |
| Code Lines | 64 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
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:
If many parameters/temporary variables are present:
Complex classes like core.apikey.ApiKeyItem.on_put() 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 os |
||
| 238 | @staticmethod |
||
| 239 | def on_put(req, resp, id_): |
||
| 240 | """ |
||
| 241 | Handle PUT requests to update an API key |
||
| 242 | |||
| 243 | Updates an existing API key with new name and expiration date. |
||
| 244 | The token itself cannot be changed - only metadata. |
||
| 245 | |||
| 246 | Args: |
||
| 247 | req: Falcon request object containing update data: |
||
| 248 | - name: New API key name (required) |
||
| 249 | - expires_datetime: New expiration date (required) |
||
| 250 | resp: Falcon response object |
||
| 251 | id_: API key ID to update |
||
| 252 | """ |
||
| 253 | admin_control(req) |
||
| 254 | try: |
||
| 255 | raw_json = req.stream.read().decode('utf-8') |
||
| 256 | except UnicodeDecodeError as ex: |
||
| 257 | print("Failed to decode request") |
||
| 258 | raise falcon.HTTPError(status=falcon.HTTP_400, |
||
| 259 | title='API.BAD_REQUEST', |
||
| 260 | description='API.INVALID_ENCODING') |
||
| 261 | except Exception as ex: |
||
| 262 | print("Unexpected error reading request stream") |
||
| 263 | raise falcon.HTTPError(status=falcon.HTTP_400, |
||
| 264 | title='API.BAD_REQUEST', |
||
| 265 | description='API.FAILED_TO_READ_REQUEST_STREAM') |
||
| 266 | |||
| 267 | if not id_.isdigit() or int(id_) <= 0: |
||
| 268 | raise falcon.HTTPError(status=falcon.HTTP_400, |
||
| 269 | title="API.INVALID_API_KEY_ID") |
||
| 270 | |||
| 271 | new_values = json.loads(raw_json) |
||
| 272 | |||
| 273 | # Validate API key name |
||
| 274 | if 'name' not in new_values['data'].keys() or \ |
||
| 275 | not isinstance(new_values['data']['name'], str) or \ |
||
| 276 | len(str.strip(new_values['data']['name'])) == 0: |
||
| 277 | raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST', |
||
| 278 | description='API.INVALID_API_KEY_NAME') |
||
| 279 | name = str.strip(new_values['data']['name']) |
||
| 280 | |||
| 281 | # Validate expiration datetime |
||
| 282 | if 'expires_datetime' not in new_values['data'].keys() or \ |
||
| 283 | not isinstance(new_values['data']['expires_datetime'], str) or \ |
||
| 284 | len(str.strip(new_values['data']['expires_datetime'])) == 0: |
||
| 285 | raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST', |
||
| 286 | description='API.INVALID_EXPIRES_DATETIME') |
||
| 287 | expires_datetime_local = str.strip(new_values['data']['expires_datetime']) |
||
| 288 | |||
| 289 | # Calculate timezone offset for datetime conversion |
||
| 290 | timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6]) |
||
| 291 | if config.utc_offset[0] == '-': |
||
| 292 | timezone_offset = -timezone_offset |
||
| 293 | |||
| 294 | # Parse and convert expiration datetime to UTC |
||
| 295 | try: |
||
| 296 | expires_datetime_local = datetime.strptime(expires_datetime_local, '%Y-%m-%dT%H:%M:%S') |
||
| 297 | expires_datetime_utc = expires_datetime_local.replace(tzinfo=timezone.utc) - \ |
||
| 298 | timedelta(minutes=timezone_offset) |
||
| 299 | except ValueError: |
||
| 300 | raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST', |
||
| 301 | description="API.INVALID_EXPIRES_DATETIME") |
||
| 302 | |||
| 303 | cnx = mysql.connector.connect(**config.myems_user_db) |
||
| 304 | cursor = cnx.cursor() |
||
| 305 | |||
| 306 | # Check if new name conflicts with existing API keys |
||
| 307 | cursor.execute(" SELECT name " |
||
| 308 | " FROM tbl_api_keys " |
||
| 309 | " WHERE name = %s ", (name,)) |
||
| 310 | if cursor.fetchall() is not None and \ |
||
| 311 | len(cursor.fetchall()) > 0: |
||
| 312 | cursor.close() |
||
| 313 | cnx.close() |
||
| 314 | raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND', |
||
| 315 | description='API.API_KEY_NAME_IS_ALREADY_IN_USE') |
||
| 316 | |||
| 317 | # Check if API key exists |
||
| 318 | cursor.execute(" SELECT token " |
||
| 319 | " FROM tbl_api_keys " |
||
| 320 | " WHERE id = %s ", (id_,)) |
||
| 321 | if cursor.fetchone() is None: |
||
| 322 | cursor.close() |
||
| 323 | cnx.close() |
||
| 324 | raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND', |
||
| 325 | description='API.API_KEY_NOT_FOUND') |
||
| 326 | |||
| 327 | # Update API key information |
||
| 328 | cursor.execute(" UPDATE tbl_api_keys " |
||
| 329 | " SET name = %s, expires_datetime_utc = %s " |
||
| 330 | " WHERE id = %s ", (name, expires_datetime_utc, id_)) |
||
| 331 | cnx.commit() |
||
| 332 | |||
| 333 | cursor.close() |
||
| 334 | cnx.close() |
||
| 335 | |||
| 336 | resp.status = falcon.HTTP_200 |
||
| 337 | |||
| 377 |