Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UPY-13] Add file ACL update functionality with tests #13

Merged
merged 1 commit into from
Feb 21, 2025

Conversation

farmisen
Copy link
Owner

@farmisen farmisen commented Feb 18, 2025

Add ACL (Access Control List) update functionality with corresponding tests and documentation

This change introduces a new API capability to modify access control settings for uploaded files, supporting both file keys and custom IDs. The implementation includes synchronous and asynchronous client methods, comprehensive test coverage, and documentation updates.

Changes

  • Added new update_acl() method to both sync and async API clients
  • Implemented UpdateACLResponse schema class for ACL operation results
  • Added comprehensive test coverage for ACL updates including different identifier types
  • Updated README with new ACL update API documentation and examples
  • Extended example scripts to demonstrate ACL functionality

Impact

  • Enhances file access control management capabilities
  • Maintains backward compatibility with existing API functionality
  • No breaking changes to existing interfaces
  • Minimal performance impact - single API endpoint call per update operation

Summary by CodeRabbit

  • New Features

    • Introduced the ability to update file access permissions (public or private) after uploads.
    • Enhanced examples showcase both synchronous and asynchronous workflows for managing file permissions.
  • Documentation

    • Updated the user guide with clear instructions and code examples on configuring file access settings.
    • Added new response types and method signatures to the documentation for better clarity on usage.
  • Tests

    • Added multiple test cases to validate the functionality of updating Access Control List (ACL) settings.
    • Standardized response format in existing tests to ensure consistency.
  • Chores

    • Updated .gitignore to exclude specific files from version control.

Copy link

coderabbitai bot commented Feb 18, 2025

Walkthrough

This pull request introduces the update_acl functionality to manage file permission settings. It adds the new update_acl methods in both the synchronous (UTApi) and asynchronous (AsyncUTApi) API clients, along with a corresponding response model, UpdateACLResponse. Documentation in the README is extended with examples, and example scripts are updated to showcase the new feature. Additionally, several tests have been added and modified to validate the ACL update behavior and standardize response key naming.

Changes

File(s) Change Summary
README.md Added a new section documenting the update_acl method, its signature, parameters, and the new UpdateACLResponse model with code examples.
examples/main.py, examples/async_main.py Inserted code examples demonstrating the use of the update_acl method for updating ACL settings of files in both synchronous and asynchronous flows.
tests/test_async_client.py, tests/test_client.py, tests/test_utils.py Added new tests (test_update_acl, test_update_acl_with_custom_id, test_update_acl_mixed_updates) to verify ACL update functionality, and updated existing mock responses by converting keys from snake_case to camelCase for consistency.
upyloadthing/__init__.py, upyloadthing/async_client.py, upyloadthing/client.py, upyloadthing/schemas.py Introduced the new update_acl methods in both the asynchronous and synchronous API classes, added the UpdateACLResponse class to the schemas, and updated the public exports to include UpdateACLResponse.
upyloadthing/base_client.py Added a new method _validate_acl_updates to validate ACL update requests, ensuring proper structure and values before processing.
.gitignore Added .qodo/history.sqlite to ignore this file in version control.

Sequence Diagram(s)

sequenceDiagram
    participant App as Client Application
    participant API as UTApi/AsyncUTApi
    participant Server as /v6/updateACL Endpoint

    App->>API: Call update_acl(updates)
    API->>Server: POST /v6/updateACL with updates payload
    Server-->>API: JSON response { success, updated_count }
    API-->>App: Return UpdateACLResponse
Loading

Possibly related PRs

  • [UPY-7] Support async operations #6: The changes in the main PR, which introduce the update_acl method and the UpdateACLResponse model, are directly related to the modifications in the retrieved PR, as both involve enhancements to the UTApi and AsyncUTApi classes for managing Access Control List (ACL) settings.
  • [UPY-11] Implement the rename file fucntion #12: The changes in the main PR, which introduce the update_acl method and the UpdateACLResponse model, are related to the changes in the retrieved PR, which implements the rename_files method and the RenameFilesResponse model, as both PRs add new methods to the UTApi and AsyncUTApi classes that handle file management operations.

Poem

I'm a rabbit in the code, with a joyful hop,
Updating ACLs so our file permissions never stop.
I nibble on code like a crunchy carrot treat,
With tests and docs, our updates are neat!
Thump-thump, I celebrate each line—what a delightful feat!
🐇 Cheers to a secure and playful code retreat!
Hop on, code friends, let the changes be complete!


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 53b328a and 1b3cdce.

📒 Files selected for processing (12)
  • .gitignore (1 hunks)
  • README.md (3 hunks)
  • examples/async_main.py (1 hunks)
  • examples/main.py (1 hunks)
  • tests/test_async_client.py (8 hunks)
  • tests/test_client.py (8 hunks)
  • tests/test_utils.py (2 hunks)
  • upyloadthing/__init__.py (2 hunks)
  • upyloadthing/async_client.py (2 hunks)
  • upyloadthing/base_client.py (2 hunks)
  • upyloadthing/client.py (2 hunks)
  • upyloadthing/schemas.py (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • .gitignore
  • examples/async_main.py
  • tests/test_utils.py
  • upyloadthing/async_client.py
  • upyloadthing/init.py
  • examples/main.py
  • upyloadthing/client.py
  • upyloadthing/schemas.py
🔇 Additional comments (33)
upyloadthing/base_client.py (3)

14-14: Successfully imported ACLValue

No issues found with this import; it is used neatly in the new _validate_acl_updates method.


260-260: No functional changes at this line

This appears to be a blank or spacing change. No action necessary.


261-286: Robust ACL updates validation

The _validate_acl_updates method correctly checks for required identifiers (fileKey or customId) and the presence of a valid acl field aligned with the ACLValue enum. This thoroughly enforces correctness on incoming ACL updates.

tests/test_client.py (14)

10-14: Added imports for ACL testing

Inclusion of ACLValue and UpdateACLResponse is consistent with the newly introduced ACL update functionality.


207-207: Switched to camelCase in delete response

Changing to "deletedCount" aligns well with other camelCase response fields.


233-233: Use of uploadedAt field

Switching to "uploadedAt" for consistency in naming. Looks good.


250-257: Updated usage info keys to camelCase

Migrating from snake_case (total_bytes, app_total_bytes, etc.) to "totalBytes", "appTotalBytes", "filesUploaded", and "limitBytes" ensures consistent response formatting.


275-275: Use of renamedCount in rename response

Good move to standardize rename counts as "renamedCount".


294-294: Consistent rename count in custom ID rename test

Same enhancement for "renamedCount". Matches the standardized response keys.


313-313: Mixed rename updates also adopting renamedCount

Continued alignment with camelCase naming convention.


353-354: Blank lines

No meaningful changes here.


355-374: Test coverage for fileKey-based ACL updates

test_update_acl thoroughly verifies the update flow and checks the response.


376-394: Test coverage for custom ID-based ACL updates

test_update_acl_with_custom_id ensures correct handling of the customId field.


396-414: Mixed identifier ACL updates test

test_update_acl_mixed_updates covers scenarios using both fileKey and customId. Well done.


416-431: Invalid ACL value test

test_update_acl_with_invalid_acl correctly checks for enum validation failure and ensures the request is not sent if validation fails.


434-447: Missing acl field test

test_update_acl_with_missing_acl verifies the required acl field presence before sending requests.


450-468: Missing identifier test

test_update_acl_with_missing_identifier confirms that at least one valid identifier (fileKey or customId) must be present.

tests/test_async_client.py (14)

10-15: New imports for ACL

Including ACLValue and UpdateACLResponse suits the added ACL update tests.


202-202: Adopting deletedCount in async delete tests

Ensures consistency with other responses in camelCase.


229-229: uploadedAt field alignment

CamelCase naming helps maintain consistency across responses.


251-254: Async usage info now in camelCase

Fields like "totalBytes", "appTotalBytes", "filesUploaded", and "limitBytes" are updated. The naming convention is coherent throughout.


273-273: Async rename: renamedCount usage

Good standardization in rename response structure.


296-296: Consistent rename count in custom ID rename test (async)

Maintaining renamedCount naming matches the rest of the codebase.


319-319: Mixed rename updates also reflect renamedCount

This ensures uniform naming in all rename scenarios.


363-363: Blank line change

No impact on functionality.


364-383: Async ACL update with file keys

test_update_acl confirms correct handling and response mapping for multiple file keys.


385-404: Async ACL update with custom IDs

test_update_acl_with_custom_id validates customId usage thoroughly.


406-425: Mixed ACL updates in async context

test_update_acl_mixed_updates effectively covers combined identifier scenarios.


429-446: Async invalid ACL handling

test_update_acl_with_invalid_acl checks enum validation and ensures no outgoing request on failure.


450-465: Missing acl in async updates

test_update_acl_with_missing_acl makes sure the acl field is mandatory.


467-486: Missing identifier in async updates

test_update_acl_with_missing_identifier confirms that either fileKey or customId must be included.

README.md (2)

85-106: New ACL Update Section Documentation Review
The newly added "Update ACL Settings" section is well-documented with clear examples showing how to update ACL settings using file keys, custom IDs, or a mix of both. The examples correctly illustrate the use of the update_acl method and provide a complete, runnable sample. Ensure that the allowed ACL values ('public-read' and 'private') and the required keys (either fileKey or customId) mentioned in the examples match the backend specifications.


190-196: ACL Method Documentation Update
The addition to the "Methods" section for the update_acl method is concise and matches the new functionality. The documentation appropriately lists the required update list structure and the expected response model (UpdateACLResponse). For clarity, consider briefly mentioning any error conditions or edge cases that might arise during ACL updates.

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
upyloadthing/schemas.py (1)

49-52: Add field validation rules.

Consider adding validation rules to ensure:

  • updated_count is non-negative
  • success aligns with updated_count (e.g., success should be False when count is 0)
 class UpdateACLResponse(BaseModel):
     success: bool
-    updated_count: int
+    updated_count: int = Field(ge=0)
+
+    @validator('success')
+    def validate_success(cls, v: bool, values: Dict[str, Any]) -> bool:
+        if 'updated_count' in values and values['updated_count'] == 0:
+            return False
+        return v
tests/test_utils.py (1)

54-54: Add test case for ACL-related field names.

Since we're adding ACL update functionality, consider adding test cases for ACL-related field names:

     assert snakify("someString") == "someString"
     assert snakify("limitBytes") == "limitBytes"
+    assert snakify("fileACL") == "file_acl"
+    assert snakify("publicACL") == "public_acl"
     assert snakify(True) is True
examples/main.py (2)

75-78: Add example for custom ID-based updates.

Consider demonstrating both file key and custom ID-based ACL updates:

     acl_updates = [
         {"fileKey": upload_results[0].file_key, "acl": "public-read"},
         {"fileKey": upload_results[1].file_key, "acl": "public-read"},
+        # Example with custom ID
+        {"customId": "my-custom-id", "acl": "private"},
     ]

73-83: Extract ACL values as constants.

Consider extracting ACL values as constants to improve maintainability and prevent typos:

+# ACL constants
+PUBLIC_READ_ACL = "public-read"
+PRIVATE_ACL = "private"
+
 def main():
     # ... existing code ...
     
     # Update ACL test
     print("🔒 Updating ACL settings...")
     acl_updates = [
-        {"fileKey": upload_results[0].file_key, "acl": "public-read"},
-        {"fileKey": upload_results[1].file_key, "acl": "public-read"},
+        {"fileKey": upload_results[0].file_key, "acl": PUBLIC_READ_ACL},
+        {"fileKey": upload_results[1].file_key, "acl": PUBLIC_READ_ACL},
     ]
examples/async_main.py (1)

84-93: Enhance the example to demonstrate both ACL settings.

The example could be more comprehensive by demonstrating both 'public-read' and 'private' ACL settings.

Apply this diff to enhance the example:

-        {"fileKey": upload_results[0].file_key, "acl": "public-read"},
-        {"fileKey": upload_results[1].file_key, "acl": "public-read"},
+        {"fileKey": upload_results[0].file_key, "acl": "private"},
+        {"fileKey": upload_results[1].file_key, "acl": "public-read"},
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 54c942a and bad5d21.

📒 Files selected for processing (10)
  • README.md (3 hunks)
  • examples/async_main.py (1 hunks)
  • examples/main.py (1 hunks)
  • tests/test_async_client.py (8 hunks)
  • tests/test_client.py (8 hunks)
  • tests/test_utils.py (2 hunks)
  • upyloadthing/__init__.py (2 hunks)
  • upyloadthing/async_client.py (2 hunks)
  • upyloadthing/client.py (2 hunks)
  • upyloadthing/schemas.py (1 hunks)
🔇 Additional comments (7)
upyloadthing/__init__.py (1)

8-8: LGTM!

The UpdateACLResponse schema is correctly imported and exported, maintaining the module's organization and alphabetical order.

Also applies to: 26-26

tests/test_utils.py (1)

66-80: LGTM!

The new test function test_snakify_dict_other is well-structured and provides good coverage for usage info response fields.

tests/test_async_client.py (3)

14-14: LGTM!

The addition of UpdateACLResponse to the imports aligns with the new ACL update functionality.


201-201: LGTM!

The response field names have been consistently updated to use camelCase format, aligning with the API response structure.

Also applies to: 228-228, 250-253, 272-272, 295-295, 318-318


363-424: LGTM! Comprehensive test coverage for ACL updates.

The test suite thoroughly covers all ACL update scenarios:

  • Updates using file keys
  • Updates using custom IDs
  • Mixed updates using both identifiers
README.md (2)

85-105: LGTM! Clear and comprehensive examples.

The examples effectively demonstrate all ACL update scenarios and follow the established documentation pattern.


190-196: LGTM! Clear and complete API documentation.

The API reference updates thoroughly document:

  • The new update_acl method signature and parameters
  • The UpdateACLResponse model structure

Also applies to: 224-226

Comment on lines 184 to 198
def update_acl(self, updates: List[dict[str, str]]) -> UpdateACLResponse:
"""Update ACL settings for one or more files synchronously.

Args:
updates: List of update objects containing either:
- fileKey and acl
- customId and acl
where acl can be 'public-read' or 'private'

Returns:
UpdateACLResponse: Response containing update results
"""
result = self._request("POST", "/v6/updateACL", {"updates": updates})
return UpdateACLResponse(**result)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add input validation for ACL values.

The method should validate that the ACL values are either 'public-read' or 'private' before making the request.

Apply this diff to add input validation:

     def update_acl(self, updates: List[dict[str, str]]) -> UpdateACLResponse:
         """Update ACL settings for one or more files synchronously.
 
         Args:
             updates: List of update objects containing either:
                     - fileKey and acl
                     - customId and acl
                     where acl can be 'public-read' or 'private'
 
         Returns:
             UpdateACLResponse: Response containing update results
         """
+        valid_acls = {'public-read', 'private'}
+        for update in updates:
+            if 'acl' not in update or update['acl'] not in valid_acls:
+                raise ValueError("ACL must be either 'public-read' or 'private'")
         result = self._request("POST", "/v6/updateACL", {"updates": updates})
         return UpdateACLResponse(**result)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def update_acl(self, updates: List[dict[str, str]]) -> UpdateACLResponse:
"""Update ACL settings for one or more files synchronously.
Args:
updates: List of update objects containing either:
- fileKey and acl
- customId and acl
where acl can be 'public-read' or 'private'
Returns:
UpdateACLResponse: Response containing update results
"""
result = self._request("POST", "/v6/updateACL", {"updates": updates})
return UpdateACLResponse(**result)
def update_acl(self, updates: List[dict[str, str]]) -> UpdateACLResponse:
"""Update ACL settings for one or more files synchronously.
Args:
updates: List of update objects containing either:
- fileKey and acl
- customId and acl
where acl can be 'public-read' or 'private'
Returns:
UpdateACLResponse: Response containing update results
"""
valid_acls = {'public-read', 'private'}
for update in updates:
if 'acl' not in update or update['acl'] not in valid_acls:
raise ValueError("ACL must be either 'public-read' or 'private'")
result = self._request("POST", "/v6/updateACL", {"updates": updates})
return UpdateACLResponse(**result)

Comment on lines 198 to 216
async def update_acl(
self, updates: List[dict[str, str]]
) -> UpdateACLResponse:
"""Update ACL settings for one or more files asynchronously.

Args:
updates: List of update objects containing either:
- fileKey and acl
- customId and acl
where acl can be 'public-read' or 'private'

Returns:
UpdateACLResponse: Response containing update results
"""
result = await self._request(
"POST", "/v6/updateACL", {"updates": updates}
)
return UpdateACLResponse(**result)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add input validation for ACL values.

The method should validate that the ACL values are either 'public-read' or 'private' before making the request.

Apply this diff to add input validation:

     async def update_acl(
         self, updates: List[dict[str, str]]
     ) -> UpdateACLResponse:
         """Update ACL settings for one or more files asynchronously.
 
         Args:
             updates: List of update objects containing either:
                     - fileKey and acl
                     - customId and acl
                     where acl can be 'public-read' or 'private'
 
         Returns:
             UpdateACLResponse: Response containing update results
         """
+        valid_acls = {'public-read', 'private'}
+        for update in updates:
+            if 'acl' not in update or update['acl'] not in valid_acls:
+                raise ValueError("ACL must be either 'public-read' or 'private'")
         result = await self._request(
             "POST", "/v6/updateACL", {"updates": updates}
         )
         return UpdateACLResponse(**result)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async def update_acl(
self, updates: List[dict[str, str]]
) -> UpdateACLResponse:
"""Update ACL settings for one or more files asynchronously.
Args:
updates: List of update objects containing either:
- fileKey and acl
- customId and acl
where acl can be 'public-read' or 'private'
Returns:
UpdateACLResponse: Response containing update results
"""
result = await self._request(
"POST", "/v6/updateACL", {"updates": updates}
)
return UpdateACLResponse(**result)
async def update_acl(
self, updates: List[dict[str, str]]
) -> UpdateACLResponse:
"""Update ACL settings for one or more files asynchronously.
Args:
updates: List of update objects containing either:
- fileKey and acl
- customId and acl
where acl can be 'public-read' or 'private'
Returns:
UpdateACLResponse: Response containing update results
"""
valid_acls = {'public-read', 'private'}
for update in updates:
if 'acl' not in update or update['acl'] not in valid_acls:
raise ValueError("ACL must be either 'public-read' or 'private'")
result = await self._request(
"POST", "/v6/updateACL", {"updates": updates}
)
return UpdateACLResponse(**result)

Comment on lines 354 to 412
@respx.mock
def test_update_acl(respx_mock: respx.MockRouter, ut_api):
"""Test updating ACL settings with file keys."""
acl_response = {"success": True, "updatedCount": 2}

respx_mock.post(f"{API_URL}/v6/updateACL").mock(
return_value=httpx.Response(200, json=acl_response)
)

updates = [
{"fileKey": "file_key_1", "acl": "private"},
{"fileKey": "file_key_2", "acl": "public-read"},
]

result = ut_api.update_acl(updates)
assert isinstance(result, UpdateACLResponse)
assert result.success is True
assert result.updated_count == 2


@respx.mock
def test_update_acl_with_custom_id(respx_mock: respx.MockRouter, ut_api):
"""Test updating ACL settings with custom IDs."""
acl_response = {"success": True, "updatedCount": 2}

respx_mock.post(f"{API_URL}/v6/updateACL").mock(
return_value=httpx.Response(200, json=acl_response)
)

updates = [
{"customId": "custom_123", "acl": "private"},
{"customId": "custom_456", "acl": "public-read"},
]

result = ut_api.update_acl(updates)
assert isinstance(result, UpdateACLResponse)
assert result.success is True
assert result.updated_count == 2


@respx.mock
def test_update_acl_mixed_updates(respx_mock: respx.MockRouter, ut_api):
"""Test updating ACL settings with mixed update types."""
acl_response = {"success": True, "updatedCount": 2}

respx_mock.post(f"{API_URL}/v6/updateACL").mock(
return_value=httpx.Response(200, json=acl_response)
)

updates = [
{"fileKey": "file_key_123", "acl": "private"},
{"customId": "custom_456", "acl": "public-read"},
]

result = ut_api.update_acl(updates)
assert isinstance(result, UpdateACLResponse)
assert result.success is True
assert result.updated_count == 2
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error case tests for ACL updates.

The tests should cover error cases such as invalid ACL values and missing required fields.

Add the following test cases:

@respx.mock
def test_update_acl_with_invalid_acl(respx_mock: respx.MockRouter, ut_api):
    """Test updating ACL settings with invalid ACL value."""
    updates = [
        {"fileKey": "file_key_1", "acl": "invalid-acl"},
    ]
    
    with pytest.raises(ValueError, match="ACL must be either 'public-read' or 'private'"):
        ut_api.update_acl(updates)

@respx.mock
def test_update_acl_with_missing_acl(respx_mock: respx.MockRouter, ut_api):
    """Test updating ACL settings with missing ACL field."""
    updates = [
        {"fileKey": "file_key_1"},  # Missing acl field
    ]
    
    with pytest.raises(ValueError, match="ACL must be either 'public-read' or 'private'"):
        ut_api.update_acl(updates)

@respx.mock
def test_update_acl_with_missing_identifier(respx_mock: respx.MockRouter, ut_api):
    """Test updating ACL settings with missing identifier."""
    updates = [
        {"acl": "public-read"},  # Missing fileKey/customId
    ]
    
    acl_response = {"success": False, "error": "Missing identifier"}
    respx_mock.post(f"{API_URL}/v6/updateACL").mock(
        return_value=httpx.Response(400, json=acl_response)
    )
    
    with pytest.raises(httpx.HTTPError):
        ut_api.update_acl(updates)

@farmisen farmisen force-pushed the farmisen/upy-13-implement-the-update-acl-function branch from 53b328a to 1b3cdce Compare February 21, 2025 17:05
@farmisen farmisen merged commit 0cef103 into main Feb 21, 2025
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant