-
Notifications
You must be signed in to change notification settings - Fork 108
expose include_last_used_time parameter, return created_at and api_key_first_letters #1965
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
Changes from all commits
a6ce39d
cce01dd
0313b9a
5145af7
67884e0
ec2f79c
faeb2f9
36ad580
df418d0
5809d01
f144d5e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| from datetime import datetime, timezone | ||
| from typing import Any, Dict, Generic, List, Literal, Optional, Union, cast, overload | ||
|
|
||
| from httpx import Response | ||
|
|
@@ -20,6 +21,16 @@ | |
| ) | ||
| from weaviate.util import _decode_json_response_dict, escape_string | ||
|
|
||
| # Go's zero time value, returned by the server when a timestamp is not set | ||
| _GO_ZERO_TIME = datetime(1, 1, 1, 0, 0, tzinfo=timezone.utc) | ||
|
|
||
|
|
||
| def _parse_last_used_at(value: Optional[str]) -> Optional[datetime]: | ||
| if value is None: | ||
| return None | ||
| dt = datetime.fromisoformat(value.replace("Z", "+00:00")) | ||
| return None if dt == _GO_ZERO_TIME else dt | ||
|
Comment on lines
+24
to
+32
|
||
|
|
||
|
|
||
| class _BaseExecutor(Generic[ConnectionType]): | ||
| def __init__(self, connection: ConnectionType): | ||
|
|
@@ -451,35 +462,51 @@ def resp(res: Response) -> bool: | |
| status_codes=_ExpectedStatusCodes(ok_in=[200, 409], error="Deactivate user"), | ||
| ) | ||
|
|
||
| def get(self, *, user_id: str) -> executor.Result[Optional[UserDB]]: | ||
| def get( | ||
| self, *, user_id: str, include_last_used_time: bool = False | ||
| ) -> executor.Result[Optional[UserDB]]: | ||
| """Get all information about an user. | ||
|
|
||
| Args: | ||
| user_id: The id of the user. | ||
| include_last_used_time: If True, the last used time of the user will be included. | ||
| """ | ||
|
|
||
| def resp(res: Response) -> Optional[UserDB]: | ||
| if res.status_code == 404: | ||
| return None | ||
| parsed = _decode_json_response_dict(res, "Get user") | ||
| assert parsed is not None | ||
| created_at = parsed.get("createdAt") | ||
| return UserDB( | ||
| user_id=parsed["userId"], | ||
| role_names=parsed["roles"], | ||
| active=parsed["active"], | ||
| user_type=UserTypes(parsed["dbUserType"]), | ||
| created_at=( | ||
| datetime.fromisoformat(created_at.replace("Z", "+00:00")) | ||
| if created_at is not None | ||
| else None | ||
| ), | ||
| last_used_time=_parse_last_used_at(parsed.get("lastUsedAt")), | ||
| api_key_first_letters=parsed.get("apiKeyFirstLetters"), | ||
| ) | ||
|
|
||
| return executor.execute( | ||
| response_callback=resp, | ||
| method=self._connection.get, | ||
| path=f"/users/db/{user_id}", | ||
| params={"includeLastUsedTime": include_last_used_time}, | ||
| error_msg=f"Could not get user '{user_id}'", | ||
|
Comment on lines
495
to
500
|
||
| status_codes=_ExpectedStatusCodes(ok_in=[200, 404], error="get user"), | ||
| ) | ||
|
|
||
| def list_all(self) -> executor.Result[List[UserDB]]: | ||
| """List all DB users.""" | ||
| def list_all(self, *, include_last_used_time: bool = False) -> executor.Result[List[UserDB]]: | ||
| """List all DB users. | ||
|
|
||
| Args: | ||
| include_last_used_time: If True, the last used time of each user will be included. | ||
| """ | ||
|
|
||
| def resp(res: Response) -> List[UserDB]: | ||
| parsed = _decode_json_response_dict(res, "Get user") | ||
|
|
@@ -490,6 +517,13 @@ def resp(res: Response) -> List[UserDB]: | |
| role_names=user["roles"], | ||
| active=user["active"], | ||
| user_type=UserTypes(user["dbUserType"]), | ||
| created_at=( | ||
| datetime.fromisoformat(ca.replace("Z", "+00:00")) | ||
| if (ca := user.get("createdAt")) is not None | ||
| else None | ||
| ), | ||
| last_used_time=_parse_last_used_at(user.get("lastUsedAt")), | ||
| api_key_first_letters=user.get("apiKeyFirstLetters"), | ||
| ) | ||
| for user in cast(List[WeaviateDBUserRoleNames], parsed) | ||
| ] | ||
|
|
@@ -498,6 +532,7 @@ def resp(res: Response) -> List[UserDB]: | |
| response_callback=resp, | ||
| method=self._connection.get, | ||
| path="/users/db", | ||
| params={"includeLastUsedTime": include_last_used_time}, | ||
| error_msg="Could not list all users", | ||
| status_codes=_ExpectedStatusCodes(ok_in=[200], error="list all users"), | ||
| ) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cleanup loop deletes
list-all-{i}but the test createslist-all-user-{i}. This leaves the created users behind and can pollute later tests/runs; update the delete call to match the created IDs (and ideally assert the delete succeeded).