Skip to content

Commit c7d72b6

Browse files
committed
Added user token handlers
1 parent e480f97 commit c7d72b6

7 files changed

Lines changed: 130 additions & 33 deletions

File tree

bugout/__main__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ def main() -> None:
2929

3030
parser.add_argument(
3131
"--brood_url",
32-
default="http://localhost:7474",
32+
default="http://localhost",
3333
help="Brood url",
3434
)
3535
parser.add_argument(
3636
"--spire_url",
37-
default="http://localhost:7475",
37+
default="http://localhost",
3838
help="Spire url",
3939
)
4040

bugout/app.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88

99

1010
class Bugout:
11-
def __init__(self, brood_api_url: str, spire_api_url: str) -> None:
11+
def __init__(
12+
self, brood_api_url: Optional[str] = None, spire_api_url: Optional[str] = None
13+
) -> None:
1214
self.brood_api_url = brood_api_url
1315
self.spire_api_url = spire_api_url
16+
1417
self.user = User(self.brood_api_url)
1518
self.group = Group(self.brood_api_url)
1619
self.journal = Journal(self.spire_api_url)
@@ -19,12 +22,17 @@ def __init__(self, brood_api_url: str, spire_api_url: str) -> None:
1922
def brood_url(self):
2023
return self.brood_api_url
2124

25+
@property
26+
def spire_url(self):
27+
return self.spire_api_url
28+
2229
def brood_ping(self) -> Dict[str, str]:
2330
return calls.ping(self.brood_api_url)
2431

2532
def spire_ping(self) -> Dict[str, str]:
2633
return calls.ping(self.spire_api_url)
2734

35+
# User handlers
2836
def get_user(self, token: str) -> data.BugoutUser:
2937
return self.user.get_user(token)
3038

@@ -39,8 +47,24 @@ def create_user(
3947
username, email, password, autogenerated_token=autogenerated_token
4048
)
4149

50+
def create_token(self, username: str, password: str) -> data.BugoutToken:
51+
return self.user.create_token(username, password)
52+
53+
def revoke_token(self, token: str) -> data.BugoutToken:
54+
return self.user.revoke_token(token)
55+
56+
def update_token(
57+
self,
58+
token: str,
59+
token_type: Optional[str] = None,
60+
token_note: Optional[str] = None,
61+
) -> data.BugoutToken:
62+
return self.user.update_token(token, token_type, token_note)
63+
64+
# Group handlers
4265
def get_group(self, group_id: str, token: str) -> data.BugoutGroup:
4366
return self.group.get_group(group_id, token)
4467

68+
# Journal handlers
4569
def get_journal(self, journal_id: str, token: str) -> data.BugoutJournal:
4670
return self.journal.get_journal(journal_id, token)

bugout/calls.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
logger = logging.getLogger(__name__)
99

1010

11+
class InvalidUrlSpec(ValueError):
12+
"""
13+
Raised when an invalid url is specified.
14+
"""
15+
16+
1117
class BugoutUnexpectedResponse(Exception):
1218
"""
1319
Raised when Bugout server response is unexpected (e.g. unparseable).

bugout/data.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,17 @@
88

99
@unique
1010
class Method(Enum):
11+
delete = "delete"
1112
get = "get"
1213
post = "post"
13-
delete = "delete"
14+
put = "put"
15+
16+
17+
@unique
18+
class TokenType(Enum):
19+
bugout = "bugout"
20+
slack = "slack"
21+
github = "github"
1422

1523

1624
class BugoutUser(BaseModel):
@@ -37,3 +45,9 @@ class BugoutJournal(BaseModel):
3745
name: str
3846
created_at: datetime
3947
updated_at: datetime
48+
49+
50+
class BugoutToken(BaseModel):
51+
id: uuid.UUID
52+
token_type: Optional[str]
53+
token_note: Optional[str]

bugout/group.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22
from typing import Any, Dict, List, Optional, Tuple
33

4-
from .calls import make_request
4+
from .calls import make_request, InvalidUrlSpec
55
from .data import BugoutGroup, Method
66

77
logger = logging.getLogger(__name__)
@@ -18,7 +18,9 @@ class Group:
1818
Represent a group from Bugout.
1919
"""
2020

21-
def __init__(self, url) -> None:
21+
def __init__(self, url: Optional[str] = None) -> None:
22+
if url is None:
23+
raise InvalidUrlSpec("Invalid brood url specified")
2224
self.url = url
2325

2426
def _call(self, method: Method, path: str, **kwargs):

bugout/journal.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22
from typing import Any, Dict, List, Optional, Tuple
33

4-
from .calls import make_request
4+
from .calls import make_request, InvalidUrlSpec
55
from .data import BugoutJournal, Method
66

77
logger = logging.getLogger(__name__)
@@ -18,7 +18,9 @@ class Journal:
1818
Represent a journal from Bugout.
1919
"""
2020

21-
def __init__(self, url) -> None:
21+
def __init__(self, url: Optional[str] = None) -> None:
22+
if url is None:
23+
raise InvalidUrlSpec("Invalid spire url specified")
2224
self.url = url
2325

2426
def _call(self, method: Method, path: str, **kwargs):

bugout/user.py

Lines changed: 74 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import logging
22
from typing import Any, Dict, List, Optional, Tuple
33

4-
from .calls import make_request
5-
from .data import BugoutUser, Method
4+
from .calls import make_request, InvalidUrlSpec
5+
from .data import BugoutUser, BugoutToken, Method, TokenType
66

77
logger = logging.getLogger(__name__)
88

@@ -13,43 +13,55 @@ class UserNotFound(Exception):
1313
"""
1414

1515

16+
class TokenInvalidParameters(ValueError):
17+
"""
18+
Raised when operations are applied to a token but invalid parameters are provided with which to
19+
specify that token.
20+
"""
21+
22+
1623
class User:
1724
"""
1825
Represent a user from Bugout.
1926
"""
2027

21-
def __init__(self, url) -> None:
28+
def __init__(self, url: Optional[str] = None) -> None:
29+
if url is None:
30+
raise InvalidUrlSpec("Invalid brood url specified")
2231
self.url = url
2332

2433
def _call(self, method: Method, path: str, **kwargs):
2534
url = f"{self.url.rstrip('/')}/{path.rstrip('/')}"
2635
result = make_request(method=method, url=url, **kwargs)
2736
return result
2837

29-
def get_user(self, token: str) -> BugoutUser:
38+
def _user_model_converter(self, user_object: Dict[str, Any]) -> BugoutUser:
39+
return BugoutUser(
40+
id=user_object.get("user_id"),
41+
username=user_object.get("username"),
42+
email=user_object.get("email"),
43+
normalized_email=user_object.get("normalized_email"),
44+
verified=user_object.get("verified"),
45+
autogenerated=user_object.get("autogenerated"),
46+
created_at=user_object.get("created_at"),
47+
updated_at=user_object.get("updated_at"),
48+
)
49+
50+
def get_user(self, token: str) -> Dict[str, Any]:
3051
get_user_path = "user"
3152
headers = {
3253
"Authorization": f"Bearer {token}",
3354
}
3455
result = self._call(method=Method.get, path=get_user_path, headers=headers)
35-
return BugoutUser(
36-
id=result.get("user_id"),
37-
username=result.get("username"),
38-
email=result.get("email"),
39-
normalized_email=result.get("normalized_email"),
40-
verified=result.get("verified"),
41-
autogenerated=result.get("autogenerated"),
42-
created_at=result.get("created_at"),
43-
updated_at=result.get("updated_at"),
44-
)
56+
return self._user_model_converter(result)
4557

4658
def create_user(
4759
self,
4860
username: str,
4961
email: str,
5062
password: str,
51-
autogenerated_token: str = None,
52-
):
63+
autogenerated_token: Optional[str] = None,
64+
) -> Dict[str, Any]:
5365
create_user_path = "user"
5466
data = {
5567
"username": username,
@@ -64,13 +76,50 @@ def create_user(
6476
result = self._call(
6577
method=Method.post, path=create_user_path, headers=headers, data=data
6678
)
67-
return BugoutUser(
68-
id=result.get("user_id"),
69-
username=result.get("username"),
70-
email=result.get("email"),
71-
normalized_email=result.get("normalized_email"),
72-
verified=result.get("verified"),
73-
autogenerated=result.get("autogenerated"),
74-
created_at=result.get("created_at"),
75-
updated_at=result.get("updated_at"),
79+
return self._user_model_converter(result)
80+
81+
def create_token(self, username: str, password: str) -> BugoutToken:
82+
create_token_path = "token"
83+
data = {
84+
"username": username,
85+
"password": password,
86+
}
87+
result = self._call(method=Method.post, path=create_token_path, data=data)
88+
return BugoutToken(
89+
id=result.get("access_token"),
90+
token_type=result.get("token_type"),
7691
)
92+
93+
def revoke_token(self, token: str) -> BugoutToken:
94+
create_token_path = "token"
95+
headers = {
96+
"Authorization": f"Bearer {token}",
97+
}
98+
result = self._call(
99+
method=Method.delete, path=create_token_path, headers=headers
100+
)
101+
return BugoutToken(id=result)
102+
103+
def update_token(
104+
self,
105+
token: str,
106+
token_type: Optional[str] = None,
107+
token_note: Optional[str] = None,
108+
) -> BugoutToken:
109+
create_token_path = "token"
110+
111+
data = {"access_token": token}
112+
if token_type is None and token_note is None:
113+
raise TokenInvalidParameters(
114+
"In order to update token, at least one of token_type, or token_note must be specified"
115+
)
116+
if token_type not in TokenType.__members__:
117+
raise TokenInvalidParameters("Incorrect token type provided")
118+
119+
if token_type is not None:
120+
data.update({"token_type": token_type})
121+
if token_note is not None:
122+
data.update({"token_note": token_note})
123+
124+
result = self._call(method=Method.put, path=create_token_path, data=data)
125+
return BugoutToken(id=result, token_type=token_type, token_note=token_note)

0 commit comments

Comments
 (0)