aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhalcy <halcy@ARARAGI-KUN>2022-11-19 02:34:01 +0200
committerhalcy <halcy@ARARAGI-KUN>2022-11-19 02:34:01 +0200
commit853cd82ecb9e1d25f395514b3bb1616071d43493 (patch)
treea0812b4fa12fadd299886615669f86be6f7bd2cf
parentf26bf0db1dfc93fafa344977bd999a334a55cd36 (diff)
downloadmastodon.py-853cd82ecb9e1d25f395514b3bb1616071d43493.tar.gz
add ability to get detailed signup error from create_account
-rw-r--r--CHANGELOG.rst1
-rw-r--r--TODO.md2
-rw-r--r--mastodon/Mastodon.py106
-rw-r--r--tests/cassettes/test_app_account_create_invalid.yaml245
-rw-r--r--tests/cassettes/test_push_set.yaml122
-rw-r--r--tests/test_create_app.py23
6 files changed, 331 insertions, 168 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index fb69ded..7526873 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -8,6 +8,7 @@ v1.6.3
8* Add confirmation email resend API (`email_resend_confirmation`) 8* Add confirmation email resend API (`email_resend_confirmation`)
9* Add account lookup API (`account_lookup`) 9* Add account lookup API (`account_lookup`)
10* Add `policy` param to control notification sources for `push_subscription_set` 10* Add `policy` param to control notification sources for `push_subscription_set`
11* Add ability to get detailed signup error to `create_account`
11 12
12v1.6.2 13v1.6.2
13------ 14------
diff --git a/TODO.md b/TODO.md
index bf73f06..7be1c70 100644
--- a/TODO.md
+++ b/TODO.md
@@ -33,7 +33,7 @@ Refer to mastodon changelog and API docs for details when implementing, add or m
33* [x] Add POST /api/v1/emails/confirmations to REST API 33* [x] Add POST /api/v1/emails/confirmations to REST API
34* [x] Add GET /api/v1/accounts/lookup to REST API 34* [x] Add GET /api/v1/accounts/lookup to REST API
35* [x] Add policy param to POST /api/v1/push/subscriptions in REST API 35* [x] Add policy param to POST /api/v1/push/subscriptions in REST API
36* [ ] Add details to error response for POST /api/v1/accounts in REST API 36* [x] Add details to error response for POST /api/v1/accounts in REST API
37 37
383.4.2 383.4.2
39----- 39-----
diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py
index 12a054a..ae560c5 100644
--- a/mastodon/Mastodon.py
+++ b/mastodon/Mastodon.py
@@ -605,8 +605,7 @@ class Mastodon:
605 params['scope'] = " ".join(scopes) 605 params['scope'] = " ".join(scopes)
606 606
607 try: 607 try:
608 response = self.__api_request( 608 response = self.__api_request('POST', '/oauth/token', params, do_ratelimiting=False)
609 'POST', '/oauth/token', params, do_ratelimiting=False)
610 self.access_token = response['access_token'] 609 self.access_token = response['access_token']
611 self.__set_refresh_token(response.get('refresh_token')) 610 self.__set_refresh_token(response.get('refresh_token'))
612 self.__set_token_expired(int(response.get('expires_in', 0))) 611 self.__set_token_expired(int(response.get('expires_in', 0)))
@@ -658,8 +657,8 @@ class Mastodon:
658 self.access_token = None 657 self.access_token = None
659 self.__logged_in_id = None 658 self.__logged_in_id = None
660 659
661 @api_version("2.7.0", "2.7.0", "2.7.0") 660 @api_version("2.7.0", "2.7.0", "3.4.0")
662 def create_account(self, username, password, email, agreement=False, reason=None, locale="en", scopes=__DEFAULT_SCOPES, to_file=None): 661 def create_account(self, username, password, email, agreement=False, reason=None, locale="en", scopes=__DEFAULT_SCOPES, to_file=None, return_detailed_error=False):
663 """ 662 """
664 Creates a new user account with the given username, password and email. "agreement" 663 Creates a new user account with the given username, password and email. "agreement"
665 must be set to true (after showing the user the instance's user agreement and having 664 must be set to true (after showing the user the instance's user agreement and having
@@ -674,6 +673,26 @@ class Mastodon:
674 Returns an access token (just like log_in), which it can also persist to to_file, 673 Returns an access token (just like log_in), which it can also persist to to_file,
675 and sets it internally so that the user is now logged in. Note that this token 674 and sets it internally so that the user is now logged in. Note that this token
676 can only be used after the user has confirmed their email. 675 can only be used after the user has confirmed their email.
676
677 By default, the function will throw if the account could not be created. Alternately,
678 when `return_detailed_error` is passed, Mastodon.py will return the detailed error
679 response that the API provides (Starting from version 3.4.0 - not checked here) as an dict with
680 error details as the second return value and the token returned as `None` in case of error.
681 The dict will contain a text `error` values as well as a `details` value which is a dict with
682 one optional key for each potential field (`username`, `password`, `email` and `agreement`),
683 each if present containing a dict with an `error` category and free text `description`.
684 Valid error categories are:
685
686 * ERR_BLOCKED - When e-mail provider is not allowed
687 * ERR_UNREACHABLE - When e-mail address does not resolve to any IP via DNS (MX, A, AAAA)
688 * ERR_TAKEN - When username or e-mail are already taken
689 * ERR_RESERVED - When a username is reserved, e.g. "webmaster" or "admin"
690 * ERR_ACCEPTED - When agreement has not been accepted
691 * ERR_BLANK - When a required attribute is blank
692 * ERR_INVALID - When an attribute is malformed, e.g. wrong characters or invalid e-mail address
693 * ERR_TOO_LONG - When an attribute is over the character limit
694 * ERR_TOO_SHORT - When an attribute is under the character requirement
695 * ERR_INCLUSION - When an attribute is not one of the allowed values, e.g. unsupported locale
677 """ 696 """
678 params = self.__generate_params(locals(), ['to_file', 'scopes']) 697 params = self.__generate_params(locals(), ['to_file', 'scopes'])
679 params['client_id'] = self.client_id 698 params['client_id'] = self.client_id
@@ -690,8 +709,7 @@ class Mastodon:
690 oauth_params['client_secret'] = self.client_secret 709 oauth_params['client_secret'] = self.client_secret
691 oauth_params['grant_type'] = 'client_credentials' 710 oauth_params['grant_type'] = 'client_credentials'
692 711
693 response = self.__api_request( 712 response = self.__api_request('POST', '/oauth/token', oauth_params, do_ratelimiting=False)
694 'POST', '/oauth/token', oauth_params, do_ratelimiting=False)
695 temp_access_token = response['access_token'] 713 temp_access_token = response['access_token']
696 except Exception as e: 714 except Exception as e:
697 raise MastodonIllegalArgumentError( 715 raise MastodonIllegalArgumentError(
@@ -699,13 +717,16 @@ class Mastodon:
699 717
700 # Step 2: Use that to create a user 718 # Step 2: Use that to create a user
701 try: 719 try:
702 response = self.__api_request('POST', '/api/v1/accounts', params, do_ratelimiting=False, 720 response = self.__api_request('POST', '/api/v1/accounts', params, do_ratelimiting=False, access_token_override=temp_access_token, skip_error_check=True)
703 access_token_override=temp_access_token) 721 if "error" in response:
722 if return_detailed_error:
723 return None, response
724 raise MastodonIllegalArgumentError('Invalid request: %s' % e)
704 self.access_token = response['access_token'] 725 self.access_token = response['access_token']
705 self.__set_refresh_token(response.get('refresh_token')) 726 self.__set_refresh_token(response.get('refresh_token'))
706 self.__set_token_expired(int(response.get('expires_in', 0))) 727 self.__set_token_expired(int(response.get('expires_in', 0)))
707 except Exception as e: 728 except Exception as e:
708 raise MastodonIllegalArgumentError('Invalid request: %s' % e) 729 raise MastodonIllegalArgumentError('Invalid request')
709 730
710 # Step 3: Check scopes, persist, et cetera 731 # Step 3: Check scopes, persist, et cetera
711 received_scopes = response["scope"].split(" ") 732 received_scopes = response["scope"].split(" ")
@@ -714,8 +735,7 @@ class Mastodon:
714 received_scopes += self.__SCOPE_SETS[scope_set] 735 received_scopes += self.__SCOPE_SETS[scope_set]
715 736
716 if not set(scopes) <= set(received_scopes): 737 if not set(scopes) <= set(received_scopes):
717 raise MastodonAPIError( 738 raise MastodonAPIError('Granted scopes "' + " ".join(received_scopes) + '" do not contain all of the requested scopes "' + " ".join(scopes) + '".')
718 'Granted scopes "' + " ".join(received_scopes) + '" do not contain all of the requested scopes "' + " ".join(scopes) + '".')
719 739
720 if to_file is not None: 740 if to_file is not None:
721 with open(to_file, 'w') as token_file: 741 with open(to_file, 'w') as token_file:
@@ -724,7 +744,10 @@ class Mastodon:
724 744
725 self.__logged_in_id = None 745 self.__logged_in_id = None
726 746
727 return response['access_token'] 747 if return_detailed_error:
748 return response['access_token'], {}
749 else:
750 return response['access_token']
728 751
729 @api_version("3.4.0", "3.4.0", "3.4.0") 752 @api_version("3.4.0", "3.4.0", "3.4.0")
730 def email_resend_confirmation(self): 753 def email_resend_confirmation(self):
@@ -2775,7 +2798,7 @@ class Mastodon:
2775 """ 2798 """
2776 if not policy in ['all', 'none', 'follower', 'followed']: 2799 if not policy in ['all', 'none', 'follower', 'followed']:
2777 raise MastodonIllegalArgumentError("Valid values for policy are 'all', 'none', 'follower' or 'followed'.") 2800 raise MastodonIllegalArgumentError("Valid values for policy are 'all', 'none', 'follower' or 'followed'.")
2778 2801
2779 endpoint = Mastodon.__protocolize(endpoint) 2802 endpoint = Mastodon.__protocolize(endpoint)
2780 2803
2781 push_pubkey_b64 = base64.b64encode(encrypt_params['pubkey']) 2804 push_pubkey_b64 = base64.b64encode(encrypt_params['pubkey'])
@@ -3506,7 +3529,7 @@ class Mastodon:
3506 isotime = isotime[:-2] + ":" + isotime[-2:] 3529 isotime = isotime[:-2] + ":" + isotime[-2:]
3507 return isotime 3530 return isotime
3508 3531
3509 def __api_request(self, method, endpoint, params={}, files={}, headers={}, access_token_override=None, base_url_override=None, do_ratelimiting=True, use_json=False, parse=True, return_response_object=False): 3532 def __api_request(self, method, endpoint, params={}, files={}, headers={}, access_token_override=None, base_url_override=None, do_ratelimiting=True, use_json=False, parse=True, return_response_object=False, skip_error_check=False):
3510 """ 3533 """
3511 Internal API request helper. 3534 Internal API request helper.
3512 """ 3535 """
@@ -3657,35 +3680,32 @@ class Mastodon:
3657 time.sleep(to_next) 3680 time.sleep(to_next)
3658 request_complete = False 3681 request_complete = False
3659 continue 3682 continue
3683
3684 if skip_error_check == False:
3685 if response_object.status_code == 404:
3686 ex_type = MastodonNotFoundError
3687 if not error_msg:
3688 error_msg = 'Endpoint not found.'
3689 # this is for compatibility with older versions
3690 # which raised MastodonAPIError('Endpoint not found.')
3691 # on any 404
3692 elif response_object.status_code == 401:
3693 ex_type = MastodonUnauthorizedError
3694 elif response_object.status_code == 500:
3695 ex_type = MastodonInternalServerError
3696 elif response_object.status_code == 502:
3697 ex_type = MastodonBadGatewayError
3698 elif response_object.status_code == 503:
3699 ex_type = MastodonServiceUnavailableError
3700 elif response_object.status_code == 504:
3701 ex_type = MastodonGatewayTimeoutError
3702 elif response_object.status_code >= 500 and \
3703 response_object.status_code <= 511:
3704 ex_type = MastodonServerError
3705 else:
3706 ex_type = MastodonAPIError
3660 3707
3661 if response_object.status_code == 404: 3708 raise ex_type('Mastodon API returned error', response_object.status_code, response_object.reason, error_msg)
3662 ex_type = MastodonNotFoundError
3663 if not error_msg:
3664 error_msg = 'Endpoint not found.'
3665 # this is for compatibility with older versions
3666 # which raised MastodonAPIError('Endpoint not found.')
3667 # on any 404
3668 elif response_object.status_code == 401:
3669 ex_type = MastodonUnauthorizedError
3670 elif response_object.status_code == 500:
3671 ex_type = MastodonInternalServerError
3672 elif response_object.status_code == 502:
3673 ex_type = MastodonBadGatewayError
3674 elif response_object.status_code == 503:
3675 ex_type = MastodonServiceUnavailableError
3676 elif response_object.status_code == 504:
3677 ex_type = MastodonGatewayTimeoutError
3678 elif response_object.status_code >= 500 and \
3679 response_object.status_code <= 511:
3680 ex_type = MastodonServerError
3681 else:
3682 ex_type = MastodonAPIError
3683
3684 raise ex_type(
3685 'Mastodon API returned error',
3686 response_object.status_code,
3687 response_object.reason,
3688 error_msg)
3689 3709
3690 if return_response_object: 3710 if return_response_object:
3691 return response_object 3711 return response_object
diff --git a/tests/cassettes/test_app_account_create_invalid.yaml b/tests/cassettes/test_app_account_create_invalid.yaml
new file mode 100644
index 0000000..bbf4843
--- /dev/null
+++ b/tests/cassettes/test_app_account_create_invalid.yaml
@@ -0,0 +1,245 @@
1interactions:
2- request:
3 body: client_name=mastodon.py+generated+test+app&scopes=read+write+follow+push&redirect_uris=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob
4 headers:
5 Accept:
6 - '*/*'
7 Accept-Encoding:
8 - gzip, deflate
9 Connection:
10 - keep-alive
11 Content-Length:
12 - '122'
13 Content-Type:
14 - application/x-www-form-urlencoded
15 User-Agent:
16 - python-requests/2.28.1
17 method: POST
18 uri: http://localhost:3000/api/v1/apps
19 response:
20 body:
21 string: '{"id":"4","name":"mastodon.py generated test app","website":null,"redirect_uri":"urn:ietf:wg:oauth:2.0:oob","client_id":"OueO_7-PGuI_wJwqr3gJCO3Mfp-CnB7ntLm2BDNgwoE","client_secret":"i74hCQQyscpk-AoXt8gL1lBYLlgsQw7r-vP_cuKWquA","vapid_key":"BFu6DBpfcm8_h8gm3rHUkfaOLg7azvYN_auFI4KcNuh5SLBVMhTkKKvUaLENtA_c6v5Hmrucvh0WwsN1o9NFQRU="}'
22 headers:
23 Cache-Control:
24 - no-store
25 Content-Security-Policy:
26 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
27 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
28 style-src ''self'' http://localhost:3000 ''nonce-eWGkzakxkoJqETI+J7AOfA=='';
29 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
30 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
31 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
32 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
33 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
34 worker-src ''self'' blob: http://localhost:3000'
35 Content-Type:
36 - application/json; charset=utf-8
37 ETag:
38 - W/"e57c57d0ecbadb4122581beb6057bf7b"
39 Referrer-Policy:
40 - strict-origin-when-cross-origin
41 Transfer-Encoding:
42 - chunked
43 Vary:
44 - Accept, Origin
45 X-Content-Type-Options:
46 - nosniff
47 X-Download-Options:
48 - noopen
49 X-Frame-Options:
50 - SAMEORIGIN
51 X-Permitted-Cross-Domain-Policies:
52 - none
53 X-Request-Id:
54 - c5d33842-2156-4850-ac91-154f71f72d2e
55 X-Runtime:
56 - '0.017495'
57 X-XSS-Protection:
58 - 1; mode=block
59 status:
60 code: 200
61 message: OK
62- request:
63 body: null
64 headers:
65 Accept:
66 - '*/*'
67 Accept-Encoding:
68 - gzip, deflate
69 Connection:
70 - keep-alive
71 User-Agent:
72 - mastodonpy
73 method: GET
74 uri: http://localhost:3000/api/v1/instance/
75 response:
76 body:
77 string: '{"uri":"localhost:3000","title":"Mastodon","short_description":"","description":"","email":"","version":"4.0.0rc2","urls":{"streaming_api":"ws://localhost:4000"},"stats":{"user_count":4,"status_count":5,"domain_count":0},"thumbnail":"http://localhost:3000/packs/media/images/preview-6399aebd96ccf025654e2977454f168f.png","languages":["en"],"registrations":true,"approval_required":false,"invites_enabled":true,"configuration":{"accounts":{"max_featured_tags":10},"statuses":{"max_characters":500,"max_media_attachments":4,"characters_reserved_per_url":23},"media_attachments":{"supported_mime_types":["image/jpeg","image/png","image/gif","image/heic","image/heif","image/webp","image/avif","video/webm","video/mp4","video/quicktime","video/ogg","audio/wave","audio/wav","audio/x-wav","audio/x-pn-wave","audio/vnd.wave","audio/ogg","audio/vorbis","audio/mpeg","audio/mp3","audio/webm","audio/flac","audio/aac","audio/m4a","audio/x-m4a","audio/mp4","audio/3gpp","video/x-ms-asf"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":2304000},"polls":{"max_options":4,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"contact_account":null,"rules":[]}'
78 headers:
79 Cache-Control:
80 - max-age=180, public
81 Content-Security-Policy:
82 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
83 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
84 style-src ''self'' http://localhost:3000 ''nonce-pTVYgmBqNUhkaog/3BIWrg=='';
85 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
86 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
87 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
88 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
89 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
90 worker-src ''self'' blob: http://localhost:3000'
91 Content-Type:
92 - application/json; charset=utf-8
93 Date:
94 - Sat, 19 Nov 2022 00:05:11 GMT
95 ETag:
96 - W/"58e74f5c697f043d86089eae87509b84"
97 Referrer-Policy:
98 - strict-origin-when-cross-origin
99 Transfer-Encoding:
100 - chunked
101 Vary:
102 - Accept, Origin
103 X-Content-Type-Options:
104 - nosniff
105 X-Download-Options:
106 - noopen
107 X-Frame-Options:
108 - SAMEORIGIN
109 X-Permitted-Cross-Domain-Policies:
110 - none
111 X-Request-Id:
112 - 3f3580e9-a01c-4cb3-a8ff-e933a5b0a878
113 X-Runtime:
114 - '0.038202'
115 X-XSS-Protection:
116 - 1; mode=block
117 status:
118 code: 200
119 message: OK
120- request:
121 body: scope=read+write+follow+push&client_id=OueO_7-PGuI_wJwqr3gJCO3Mfp-CnB7ntLm2BDNgwoE&client_secret=i74hCQQyscpk-AoXt8gL1lBYLlgsQw7r-vP_cuKWquA&grant_type=client_credentials
122 headers:
123 Accept:
124 - '*/*'
125 Accept-Encoding:
126 - gzip, deflate
127 Connection:
128 - keep-alive
129 Content-Length:
130 - '170'
131 Content-Type:
132 - application/x-www-form-urlencoded
133 User-Agent:
134 - mastodonpy
135 method: POST
136 uri: http://localhost:3000/oauth/token
137 response:
138 body:
139 string: '{"access_token":"dDfMnIWbtYShiuOouwPaH1j8ZzGRdcg39Ns0nV5jXpo","token_type":"Bearer","scope":"read
140 write follow push","created_at":1668816311}'
141 headers:
142 Cache-Control:
143 - no-store
144 Content-Security-Policy:
145 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
146 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
147 style-src ''self'' http://localhost:3000 ''nonce-2oP2TTFLzbSaiZa7hgho0w=='';
148 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
149 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
150 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
151 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
152 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
153 worker-src ''self'' blob: http://localhost:3000'
154 Content-Type:
155 - application/json; charset=utf-8
156 ETag:
157 - W/"d29d21f6cdf89562d22826c8794a7259"
158 Pragma:
159 - no-cache
160 Referrer-Policy:
161 - strict-origin-when-cross-origin
162 Transfer-Encoding:
163 - chunked
164 Vary:
165 - Accept, Origin
166 X-Content-Type-Options:
167 - nosniff
168 X-Download-Options:
169 - noopen
170 X-Frame-Options:
171 - SAMEORIGIN
172 X-Permitted-Cross-Domain-Policies:
173 - none
174 X-Request-Id:
175 - 10f9efb8-85eb-4b30-ad16-9656fe53fd44
176 X-Runtime:
177 - '0.022478'
178 X-XSS-Protection:
179 - 1; mode=block
180 status:
181 code: 200
182 message: OK
183- request:
184 body: username=coolguy73878&password=&email=email%40localhost73878&locale=en&client_id=OueO_7-PGuI_wJwqr3gJCO3Mfp-CnB7ntLm2BDNgwoE&client_secret=i74hCQQyscpk-AoXt8gL1lBYLlgsQw7r-vP_cuKWquA
185 headers:
186 Accept:
187 - '*/*'
188 Accept-Encoding:
189 - gzip, deflate
190 Authorization:
191 - Bearer dDfMnIWbtYShiuOouwPaH1j8ZzGRdcg39Ns0nV5jXpo
192 Connection:
193 - keep-alive
194 Content-Length:
195 - '182'
196 Content-Type:
197 - application/x-www-form-urlencoded
198 User-Agent:
199 - mastodonpy
200 method: POST
201 uri: http://localhost:3000/api/v1/accounts
202 response:
203 body:
204 string: '{"error":"Validation failed: Password can''t be blank, Service agreement
205 must be accepted","details":{"password":[{"error":"ERR_BLANK","description":"can''t
206 be blank"}],"agreement":[{"error":"ERR_ACCEPTED","description":"must be accepted"}]}}'
207 headers:
208 Cache-Control:
209 - no-store
210 Content-Security-Policy:
211 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
212 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
213 style-src ''self'' http://localhost:3000 ''nonce-OtVYUk9hlx5v/TcbXUduUA=='';
214 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
215 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
216 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
217 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
218 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
219 worker-src ''self'' blob: http://localhost:3000'
220 Content-Type:
221 - application/json; charset=utf-8
222 Referrer-Policy:
223 - strict-origin-when-cross-origin
224 Transfer-Encoding:
225 - chunked
226 Vary:
227 - Accept, Origin
228 X-Content-Type-Options:
229 - nosniff
230 X-Download-Options:
231 - noopen
232 X-Frame-Options:
233 - SAMEORIGIN
234 X-Permitted-Cross-Domain-Policies:
235 - none
236 X-Request-Id:
237 - 48f3d7ec-0b4f-48ce-bf0c-acbec7479c71
238 X-Runtime:
239 - '0.561200'
240 X-XSS-Protection:
241 - 1; mode=block
242 status:
243 code: 422
244 message: Unprocessable Entity
245version: 1
diff --git a/tests/cassettes/test_push_set.yaml b/tests/cassettes/test_push_set.yaml
deleted file mode 100644
index 4995277..0000000
--- a/tests/cassettes/test_push_set.yaml
+++ /dev/null
@@ -1,122 +0,0 @@
1interactions:
2- request:
3 body: subscription%5Bendpoint%5D=https%3A%2F%2Fexample.com&subscription%5Bkeys%5D%5Bp256dh%5D=BKFO5w6Uf%2B%2F2wo89ovbphk5Zrb0mcAKjZrIyrX66f2IAijRtuXx4yK6J9hR%2FemKnF2DyQcyx7%2F4IGhKHBk0OTEk%3D&subscription%5Bkeys%5D%5Bauth%5D=6T8gVmd01DhQUbejRj%2Bxmg%3D%3D&policy=none&data%5Balerts%5D%5Bfollow%5D=1&data%5Balerts%5D%5Bfavourite%5D=1&data%5Balerts%5D%5Breblog%5D=1&data%5Balerts%5D%5Bmention%5D=1&data%5Balerts%5D%5Bpoll%5D=1&data%5Balerts%5D%5Bfollow_request%5D=1&data%5Balerts%5D%5Bstatus%5D=1
4 headers:
5 Accept:
6 - '*/*'
7 Accept-Encoding:
8 - gzip, deflate
9 Authorization:
10 - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
11 Connection:
12 - keep-alive
13 Content-Length:
14 - '489'
15 Content-Type:
16 - application/x-www-form-urlencoded
17 User-Agent:
18 - tests/v311
19 method: POST
20 uri: http://localhost:3000/api/v1/push/subscription
21 response:
22 body:
23 string: '{"id":5,"endpoint":"https://example.com","alerts":{"mention":true,"status":true,"reblog":true,"follow":true,"follow_request":true,"favourite":true,"poll":true},"server_key":"BFu6DBpfcm8_h8gm3rHUkfaOLg7azvYN_auFI4KcNuh5SLBVMhTkKKvUaLENtA_c6v5Hmrucvh0WwsN1o9NFQRU="}'
24 headers:
25 Cache-Control:
26 - no-store
27 Content-Security-Policy:
28 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
29 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
30 style-src ''self'' http://localhost:3000 ''nonce-bz+9uelNbajqElylgkM2Gg=='';
31 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
32 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
33 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
34 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
35 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
36 worker-src ''self'' blob: http://localhost:3000'
37 Content-Type:
38 - application/json; charset=utf-8
39 ETag:
40 - W/"083c3b807a4d145ec452ffd03c768d76"
41 Referrer-Policy:
42 - strict-origin-when-cross-origin
43 Transfer-Encoding:
44 - chunked
45 Vary:
46 - Accept, Origin
47 X-Content-Type-Options:
48 - nosniff
49 X-Download-Options:
50 - noopen
51 X-Frame-Options:
52 - SAMEORIGIN
53 X-Permitted-Cross-Domain-Policies:
54 - none
55 X-Request-Id:
56 - abb4aec7-a93a-4a99-ba4c-5a290bbbf782
57 X-Runtime:
58 - '0.027761'
59 X-XSS-Protection:
60 - 1; mode=block
61 status:
62 code: 200
63 message: OK
64- request:
65 body: null
66 headers:
67 Accept:
68 - '*/*'
69 Accept-Encoding:
70 - gzip, deflate
71 Authorization:
72 - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
73 Connection:
74 - keep-alive
75 User-Agent:
76 - tests/v311
77 method: GET
78 uri: http://localhost:3000/api/v1/push/subscription
79 response:
80 body:
81 string: '{"id":5,"endpoint":"https://example.com","alerts":{"mention":true,"status":true,"reblog":true,"follow":true,"follow_request":true,"favourite":true,"poll":true},"server_key":"BFu6DBpfcm8_h8gm3rHUkfaOLg7azvYN_auFI4KcNuh5SLBVMhTkKKvUaLENtA_c6v5Hmrucvh0WwsN1o9NFQRU="}'
82 headers:
83 Cache-Control:
84 - no-store
85 Content-Security-Policy:
86 - 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
87 ''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
88 style-src ''self'' http://localhost:3000 ''nonce-4kBQ0XWCASsxXi+/Z0W5jA=='';
89 media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
90 https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
91 data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
92 ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
93 ''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
94 worker-src ''self'' blob: http://localhost:3000'
95 Content-Type:
96 - application/json; charset=utf-8
97 ETag:
98 - W/"083c3b807a4d145ec452ffd03c768d76"
99 Referrer-Policy:
100 - strict-origin-when-cross-origin
101 Transfer-Encoding:
102 - chunked
103 Vary:
104 - Accept, Origin
105 X-Content-Type-Options:
106 - nosniff
107 X-Download-Options:
108 - noopen
109 X-Frame-Options:
110 - SAMEORIGIN
111 X-Permitted-Cross-Domain-Policies:
112 - none
113 X-Request-Id:
114 - eeb007da-a24b-4e31-b962-30ef0ba3bc16
115 X-Runtime:
116 - '0.008203'
117 X-XSS-Protection:
118 - 1; mode=block
119 status:
120 code: 200
121 message: OK
122version: 1
diff --git a/tests/test_create_app.py b/tests/test_create_app.py
index 8a7ea62..c7282df 100644
--- a/tests/test_create_app.py
+++ b/tests/test_create_app.py
@@ -70,5 +70,24 @@ def test_app_account_create():
70 # We can also test resending (marginally) 70 # We can also test resending (marginally)
71 test_app_api.email_resend_confirmation() 71 test_app_api.email_resend_confirmation()
72 72
73 73@pytest.mark.vcr(match_on=['path'])
74 74def test_app_account_create_invalid():
75 suffix = str(time.time()).replace(".", "")[-5:]
76
77 test_app = test_app = Mastodon.create_app(
78 "mastodon.py generated test app",
79 api_base_url="http://localhost:3000/"
80 )
81
82 test_app_api = Mastodon(
83 test_app[0],
84 test_app[1],
85 api_base_url="http://localhost:3000/"
86 )
87 test_token, error = test_app_api.create_account("coolguy" + suffix, "", "email@localhost" + suffix, agreement=False, return_detailed_error=True)
88 assert test_token is None
89 assert "details" in error
90 assert "password" in error.details
91 assert "password" in error.details
92 assert not "username" in error.details
93 \ No newline at end of file
Powered by cgit v1.2.3 (git 2.41.0)