From fd859bbc5c2316b8b3ed08ddcb84315dcd59cbac Mon Sep 17 00:00:00 2001 From: halcy Date: Sat, 15 Feb 2025 18:20:27 +0200 Subject: [PATCH] IP Blocks, fix some things --- CHANGELOG.rst | 2 + docs/13_admin.rst | 9 + mastodon/admin.py | 58 ++- srcgen/return_types.json | 2 +- tests/cassettes/test_admin_ip_blocks.yaml | 434 ++++++++++++++++++++++ tests/cassettes/test_admin_trends.yaml | 238 ++++++++++++ tests/test_admin.py | 37 +- 7 files changed, 777 insertions(+), 3 deletions(-) create mode 100644 tests/cassettes/test_admin_ip_blocks.yaml create mode 100644 tests/cassettes/test_admin_trends.yaml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7ceadf1..92ab721 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -38,6 +38,8 @@ v2.0.0 (IN PROGRESS) * Add email domain blocking support (`admin_email_domain_blocks`, `admin_email_domain_block`, `admin_email_domain_block_create`, `admin_email_domain_block_delete`) * Add `instance_extended_description` * Add `instance_translation_languages`, translation support (`status_translate`) +* Add trend admin functions (`admin_trending_tags`, `admin_trending_statuses`, `admin_trending_links`, `admin_approve_trending_link`, `admin_reject_trending_link`, `admin_approve_trending_status`, `admin_reject_trending_status`, `admin_approve_trending_tag`, `admin_reject_trending_tag`) +* Add admin IP block functions (`admin_ip_blocks`, `admin_ip_block`, `admin_ip_block_create`, `admin_ip_block_delete`) v1.8.1 ------ diff --git a/docs/13_admin.rst b/docs/13_admin.rst index dc1131a..b1bea1f 100644 --- a/docs/13_admin.rst +++ b/docs/13_admin.rst @@ -63,6 +63,7 @@ Canonical email blocks ---------------------- .. automethod:: Mastodon.admin_canonical_email_blocks .. automethod:: Mastodon.admin_canonical_email_block +.. automethod:: Mastodon.admin_test_canonical_email_block .. automethod:: Mastodon.admin_create_canonical_email_block .. automethod:: Mastodon.admin_delete_canonical_email_block @@ -73,6 +74,14 @@ Email domain blocks .. automethod:: Mastodon.admin_create_email_domain_block .. automethod:: Mastodon.admin_delete_email_domain_block +IP blocks +--------- +.. automethod:: Mastodon.admin_ip_blocks +.. automethod:: Mastodon.admin_ip_block +.. automethod:: Mastodon.admin_create_ip_block +.. automethod:: Mastodon.admin_update_ip_block +.. automethod:: Mastodon.admin_delete_ip_block + Trend management ---------------- .. automethod:: Mastodon.admin_trending_tags diff --git a/mastodon/admin.py b/mastodon/admin.py index 0ba17e6..1c514b3 100644 --- a/mastodon/admin.py +++ b/mastodon/admin.py @@ -6,7 +6,7 @@ from mastodon.utility import api_version from mastodon.internals import Mastodon as Internals from typing import Optional, List, Union from mastodon.return_types import IdType, PrimitiveIdType, Account, AdminAccount, AdminReport, PaginatableList, NonPaginatableList, Status, Tag,\ - PreviewCard, AdminDomainBlock, AdminMeasure, AdminDimension, AdminRetention, AdminCanonicalEmailBlock, AdminDomainAllow, AdminEmailDomainBlock + PreviewCard, AdminDomainBlock, AdminMeasure, AdminDimension, AdminRetention, AdminCanonicalEmailBlock, AdminDomainAllow, AdminEmailDomainBlock, AdminIpBlock from datetime import datetime class Mastodon(Internals): @@ -749,3 +749,59 @@ class Mastodon(Internals): """ id = self.__unpack_id(id) return self.__api_request('POST', f'/api/v1/admin/trends/tags/{id}/reject') + + @api_version("4.0.0", "4.0.0") + def admin_ip_blocks(self, max_id: Optional[IdType] = None, min_id: Optional[IdType] = None, + since_id: Optional[IdType] = None, limit: Optional[int] = None) -> PaginatableList[AdminIpBlock]: + """ + Fetches a list of blocked IP addresses and ranges. Requires scope `admin:read:ip_blocks`. + """ + params = self.__generate_params(locals()) + return self.__api_request('GET', '/api/v1/admin/ip_blocks', params) + + @api_version("4.0.0", "4.0.0") + def admin_ip_block(self, id: Union[AdminIpBlock, IdType]) -> AdminIpBlock: + """ + Fetch a single blocked IP address or range by ID. Requires scope `admin:read:ip_blocks`. + """ + id = self.__unpack_id(id) + return self.__api_request('GET', f'/api/v1/admin/ip_blocks/{id}') + + @api_version("4.0.0", "4.0.0") + def admin_create_ip_block(self, ip: str, severity: str, comment: Optional[str] = None, + expires_in: Optional[int] = None) -> AdminIpBlock: + """ + Block an IP address or range from signups. Requires scope `admin:write:ip_blocks`. + + Provide the IP address as a CIDR range, e.g. "192.168.1.1/32" to block just that IP address, or + "8.8.8.8/24" to block all addresses in the 8.8.8.* subnet. + + severity can be one of three values: + * "sign_up_requires_approval" - signups from this IP will require manual approval + * "sign_up_block" - signups from this IP will be blocked + * "no_access" - all access from this IP will be blocked + + expires_in is the number of seconds until the block expires. If not provided, the block will be permanent. + """ + params = self.__generate_params(locals()) + return self.__api_request('POST', '/api/v1/admin/ip_blocks', params) + + @api_version("4.0.0", "4.0.0") + def admin_update_ip_block(self, id: Union[AdminIpBlock, IdType], ip: Optional[str] = None, severity: Optional[str] = None, + comment: Optional[str] = None, expires_in: Optional[int] = None) -> AdminIpBlock: + """ + Update an existing IP block. Requires scope `admin:write:ip_blocks`. + + expires_in is the number of seconds until the block expires. If not provided, the block will be permanent. + """ + id = self.__unpack_id(id) + params = self.__generate_params(locals()) + return self.__api_request('PUT', f'/api/v1/admin/ip_blocks/{id}', params) + + @api_version("4.0.0", "4.0.0") + def admin_delete_ip_block(self, id: Union[AdminIpBlock, IdType]): + """ + Remove an IP block. Requires scope `admin:write:ip_blocks`. + """ + id = self.__unpack_id(id) + self.__api_request('DELETE', f'/api/v1/admin/ip_blocks/{id}') diff --git a/srcgen/return_types.json b/srcgen/return_types.json index f24985a..938640d 100644 --- a/srcgen/return_types.json +++ b/srcgen/return_types.json @@ -8381,7 +8381,7 @@ "func_call": "TODO_TO_BE_IMPLEMENTED", "func_call_real": null, "func_call_additional": null, - "func_alternate_acc": null, + "func_alternate_acc": true, "manual_update": false, "masto_doc_link": "https://docs.joinmastodon.org/entities/Admin_IpBlock", "description": "An admin IP block, to prevent certain IP addresses or address ranges from accessing the instance.", diff --git a/tests/cassettes/test_admin_ip_blocks.yaml b/tests/cassettes/test_admin_ip_blocks.yaml new file mode 100644 index 0000000..bbba8f9 --- /dev/null +++ b/tests/cassettes/test_admin_ip_blocks.yaml @@ -0,0 +1,434 @@ +interactions: +- request: + body: ip=8.8.8.0%2F24&severity=no_access&comment=Google+DNS+is+ULTRA+BANNED + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2 + Connection: + - keep-alive + Content-Length: + - '69' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - tests/v311 + method: POST + uri: http://localhost:3000/api/v1/admin/ip_blocks + response: + body: + string: '{"id":"2","ip":"8.8.8.0/24","severity":"no_access","comment":"Google + DNS is ULTRA BANNED","created_at":"2025-02-15T16:17:32.614Z","expires_at":null}' + headers: + Cache-Control: + - private, no-store + Content-Length: + - '148' + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + Content-Type: + - application/json; charset=utf-8 + ETag: + - W/"219f9620b46718276f758078ea95b372" + Referrer-Policy: + - strict-origin-when-cross-origin + Server-Timing: + - cache_read.active_support;dur=0.02, sql.active_record;dur=7.50, cache_generate.active_support;dur=4.69, + cache_write.active_support;dur=0.11, instantiation.active_record;dur=0.49, + start_processing.action_controller;dur=0.00, transaction.active_record;dur=7.31, + cache_delete.active_support;dur=0.02, render.active_model_serializers;dur=0.24, + process_action.action_controller;dur=33.49 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-RateLimit-Limit: + - '300' + X-RateLimit-Remaining: + - '299' + X-RateLimit-Reset: + - '2025-02-15T16:20:00.606713Z' + X-Request-Id: + - 374a68b3-a923-49df-8296-f6e2640c3724 + X-Runtime: + - '0.057636' + X-XSS-Protection: + - '0' + vary: + - Authorization, Origin + 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/ip_blocks/2 + response: + body: + string: '{"id":"2","ip":"8.8.8.0/24","severity":"no_access","comment":"Google + DNS is ULTRA BANNED","created_at":"2025-02-15T16:17:32.614Z","expires_at":null}' + headers: + Cache-Control: + - private, no-store + Content-Length: + - '148' + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + Content-Type: + - application/json; charset=utf-8 + ETag: + - W/"219f9620b46718276f758078ea95b372" + Referrer-Policy: + - strict-origin-when-cross-origin + Server-Timing: + - cache_read.active_support;dur=0.02, sql.active_record;dur=0.67, cache_generate.active_support;dur=0.76, + cache_write.active_support;dur=0.09, instantiation.active_record;dur=0.25, + start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.22, + process_action.action_controller;dur=20.43 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-RateLimit-Limit: + - '300' + X-RateLimit-Remaining: + - '299' + X-RateLimit-Reset: + - '2025-02-15T16:20:00.661597Z' + X-Request-Id: + - 96b094a8-d854-4090-a8ad-20639c24762c + X-Runtime: + - '0.036990' + X-XSS-Protection: + - '0' + vary: + - Authorization, Origin + 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/ip_blocks + response: + body: + string: '[{"id":"2","ip":"8.8.8.0/24","severity":"no_access","comment":"Google + DNS is ULTRA BANNED","created_at":"2025-02-15T16:17:32.614Z","expires_at":null}]' + headers: + Cache-Control: + - private, no-store + Content-Length: + - '150' + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + Content-Type: + - application/json; charset=utf-8 + ETag: + - W/"dafb1cb8debb9e4d1a34cea73ce6982e" + Link: + - ; rel="prev" + Referrer-Policy: + - strict-origin-when-cross-origin + Server-Timing: + - cache_read.active_support;dur=0.02, sql.active_record;dur=0.74, cache_generate.active_support;dur=1.09, + cache_write.active_support;dur=0.09, instantiation.active_record;dur=0.23, + start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.22, + process_action.action_controller;dur=20.96 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-RateLimit-Limit: + - '300' + X-RateLimit-Remaining: + - '299' + X-RateLimit-Reset: + - '2025-02-15T16:20:00.703742Z' + X-Request-Id: + - 9b10949b-a35d-4c26-afbe-29027e25c697 + X-Runtime: + - '0.038134' + X-XSS-Protection: + - '0' + vary: + - Authorization, Origin + status: + code: 200 + message: OK +- request: + body: id=2&comment=Updated+test+block + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - Bearer __MASTODON_PY_TEST_ACCESS_TOKEN_2 + Connection: + - keep-alive + Content-Length: + - '31' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - tests/v311 + method: PUT + uri: http://localhost:3000/api/v1/admin/ip_blocks/2 + response: + body: + string: '{"id":"2","ip":"8.8.8.0/24","severity":"no_access","comment":"Updated + test block","created_at":"2025-02-15T16:17:32.614Z","expires_at":null}' + headers: + Cache-Control: + - private, no-store + Content-Length: + - '140' + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + Content-Type: + - application/json; charset=utf-8 + ETag: + - W/"84b443beeb1ce564b88b4c659e36afa7" + Referrer-Policy: + - strict-origin-when-cross-origin + Server-Timing: + - cache_read.active_support;dur=0.02, sql.active_record;dur=9.89, cache_generate.active_support;dur=1.01, + cache_write.active_support;dur=0.17, instantiation.active_record;dur=0.40, + start_processing.action_controller;dur=0.00, unpermitted_parameters.action_controller;dur=0.00, + transaction.active_record;dur=10.14, cache_delete.active_support;dur=0.02, + render.active_model_serializers;dur=0.20, process_action.action_controller;dur=43.27 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-RateLimit-Limit: + - '300' + X-RateLimit-Remaining: + - '299' + X-RateLimit-Reset: + - '2025-02-15T16:20:00.755487Z' + X-Request-Id: + - 1f631601-7143-4f95-b8f8-bebe0f148dfb + X-Runtime: + - '0.060749' + X-XSS-Protection: + - '0' + vary: + - Authorization, Origin + 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 + Content-Length: + - '0' + User-Agent: + - tests/v311 + method: DELETE + uri: http://localhost:3000/api/v1/admin/ip_blocks/2 + response: + body: + string: '{}' + headers: + Cache-Control: + - private, no-store + Content-Length: + - '2' + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + Content-Type: + - application/json; charset=utf-8 + ETag: + - W/"44136fa355b3678a1146ad16f7e8649e" + Referrer-Policy: + - strict-origin-when-cross-origin + Server-Timing: + - cache_read.active_support;dur=0.02, sql.active_record;dur=6.41, cache_generate.active_support;dur=0.93, + cache_write.active_support;dur=0.07, instantiation.active_record;dur=0.36, + start_processing.action_controller;dur=0.00, transaction.active_record;dur=6.06, + cache_delete.active_support;dur=0.02, render.active_model_serializers;dur=0.02, + process_action.action_controller;dur=29.19 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-RateLimit-Limit: + - '300' + X-RateLimit-Remaining: + - '299' + X-RateLimit-Reset: + - '2025-02-15T16:20:00.810162Z' + X-Request-Id: + - da1e5424-7b33-4723-9572-bcbd9e9544b3 + X-Runtime: + - '0.043990' + X-XSS-Protection: + - '0' + vary: + - Authorization, Origin + 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/ip_blocks + response: + body: + string: '[]' + headers: + Cache-Control: + - private, no-store + Content-Length: + - '2' + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + Content-Type: + - application/json; charset=utf-8 + ETag: + - W/"4f53cda18c2baa0c0354bb5f9a3ecbe5" + Referrer-Policy: + - strict-origin-when-cross-origin + Server-Timing: + - cache_read.active_support;dur=0.02, sql.active_record;dur=8.21, cache_generate.active_support;dur=0.65, + cache_write.active_support;dur=0.06, instantiation.active_record;dur=0.34, + start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.04, + process_action.action_controller;dur=35.29 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-RateLimit-Limit: + - '300' + X-RateLimit-Remaining: + - '299' + X-RateLimit-Reset: + - '2025-02-15T16:20:00.857147Z' + X-Request-Id: + - ff2a6b5b-6597-4376-994d-aa3193b579e1 + X-Runtime: + - '0.049639' + X-XSS-Protection: + - '0' + vary: + - Authorization, Origin + 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/ip_blocks + response: + body: + string: '[]' + headers: + Cache-Control: + - private, no-store + Content-Length: + - '2' + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + Content-Type: + - application/json; charset=utf-8 + ETag: + - W/"4f53cda18c2baa0c0354bb5f9a3ecbe5" + Referrer-Policy: + - strict-origin-when-cross-origin + Server-Timing: + - cache_read.active_support;dur=0.02, sql.active_record;dur=0.76, cache_generate.active_support;dur=0.86, + cache_write.active_support;dur=0.08, instantiation.active_record;dur=0.23, + start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.04, + process_action.action_controller;dur=20.13 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-RateLimit-Limit: + - '300' + X-RateLimit-Remaining: + - '299' + X-RateLimit-Reset: + - '2025-02-15T16:20:00.915691Z' + X-Request-Id: + - ff5baf3e-bf99-4b36-a877-72986e6820e8 + X-Runtime: + - '0.039306' + X-XSS-Protection: + - '0' + vary: + - Authorization, Origin + status: + code: 200 + message: OK +version: 1 diff --git a/tests/cassettes/test_admin_trends.yaml b/tests/cassettes/test_admin_trends.yaml new file mode 100644 index 0000000..cd8c0ad --- /dev/null +++ b/tests/cassettes/test_admin_trends.yaml @@ -0,0 +1,238 @@ +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/trends/tags + response: + body: + string: '[]' + headers: + Cache-Control: + - private, no-store + Content-Length: + - '2' + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + Content-Type: + - application/json; charset=utf-8 + ETag: + - W/"4f53cda18c2baa0c0354bb5f9a3ecbe5" + Referrer-Policy: + - strict-origin-when-cross-origin + Server-Timing: + - cache_read.active_support;dur=0.26, sql.active_record;dur=5.15, cache_generate.active_support;dur=20.76, + cache_write.active_support;dur=0.60, instantiation.active_record;dur=3.21, + start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.36, + process_action.action_controller;dur=46.03 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-RateLimit-Limit: + - '300' + X-RateLimit-Remaining: + - '299' + X-RateLimit-Reset: + - '2025-02-15T16:10:00.736877Z' + X-Request-Id: + - 6e3c04cf-1167-4ab7-a9f3-d3c16f04f4f4 + X-Runtime: + - '0.111953' + X-XSS-Protection: + - '0' + vary: + - Authorization, Origin + 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/trends/statuses + response: + body: + string: '[]' + headers: + Cache-Control: + - private, no-store + Content-Length: + - '2' + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + Content-Type: + - application/json; charset=utf-8 + ETag: + - W/"4f53cda18c2baa0c0354bb5f9a3ecbe5" + Referrer-Policy: + - strict-origin-when-cross-origin + Server-Timing: + - cache_read.active_support;dur=0.04, sql.active_record;dur=2.06, cache_generate.active_support;dur=1.88, + cache_write.active_support;dur=0.11, instantiation.active_record;dur=0.28, + start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.04, + process_action.action_controller;dur=27.18 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-RateLimit-Limit: + - '300' + X-RateLimit-Remaining: + - '299' + X-RateLimit-Reset: + - '2025-02-15T16:10:00.803570Z' + X-Request-Id: + - f13147fc-de79-4163-b319-bd85261a3be8 + X-Runtime: + - '0.052897' + X-XSS-Protection: + - '0' + vary: + - Authorization, Accept-Language, Origin + 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/trends/links + response: + body: + string: '[]' + headers: + Cache-Control: + - private, no-store + Content-Length: + - '2' + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + Content-Type: + - application/json; charset=utf-8 + ETag: + - W/"4f53cda18c2baa0c0354bb5f9a3ecbe5" + Referrer-Policy: + - strict-origin-when-cross-origin + Server-Timing: + - cache_read.active_support;dur=0.04, sql.active_record;dur=1.56, cache_generate.active_support;dur=1.97, + cache_write.active_support;dur=0.11, instantiation.active_record;dur=0.26, + start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.06, + process_action.action_controller;dur=30.19 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-RateLimit-Limit: + - '300' + X-RateLimit-Remaining: + - '299' + X-RateLimit-Reset: + - '2025-02-15T16:10:00.859936Z' + X-Request-Id: + - c0db9719-8b7e-4900-8fde-7aeb49855d8e + X-Runtime: + - '0.053876' + X-XSS-Protection: + - '0' + vary: + - Authorization, Accept-Language, Origin + 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/trends/tags?limit=5 + response: + body: + string: '[]' + headers: + Cache-Control: + - private, no-store + Content-Length: + - '2' + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none'; form-action 'none' + Content-Type: + - application/json; charset=utf-8 + ETag: + - W/"4f53cda18c2baa0c0354bb5f9a3ecbe5" + Referrer-Policy: + - strict-origin-when-cross-origin + Server-Timing: + - cache_read.active_support;dur=0.03, sql.active_record;dur=0.93, cache_generate.active_support;dur=1.84, + cache_write.active_support;dur=0.10, instantiation.active_record;dur=0.24, + start_processing.action_controller;dur=0.00, render.active_model_serializers;dur=0.04, + process_action.action_controller;dur=23.99 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-RateLimit-Limit: + - '300' + X-RateLimit-Remaining: + - '299' + X-RateLimit-Reset: + - '2025-02-15T16:10:00.913971Z' + X-Request-Id: + - 7ac2ec04-b149-4053-b233-92e00ba9c56d + X-Runtime: + - '0.046646' + X-XSS-Protection: + - '0' + vary: + - Authorization, Origin + status: + code: 200 + message: OK +version: 1 diff --git a/tests/test_admin.py b/tests/test_admin.py index 7600540..1ef52d3 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -157,7 +157,7 @@ def test_admin_trends(api2): assert isinstance(api2.admin_trending_links(), list) assert isinstance(api2.admin_trending_tags(limit=5), list) # The management functions are unfortunately not really testable easily. - + @pytest.mark.skip(reason="reject / accept of account requests isn't really testable without modifying instance settings. anyone want to fumble those into the DB setup and write this test, please do.") def test_admin_accountrequests(api2): pass @@ -296,3 +296,38 @@ def test_admin_email_domain_blocks(api2): all_blocks_after_delete = api2.admin_email_domain_blocks() assert not any(block.id == created_block.id for block in all_blocks_after_delete) + +@pytest.mark.vcr() +def test_admin_ip_blocks(api2): + try: + test_ip = "8.8.8.0/24" + test_severity = "no_access" + test_comment = "Google DNS is ULTRA BANNED" + + created_block = api2.admin_create_ip_block(test_ip, test_severity, comment=test_comment) + assert created_block is not None + assert created_block.ip == test_ip + assert created_block.severity == test_severity + assert created_block.comment == test_comment + + retrieved_block = api2.admin_ip_block(created_block.id) + assert retrieved_block.id == created_block.id + assert retrieved_block.ip == test_ip + assert retrieved_block.severity == test_severity + + all_blocks = api2.admin_ip_blocks() + assert any(block.id == created_block.id for block in all_blocks) + + updated_comment = "Updated test block" + updated_block = api2.admin_update_ip_block(created_block.id, comment=updated_comment) + assert updated_block.id == created_block.id + assert updated_block.comment == updated_comment + + api2.admin_delete_ip_block(created_block.id) + + all_blocks_after_delete = api2.admin_ip_blocks() + assert not any(block.id == created_block.id for block in all_blocks_after_delete) + finally: + all_blocks = api2.admin_ip_blocks() + for block in all_blocks: + api2.admin_delete_ip_block(block.id)