Python SDK for PhilVault authentication and authorization APIs.
Project description
PhilVault SDK
Python SDK for integrating PhilVault authentication and authorization APIs.
Install
pip install philvault-sdk
PyPI: https://pypi.org/project/philvault-sdk/0.1.0/
Quick Start
from philvault_sdk import PhilVaultClient
client = PhilVaultClient(
base_url="http://localhost:8000",
api_key="your-api-key",
)
register_result = client.register(
username="alice",
password="secret",
email="alice@example.com",
)
access_token = register_result["access_token"]
client.set_access_token(access_token)
me = client.me()
Only base_url and api_key are required. Other options have defaults.
You can also create the client from environment variables:
from philvault_sdk import PhilVaultClient
client = PhilVaultClient.from_env()
Default env vars:
PHILVAULT_BASE_URLPHILVAULT_API_KEYPHILVAULT_ACCESS_TOKENPHILVAULT_TIMEOUTPHILVAULT_VERIFY_SSLPHILVAULT_API_KEY_HEADERPHILVAULT_USER_AGENT
Async Usage
import asyncio
from philvault_sdk import AsyncPhilVaultClient
async def main():
async with AsyncPhilVaultClient(
base_url="http://localhost:8000",
api_key="your-api-key",
) as client:
result = await client.login("alice", "secret")
client.set_access_token(result["access_token"])
me = await client.me()
print(me)
asyncio.run(main())
httpx Usage
Both clients expose request/get/post/put/patch/delete/head/options with the same
signature style as httpx. These methods return raw httpx.Response, while
helper methods like login() still return parsed JSON dictionaries.
from philvault_sdk import PhilVaultClient
with PhilVaultClient(base_url="http://localhost:8000", api_key="your-api-key") as client:
response = client.get("/healthz")
print(response.status_code, response.json())
Config Options
base_url(required): PhilVault service root, no/api/v1suffixapi_key(required): value forX-API-Keyaccess_token(optional): Bearer token for authenticated endpointstimeout(optional): request timeout in seconds, default10user_agent(optional): defaultphilvault-sdk/0.1.0verify_ssl(optional): verify HTTPS certificates, defaultTrueapi_key_header(optional): override API key header name, defaultX-API-Keyextra_headers(optional): dict of extra headers merged into every request
Client Methods
The sync and async clients expose the same methods. For async usage, add await
and use AsyncPhilVaultClient.
Lifecycle and setup
from_env(): create client from environment variables (see env var list above). Returns:PhilVaultClient/AsyncPhilVaultClientExample:from philvault_sdk import PhilVaultClient client = PhilVaultClient.from_env()
set_api_key(api_key): update API key (must be non-empty). Useful for rotating keys without re-instantiating the client. Returns:NoneExample:client.set_api_key("new-api-key")
set_access_token(access_token): set or clear bearer token used for authenticated endpoints. PassNoneor an empty string to clear. Returns:NoneExample:client.set_access_token(access_token) client.set_access_token(None)
close()/aclose(): close underlying httpx client and release resources. Returns:NoneExample:client.close() # or: await client.aclose()
- context manager: ensures automatic close when leaving the block.
Returns: client instance within the context.
Example:
from philvault_sdk import PhilVaultClient, AsyncPhilVaultClient with PhilVaultClient(base_url="http://localhost:8000", api_key="key") as client: me = client.me() async with AsyncPhilVaultClient(base_url="http://localhost:8000", api_key="key") as client: me = await client.me()
Raw HTTP (httpx style)
These return httpx.Response:
request(method, path, **kwargs)get(path, **kwargs)post(path, **kwargs)put(path, **kwargs)patch(path, **kwargs)delete(path, **kwargs)head(path, **kwargs)options(path, **kwargs)Example:
response = client.get("/healthz")
print(response.status_code)
print(response.json())
Auth endpoints
These return parsed JSON dict:
register(username, password, email=None, domain_roles=None)
POST /api/v1/auth/register/
Creates a new user and returns tokens.domain_rolesis an optional list of[domain, role]pairs, e.g.[["team-a", "admin"]].passwordmust be at least 8 characters. Returns:{"user": {...}, "access_token": "...", "refresh_token": "..."}Example:result = client.register( username="alice", password="secret", email="alice@example.com", domain_roles=[["team-a", "admin"]], ) client.set_access_token(result["access_token"])
Example response:{ "user": { "id": "64f1c2a1b2c3d4e5f6a7b8c9", "username": "alice", "email": "alice@example.com", "is_active": True, "is_superuser": False, "domain_roles": [["team-a", "admin"]], "created_at": 1730000000, "updated_at": 1730000000, "last_login": None, }, "access_token": "eyJhbGciOi...", "refresh_token": "eyJhbGciOi...", }
login(username, password)
POST /api/v1/auth/login/
Authenticates and returns access/refresh tokens. Returns:{"user": {...}, "access_token": "...", "refresh_token": "..."}Example:result = client.login("alice", "secret") client.set_access_token(result["access_token"])
Example response:{ "user": { "id": "64f1c2a1b2c3d4e5f6a7b8c9", "username": "alice", "email": "alice@example.com", "is_active": True, "is_superuser": False, "domain_roles": [["team-a", "admin"]], "created_at": 1730000000, "updated_at": 1730000000, "last_login": 1730000500, }, "access_token": "eyJhbGciOi...", "refresh_token": "eyJhbGciOi...", }
refresh(refresh_token)
POST /api/v1/auth/refresh/
Exchanges a refresh token for a new access token. Returns:{"access_token": "...", "token_type": "Bearer"}Example:refreshed = client.refresh(refresh_token) client.set_access_token(refreshed["access_token"])
Example response:{"access_token": "eyJhbGciOi...", "token_type": "Bearer"}
me()
GET /api/v1/auth/me/
Returns the current authenticated user profile. Returns:{"id": "...", "username": "...", ...}Example:profile = client.me()
Example response:{ "id": "64f1c2a1b2c3d4e5f6a7b8c9", "username": "alice", "email": "alice@example.com", "is_active": True, "is_superuser": False, "domain_roles": [["team-a", "admin"]], "created_at": 1730000000, "updated_at": 1730000000, "last_login": 1730000500, }
list_users(page=None, page_size=None, search=None)
GET /api/v1/auth/users/
Lists users with pagination and optional search (by username or email). Ifpage_sizeis omitted, the server default is used. Returns:{"users": [...], "total": 0, "page": 1, "page_size": 10}Example:result = client.list_users(page=1, page_size=20, search="alice")
Example response:{ "users": [ { "id": "64f1c2a1b2c3d4e5f6a7b8c9", "username": "alice", "email": "alice@example.com", "is_active": True, "is_superuser": False, "domain_roles": [["team-a", "admin"]], "created_at": 1730000000, "updated_at": 1730000000, "last_login": None, } ], "total": 1, "page": 1, "page_size": 20, }
update_user(user_id, username=None, email=None, is_active=None, is_superuser=None, domain_roles=None)
PUT /api/v1/auth/users/{user_id}
Updates user information by user ID. All parameters are optional - only provided fields will be updated. Returns:{"message": "...", "user": {...}}Example:result = client.update_user( user_id="64f1c2a1b2c3d4e5f6a7b8c9", username="new_username", email="new_email@example.com", is_active=True, )
Example response:{ "message": "User updated successfully", "user": { "id": "64f1c2a1b2c3d4e5f6a7b8c9", "username": "new_username", "email": "new_email@example.com", "is_active": True, "is_superuser": False, "domain_roles": [["team-a", "admin"]], "created_at": 1730000000, "updated_at": 1730001000, "last_login": None, }, }
delete_user(user_id)
DELETE /api/v1/auth/users/{user_id}
Deletes a user by user ID (soft delete). Returns:{"message": "..."}Example:result = client.delete_user("64f1c2a1b2c3d4e5f6a7b8c9")
Example response:{"message": "User deleted successfully"}
change_password(old_password, new_password)
POST /api/v1/auth/change-password/
Changes the current user's password (requires bearer token).new_passwordmust be at least 8 characters. Returns:{"message": "..."}Example:client.change_password("old-secret", "new-secret")
Example response:{"message": "Password changed successfully"}
ACL endpoints
These return parsed JSON dict:
check_permission(user_id, domain, resource_id, action)
POST /api/v1/auth/acl/enforce:check
Checks if a user can perform an action on a resource in a domain.user_idmust be a valid MongoDB ObjectId string. The backend validates the user exists (invalid id returns400, missing user returns404). Returns:{"allowed": bool, "user_id": "...", "domain": "...", "resource_id": "...", "action": "..."}Example:allowed = client.check_permission( user_id="64f1c2a1b2c3d4e5f6a7b8c9", domain="team-a", resource_id="doc_456", action="read", )
Example response:{ "allowed": True, "user_id": "64f1c2a1b2c3d4e5f6a7b8c9", "domain": "team-a", "resource_id": "doc_456", "action": "read", }
check_permission_batch(policies)
POST /api/v1/auth/acl/enforce:batch_check
Batch check.policiesis a list of{user_id, domain, resource_id, action}. Returns:{"results": [{"user_id": "...", "domain": "...", "resource_id": "...", "action": "...", "allowed": bool}, ...]}Example:result = client.check_permission_batch([ {"user_id": "64f1c2a1b2c3d4e5f6a7b8c9", "domain": "team-a", "resource_id": "doc_1", "action": "read"}, {"user_id": "64f1c2a1b2c3d4e5f6a7b8c9", "domain": "team-a", "resource_id": "doc_2", "action": "write"}, ])
Example response:{ "results": [ { "user_id": "64f1c2a1b2c3d4e5f6a7b8c9", "domain": "team-a", "resource_id": "doc_1", "action": "read", "allowed": True, }, { "user_id": "64f1c2a1b2c3d4e5f6a7b8c9", "domain": "team-a", "resource_id": "doc_2", "action": "write", "allowed": False, }, ] }
add_policy(subject, domain, object_name, action)
POST /api/v1/auth/acl/enforce:add
Adds an ACL policy rule for a subject (user or role). Returns:{"result": "Policy added", "policy": ["subject", "domain", "object", "action"]}Example:client.add_policy("user:u_123", "team-a", "doc_456", "read")
Example response:{"result": "Policy added", "policy": ["user:u_123", "team-a", "doc_456", "read"]}
revoke_policy(subject, domain, object_name, action)
POST /api/v1/auth/acl/enforce:revoke
Removes an ACL policy rule. Returns:{"result": "Policy revoked", "policy": ["subject", "domain", "object", "action"]}Example:client.revoke_policy("user:u_123", "team-a", "doc_456", "read")
Example response:{"result": "Policy revoked", "policy": ["user:u_123", "team-a", "doc_456", "read"]}
assign_domain_role(user_id, role, domain)
POST /api/v1/auth/acl/roles:assign/
Assigns a role to a user within a domain. Returns:{"result": "Role assigned", "role": ["user_id", "role", "domain"]}Example:client.assign_domain_role("64f1c2a1b2c3d4e5f6a7b8c9", "admin", "team-a")
Example response:{"result": "Role assigned", "role": ["64f1c2a1b2c3d4e5f6a7b8c9", "admin", "team-a"]}
remove_domain_role(user_id, role, domain)
POST /api/v1/auth/acl/roles:remove/
Removes a role assignment for a user. Returns:{"result": "Role removed", "role": ["user_id", "role", "domain"]}Example:client.remove_domain_role("64f1c2a1b2c3d4e5f6a7b8c9", "admin", "team-a")
Example response:{"result": "Role removed", "role": ["64f1c2a1b2c3d4e5f6a7b8c9", "admin", "team-a"]}
list_domain_roles(user_id, domain)
POST /api/v1/auth/acl/roles:list/
Lists roles for a user in a domain. Returns:{"roles": ["role_name", ...]}Example:roles = client.list_domain_roles("64f1c2a1b2c3d4e5f6a7b8c9", "team-a")
Example response:{"roles": ["admin", "editor"]}
add_resource_policy(resource_id, parent_resource_id)
POST /api/v1/auth/acl/resources:assign/
Links a resource to a parent resource (resource hierarchy). Returns:{"result": "Policy added", "policy": ["resource_id", "parent_resource_id"]}Example:client.add_resource_policy("doc_456", "folder_1")
Example response:{"result": "Policy added", "policy": ["doc_456", "folder_1"]}
remove_resource_policy(resource_id, parent_resource_id)
POST /api/v1/auth/acl/resources:remove/
Unlinks a resource from its parent. Returns:{"result": "Policy removed", "policy": ["resource_id", "parent_resource_id"]}Example:client.remove_resource_policy("doc_456", "folder_1")
Example response:{"result": "Policy removed", "policy": ["doc_456", "folder_1"]}
Error handling
All helper methods raise PhilVaultHTTPError when the HTTP status is 4xx/5xx.
The exception includes status_code, message, and (when possible) the parsed
JSON response payload.
Example:
from philvault_sdk import PhilVaultClient
from philvault_sdk.errors import PhilVaultHTTPError
client = PhilVaultClient(base_url="http://localhost:8000", api_key="bad-key")
try:
client.me()
except PhilVaultHTTPError as exc:
print(exc.status_code) # 401
print(exc.payload) # {"detail": "Invalid API key"}
Common error responses for auth/ACL endpoints use FastAPI's default shape:
{"detail": "..."}. Typical status codes include 400, 401, 404, 409,
and 500 depending on the operation.
Notes
base_urlshould point to the PhilVault service root (no/api/v1suffix).- All
/api/v1/auth/*endpoints requireX-API-Key. - Endpoints that require authentication use
Authorization: Bearer <token>.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file philvault_sdk-0.2.0.tar.gz.
File metadata
- Download URL: philvault_sdk-0.2.0.tar.gz
- Upload date:
- Size: 12.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4f6b73823e6b10e6b5793b78f63406baee1c344afa50f2c7e40448ff8e0ea748
|
|
| MD5 |
353e0181bf101aa26ba4b78910327b97
|
|
| BLAKE2b-256 |
9cd7cef1256e9b56fbd757e9847cf2388b480a10914fcb63cea82d70a54a74c9
|
File details
Details for the file philvault_sdk-0.2.0-py3-none-any.whl.
File metadata
- Download URL: philvault_sdk-0.2.0-py3-none-any.whl
- Upload date:
- Size: 11.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a61a35c0d0ed569d827f9cd8ef46033fe67bff13024fa341c9e089afe50693de
|
|
| MD5 |
ea4c1f5ed37845a0f26e848a0a624157
|
|
| BLAKE2b-256 |
058e01379b88dfb481ad357d9d6125e1d329db9770439b88dfc0540c343735fb
|