Skip to content

ERA-12676: Add user management and EULA endpoints to both clients#35

Open
JoshuaVulcan wants to merge 5 commits intomainfrom
ERA-12676/accounts-users-eula
Open

ERA-12676: Add user management and EULA endpoints to both clients#35
JoshuaVulcan wants to merge 5 commits intomainfrom
ERA-12676/accounts-users-eula

Conversation

@JoshuaVulcan
Copy link
Copy Markdown
Contributor

@JoshuaVulcan JoshuaVulcan commented Feb 11, 2026

Summary

  • Adds get_users() to AsyncERClient (sync already had it)
  • Adds get_user(id), patch_user(id, data) to both ERClient and AsyncERClient
  • Adds get_user_profiles(id) to both clients
  • Adds get_eula() and accept_eula() to both clients

Test plan

  • 12 async tests covering all new endpoints (success, 404, 403 scenarios)
  • 12 sync tests covering all new endpoints (success, 404, 403 scenarios)
  • Full test suite passes (114 tests)
  • Feature parity verified between sync and async clients

Resolves ERA-12676

ERA-12676: Adds accounts/user parity across both clients:

ERClient (sync) and AsyncERClient (async):
- get_users: List all users (async was missing)
- get_user(id): Get single user by ID or 'me'
- patch_user(id, data): Update user with partial data
- get_user_profiles(id): Get user profiles
- get_eula: Get active End-User License Agreement
- accept_eula: Accept the active EULA

Includes 24 tests (12 async + 12 sync) covering success, not-found,
and forbidden scenarios for all new endpoints.

Co-authored-by: Cursor <cursoragent@cursor.com>
@JoshuaVulcan JoshuaVulcan added autoreviewing PR is currently being auto-reviewed and removed autoreviewing PR is currently being auto-reviewed labels Feb 11, 2026
@JoshuaVulcan JoshuaVulcan requested a review from a team as a code owner February 12, 2026 01:49
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds account/user-management and EULA endpoints to the EarthRanger Python clients (sync + async) to achieve feature parity and provide typed convenience wrappers around the underlying HTTP helpers.

Changes:

  • Added user endpoints: get_users(), get_user(user_id), patch_user(user_id, data), get_user_profiles(user_id) (sync + async parity).
  • Added EULA endpoints: get_eula() and accept_eula() (sync + async parity).
  • Added new sync/async test modules covering success and authorization/not-found error scenarios for the new endpoints.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.

File Description
erclient/client.py Adds the new user/account + EULA convenience methods to ERClient and AsyncERClient.
tests/sync_client/test_accounts.py New sync tests for the added endpoints using mocked session responses.
tests/async_client/test_accounts.py New async tests for the added endpoints using respx route mocks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +24 to +29
er_client._http_session.get = MagicMock(
return_value=_mock_response(200, {"data": expected})
)
result = er_client.get_users()
er_client._http_session.get.assert_called_once()
assert result == expected
updated = {**user_response, "first_name": "Updated"}
route.return_value = httpx.Response(httpx.codes.OK, json={"data": updated})
result = await er_client.patch_user("c925e69e-51cf-43d0-b659-2000ae023664", {"first_name": "Updated"})
assert route.called
Comment on lines +176 to +182
async def test_accept_eula(er_client, eula_accept_response):
async with respx.mock(base_url=er_client._api_root("v1.0"), assert_all_called=False) as m:
route = m.post("user/eula/accept")
route.return_value = httpx.Response(httpx.codes.CREATED, json={"data": eula_accept_response})
result = await er_client.accept_eula()
assert route.called
assert result == eula_accept_response
response = MagicMock()
response.ok = 200 <= status_code < 400
response.status_code = status_code
response.text = json.dumps(json_data) if json_data else ""
:param data: Partial user data (e.g., {"first_name": "New"})
:return: Updated user data
"""
self.logger.debug(f'Patching user {user_id}: {data}')
:param data: Partial user data (e.g., {"first_name": "New"})
:return: Updated user data
"""
self.logger.debug(f'Patching user {user_id}: {data}')
Comment on lines +9 to +17
def _mock_response(status_code=200, json_data=None):
"""Helper to create a mock response object."""
response = MagicMock()
response.ok = 200 <= status_code < 400
response.status_code = status_code
response.text = json.dumps(json_data) if json_data else ""
response.json.return_value = json_data
response.url = "https://fake-site.erdomain.org/api/v1.0/test"
return response
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.

2 participants