Skip to content

Commit 381cb96

Browse files
authored
Merge pull request #2 from bugout-dev/brood-api
API for users, tokens, groups
2 parents 8a40d0c + d8193b0 commit 381cb96

File tree

8 files changed

+433
-89
lines changed

8 files changed

+433
-89
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,4 @@ dmypy.json
137137
# Custom
138138
.secrets/
139139
.bugout/
140+
test/

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ from bugout.app import Bugout
77
def main():
88
bugout = Bugout(brood_api_url="http://localhost:9001", spire_api_url="http://localhost:9002")
99
user = bugout.get_user("<user token id>")
10-
group = bugout.get_group("<group id>", "<user token id>")
10+
group = bugout.get_group("<user token id>", "<group id>")
1111

1212
if __name__ == "__main__":
1313
main()

bugout/app.py

Lines changed: 100 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from typing import Any, Dict, List, Optional, Tuple
1+
from typing import Any, Dict, List, Optional
2+
import uuid
23

34
from . import data
45
from . import calls
@@ -7,6 +8,12 @@
78
from .user import User
89

910

11+
class InvalidParameters(ValueError):
12+
"""
13+
Raised when provided invalid parameters.
14+
"""
15+
16+
1017
class Bugout:
1118
def __init__(
1219
self, brood_api_url: Optional[str] = None, spire_api_url: Optional[str] = None
@@ -27,15 +34,16 @@ def spire_url(self):
2734
return self.spire_api_url
2835

2936
def brood_ping(self) -> Dict[str, str]:
37+
if self.brood_api_url is None:
38+
raise InvalidParameters("Brood API url should be provided")
3039
return calls.ping(self.brood_api_url)
3140

3241
def spire_ping(self) -> Dict[str, str]:
42+
if self.spire_api_url is None:
43+
raise InvalidParameters("Spire API url should be provided")
3344
return calls.ping(self.spire_api_url)
3445

3546
# User handlers
36-
def get_user(self, token: str) -> data.BugoutUser:
37-
return self.user.get_user(token)
38-
3947
def create_user(
4048
self,
4149
username: str,
@@ -47,24 +55,106 @@ def create_user(
4755
username, email, password, autogenerated_token=autogenerated_token
4856
)
4957

58+
def get_user(self, token: uuid.UUID) -> data.BugoutUser:
59+
return self.user.get_user(token)
60+
61+
def get_user_by_id(self, token: uuid.UUID, user_id: uuid.UUID) -> data.BugoutUser:
62+
return self.user.get_user_by_id(token, user_id)
63+
64+
def confirm_email(
65+
self, token: uuid.UUID, verification_code: str
66+
) -> data.BugoutUser:
67+
return self.user.confirm_email(token, verification_code)
68+
69+
def restore_password(self, email: str) -> Dict[str, str]:
70+
return self.user.restore_password(email)
71+
72+
def reset_password(self, reset_id: uuid.UUID, new_password: str) -> data.BugoutUser:
73+
return self.user.reset_password(reset_id, new_password)
74+
75+
def change_password(
76+
self, token: uuid.UUID, current_password: str, new_password: str
77+
) -> data.BugoutUser:
78+
return self.user.change_password(token, current_password, new_password)
79+
80+
def delete_user(
81+
self, token: uuid.UUID, user_id: uuid.UUID, password: str
82+
) -> data.BugoutUser:
83+
return self.user.delete_user(token, user_id, password)
84+
85+
# Token handlers
5086
def create_token(self, username: str, password: str) -> data.BugoutToken:
5187
return self.user.create_token(username, password)
5288

53-
def revoke_token(self, token: str) -> data.BugoutToken:
89+
def revoke_token(self, token: uuid.UUID) -> uuid.UUID:
5490
return self.user.revoke_token(token)
5591

92+
def revoke_token_by_id(self, token: uuid.UUID) -> uuid.UUID:
93+
return self.user.revoke_token_by_id(token)
94+
5695
def update_token(
5796
self,
58-
token: str,
59-
token_type: Optional[str] = None,
97+
token: uuid.UUID,
98+
token_type: Optional[data.TokenType] = None,
6099
token_note: Optional[str] = None,
61100
) -> data.BugoutToken:
62101
return self.user.update_token(token, token_type, token_note)
63102

103+
def get_token_types(self, token: uuid.UUID) -> List[str]:
104+
return self.user.get_token_types(token)
105+
106+
def get_user_tokens(
107+
self,
108+
token: uuid.UUID,
109+
active: Optional[bool] = None,
110+
token_type: Optional[data.TokenType] = None,
111+
) -> data.BugoutUserTokens:
112+
return self.user.get_user_tokens(token, active, token_type)
113+
64114
# Group handlers
65-
def get_group(self, group_id: str, token: str) -> data.BugoutGroup:
66-
return self.group.get_group(group_id, token)
115+
def get_group(self, token: uuid.UUID, group_id: uuid.UUID) -> data.BugoutGroup:
116+
return self.group.get_group(token, group_id)
117+
118+
def get_user_groups(self, token: uuid.UUID) -> data.BugoutUserGroups:
119+
return self.group.get_user_groups(token)
120+
121+
def create_group(self, token: uuid.UUID, group_name: str) -> data.BugoutGroup:
122+
return self.group.create_group(token, group_name)
123+
124+
def set_user_group(
125+
self,
126+
token: uuid.UUID,
127+
group_id: uuid.UUID,
128+
user_type: data.Role,
129+
username: Optional[str] = None,
130+
email: Optional[str] = None,
131+
) -> data.BugoutGroupUser:
132+
return self.group.set_user_group(token, group_id, user_type, username, email)
133+
134+
def delete_user_group(
135+
self,
136+
token: uuid.UUID,
137+
group_id: uuid.UUID,
138+
username: Optional[str] = None,
139+
email: Optional[str] = None,
140+
) -> data.BugoutGroupUser:
141+
return self.group.delete_user_group(token, group_id, username, email)
142+
143+
def get_group_members(
144+
self, token: uuid.UUID, group_id: uuid.UUID
145+
) -> data.BugoutGroupMembers:
146+
return self.group.get_group_members(token, group_id)
147+
148+
def update_group(
149+
self, token: uuid.UUID, group_id: uuid.UUID, group_name: str
150+
) -> data.BugoutGroup:
151+
return self.group.update_group(token, group_id, group_name)
152+
153+
def delete_group(self, token: uuid.UUID, group_id: uuid.UUID) -> data.BugoutGroup:
154+
return self.group.delete_group(token, group_id)
67155

68156
# Journal handlers
69-
def get_journal(self, journal_id: str, token: str) -> data.BugoutJournal:
157+
def get_journal(
158+
self, journal_id: uuid.UUID, token: uuid.UUID
159+
) -> data.BugoutJournal:
70160
return self.journal.get_journal(journal_id, token)

bugout/calls.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
import logging
21
from typing import Any, Dict, List, Optional, Tuple
32

43
import requests
54

65
from .data import Method
76

8-
logger = logging.getLogger(__name__)
9-
107

118
class InvalidUrlSpec(ValueError):
129
"""
@@ -27,8 +24,7 @@ def make_request(method: Method, url: str, **kwargs) -> Any:
2724
r.raise_for_status()
2825
response_body = r.json()
2926
except Exception as e:
30-
logger.error(f"Exception {str(e)}")
31-
raise
27+
raise BugoutUnexpectedResponse(f"Exception {str(e)}")
3228
return response_body
3329

3430

bugout/data.py

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from datetime import datetime
22
from enum import Enum, unique
3-
from typing import Any, Dict, List, Optional, Tuple
3+
from typing import Any, Dict, List, Optional
44
import uuid
55

6-
from pydantic import BaseModel
6+
from pydantic import BaseModel, Field
77

88

99
@unique
@@ -14,6 +14,12 @@ class Method(Enum):
1414
put = "put"
1515

1616

17+
@unique
18+
class Role(Enum):
19+
owner = "owner"
20+
member = "member"
21+
22+
1723
@unique
1824
class TokenType(Enum):
1925
bugout = "bugout"
@@ -22,7 +28,7 @@ class TokenType(Enum):
2228

2329

2430
class BugoutUser(BaseModel):
25-
id: uuid.UUID
31+
id: uuid.UUID = Field(alias="user_id")
2632
username: str
2733
email: str
2834
normalized_email: str
@@ -32,22 +38,57 @@ class BugoutUser(BaseModel):
3238
updated_at: datetime
3339

3440

41+
class BugoutUserShort(BaseModel):
42+
id: uuid.UUID
43+
username: str
44+
email: str
45+
user_type: Role
46+
47+
48+
class BugoutToken(BaseModel):
49+
id: uuid.UUID
50+
user_id: uuid.UUID
51+
active: bool
52+
token_type: Optional[str]
53+
note: Optional[str]
54+
created_at: datetime
55+
updated_at: datetime
56+
57+
58+
class BugoutUserTokens(BaseModel):
59+
user_id: uuid.UUID
60+
username: str
61+
tokens: List[BugoutToken] = Field(alias="token")
62+
63+
3564
class BugoutGroup(BaseModel):
3665
id: uuid.UUID
3766
group_name: Optional[str]
3867
autogenerated: bool
3968

4069

70+
class BugoutGroupUser(BaseModel):
71+
group_id: uuid.UUID
72+
user_id: uuid.UUID
73+
user_type: str
74+
autogenerated: Optional[bool] = None
75+
group_name: Optional[str] = None
76+
77+
78+
class BugoutUserGroups(BaseModel):
79+
groups: List[BugoutGroupUser]
80+
81+
82+
class BugoutGroupMembers(BaseModel):
83+
id: uuid.UUID
84+
name: str
85+
users: List[BugoutUserShort]
86+
87+
4188
class BugoutJournal(BaseModel):
4289
id: uuid.UUID
4390
bugout_user_id: uuid.UUID
4491
holder_ids: List[uuid.UUID]
4592
name: str
4693
created_at: datetime
4794
updated_at: datetime
48-
49-
50-
class BugoutToken(BaseModel):
51-
id: uuid.UUID
52-
token_type: Optional[str]
53-
token_note: Optional[str]

0 commit comments

Comments
 (0)