Merge branch 'master' into doc-updates

pull/257/head
Andy Piper 2022-11-13 22:04:13 +00:00
commit 3d10b13f32
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 8FBF7373AC449A7F
4 zmienionych plików z 334 dodań i 27 usunięć

Wyświetl plik

@ -5,38 +5,44 @@ version number. Breaking changes will be indicated by a change in the minor
v1.5.3 (in progress)
--------------------
* 3.1.3 support
* Add v2 media_post api
* Added v2 media_post api
* 3.1.4 support
* Add "remote", "local" and "only_media" parameter for timelines more broadly
* Document updates to instance information api return value
* Added "remote", "local" and "only_media" parameter for timelines more broadly
* Documented updates to instance information api return value
* 3.2.0 support
* Add account notes API
* Add thumbnail support to media_post / media_update
* Document new keys in media API
* Added account notes API
* Added thumbnail support to media_post / media_update
* Documented new keys in media API
* 3.3.0 support
* Add "notify" parameter for following.
* Add support for timed mutes
* Add support for getting an accounts features tags via account_featured_tags
* Added "notify" parameter for following.
* Added support for timed mutes
* Added support for getting an accounts features tags via account_featured_tags
* Miscelaneous additions
* Added support for paginating by date via converting dates to snowflake IDs (on Mastodon only - thanks to edent for the suggestion)
* Added a method to revoke oauth tokens (thanks fluffy-critter)
* Fixes
* Various small and big fixes, improving reliablity and test coverage
* Changed URLs from "tootsuite" to "mastodon" in several places (thanks andypiper)
* Fixed some fields not converting to datetimes (thanks SouthFox-D)
* Improved oauth web flow support
v1.5.2
------
* BREAKING CHANGE (but to a representation that was intended to be internal): Greatly improve how pagination info is stored (arittner)
* Add "unknown event" handler for streaming (arittner)
* Add support for exclude_types in notifications api (MicroCheapFx)
* Add pagination to bookmarks (arittner)
* Make connecting for streaming more resilient (arittner)
* Allow specifying a user agent header (arittner)
* Add support for tagged and exclude_reblogs on account_statuses api (arittner)
* Add support for reports without attached statuses (arittner)
* Added "unknown event" handler for streaming (arittner)
* Added support for exclude_types in notifications api (MicroCheapFx)
* Added pagination to bookmarks (arittner)
* Made connecting for streaming more resilient (arittner)
* Allowed specifying a user agent header (arittner)
* Addeded support for tagged and exclude_reblogs on account_statuses api (arittner)
* Added support for reports without attached statuses (arittner)
* General fixes
* Fix a typo in __json_fruefalse_parse (zen-tools)
* Fixed a typo in __json_fruefalse_parse (zen-tools)
* Some non-mastodon related fixes
* Fix a typo in error message for content_type (rinpatch
* Add support for specifying file name when uploading (animeavi)
* Fix several crashes related to gotosocials version string (fwaggle)
* Fix an issue related to hometowns version string
* Fixed a typo in error message for content_type (rinpatch
* Added support for specifying file name when uploading (animeavi)
* Fixed several crashes related to gotosocials version string (fwaggle)
* Fixed an issue related to hometowns version string
v1.5.1
------

Wyświetl plik

@ -513,6 +513,8 @@ class Mastodon:
def auth_request_url(self, client_id=None, redirect_uris="urn:ietf:wg:oauth:2.0:oob",
scopes=__DEFAULT_SCOPES, force_login=False):
def auth_request_url(self, client_id=None, redirect_uris="urn:ietf:wg:oauth:2.0:oob", scopes=__DEFAULT_SCOPES, force_login=False, state=None):
"""
Returns the URL that a client needs to request an OAuth grant from the server.
@ -526,6 +528,10 @@ class Mastodon:
Pass force_login if you want the user to always log in even when already logged
into web Mastodon (i.e. when registering multiple different accounts in an app).
State is the oauth `state`parameter to pass to the server. It is strongly suggested
to use a random, nonguessable value (i.e. nothing meaningful and no incrementing ID)
to preserve security guarantees. It can be left out for non-web login flows.
"""
if client_id is None:
client_id = self.client_id
@ -540,12 +546,11 @@ class Mastodon:
params['redirect_uri'] = redirect_uris
params['scope'] = " ".join(scopes)
params['force_login'] = force_login
params['state'] = state
formatted_params = urlencode(params)
return "".join([self.api_base_url, "/oauth/authorize?", formatted_params])
def log_in(self, username=None, password=None,
code=None, redirect_uri="urn:ietf:wg:oauth:2.0:oob", refresh_token=None,
scopes=__DEFAULT_SCOPES, to_file=None):
def log_in(self, username=None, password=None, code=None, redirect_uri="urn:ietf:wg:oauth:2.0:oob", refresh_token=None, scopes=__DEFAULT_SCOPES, to_file=None):
"""
Get the access token for a user.
@ -620,6 +625,26 @@ class Mastodon:
return response['access_token']
def revoke_access_token(self):
"""
Revoke the oauth token the user is currently authenticated with, effectively removing
the apps access and requiring the user to log in again.
"""
if self.access_token is None:
raise MastodonIllegalArgumentError("Not logged in, do not have a token to revoke.")
if self.client_id is None or self.client_secret is None:
raise MastodonIllegalArgumentError("Client authentication (id + secret) is required to revoke tokens.")
params = collections.OrderedDict([])
params['client_id'] = self.client_id
params['client_secret'] = self.client_secret
params['token'] = self.access_token
self.__api_request('POST', '/oauth/revoke', params)
# We are now logged out, clear token and logged in id
self.access_token = None
self.__logged_in_id = None
@api_version("2.7.0", "2.7.0", "2.7.0")
def create_account(self, username, password, email, agreement=False, reason=None, locale="en", scopes=__DEFAULT_SCOPES, to_file=None):
"""

Wyświetl plik

@ -0,0 +1,253 @@
interactions:
- request:
body: username=mastodonpy_test_2%40localhost%3A3000&password=5fc638e0e53eafd9c4145b6bb852667d&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&grant_type=password&client_id=__MASTODON_PY_TEST_CLIENT_ID&client_secret=__MASTODON_PY_TEST_CLIENT_SECRET&scope=read+write+follow+push
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '271'
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- tests/v311
method: POST
uri: http://localhost:3000/oauth/token
response:
body:
string: '{"access_token":"s3ZSxpaa2Uhe9EcHankvkfaQZQGiWpdEWIhX7GuhDlk","token_type":"Bearer","scope":"read
write follow push","created_at":1668370881}'
headers:
Cache-Control:
- no-store
Content-Security-Policy:
- 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
style-src ''self'' http://localhost:3000 ''nonce-pCi2AQ9aKYXwS29cp2OHAg=='';
media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
worker-src ''self'' blob: http://localhost:3000'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"b4c5259bc2edbe94aab5df0f3b8ba79a"
Pragma:
- no-cache
Referrer-Policy:
- strict-origin-when-cross-origin
Transfer-Encoding:
- chunked
Vary:
- Accept, Origin
X-Content-Type-Options:
- nosniff
X-Download-Options:
- noopen
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- 086350f4-00fc-4d82-a5ce-2b557df59682
X-Runtime:
- '0.040539'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
- request:
body: client_id=__MASTODON_PY_TEST_CLIENT_ID&client_secret=__MASTODON_PY_TEST_CLIENT_SECRET&token=s3ZSxpaa2Uhe9EcHankvkfaQZQGiWpdEWIhX7GuhDlk
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer s3ZSxpaa2Uhe9EcHankvkfaQZQGiWpdEWIhX7GuhDlk
Connection:
- keep-alive
Content-Length:
- '135'
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- tests/v311
method: POST
uri: http://localhost:3000/oauth/revoke
response:
body:
string: '{}'
headers:
Cache-Control:
- max-age=0, private, must-revalidate
Content-Security-Policy:
- 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
style-src ''self'' http://localhost:3000 ''nonce-PqM4ChK427oGZ5jIKprkYQ=='';
media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
worker-src ''self'' blob: http://localhost:3000'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"44136fa355b3678a1146ad16f7e8649e"
Referrer-Policy:
- strict-origin-when-cross-origin
Transfer-Encoding:
- chunked
Vary:
- Accept
X-Content-Type-Options:
- nosniff
X-Download-Options:
- noopen
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- 36ec7e63-b15b-487a-aa4a-c396db945794
X-Runtime:
- '0.010431'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
- request:
body: status=illegal+access+detected
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '30'
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- tests/v311
method: POST
uri: http://localhost:3000/api/v1/statuses
response:
body:
string: '{"error":"The access token is invalid"}'
headers:
Cache-Control:
- no-store
Content-Security-Policy:
- 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
style-src ''self'' http://localhost:3000 ''nonce-UClOh6+Y0zf3a4O/ysqT/w=='';
media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
worker-src ''self'' blob: http://localhost:3000'
Content-Type:
- application/json; charset=utf-8
Pragma:
- no-cache
Referrer-Policy:
- strict-origin-when-cross-origin
Transfer-Encoding:
- chunked
Vary:
- Accept, Origin
WWW-Authenticate:
- Bearer realm="Doorkeeper", error="invalid_token", error_description="The access
token is invalid"
X-Content-Type-Options:
- nosniff
X-Download-Options:
- noopen
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- ab1f9d04-149b-431a-b2b0-79921d45f3bc
X-Runtime:
- '0.005292'
X-XSS-Protection:
- 1; mode=block
status:
code: 401
message: Unauthorized
- request:
body: status=illegal+access+detected
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '30'
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- tests/v311
method: POST
uri: http://localhost:3000/api/v1/statuses
response:
body:
string: '{"error":"The access token is invalid"}'
headers:
Cache-Control:
- no-store
Content-Security-Policy:
- 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
style-src ''self'' http://localhost:3000 ''nonce-ZTmQUUs9q7lX74Aa3bTgzA=='';
media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
worker-src ''self'' blob: http://localhost:3000'
Content-Type:
- application/json; charset=utf-8
Pragma:
- no-cache
Referrer-Policy:
- strict-origin-when-cross-origin
Transfer-Encoding:
- chunked
Vary:
- Accept, Origin
WWW-Authenticate:
- Bearer realm="Doorkeeper", error="invalid_token", error_description="The access
token is invalid"
X-Content-Type-Options:
- nosniff
X-Download-Options:
- noopen
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- 9a7ad262-0d94-4df6-92a5-a670d6515979
X-Runtime:
- '0.004613'
X-XSS-Protection:
- 1; mode=block
status:
code: 401
message: Unauthorized
version: 1

Wyświetl plik

@ -22,14 +22,37 @@ def test_log_in_none(api_anonymous):
with pytest.raises(MastodonIllegalArgumentError):
api_anonymous.log_in()
@pytest.mark.vcr()
def test_log_in_password(api_anonymous):
token = api_anonymous.log_in(
username='mastodonpy_test_2@localhost:3000',
password='5fc638e0e53eafd9c4145b6bb852667d')
password='5fc638e0e53eafd9c4145b6bb852667d'
)
assert token
@pytest.mark.vcr()
def test_revoke(api_anonymous):
token = api_anonymous.log_in(
username='mastodonpy_test_2@localhost:3000',
password='5fc638e0e53eafd9c4145b6bb852667d'
)
api_anonymous.revoke_access_token()
try:
api_anonymous.toot("illegal access detected")
assert False
except Exception as e:
print(e)
pass
api_revoked_token = Mastodon(access_token = token)
try:
api_anonymous.toot("illegal access detected")
assert False
except Exception as e:
print(e)
pass
@pytest.mark.vcr()
def test_log_in_password_incorrect(api_anonymous):
with pytest.raises(MastodonIllegalArgumentError):