1######################################################################
2#
3# File: b2sdk/application_key.py
4#
5# Copyright 2021 Backblaze Inc. All Rights Reserved.
6#
7# License https://www.backblaze.com/using_b2_code.html
8#
9######################################################################
10
11from typing import List, Optional
12
13
14class BaseApplicationKey:
15    """Common methods for ApplicationKey and FullApplicationKey."""
16
17    def __init__(
18        self,
19        key_name: str,
20        application_key_id: str,
21        capabilities: List[str],
22        account_id: str,
23        expiration_timestamp_millis: Optional[int] = None,
24        bucket_id: Optional[str] = None,
25        name_prefix: Optional[str] = None,
26        options: Optional[List[str]] = None,
27    ):
28        """
29        :param key_name: name of the key, assigned by user
30        :param application_key_id: key id, used to authenticate
31        :param capabilities: list of capabilities assigned to this key
32        :param account_id: account's id
33        :param expiration_timestamp_millis: expiration time of the key
34        :param bucket_id: if restricted to a bucket, this is the bucket's id
35        :param name_prefix: if restricted to some files, this is their prefix
36        :param options: reserved for future use
37        """
38        self.key_name = key_name
39        self.id_ = application_key_id
40        self.capabilities = capabilities
41        self.account_id = account_id
42        self.expiration_timestamp_millis = expiration_timestamp_millis
43        self.bucket_id = bucket_id
44        self.name_prefix = name_prefix
45        self.options = options
46
47    @classmethod
48    def parse_response_dict(cls, response: dict):
49        mandatory_args = {
50            'key_name': response['keyName'],
51            'application_key_id': response['applicationKeyId'],
52            'capabilities': response['capabilities'],
53            'account_id': response['accountId'],
54        }
55
56        optional_args = {
57            'expiration_timestamp_millis': response.get('expirationTimestamp'),
58            'bucket_id': response.get('bucketId'),
59            'name_prefix': response.get('namePrefix'),
60            'options': response.get('options'),
61        }
62        return {
63            **mandatory_args,
64            **{key: value
65               for key, value in optional_args.items() if value is not None},
66        }
67
68    def as_dict(self):
69        """Represent the key as a dict, like the one returned by B2 cloud"""
70        mandatory_keys = {
71            'keyName': self.key_name,
72            'applicationKeyId': self.id_,
73            'capabilities': self.capabilities,
74            'accountId': self.account_id,
75        }
76        optional_keys = {
77            'expirationTimestamp': self.expiration_timestamp_millis,
78            'bucketId': self.bucket_id,
79            'namePrefix': self.name_prefix,
80            'options': self.options,
81        }
82        return {
83            **mandatory_keys,
84            **{key: value
85               for key, value in optional_keys.items() if value is not None},
86        }
87
88
89class ApplicationKey(BaseApplicationKey):
90    """Dataclass for storing info about an application key returned by delete-key or list-keys."""
91
92    @classmethod
93    def from_api_response(cls, response: dict) -> 'ApplicationKey':
94        """Create an ApplicationKey object from a delete-key or list-key response (a parsed json object)."""
95        return cls(**cls.parse_response_dict(response))
96
97
98class FullApplicationKey(BaseApplicationKey):
99    """Dataclass for storing info about an application key, including the actual key, as returned by create-key."""
100
101    def __init__(
102        self,
103        key_name: str,
104        application_key_id: str,
105        application_key: str,
106        capabilities: List[str],
107        account_id: str,
108        expiration_timestamp_millis: Optional[int] = None,
109        bucket_id: Optional[str] = None,
110        name_prefix: Optional[str] = None,
111        options: Optional[List[str]] = None,
112    ):
113        """
114        :param key_name: name of the key, assigned by user
115        :param application_key_id: key id, used to authenticate
116        :param application_key: the actual secret key
117        :param capabilities: list of capabilities assigned to this key
118        :param account_id: account's id
119        :param expiration_timestamp_millis: expiration time of the key
120        :param bucket_id: if restricted to a bucket, this is the bucket's id
121        :param name_prefix: if restricted to some files, this is their prefix
122        :param options: reserved for future use
123        """
124        self.application_key = application_key
125        super().__init__(
126            key_name=key_name,
127            application_key_id=application_key_id,
128            capabilities=capabilities,
129            account_id=account_id,
130            expiration_timestamp_millis=expiration_timestamp_millis,
131            bucket_id=bucket_id,
132            name_prefix=name_prefix,
133            options=options,
134        )
135
136    @classmethod
137    def from_create_response(cls, response: dict) -> 'FullApplicationKey':
138        """Create a FullApplicationKey object from a create-key response (a parsed json object)."""
139        return cls(**cls.parse_response_dict(response))
140
141    @classmethod
142    def parse_response_dict(cls, response: dict):
143        result = super().parse_response_dict(response)
144        result['application_key'] = response['applicationKey']
145        return result
146
147    def as_dict(self):
148        """Represent the key as a dict, like the one returned by B2 cloud"""
149        return {
150            **super().as_dict(),
151            'applicationKey': self.application_key,
152        }
153