-
Notifications
You must be signed in to change notification settings - Fork 122
feat: Google drive impersonator #733
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
Open
maxpill
wants to merge
34
commits into
develop
Choose a base branch
from
feat/gdrive-impersonator
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
da462ae
application/pdf export to mime map
pocucan-ds 5f6b8a6
impersonation feature for client.
pocucan-ds 38ffe8b
remove impersonation at class level and define it at instance level.
pocucan-ds 466fe37
updated tests
pocucan-ds 5dd7fe4
impersonation same loop
pocucan-ds 238f8fd
updated environment variables.
pocucan-ds 4524989
impersonation support changelog
pocucan-ds f3e5255
Merge branch 'main' into extension/source/googledrive/impersonator
pocucan-ds 6a65354
updated how to and formatted.
pocucan-ds 4041158
Merge branch 'extension/source/googledrive/impersonator' of https://g…
pocucan-ds 20df7d2
updated for ruff
pocucan-ds 54da82b
updated signature
pocucan-ds da272a8
Add impersonation attributes to GoogleDriveSource and update tests fo…
maxpill 7f095c1
Merge branch 'main' into feat/gdrive-impersonator
maxpill 55c3f34
Add GoogleDriveExportFormat enum and update MIME type handling in Goo…
maxpill 43e507d
feat: force tool calling support (#751)
GlockPL 5de31a6
Merge branch 'main' into feat/gdrive-impersonator
maxpill ca72a0f
Merge branch 'feat/gdrive-impersonator' of https://github.com/deepsen…
maxpill 9290b3e
feat: force tool calling support (#751)
GlockPL c5b3f73
feat: add PydanticAI agents support (#755)
akotyla 4e60aeb
feat: Autogenerate TS types (#727)
jakubduda-dsai f267d39
fix: prompt consumes same iterator twice (#768)
ds-sebastianchwilczynski 14b1e77
feat(ui): page title & favicon customization (#767)
dazy-ds d74a13b
feat(google_drive): enhance impersonation capabilities with class-lev…
maxpill d2d5537
Merge branch 'main' into feat/gdrive-impersonator
maxpill ac54d78
fix(google_drive): remove redundant comment in credentials file path
maxpill 84e4f7f
Merge branch 'feat/gdrive-impersonator' of https://github.com/deepsen…
maxpill 6309afc
feat(google_drive): add class method for default impersonation target
maxpill a7352a9
Merge branch 'develop' of https://github.com/deepsense-ai/ragbits int…
maxpill 04ad536
feat: Optional parallel batches execution in ragbits.evaluate.Evaluat…
vladimir-kivi-ds 6cfb38c
feat(auth): Backend authentication into the chat (#761)
GlockPL 67fbd71
feat(lazy-loading): Decreasing the time needed to start the app (#753)
GlockPL f7c920a
feat(ui): initial auth plugin (#763)
dazy-ds 6316196
Merge branch 'develop' into feat/gdrive-impersonator
GlockPL File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -187,6 +187,50 @@ async def process_drive_documents(): | |
asyncio.run(process_drive_documents()) | ||
``` | ||
|
||
## Impersonating Google Accounts | ||
|
||
You can configure your Google service account to impersonate other users in your Google Workspace domain. This is useful when you need to access files or perform actions on behalf of specific users. | ||
|
||
### Step 1: Enable Domain-Wide Delegation | ||
|
||
1. **Sign in to the [Google Admin Console](https://admin.google.com/) as a Super Admin.** | ||
2. Navigate to: | ||
**Security > Access and data control > API controls > MANAGE DOMAIN WIDE DELEGATION** | ||
3. Add a new API client or edit an existing one, and include the following OAuth scopes: | ||
- `https://www.googleapis.com/auth/cloud-platform` | ||
- `https://www.googleapis.com/auth/drive` | ||
4. Click **Authorize** or **Save** to apply the changes. | ||
|
||
### Step 2: Impersonate a User in Your Code | ||
|
||
After configuring domain-wide delegation, you can specify a target user to impersonate when using the `GoogleDriveSource` in your code. | ||
|
||
```python | ||
from ragbits.core.sources.google_drive import GoogleDriveSource | ||
|
||
target_email = "[email protected]" | ||
credentials_file = "service-account-key.json" | ||
|
||
# Set the path to your service account key file | ||
GoogleDriveSource.set_credentials_file_path(credentials_file) | ||
|
||
# Option 1: Set default impersonation for all instances (class-level) | ||
GoogleDriveSource.set_default_impersonation_target(target_email) | ||
|
||
# Option 2: Set impersonation for specific instances | ||
sources = await GoogleDriveSource.from_uri("folder_id/**", impersonate_target_email=target_email) | ||
|
||
# Option 3: Set impersonation on individual instances | ||
source = GoogleDriveSource(file_id="...", file_name="...", mime_type="...") | ||
source.set_impersonation_target(target_email) | ||
``` | ||
|
||
**Note:** | ||
- The `target_email` must be a valid user in your Google Workspace domain. | ||
- Ensure your service account has been granted domain-wide delegation as described above. | ||
|
||
This setup allows your service account to act on behalf of the specified user, enabling access to their Google Drive files and resources as permitted by the assigned scopes. | ||
|
||
## Troubleshooting | ||
|
||
### Common Issues | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
# Authenticated Chat Example | ||
|
||
This example demonstrates how to create a chat interface with user authentication using Ragbits Chat. | ||
|
||
## Features | ||
|
||
- 🔐 **User Authentication**: Login/logout with username/password | ||
- 👤 **Role-based Access**: Different user roles (admin, moderator, user) with specific capabilities | ||
- 🛡️ **Secure Sessions**: Session-based authentication with Bearer tokens | ||
- 📊 **Personalized Responses**: User-specific chat responses based on profile and roles | ||
- 🔄 **Live Updates**: Role-specific live updates during processing | ||
- 📚 **User Context**: Reference documents with user profile information | ||
- 🎨 **UI Customization**: Custom welcome messages, headers, and branding | ||
- 📝 **Feedback System**: Like/dislike forms with custom Pydantic models | ||
- ⚙️ **User Settings**: Configurable user preferences (e.g., language selection) | ||
|
||
## Files | ||
|
||
- `authenticated_chat.py` - Main authenticated chat implementation | ||
- `README_authenticated.md` - This documentation | ||
|
||
## Quick Start | ||
|
||
### 1. Start the Server | ||
|
||
#### Full Authentication Support (Recommended) | ||
```bash | ||
# From the examples/chat directory - includes login/logout endpoints | ||
uv run python authenticated_chat.py | ||
``` | ||
|
||
#### Alternative Methods | ||
```bash | ||
# From project root | ||
python examples/chat/authenticated_chat.py | ||
|
||
# Via CLI with authentication support | ||
uv run ragbits api run examples.chat.authenticated_chat:MyAuthenticatedChat --auth examples.chat.authenticated_chat:get_auth_backend | ||
``` | ||
|
||
The server will start at `http://127.0.0.1:8000` with a web interface. | ||
|
||
**Note**: When using the CLI, include the `--auth` flag with the authentication backend factory function to enable full authentication features including login/logout endpoints. | ||
|
||
### 2. Test Users | ||
|
||
The example includes these test users: | ||
|
||
| Username | Password | Roles | Description | | ||
|-----------|-----------|--------------------------|---------------------| | ||
| `admin` | `admin123` | admin, moderator, user | System administrator | | ||
| `moderator` | `mod123` | moderator, user | Community moderator | | ||
| `alice` | `alice123` | user | Regular user | | ||
| `bob` | `bob123` | user | Regular user | | ||
|
||
### 3. Authentication Workflow | ||
|
||
#### Web Interface | ||
1. Open `http://127.0.0.1:8000` in your browser | ||
2. Use the login form with any test user credentials | ||
3. Start chatting after successful authentication | ||
|
||
#### API Endpoints | ||
1. **Login**: `POST /api/auth/login` | ||
```json | ||
{ | ||
"username": "admin", | ||
"password": "admin123" | ||
} | ||
``` | ||
|
||
2. **Chat**: `POST /api/chat` (with Bearer token) | ||
```bash | ||
Authorization: Bearer <session_id> | ||
``` | ||
|
||
3. **Logout**: `POST /api/auth/logout` | ||
```json | ||
{ | ||
"session_id": "<session_id>" | ||
} | ||
``` | ||
|
||
## Testing | ||
|
||
You can test the authentication functionality using: | ||
|
||
### Web Interface Testing | ||
1. Start the server: `python examples/chat/authenticated_chat.py` | ||
2. Open `http://127.0.0.1:8000` in your browser | ||
3. Use the login form with any of the test user credentials | ||
4. Test different roles and their specific features | ||
|
||
### API Testing with curl | ||
```bash | ||
# Login | ||
curl -X POST http://127.0.0.1:8000/api/auth/login \ | ||
-H "Content-Type: application/json" \ | ||
-d '{"username": "admin", "password": "admin123"}' | ||
|
||
# Chat (replace <session_id> with the session_id from login response) | ||
curl -X POST http://127.0.0.1:8000/api/chat \ | ||
-H "Content-Type: application/json" \ | ||
-H "Authorization: Bearer <session_id>" \ | ||
-d '{"message": "Hello!"}' | ||
|
||
# Logout | ||
curl -X POST http://127.0.0.1:8000/api/auth/logout \ | ||
-H "Content-Type: application/json" \ | ||
-d '{"session_id": "<session_id>"}' | ||
``` | ||
|
||
## Example Chat Interactions | ||
|
||
### As Admin User | ||
``` | ||
💬 You: What admin features are available? | ||
🤖 Bot: As an administrator, you have full system access including: | ||
- User management and permissions | ||
- System configuration and monitoring | ||
- Content moderation capabilities | ||
- Administrative dashboards and reports | ||
``` | ||
|
||
### As Regular User | ||
``` | ||
💬 You: Tell me about my profile | ||
🤖 Bot: Hello Alice Johnson! You're logged in as 'alice' with user role. | ||
Your profile shows you're part of the Marketing department. | ||
``` | ||
|
||
## Architecture | ||
### ListAuthBackend | ||
- In-memory user storage with hashed passwords | ||
- Session management with expiration | ||
- User roles and metadata support | ||
- Suitable for development and small deployments | ||
|
||
### Role-based Features | ||
- **Admin**: Full system access, admin-specific live updates, special admin profile images | ||
- **Moderator**: Content moderation features with policy checks and content guidelines | ||
- **User**: Standard chat features with personalized responses and user-specific context | ||
|
||
## Customization | ||
|
||
### Adding New Users | ||
Edit the `get_auth_backend()` factory function in `authenticated_chat.py`: | ||
|
||
```python | ||
users = [ | ||
{ | ||
"username": "newuser", | ||
"password": "newpass123", | ||
"email": "[email protected]", | ||
"full_name": "New User", | ||
"roles": ["user"], | ||
"metadata": {"department": "Engineering"} | ||
} | ||
] | ||
``` | ||
|
||
|
||
### Role-specific Responses | ||
Modify the `chat()` method to customize responses based on user roles: | ||
|
||
```python | ||
# Get user info from context | ||
user_info = context.state.get("authenticated_user") if context else None | ||
user_roles = user_info.roles if user_info else [] | ||
|
||
if "admin" in user_roles: | ||
yield self.create_text_response("🔧 Admin-specific content...") | ||
elif "moderator" in user_roles: | ||
yield self.create_text_response("🛡️ Moderator-specific content...") | ||
``` | ||
|
||
### UI Customization | ||
|
||
The example demonstrates UI customization features: | ||
|
||
```python | ||
from ragbits.chat.interface.ui_customization import HeaderCustomization, UICustomization | ||
|
||
ui_customization = UICustomization( | ||
header=HeaderCustomization( | ||
title="🔐 Authenticated Ragbits Chat", | ||
subtitle="by deepsense.ai - Secure Chat Experience", | ||
logo="🛡️" | ||
), | ||
welcome_message="🔐 **Welcome to Authenticated Ragbits Chat!**\n\n..." | ||
) | ||
``` | ||
|
||
### Feedback Configuration | ||
|
||
Custom feedback forms using Pydantic models: | ||
|
||
```python | ||
from ragbits.chat.interface.forms import FeedbackConfig | ||
|
||
feedback_config = FeedbackConfig( | ||
like_enabled=True, | ||
like_form=LikeFormExample, # Custom Pydantic model | ||
dislike_enabled=True, | ||
dislike_form=DislikeFormExample, # Custom Pydantic model | ||
) | ||
``` | ||
|
||
## Security Notes | ||
|
||
- Passwords are hashed using bcrypt in `ListAuthBackend` | ||
- Sessions have configurable expiration times | ||
- Bearer tokens are used for API authentication | ||
- CORS is configured for web interface access | ||
- State signatures prevent tampering with conversation state |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
I'd put link to the part about creating this credential_file here.
This how-to is very long and I believe someone may forgot what this credential file is all about long ago. Or if they come directly to this place, they're cooked