Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1"""LICENSE 

2Copyright 2020 Hermann Krumrey <hermann@krumreyh.com> 

3 

4This file is part of jerrycan. 

5 

6jerrycan is free software: you can redistribute it and/or modify 

7it under the terms of the GNU General Public License as published by 

8the Free Software Foundation, either version 3 of the License, or 

9(at your option) any later version. 

10 

11jerrycan is distributed in the hope that it will be useful, 

12but WITHOUT ANY WARRANTY; without even the implied warranty of 

13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

14GNU General Public License for more details. 

15 

16You should have received a copy of the GNU General Public License 

17along with jerrycan. If not, see <http://www.gnu.org/licenses/>. 

18LICENSE""" 

19 

20from typing import Dict, Any 

21from flask import Blueprint, request 

22from flask_login import login_required 

23from puffotter.crypto import generate_random, generate_hash 

24from jerrycan.base import db 

25from jerrycan.Config import Config 

26from jerrycan.db.User import User 

27from jerrycan.db.ApiKey import ApiKey 

28from jerrycan.exceptions import ApiException 

29from jerrycan.routes.decorators import api, api_login_required 

30 

31 

32def define_blueprint(blueprint_name: str) -> Blueprint: 

33 """ 

34 Defines the blueprint for this route 

35 :param blueprint_name: The name of the blueprint 

36 :return: The blueprint 

37 """ 

38 blueprint = Blueprint(blueprint_name, __name__) 

39 api_base = f"/api/v{Config.API_VERSION}" 

40 

41 @blueprint.route(f"{api_base}/key", methods=["POST", "DELETE"]) 

42 @api 

43 def api_key() -> Dict[str, Any]: 

44 """ 

45 Allows users to request a new API key or revoke an existing API key 

46 :return: The JSON response 

47 """ 

48 data = request.get_json() 

49 assert data is not None 

50 if request.method == "POST": 

51 username = data["username"] 

52 password = data["password"] 

53 user = User.query.filter_by(username=username).first() 

54 

55 if user is None: 

56 raise ApiException("user does not exist", 401) 

57 elif not user.confirmed: 

58 raise ApiException("user is not confirmed", 401) 

59 elif not user.verify_password(password): 

60 raise ApiException("password is incorrect", 401) 

61 else: 

62 key = generate_random(32) 

63 hashed = generate_hash(key) 

64 _api_key = ApiKey(user=user, key_hash=hashed) 

65 db.session.add(_api_key) 

66 db.session.commit() 

67 

68 return { 

69 "api_key": "{}:{}".format(_api_key.id, key), 

70 "expiration": ( 

71 int(_api_key.creation_time) 

72 + Config.MAX_API_KEY_AGE 

73 ), 

74 "user": user.__json__(False) 

75 } 

76 

77 else: # request.method == "DELETE" 

78 key = data["api_key"] 

79 _api_key = ApiKey.query.get(key.split(":", 1)[0]) 

80 

81 if _api_key is None: 

82 raise ApiException("api key does not exist", 401) 

83 elif not _api_key.verify_key(key): 

84 raise ApiException("api key not valid", 401) 

85 else: 

86 db.session.delete(_api_key) 

87 db.session.commit() 

88 return {} 

89 

90 @blueprint.route(f"{api_base}/authorize", methods=["GET"]) 

91 @api_login_required 

92 @login_required 

93 @api 

94 def api_authorize() -> Dict[str, Any]: 

95 """ 

96 Allows a user to check if an API key is authorized or not 

97 :return: None 

98 """ 

99 return {} # Checks done by @login_required 

100 

101 return blueprint