Skip to content

Commit 8555586

Browse files
committed
feat(client): add invitation related endpoints
1 parent 8e9748d commit 8555586

File tree

7 files changed

+430
-9
lines changed

7 files changed

+430
-9
lines changed

pygitguardian/client.py

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
)
2727
from .models import (
2828
APITokensResponse,
29+
CreateInvitation,
30+
CreateInvitationParameter,
2931
CreateTeam,
3032
CreateTeamInvitation,
3133
CreateTeamMember,
@@ -37,6 +39,8 @@
3739
HealthCheckResponse,
3840
HoneytokenResponse,
3941
HoneytokenWithContextResponse,
42+
Invitation,
43+
InvitationParameter,
4044
JWTResponse,
4145
JWTService,
4246
Member,
@@ -929,7 +933,7 @@ def list_members(
929933

930934
response = self.get(
931935
endpoint="members",
932-
data=query_parameters.to_dict() if query_parameters else {},
936+
params=query_parameters.to_dict() if query_parameters else {},
933937
extra_headers=extra_headers,
934938
)
935939

@@ -1106,7 +1110,7 @@ def list_team_invitations(
11061110
) -> Union[Detail, CursorPaginatedResponse[TeamInvitation]]:
11071111
response = self.get(
11081112
endpoint=f"teams/{team_id}/team_invitations",
1109-
data=parameters.to_dict() if parameters else {},
1113+
params=parameters.to_dict() if parameters else {},
11101114
extra_headers=extra_headers,
11111115
)
11121116

@@ -1166,7 +1170,7 @@ def list_team_members(
11661170
) -> Union[Detail, CursorPaginatedResponse[TeamMember]]:
11671171
response = self.get(
11681172
endpoint=f"teams/{team_id}/team_memberships",
1169-
data=parameters.to_dict() if parameters else {},
1173+
params=parameters.to_dict() if parameters else {},
11701174
extra_headers=extra_headers,
11711175
)
11721176

@@ -1225,7 +1229,7 @@ def list_sources(
12251229
) -> Union[Detail, CursorPaginatedResponse[Source]]:
12261230
response = self.get(
12271231
endpoint="sources",
1228-
data=parameters.to_dict() if parameters else {},
1232+
params=parameters.to_dict() if parameters else {},
12291233
extra_headers=extra_headers,
12301234
)
12311235

@@ -1246,7 +1250,7 @@ def list_teams_sources(
12461250
) -> Union[Detail, CursorPaginatedResponse[Source]]:
12471251
response = self.get(
12481252
endpoint=f"teams/{team_id}/sources",
1249-
data=parameters.to_dict() if parameters else {},
1253+
params=parameters.to_dict() if parameters else {},
12501254
extra_headers=extra_headers,
12511255
)
12521256

@@ -1278,3 +1282,61 @@ def update_team_source(
12781282
return 204
12791283

12801284
return load_detail(response)
1285+
1286+
def list_invitations(
1287+
self,
1288+
parameters: Optional[InvitationParameter] = None,
1289+
extra_headers: Optional[Dict[str, str]] = None,
1290+
) -> Union[Detail, CursorPaginatedResponse[Invitation]]:
1291+
response = self.get(
1292+
endpoint="invitations",
1293+
params=parameters.to_dict() if parameters else {},
1294+
extra_headers=extra_headers,
1295+
)
1296+
1297+
obj: Union[Detail, CursorPaginatedResponse[Invitation]]
1298+
if is_ok(response):
1299+
obj = CursorPaginatedResponse[Invitation].from_response(
1300+
response, Invitation
1301+
)
1302+
else:
1303+
obj = load_detail(response)
1304+
1305+
obj.status_code
1306+
return obj
1307+
1308+
def send_invitation(
1309+
self,
1310+
invitation: CreateInvitation,
1311+
parameters: Optional[CreateInvitationParameter] = None,
1312+
extra_headers: Optional[Dict[str, str]] = None,
1313+
) -> Union[Detail, Invitation]:
1314+
response = self.post(
1315+
endpoint="invitations",
1316+
data=CreateInvitation.to_dict(invitation),
1317+
params=parameters.to_dict() if parameters else {},
1318+
extra_headers=extra_headers,
1319+
)
1320+
1321+
obj: Union[Detail, Invitation]
1322+
if is_create_ok(response):
1323+
obj = Invitation.from_dict(response.json())
1324+
else:
1325+
obj = load_detail(response)
1326+
1327+
obj.status_code = response.status_code
1328+
return obj
1329+
1330+
def delete_invitation(
1331+
self,
1332+
invitation_id: int,
1333+
extra_headers: Optional[Dict[str, str]] = None,
1334+
) -> Union[Detail, int]:
1335+
response = self.delete(
1336+
endpoint=f"invitations/{invitation_id}", extra_headers=extra_headers
1337+
)
1338+
1339+
if is_delete_ok(response):
1340+
return response.status_code
1341+
1342+
return load_detail(response)

pygitguardian/models.py

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,10 +1199,16 @@ class MembersParameters(PaginationParameter, SearchParameter, ToDictMixin):
11991199
] = None
12001200

12011201

1202-
MembersParametersSchema = cast(
1203-
Type[BaseSchema],
1204-
marshmallow_dataclass.class_schema(MembersParameters, base_schema=BaseSchema),
1205-
)
1202+
class MembersParametersSchema(BaseSchema):
1203+
access_level = fields.Enum(AccessLevel, by_value=True, allow_none=True)
1204+
active = fields.Bool(allow_none=True)
1205+
ordering = fields.Str(allow_none=True)
1206+
1207+
@post_load
1208+
def return_members_parameters(self, data: dict[str, Any], **kwargs: dict[str, Any]):
1209+
return MembersParameters(**data)
1210+
1211+
12061212
MembersParameters.SCHEMA = MembersParametersSchema()
12071213

12081214

@@ -1565,3 +1571,64 @@ class SourceParameters(TeamSourceParameters):
15651571
marshmallow_dataclass.class_schema(SourceParameters, base_schema=BaseSchema),
15661572
)
15671573
SourceParameters.SCHEMA = SourceParametersSchema()
1574+
1575+
1576+
@dataclass
1577+
class InvitationParameter(
1578+
PaginationParameter, SearchParameter, FromDictMixin, ToDictMixin
1579+
):
1580+
ordering: Literal["date", "-date"]
1581+
1582+
1583+
@dataclass
1584+
class Invitation(Base, FromDictMixin):
1585+
id: int
1586+
email: str
1587+
access_level: AccessLevel
1588+
date: datetime
1589+
1590+
1591+
class InvitationSchema(BaseSchema):
1592+
id = fields.Int(required=True)
1593+
email = fields.Str(required=True)
1594+
access_level = fields.Enum(AccessLevel, by_value=True, required=True)
1595+
date = fields.DateTime(required=True)
1596+
1597+
@post_load
1598+
def return_invitation(self, data: dict[str, Any], **kwargs: dict[str, Any]):
1599+
return Invitation(**data)
1600+
1601+
1602+
Invitation.SCHEMA = InvitationSchema()
1603+
1604+
1605+
@dataclass
1606+
class CreateInvitationParameter(FromDictMixin, ToDictMixin):
1607+
send_email: Optional[bool] = None
1608+
1609+
1610+
CreateInvitationParameterSchema = cast(
1611+
Type[BaseSchema],
1612+
marshmallow_dataclass.class_schema(
1613+
CreateInvitationParameter, base_schema=BaseSchema
1614+
),
1615+
)
1616+
CreateInvitationParameter.SCHEMA = CreateInvitationParameterSchema()
1617+
1618+
1619+
@dataclass
1620+
class CreateInvitation(FromDictMixin, ToDictMixin):
1621+
email: str
1622+
access_level: AccessLevel
1623+
1624+
1625+
class CreateInvitationSchema(BaseSchema):
1626+
email = fields.Str(required=True)
1627+
access_level = fields.Enum(AccessLevel, by_value=True, required=True)
1628+
1629+
@post_load
1630+
def return_invitation(self, data: dict[str, Any], **kwargs: dict[str, Any]):
1631+
return CreateInvitation(**data)
1632+
1633+
1634+
CreateInvitation.SCHEMA = CreateInvitationSchema()
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
interactions:
2+
- request:
3+
body: null
4+
headers:
5+
Accept:
6+
- '*/*'
7+
Accept-Encoding:
8+
- gzip, deflate
9+
Connection:
10+
- keep-alive
11+
Content-Length:
12+
- '0'
13+
User-Agent:
14+
- pygitguardian/1.18.0 (Darwin;py3.11.8)
15+
method: DELETE
16+
uri: https://api.gitguardian.com/v1/invitations/2
17+
response:
18+
body:
19+
string: ''
20+
headers:
21+
Access-Control-Expose-Headers:
22+
- X-App-Version
23+
Allow:
24+
- DELETE, OPTIONS
25+
Connection:
26+
- keep-alive
27+
Content-Length:
28+
- '0'
29+
Cross-Origin-Opener-Policy:
30+
- same-origin
31+
Date:
32+
- Fri, 06 Dec 2024 13:38:57 GMT
33+
Referrer-Policy:
34+
- same-origin
35+
Server:
36+
- nginx/1.24.0
37+
Vary:
38+
- Cookie
39+
X-App-Version:
40+
- dev
41+
X-Content-Type-Options:
42+
- nosniff
43+
X-Frame-Options:
44+
- DENY
45+
X-Request-ID:
46+
- fd715a797aabb2eddf49823db3e54209
47+
X-SCA-Engine-Version:
48+
- 2.2.0
49+
X-Secrets-Engine-Version:
50+
- 2.127.0
51+
status:
52+
code: 204
53+
message: No Content
54+
version: 1
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
interactions:
2+
- request:
3+
body: null
4+
headers:
5+
Accept:
6+
- '*/*'
7+
Accept-Encoding:
8+
- gzip, deflate
9+
Connection:
10+
- keep-alive
11+
User-Agent:
12+
- pygitguardian/1.18.0 (Darwin;py3.11.8)
13+
method: GET
14+
uri: https://api.gitguardian.com/v1/invitations
15+
response:
16+
body:
17+
string: '[{"id":1,"date":"2024-12-05T17:35:12.273332Z","email":"toto+test@gg.com","role":"member","access_level":"member"}]'
18+
headers:
19+
Access-Control-Expose-Headers:
20+
- X-App-Version
21+
Allow:
22+
- GET, POST, HEAD, OPTIONS
23+
Connection:
24+
- keep-alive
25+
Content-Length:
26+
- '114'
27+
Content-Type:
28+
- application/json
29+
Cross-Origin-Opener-Policy:
30+
- same-origin
31+
Date:
32+
- Fri, 06 Dec 2024 13:33:31 GMT
33+
Link:
34+
- ''
35+
Referrer-Policy:
36+
- same-origin
37+
Server:
38+
- nginx/1.24.0
39+
Vary:
40+
- Cookie
41+
X-App-Version:
42+
- dev
43+
X-Content-Type-Options:
44+
- nosniff
45+
X-Frame-Options:
46+
- DENY
47+
X-Per-Page:
48+
- '20'
49+
X-Request-ID:
50+
- 182ad8123736b9315def7a957569ef89
51+
X-SCA-Engine-Version:
52+
- 2.2.0
53+
X-Secrets-Engine-Version:
54+
- 2.127.0
55+
status:
56+
code: 200
57+
message: OK
58+
version: 1
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
interactions:
2+
- request:
3+
body: null
4+
headers:
5+
Accept:
6+
- '*/*'
7+
Accept-Encoding:
8+
- gzip, deflate
9+
Connection:
10+
- keep-alive
11+
User-Agent:
12+
- pygitguardian/1.18.0 (Darwin;py3.11.8)
13+
method: GET
14+
uri: https://api.gitguardian.com/v1/members?access_level=manager
15+
response:
16+
body:
17+
string: '[]'
18+
headers:
19+
Access-Control-Expose-Headers:
20+
- X-App-Version
21+
Allow:
22+
- GET, HEAD, OPTIONS
23+
Connection:
24+
- keep-alive
25+
Content-Length:
26+
- '2'
27+
Content-Type:
28+
- application/json
29+
Cross-Origin-Opener-Policy:
30+
- same-origin
31+
Date:
32+
- Fri, 06 Dec 2024 13:53:52 GMT
33+
Link:
34+
- ''
35+
Referrer-Policy:
36+
- same-origin
37+
Server:
38+
- nginx/1.24.0
39+
Vary:
40+
- Cookie
41+
X-App-Version:
42+
- dev
43+
X-Content-Type-Options:
44+
- nosniff
45+
X-Frame-Options:
46+
- DENY
47+
X-Per-Page:
48+
- '20'
49+
X-Request-ID:
50+
- 345625b0c1e6c814a9b997bd7ea3ea96
51+
X-SCA-Engine-Version:
52+
- 2.2.0
53+
X-Secrets-Engine-Version:
54+
- 2.127.0
55+
status:
56+
code: 200
57+
message: OK
58+
version: 1

0 commit comments

Comments
 (0)