diff --git a/github/Organization.py b/github/Organization.py index 65e167cba6..42434b92a9 100644 --- a/github/Organization.py +++ b/github/Organization.py @@ -1044,6 +1044,18 @@ def invite_user( input=parameters, ) + def cancel_invitation(self, invitee): + """ + :calls: `DELETE /orgs/{org}/invitations/{invitation_id} `_ + :param invitee: :class:`github.NamedUser.NamedUser` + :rtype: None + """ + assert isinstance(invitee, github.NamedUser.NamedUser), invitee + status, headers, data = self._requester.requestJson( + "DELETE", f"{self.url}/invitations/{invitee.id}" + ) + return status == 204 + def has_in_members(self, member): """ :calls: `GET /orgs/{org}/members/{user} `_ diff --git a/github/Organization.pyi b/github/Organization.pyi index cd5f2086e4..fc2e4e13a1 100644 --- a/github/Organization.pyi +++ b/github/Organization.pyi @@ -168,6 +168,7 @@ class Organization(CompletableGithubObject): role: Union[str, _NotSetType] = ..., teams: Union[List[Team], _NotSetType] = ..., ) -> None: ... + def cancel_invitation(self, invitee: NamedUser) -> bool: ... @property def location(self) -> str: ... @property diff --git a/tests/Organization2072.py b/tests/Organization2072.py new file mode 100644 index 0000000000..0c42fcfae7 --- /dev/null +++ b/tests/Organization2072.py @@ -0,0 +1,40 @@ +############################ Copyrights and license ############################ +# # +# Copyright 2021 James Simpson # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +from . import Framework + + +class Organization2072(Framework.TestCase): + def setUp(self): + super().setUp() + self.org = self.g.get_organization("TestOrganization2072") + + def testCancelInvitation(self): + self.assertFalse( + any([i for i in self.org.invitations() if i.email == "foo@bar.org"]) + ) + self.org.invite_user(email="foo@bar.org") + self.assertTrue( + any([i for i in self.org.invitations() if i.email == "foo@bar.org"]) + ) + invitation = [i for i in self.org.invitations() if i.email == "foo@bar.org"][0] + self.assertTrue(self.org.cancel_invitation(invitation)) diff --git a/tests/ReplayData/Organization2072.setUp.txt b/tests/ReplayData/Organization2072.setUp.txt new file mode 100644 index 0000000000..5d157b5dc1 --- /dev/null +++ b/tests/ReplayData/Organization2072.setUp.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/orgs/TestOrganization2072 +{'Authorization': 'Bearer jwt_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Mon, 11 Oct 2021 05:58:42 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"a4075a2c2ee087533d91b22bbcc723d96ba3381075cee9fb4910bdb081bdfc48"'), ('Last-Modified', 'Mon, 11 Oct 2021 05:17:24 GMT'), ('X-OAuth-Scopes', 'admin:org, admin:org_hook'), ('X-Accepted-OAuth-Scopes', 'admin:org, read:org, repo, user, write:org'), ('github-authentication-token-expiration', '2021-10-18 05:11:21 UTC'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4993'), ('X-RateLimit-Reset', '1633933862'), ('X-RateLimit-Used', '7'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'C364:057F:173685:19010C:6163D292')] +{"login":"TestOrganization2072","id":92288976,"node_id":"O_kgDOBYA30A","url":"https://api.github.com/orgs/TestOrganization2072","repos_url":"https://api.github.com/orgs/TestOrganization2072/repos","events_url":"https://api.github.com/orgs/TestOrganization2072/events","hooks_url":"https://api.github.com/orgs/TestOrganization2072/hooks","issues_url":"https://api.github.com/orgs/TestOrganization2072/issues","members_url":"https://api.github.com/orgs/TestOrganization2072/members{/member}","public_members_url":"https://api.github.com/orgs/TestOrganization2072/public_members{/member}","avatar_url":"https://avatars.githubusercontent.com/u/92288976?v=4","description":null,"is_verified":false,"has_organization_projects":true,"has_repository_projects":true,"public_repos":0,"public_gists":0,"followers":0,"following":0,"html_url":"https://github.com/TestOrganization2072","created_at":"2021-10-11T05:17:24Z","updated_at":"2021-10-11T05:17:24Z","type":"Organization","total_private_repos":0,"owned_private_repos":0,"private_gists":0,"disk_usage":0,"collaborators":0,"billing_email":"james@snowterminal.com","default_repository_permission":"read","members_can_create_repositories":true,"two_factor_requirement_enabled":false,"members_allowed_repository_creation_type":"all","members_can_create_public_repositories":true,"members_can_create_private_repositories":true,"members_can_create_internal_repositories":false,"members_can_create_pages":true,"members_can_create_public_pages":true,"members_can_create_private_pages":true,"plan":{"name":"free","space":976562499,"private_repos":10000,"filled_seats":1,"seats":0}} + diff --git a/tests/ReplayData/Organization2072.testCancelInvitation.txt b/tests/ReplayData/Organization2072.testCancelInvitation.txt new file mode 100644 index 0000000000..23529795e9 --- /dev/null +++ b/tests/ReplayData/Organization2072.testCancelInvitation.txt @@ -0,0 +1,55 @@ +https +GET +api.github.com +None +/orgs/TestOrganization2072/invitations +{'Accept': 'application/vnd.github.dazzler-preview+json', 'Authorization': 'Bearer jwt_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Mon, 11 Oct 2021 05:58:43 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '2'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', '"8c90a0d7033b64e2379559696e2721dba236c2bf7e8efcc74c3f7fed177ab918"'), ('X-OAuth-Scopes', 'admin:org, admin:org_hook'), ('X-Accepted-OAuth-Scopes', 'admin:org, repo'), ('github-authentication-token-expiration', '2021-10-18 05:11:21 UTC'), ('X-GitHub-Media-Type', 'github.v3; param=dazzler-preview; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4992'), ('X-RateLimit-Reset', '1633933862'), ('X-RateLimit-Used', '8'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-GitHub-Request-Id', 'C366:5177:B05A9:BC595:6163D292')] +[] + +https +POST +api.github.com +None +/orgs/TestOrganization2072/invitations +{'Accept': 'application/vnd.github.dazzler-preview+json', 'Authorization': 'Bearer jwt_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'} +{"email": "foo@bar.org"} +201 +[('Server', 'GitHub.com'), ('Date', 'Mon, 11 Oct 2021 05:58:43 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '1203'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', '"dd358302b1f7c80a31b1b6ca3de6eda6e4d9d6c73247b78ae8039d239e48bd85"'), ('X-OAuth-Scopes', 'admin:org, admin:org_hook'), ('X-Accepted-OAuth-Scopes', 'admin:org'), ('github-authentication-token-expiration', '2021-10-18 05:11:21 UTC'), ('X-GitHub-Media-Type', 'github.v3; param=dazzler-preview; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4991'), ('X-RateLimit-Reset', '1633933862'), ('X-RateLimit-Used', '9'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-GitHub-Request-Id', 'C368:5177:B05C8:BC5B3:6163D293')] +{"id":28941455,"node_id":"OI_kwDOBYA30M4BuZyP","login":null,"email":"foo@bar.org","role":"direct_member","created_at":"2021-10-11T05:58:43Z","inviter":{"login":"jsimpso","id":10970100,"node_id":"MDQ6VXNlcjEwOTcwMTAw","avatar_url":"https://avatars.githubusercontent.com/u/10970100?u=303b0ceb6458644496499b0031b67badce03d5e4&v=4","gravatar_id":"","url":"https://api.github.com/users/jsimpso","html_url":"https://github.com/jsimpso","followers_url":"https://api.github.com/users/jsimpso/followers","following_url":"https://api.github.com/users/jsimpso/following{/other_user}","gists_url":"https://api.github.com/users/jsimpso/gists{/gist_id}","starred_url":"https://api.github.com/users/jsimpso/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jsimpso/subscriptions","organizations_url":"https://api.github.com/users/jsimpso/orgs","repos_url":"https://api.github.com/users/jsimpso/repos","events_url":"https://api.github.com/users/jsimpso/events{/privacy}","received_events_url":"https://api.github.com/users/jsimpso/received_events","type":"User","site_admin":false},"team_count":0,"invitation_teams_url":"https://api.github.com/organizations/92288976/invitations/28941455/teams"} + +https +GET +api.github.com +None +/orgs/TestOrganization2072/invitations +{'Accept': 'application/vnd.github.dazzler-preview+json', 'Authorization': 'Bearer jwt_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Mon, 11 Oct 2021 05:58:44 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"4d733ff648b653478e453f482e76db08f21cc351df6f0c1f14d6c293b9d5f267"'), ('X-OAuth-Scopes', 'admin:org, admin:org_hook'), ('X-Accepted-OAuth-Scopes', 'admin:org, repo'), ('github-authentication-token-expiration', '2021-10-18 05:11:21 UTC'), ('X-GitHub-Media-Type', 'github.v3; param=dazzler-preview; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4990'), ('X-RateLimit-Reset', '1633933862'), ('X-RateLimit-Used', '10'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'C36A:5177:B05ED:BC5D5:6163D293')] +[{"id":28941455,"node_id":"OI_kwDOBYA30M4BuZyP","login":null,"email":"foo@bar.org","role":"direct_member","created_at":"2021-10-11T13:58:43.000+08:00","failed_at":null,"failed_reason":null,"inviter":{"login":"jsimpso","id":10970100,"node_id":"MDQ6VXNlcjEwOTcwMTAw","avatar_url":"https://avatars.githubusercontent.com/u/10970100?v=4","gravatar_id":"","url":"https://api.github.com/users/jsimpso","html_url":"https://github.com/jsimpso","followers_url":"https://api.github.com/users/jsimpso/followers","following_url":"https://api.github.com/users/jsimpso/following{/other_user}","gists_url":"https://api.github.com/users/jsimpso/gists{/gist_id}","starred_url":"https://api.github.com/users/jsimpso/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jsimpso/subscriptions","organizations_url":"https://api.github.com/users/jsimpso/orgs","repos_url":"https://api.github.com/users/jsimpso/repos","events_url":"https://api.github.com/users/jsimpso/events{/privacy}","received_events_url":"https://api.github.com/users/jsimpso/received_events","type":"User","site_admin":false},"team_count":0,"invitation_teams_url":"https://api.github.com/organizations/92288976/invitations/28941455/teams"}] + +https +GET +api.github.com +None +/orgs/TestOrganization2072/invitations +{'Accept': 'application/vnd.github.dazzler-preview+json', 'Authorization': 'Bearer jwt_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Mon, 11 Oct 2021 05:58:44 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"4d733ff648b653478e453f482e76db08f21cc351df6f0c1f14d6c293b9d5f267"'), ('X-OAuth-Scopes', 'admin:org, admin:org_hook'), ('X-Accepted-OAuth-Scopes', 'admin:org, repo'), ('github-authentication-token-expiration', '2021-10-18 05:11:21 UTC'), ('X-GitHub-Media-Type', 'github.v3; param=dazzler-preview; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4989'), ('X-RateLimit-Reset', '1633933862'), ('X-RateLimit-Used', '11'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'C36C:79CC:DA6F4:EB3C2:6163D294')] +[{"id":28941455,"node_id":"OI_kwDOBYA30M4BuZyP","login":null,"email":"foo@bar.org","role":"direct_member","created_at":"2021-10-11T13:58:43.000+08:00","failed_at":null,"failed_reason":null,"inviter":{"login":"jsimpso","id":10970100,"node_id":"MDQ6VXNlcjEwOTcwMTAw","avatar_url":"https://avatars.githubusercontent.com/u/10970100?v=4","gravatar_id":"","url":"https://api.github.com/users/jsimpso","html_url":"https://github.com/jsimpso","followers_url":"https://api.github.com/users/jsimpso/followers","following_url":"https://api.github.com/users/jsimpso/following{/other_user}","gists_url":"https://api.github.com/users/jsimpso/gists{/gist_id}","starred_url":"https://api.github.com/users/jsimpso/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jsimpso/subscriptions","organizations_url":"https://api.github.com/users/jsimpso/orgs","repos_url":"https://api.github.com/users/jsimpso/repos","events_url":"https://api.github.com/users/jsimpso/events{/privacy}","received_events_url":"https://api.github.com/users/jsimpso/received_events","type":"User","site_admin":false},"team_count":0,"invitation_teams_url":"https://api.github.com/organizations/92288976/invitations/28941455/teams"}] + +https +DELETE +api.github.com +None +/orgs/TestOrganization2072/invitations/28941455 +{'Authorization': 'Bearer jwt_removed', 'User-Agent': 'PyGithub/Python'} +None +204 +[('Server', 'GitHub.com'), ('Date', 'Mon, 11 Oct 2021 05:58:45 GMT'), ('X-OAuth-Scopes', 'admin:org, admin:org_hook'), ('X-Accepted-OAuth-Scopes', 'admin:org'), ('github-authentication-token-expiration', '2021-10-18 05:11:21 UTC'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4988'), ('X-RateLimit-Reset', '1633933862'), ('X-RateLimit-Used', '12'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Vary', 'Accept-Encoding, Accept, X-Requested-With'), ('X-GitHub-Request-Id', 'C36E:79CB:4A7D4:5AA4F:6163D294')] + +