From dbceccb210d401887002abf0ea3c746260423f1f Mon Sep 17 00:00:00 2001 From: halcy Date: Mon, 28 Nov 2022 00:55:41 +0200 Subject: Add v2 admin accounts API --- CHANGELOG.rst | 2 + TODO.md | 2 +- docs/index.rst | 2 + mastodon/Mastodon.py | 88 ++++++++++- tests/cassettes/test_admin_accounts_v1.yaml | 179 +++++++++++++++++++++ tests/cassettes/test_admin_accounts_v2.yaml | 237 ++++++++++++++++++++++++++++ tests/test_admin.py | 38 +++++ tests/test_constructor.py | 11 +- 8 files changed, 548 insertions(+), 11 deletions(-) create mode 100644 tests/cassettes/test_admin_accounts_v1.yaml create mode 100644 tests/cassettes/test_admin_accounts_v2.yaml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c6d7c91..d83513c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,8 @@ v1.8.0 (in progress) * Added client auth data to access token file. * Added `account_familiar_followers` API * Added `account_remove_from_followers` API +* Added `admin_accounts_v2` API +* FUTURE BREAKING CHANGE WARNING: For now, `admin_accounts` still calls v1, but this may change in the future. You are encouraged to use v2 instead. v1.7.0 ------ diff --git a/TODO.md b/TODO.md index b991906..173662c 100644 --- a/TODO.md +++ b/TODO.md @@ -51,7 +51,7 @@ Refer to mastodon changelog and API docs for details when implementing, add or m * [x] Add global lang param to REST API * [x] Add types param to GET /api/v1/notifications in REST API * [x] Add notifications for moderators about new sign-ups -* [ ] v2 admin account api +* [x] v2 admin account api 3.5.3 ----- diff --git a/docs/index.rst b/docs/index.rst index f44ee55..5103b0b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1504,7 +1504,9 @@ EXTREME CARE. This is not to say that you should not treat access tokens from admin accounts that do not have admin: scopes attached with a lot of care, but be extra careful with those that do. +.. automethod:: Mastodon.admin_accounts_v2 .. automethod:: Mastodon.admin_accounts +.. automethod:: Mastodon.admin_accounts_v1 .. automethod:: Mastodon.admin_account .. automethod:: Mastodon.admin_account_enable .. automethod:: Mastodon.admin_account_approve diff --git a/mastodon/Mastodon.py b/mastodon/Mastodon.py index 2adcd74..895fa36 100644 --- a/mastodon/Mastodon.py +++ b/mastodon/Mastodon.py @@ -255,7 +255,7 @@ class Mastodon: __DICT_VERSION_CONVERSATION = bigger_version(bigger_version("2.6.0", __DICT_VERSION_ACCOUNT), __DICT_VERSION_STATUS) __DICT_VERSION_SCHEDULED_STATUS = bigger_version("2.7.0", __DICT_VERSION_STATUS) __DICT_VERSION_PREFERENCES = "2.8.0" - __DICT_VERSION_ADMIN_ACCOUNT = bigger_version("2.9.1", __DICT_VERSION_ACCOUNT) + __DICT_VERSION_ADMIN_ACCOUNT = bigger_version("4.0.0", __DICT_VERSION_ACCOUNT) __DICT_VERSION_FEATURED_TAG = "3.0.0" __DICT_VERSION_MARKER = "3.0.0" __DICT_VERSION_REACTION = "3.1.0" @@ -666,8 +666,7 @@ class Mastodon: received_scopes += self.__SCOPE_SETS[scope_set] if not set(scopes) <= set(received_scopes): - raise MastodonAPIError( - 'Granted scopes "' + " ".join(received_scopes) + '" do not contain all of the requested scopes "' + " ".join(scopes) + '".') + raise MastodonAPIError('Granted scopes "' + " ".join(received_scopes) + '" do not contain all of the requested scopes "' + " ".join(scopes) + '".') if to_file is not None: with open(to_file, 'w') as token_file: @@ -3130,8 +3129,80 @@ class Mastodon: ### # Moderation API ### + @api_version("2.9.1", "4.0.0", __DICT_VERSION_ADMIN_ACCOUNT) + def admin_accounts_v2(self, origin=None, by_domain=None, status=None, username=None, display_name=None, email=None, ip=None, + permissions=None, invited_by=None, role_ids=None, max_id=None, min_id=None, since_id=None, limit=None): + """ + Fetches a list of accounts that match given criteria. By default, local accounts are returned. + + * Set `origin` to "local" or "remote" to get only local or remote accounts. + * Set `by_domain` to a domain to get only accounts from that domain. + * Set `status` to one of "active", "pending", "disabled", "silenced" or "suspended" to get only accounts with that moderation status (default: active) + * Set `username` to a string to get only accounts whose username contains this string. + * Set `display_name` to a string to get only accounts whose display name contains this string. + * Set `email` to an email to get only accounts with that email (this only works on local accounts). + * Set `ip` to an ip (as a string, standard v4/v6 notation) to get only accounts whose last active ip is that ip (this only works on local accounts). + * Set `permissions` to "staff" to only get accounts with staff permissions. + * Set `invited_by` to an account id to get only accounts invited by this user. + * Set `role_ids` to a list of role IDs to get only accounts with those roles. + + Returns a list of `admin account dicts`_. + """ + if max_id is not None: + max_id = self.__unpack_id(max_id, dateconv=True) + + if min_id is not None: + min_id = self.__unpack_id(min_id, dateconv=True) + + if since_id is not None: + since_id = self.__unpack_id(since_id, dateconv=True) + + if role_ids is not None: + if not isinstance(role_ids, list): + role_ids = [role_ids] + role_ids = list(map(self.__unpack_id, role_ids)) + + if invited_by is not None: + invited_by = self.__unpack_id(invited_by) + + if permissions is not None and not permissions in ["staff"]: + raise MastodonIllegalArgumentError("Permissions must be staff if passed") + + if origin is not None and not origin in ["local", "remote"]: + raise MastodonIllegalArgumentError("Origin must be local or remote") + + if status is not None and not status in ["active", "pending", "disabled", "silenced", "suspended"]: + raise MastodonIllegalArgumentError("Status must be local or active, pending, disabled, silenced or suspended") + + if not by_domain is None: + by_domain = self.__deprotocolize(by_domain) + + params = self.__generate_params(locals()) + return self.__api_request('GET', '/api/v2/admin/accounts', params) + @api_version("2.9.1", "2.9.1", __DICT_VERSION_ADMIN_ACCOUNT) def admin_accounts(self, remote=False, by_domain=None, status='active', username=None, display_name=None, email=None, ip=None, staff_only=False, max_id=None, min_id=None, since_id=None, limit=None): + """ + Currently a synonym for admin_accounts_v1, now deprecated. You are strongly encouraged to use admin_accounts_v2 instead, since this one is kind of bad. + + !!!!! This function may be switched to calling the v2 API in the future. This is your warning. If you want to keep using v1, use it explicitly. !!!!! + """ + return self.admin_accounts_v1( + remote=remote, + by_domain=by_domain, + status=status, + username=username, + display_name=display_name, + email=email, + ip=ip, + staff_only=staff_only, + max_id=max_id, + min_id=min_id, + since_id=since_id + ) + + @api_version("2.9.1", "2.9.1", __DICT_VERSION_ADMIN_ACCOUNT) + def admin_accounts_v1(self, remote=False, by_domain=None, status='active', username=None, display_name=None, email=None, ip=None, staff_only=False, max_id=None, min_id=None, since_id=None, limit=None): """ Fetches a list of accounts that match given criteria. By default, local accounts are returned. @@ -3147,6 +3218,8 @@ class Mastodon: Note that setting the boolean parameters to False does not mean "give me users to which this does not apply" but instead means "I do not care if users have this attribute". + Deprecated in Mastodon version 3.5.0. + Returns a list of `admin account dicts`_. """ if max_id is not None: @@ -3158,14 +3231,12 @@ class Mastodon: if since_id is not None: since_id = self.__unpack_id(since_id, dateconv=True) - params = self.__generate_params( - locals(), ['remote', 'status', 'staff_only']) + params = self.__generate_params(locals(), ['remote', 'status', 'staff_only']) if remote: params["remote"] = True - mod_statuses = ["active", "pending", - "disabled", "silenced", "suspended"] + mod_statuses = ["active", "pending", "disabled", "silenced", "suspended"] if not status in mod_statuses: raise ValueError("Invalid moderation status requested.") @@ -3176,6 +3247,9 @@ class Mastodon: if status == mod_status: params[status] = True + if not by_domain is None: + by_domain = self.__deprotocolize(by_domain) + return self.__api_request('GET', '/api/v1/admin/accounts', params) @api_version("2.9.1", "2.9.1", __DICT_VERSION_ADMIN_ACCOUNT) diff --git a/tests/cassettes/test_admin_accounts_v1.yaml b/tests/cassettes/test_admin_accounts_v1.yaml new file mode 100644 index 0000000..0c9b187 --- /dev/null +++ b/tests/cassettes/test_admin_accounts_v1.yaml @@ -0,0 +1,179 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2 + Connection: + - keep-alive + User-Agent: + - tests/v311 + method: GET + uri: http://localhost:3000/api/v1/admin/accounts?active=True + response: + body: + string: '[{"id":"109411886050231694","username":"mastodonpy_test_2","domain":null,"created_at":"2022-11-26T20:01:30.195Z","email":"mastodonpy_test_2@localhost:3000","ip":null,"role":{"id":-99,"name":"","color":"","position":-1,"permissions":65536,"highlighted":false,"created_at":"2022-11-26T20:01:24.328Z","updated_at":"2022-11-26T20:01:24.328Z"},"confirmed":true,"suspended":false,"silenced":false,"sensitized":false,"disabled":false,"approved":true,"locale":"ja","invite_request":null,"ips":[],"account":{"id":"109411886050231694","username":"mastodonpy_test_2","acct":"mastodonpy_test_2","display_name":"","locked":false,"bot":false,"discoverable":true,"group":false,"created_at":"2022-11-26T00:00:00.000Z","note":"","url":"http://localhost:3000/@mastodonpy_test_2","avatar":"http://localhost:3000/avatars/original/missing.png","avatar_static":"http://localhost:3000/avatars/original/missing.png","header":"http://localhost:3000/headers/original/missing.png","header_static":"http://localhost:3000/headers/original/missing.png","followers_count":0,"following_count":0,"statuses_count":0,"last_status_at":null,"noindex":false,"emojis":[],"fields":[]}},{"id":"109411885927532888","username":"mastodonpy_test","domain":null,"created_at":"2022-11-26T20:01:28.322Z","email":"mastodonpy_test@localhost:3000","ip":null,"role":{"id":-99,"name":"","color":"","position":-1,"permissions":65536,"highlighted":false,"created_at":"2022-11-26T20:01:24.328Z","updated_at":"2022-11-26T20:01:24.328Z"},"confirmed":true,"suspended":false,"silenced":false,"sensitized":false,"disabled":false,"approved":true,"locale":"ja","invite_request":null,"ips":[],"account":{"id":"109411885927532888","username":"mastodonpy_test","acct":"mastodonpy_test","display_name":"","locked":true,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-26T00:00:00.000Z","note":"","url":"http://localhost:3000/@mastodonpy_test","avatar":"http://localhost:3000/avatars/original/missing.png","avatar_static":"http://localhost:3000/avatars/original/missing.png","header":"http://localhost:3000/headers/original/missing.png","header_static":"http://localhost:3000/headers/original/missing.png","followers_count":0,"following_count":0,"statuses_count":0,"last_status_at":null,"noindex":false,"emojis":[],"fields":[]}},{"id":"109411885799291132","username":"admin2","domain":null,"created_at":"2022-11-26T20:01:26.347Z","email":"zerocool@example.com","ip":"127.0.0.1","role":{"id":3,"name":"Owner","color":"","position":1000,"permissions":1,"highlighted":true,"created_at":"2022-11-26T20:01:24.338Z","updated_at":"2022-11-26T20:01:24.338Z"},"confirmed":true,"suspended":false,"silenced":false,"sensitized":false,"disabled":false,"approved":true,"locale":"de","invite_request":null,"ips":[{"ip":"127.0.0.1","used_at":"2022-11-26T20:02:19.675Z"}],"account":{"id":"109411885799291132","username":"admin2","acct":"admin2","display_name":"","locked":false,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-26T00:00:00.000Z","note":"","url":"http://localhost:3000/@admin2","avatar":"http://localhost:3000/avatars/original/missing.png","avatar_static":"http://localhost:3000/avatars/original/missing.png","header":"http://localhost:3000/headers/original/missing.png","header_static":"http://localhost:3000/headers/original/missing.png","followers_count":0,"following_count":0,"statuses_count":0,"last_status_at":null,"noindex":false,"emojis":[],"fields":[]}},{"id":"109411885671340064","username":"admin","domain":null,"created_at":"2022-11-26T20:01:24.342Z","email":"admin@localhost:3000","ip":null,"role":{"id":3,"name":"Owner","color":"","position":1000,"permissions":1,"highlighted":true,"created_at":"2022-11-26T20:01:24.338Z","updated_at":"2022-11-26T20:01:24.338Z"},"confirmed":true,"suspended":false,"silenced":false,"sensitized":false,"disabled":false,"approved":true,"locale":null,"invite_request":null,"ips":[],"account":{"id":"109411885671340064","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-26T00:00:00.000Z","note":"","url":"http://localhost:3000/@admin","avatar":"http://localhost:3000/avatars/original/missing.png","avatar_static":"http://localhost:3000/avatars/original/missing.png","header":"http://localhost:3000/headers/original/missing.png","header_static":"http://localhost:3000/headers/original/missing.png","followers_count":0,"following_count":0,"statuses_count":0,"last_status_at":null,"noindex":false,"emojis":[],"fields":[]}}]' + 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-rha1g8vCqT8/tDp8mtlrdg==''; + 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/"70761e00feb13529509779ca3060705b" + Link: + - ; + rel="prev" + 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: + - 2e6b413e-114f-495b-8e0e-870b11ea4195 + X-Runtime: + - '0.174018' + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2 + Connection: + - keep-alive + User-Agent: + - tests/v311 + method: GET + uri: http://localhost:3000/api/v1/accounts/verify_credentials + response: + body: + string: '{"id":"109411885671340064","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-26T00:00:00.000Z","note":"","url":"http://localhost:3000/@admin","avatar":"http://localhost:3000/avatars/original/missing.png","avatar_static":"http://localhost:3000/avatars/original/missing.png","header":"http://localhost:3000/headers/original/missing.png","header_static":"http://localhost:3000/headers/original/missing.png","followers_count":0,"following_count":0,"statuses_count":0,"last_status_at":null,"noindex":false,"source":{"privacy":"public","sensitive":false,"language":null,"note":"","fields":[],"follow_requests_count":0},"emojis":[],"fields":[],"role":{"id":"3","name":"Owner","permissions":"1048575","color":"","highlighted":true}}' + 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-SRfegda7FJ4bXLLndhYA9g==''; + 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/"a92dcb08b6f874d680c45eede3cca2ec" + 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: + - 5b1a9983-a201-4b01-8279-4f24d394cde0 + X-Runtime: + - '0.019987' + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2 + Connection: + - keep-alive + User-Agent: + - tests/v311 + method: GET + uri: http://localhost:3000/api/v1/admin/accounts/109411885671340064 + response: + body: + string: '{"id":"109411885671340064","username":"admin","domain":null,"created_at":"2022-11-26T20:01:24.342Z","email":"admin@localhost:3000","ip":null,"role":{"id":3,"name":"Owner","color":"","position":1000,"permissions":1,"highlighted":true,"created_at":"2022-11-26T20:01:24.338Z","updated_at":"2022-11-26T20:01:24.338Z"},"confirmed":true,"suspended":false,"silenced":false,"sensitized":false,"disabled":false,"approved":true,"locale":null,"invite_request":null,"ips":[],"account":{"id":"109411885671340064","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-26T00:00:00.000Z","note":"","url":"http://localhost:3000/@admin","avatar":"http://localhost:3000/avatars/original/missing.png","avatar_static":"http://localhost:3000/avatars/original/missing.png","header":"http://localhost:3000/headers/original/missing.png","header_static":"http://localhost:3000/headers/original/missing.png","followers_count":0,"following_count":0,"statuses_count":0,"last_status_at":null,"noindex":false,"emojis":[],"fields":[]}}' + 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-Xr1816+FDipTuvfoqQHZ2A==''; + 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/"7fabd2598ffb35064504f9e5215e21e6" + 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: + - eec919d4-f033-4d8a-a74c-b7c5f9f82df2 + X-Runtime: + - '0.020002' + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/cassettes/test_admin_accounts_v2.yaml b/tests/cassettes/test_admin_accounts_v2.yaml new file mode 100644 index 0000000..5b5e041 --- /dev/null +++ b/tests/cassettes/test_admin_accounts_v2.yaml @@ -0,0 +1,237 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2 + Connection: + - keep-alive + User-Agent: + - tests/v311 + method: GET + uri: http://localhost:3000/api/v2/admin/accounts?origin=local&permissions=staff + response: + body: + string: '[{"id":"109411885799291132","username":"admin2","domain":null,"created_at":"2022-11-26T20:01:26.347Z","email":"zerocool@example.com","ip":"127.0.0.1","role":{"id":3,"name":"Owner","color":"","position":1000,"permissions":1,"highlighted":true,"created_at":"2022-11-26T20:01:24.338Z","updated_at":"2022-11-26T20:01:24.338Z"},"confirmed":true,"suspended":false,"silenced":false,"sensitized":false,"disabled":false,"approved":true,"locale":"de","invite_request":null,"ips":[{"ip":"127.0.0.1","used_at":"2022-11-26T20:02:19.675Z"}],"account":{"id":"109411885799291132","username":"admin2","acct":"admin2","display_name":"","locked":false,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-26T00:00:00.000Z","note":"","url":"http://localhost:3000/@admin2","avatar":"http://localhost:3000/avatars/original/missing.png","avatar_static":"http://localhost:3000/avatars/original/missing.png","header":"http://localhost:3000/headers/original/missing.png","header_static":"http://localhost:3000/headers/original/missing.png","followers_count":0,"following_count":0,"statuses_count":0,"last_status_at":null,"noindex":false,"emojis":[],"fields":[]}},{"id":"109411885671340064","username":"admin","domain":null,"created_at":"2022-11-26T20:01:24.342Z","email":"admin@localhost:3000","ip":null,"role":{"id":3,"name":"Owner","color":"","position":1000,"permissions":1,"highlighted":true,"created_at":"2022-11-26T20:01:24.338Z","updated_at":"2022-11-26T20:01:24.338Z"},"confirmed":true,"suspended":false,"silenced":false,"sensitized":false,"disabled":false,"approved":true,"locale":null,"invite_request":null,"ips":[],"account":{"id":"109411885671340064","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-26T00:00:00.000Z","note":"","url":"http://localhost:3000/@admin","avatar":"http://localhost:3000/avatars/original/missing.png","avatar_static":"http://localhost:3000/avatars/original/missing.png","header":"http://localhost:3000/headers/original/missing.png","header_static":"http://localhost:3000/headers/original/missing.png","followers_count":0,"following_count":0,"statuses_count":0,"last_status_at":null,"noindex":false,"emojis":[],"fields":[]}}]' + 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-i6KQJf/pTUkNc5Iqg28llQ==''; + 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/"4ad52a55c7bd828f38a03190a044caff" + Link: + - ; + rel="prev" + 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: + - 67ac51e6-39dd-4859-896c-db8daa32e970 + X-Runtime: + - '0.031220' + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2 + Connection: + - keep-alive + User-Agent: + - tests/v311 + method: GET + uri: http://localhost:3000/api/v1/accounts/verify_credentials + response: + body: + string: '{"id":"109411885671340064","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-26T00:00:00.000Z","note":"","url":"http://localhost:3000/@admin","avatar":"http://localhost:3000/avatars/original/missing.png","avatar_static":"http://localhost:3000/avatars/original/missing.png","header":"http://localhost:3000/headers/original/missing.png","header_static":"http://localhost:3000/headers/original/missing.png","followers_count":0,"following_count":0,"statuses_count":0,"last_status_at":null,"noindex":false,"source":{"privacy":"public","sensitive":false,"language":null,"note":"","fields":[],"follow_requests_count":0},"emojis":[],"fields":[],"role":{"id":"3","name":"Owner","permissions":"1048575","color":"","highlighted":true}}' + 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-4FwT6Ya41GHCR7ZSi+el3A==''; + 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/"a92dcb08b6f874d680c45eede3cca2ec" + 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: + - f5d704f6-5e3b-4438-b406-5dea67ed9a86 + X-Runtime: + - '0.016054' + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2 + Connection: + - keep-alive + User-Agent: + - tests/v311 + method: GET + uri: http://localhost:3000/api/v1/admin/accounts/109411885671340064 + response: + body: + string: '{"id":"109411885671340064","username":"admin","domain":null,"created_at":"2022-11-26T20:01:24.342Z","email":"admin@localhost:3000","ip":null,"role":{"id":3,"name":"Owner","color":"","position":1000,"permissions":1,"highlighted":true,"created_at":"2022-11-26T20:01:24.338Z","updated_at":"2022-11-26T20:01:24.338Z"},"confirmed":true,"suspended":false,"silenced":false,"sensitized":false,"disabled":false,"approved":true,"locale":null,"invite_request":null,"ips":[],"account":{"id":"109411885671340064","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"discoverable":null,"group":false,"created_at":"2022-11-26T00:00:00.000Z","note":"","url":"http://localhost:3000/@admin","avatar":"http://localhost:3000/avatars/original/missing.png","avatar_static":"http://localhost:3000/avatars/original/missing.png","header":"http://localhost:3000/headers/original/missing.png","header_static":"http://localhost:3000/headers/original/missing.png","followers_count":0,"following_count":0,"statuses_count":0,"last_status_at":null,"noindex":false,"emojis":[],"fields":[]}}' + 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-7x8Gs/Uz7sVtsdZvlOnFsQ==''; + 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/"7fabd2598ffb35064504f9e5215e21e6" + 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: + - 86e6959f-0c1d-4f6c-840d-59619a50a4cd + X-Runtime: + - '0.016896' + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2 + Connection: + - keep-alive + User-Agent: + - tests/v311 + method: GET + uri: http://localhost:3000/api/v2/admin/accounts?origin=remote&permissions=staff + response: + body: + string: '[]' + 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-deIQ40i1Hr9YZswIHlu1Wg==''; + 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/"4f53cda18c2baa0c0354bb5f9a3ecbe5" + 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: + - b0b0702f-c15a-4d39-9996-a2c4c2ad5a6f + X-Runtime: + - '0.016651' + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/test_admin.py b/tests/test_admin.py index d937ed8..b0716e5 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -16,6 +16,44 @@ def test_admin_accounts(api2): assert(account_admin) assert(account_admin.id == account_self.id) +@pytest.mark.vcr() +def test_admin_accounts_v1(api2): + accounts = api2.admin_accounts_v1() + + assert accounts + assert len(accounts) > 0 + + account_self = api2.account_verify_credentials() + account_admin = api2.admin_account(account_self) + + assert(account_admin) + assert(account_admin.id == account_self.id) + +@pytest.mark.vcr() +def test_admin_accounts_v2(api2): + accounts = api2.admin_accounts_v2(permissions="staff", origin="local") + + assert accounts + assert len(accounts) > 0 + + account_self = api2.account_verify_credentials() + account_admin = api2.admin_account(account_self) + + assert(account_admin) + assert(account_admin.id == account_self.id) + + accounts = api2.admin_accounts_v2(permissions="staff", origin="remote") + assert len(accounts) == 0 + + with pytest.raises(MastodonIllegalArgumentError): + accounts = api2.admin_accounts_v2(permissions="stave") + + with pytest.raises(MastodonIllegalArgumentError): + accounts = api2.admin_accounts_v2(origin="global") + + with pytest.raises(MastodonIllegalArgumentError): + accounts = api2.admin_accounts_v2(status="sick") + @pytest.mark.vcr(match_on=['path']) def test_admin_moderation(api, api2): account_initial = api.account_verify_credentials() diff --git a/tests/test_constructor.py b/tests/test_constructor.py index ed38b9c..2531e19 100644 --- a/tests/test_constructor.py +++ b/tests/test_constructor.py @@ -18,9 +18,14 @@ def test_constructor_from_filenames(tmpdir): def test_constructor_illegal_ratelimit(): with pytest.raises(MastodonIllegalArgumentError): - api = Mastodon( - 'foo', client_secret='bar', - ratelimit_method='baz') + api = Mastodon('foo', client_secret='bar', ratelimit_method='baz', api_base_url="whatever") + +def test_constructor_no_url(): + with pytest.raises(MastodonIllegalArgumentError): + api = Mastodon('foo', client_secret='bar') + + with pytest.raises(MastodonIllegalArgumentError): + api = Mastodon(access_token='baz') def test_constructor_illegal_versioncheckmode(): with pytest.raises(MastodonIllegalArgumentError): -- cgit v1.2.3