Skip to content

Commit 80eafab

Browse files
committed
2 parents aac8215 + b62d52d commit 80eafab

File tree

8 files changed

+606
-115
lines changed

8 files changed

+606
-115
lines changed

.claude/settings.local.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,16 @@
3535
"Bash(gcloud run services describe:*)",
3636
"Bash(gcloud builds list:*)",
3737
"Bash(chmod:*)",
38-
"Bash(gcloud logging read:*)"
38+
"Bash(gcloud logging read:*)",
39+
"Bash(./deploy.sh:*)",
40+
"Bash(echo:*)",
41+
"Bash(gcloud run services update:*)",
42+
"Bash(gcloud logging tail:*)",
43+
"Bash(gcloud builds submit:*)",
44+
"Bash(tee:*)",
45+
"Bash(gcloud run deploy:*)",
46+
"Bash(tr:*)",
47+
"Bash(gcloud iam service-accounts describe:*)"
3948
],
4049
"deny": [],
4150
"ask": []

DOMAIN_WIDE_DELEGATION_SETUP.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# Domain-Wide Delegation Setup for Google Chat Notifications
2+
3+
This guide explains how to enable **domain-wide delegation** so the Employee Portal can send proactive Google Chat messages to users (like Google Drive does).
4+
5+
## Why Domain-Wide Delegation?
6+
7+
Google Chat bots with service accounts cannot proactively send DM messages **UNLESS** they use domain-wide delegation to impersonate users. This is how Google Workspace apps like Drive, Calendar, etc. send you notifications.
8+
9+
## Prerequisites
10+
11+
- Google Workspace Admin access
12+
- Service account: `employee-portal-runtime@edvolution-admon.iam.gserviceaccount.com`
13+
- OAuth Client ID: `115131457162383560161`
14+
15+
---
16+
17+
## Step 1: Enable Domain-Wide Delegation on Service Account
18+
19+
1. Go to [Google Cloud Console - IAM & Admin - Service Accounts](https://console.cloud.google.com/iam-admin/serviceaccounts?project=edvolution-admon)
20+
21+
2. Find service account: `employee-portal-runtime@edvolution-admon.iam.gserviceaccount.com`
22+
23+
3. Click on the service account
24+
25+
4. Go to **"Advanced Settings"** section
26+
27+
5. Click **"Enable Google Workspace Domain-wide Delegation"**
28+
29+
6. Save the OAuth2 Client ID: `115131457162383560161`
30+
31+
---
32+
33+
## Step 2: Authorize API Scopes in Google Workspace Admin Console
34+
35+
1. Go to [Google Workspace Admin Console](https://admin.google.com)
36+
37+
2. Navigate to: **Security****Access and data control****API Controls**
38+
39+
3. Click **"Manage Domain Wide Delegation"**
40+
41+
4. Click **"Add new"**
42+
43+
5. Enter the Client ID: `115131457162383560161`
44+
45+
6. Add the following OAuth Scopes (comma-separated):
46+
```
47+
https://www.googleapis.com/auth/chat.messages,https://www.googleapis.com/auth/chat.spaces
48+
```
49+
50+
7. Click **"Authorize"**
51+
52+
---
53+
54+
## Step 3: Verify Configuration
55+
56+
Run this test to verify domain-wide delegation works:
57+
58+
```bash
59+
python3 << 'EOF'
60+
from google.oauth2 import service_account
61+
from googleapiclient.discovery import build
62+
63+
# This should be your service account credentials
64+
SCOPES = [
65+
'https://www.googleapis.com/auth/chat.messages',
66+
'https://www.googleapis.com/auth/chat.spaces'
67+
]
68+
69+
# Test impersonation
70+
USER_EMAIL = 'dirk@edvolution.io'
71+
72+
try:
73+
from google.auth import default
74+
credentials, project = default(scopes=SCOPES)
75+
76+
if hasattr(credentials, 'with_subject'):
77+
delegated_creds = credentials.with_subject(USER_EMAIL)
78+
chat = build('chat', 'v1', credentials=delegated_creds)
79+
print(f"✅ Domain-wide delegation is configured correctly!")
80+
print(f" Service can impersonate: {USER_EMAIL}")
81+
else:
82+
print("❌ Credentials do not support domain-wide delegation")
83+
print(" Make sure you're using a service account with delegation enabled")
84+
except Exception as e:
85+
print(f"❌ Error: {e}")
86+
print(" Domain-wide delegation may not be set up correctly")
87+
EOF
88+
```
89+
90+
---
91+
92+
## Step 4: Update Application Code (Already Done)
93+
94+
The code has been updated to support domain-wide delegation:
95+
- `NotificationService._get_chat_service(impersonate_user=email)` now supports impersonation
96+
- `send_approval_chat_card()` will use delegation when available
97+
98+
---
99+
100+
## Step 5: Test Proactive Notifications
101+
102+
After completing setup, test by creating a time-off request:
103+
104+
1. Log into the Employee Portal
105+
2. Create a time-off request
106+
3. The manager should receive:
107+
- ✅ Email notification (works now)
108+
- ✅ Google Chat DM (will work after domain-wide delegation)
109+
110+
Check logs:
111+
```bash
112+
gcloud logging read 'resource.type=cloud_run_revision AND resource.labels.service_name=employee-portal AND textPayload=~"domain-wide delegation"' --limit 10 --format="table(timestamp,textPayload)" --freshness=1h
113+
```
114+
115+
---
116+
117+
## Security Considerations
118+
119+
**Domain-wide delegation is powerful** - it allows the service account to act as any user in your domain.
120+
121+
**Best practices:**
122+
1. ✅ Only grant minimum required scopes (`chat.messages`, `chat.spaces`)
123+
2. ✅ Limit to one service account
124+
3. ✅ Monitor usage via Cloud Logging
125+
4. ✅ Document who has access
126+
5. ✅ Review periodically
127+
128+
**What the service can do:**
129+
- ✅ Send Chat messages on behalf of users
130+
- ✅ Create spaces on behalf of users
131+
- ❌ Cannot read messages (we didn't request that scope)
132+
- ❌ Cannot access other Google Workspace data (Drive, Gmail, etc.)
133+
134+
---
135+
136+
## Troubleshooting
137+
138+
### Error: "Request had insufficient authentication scopes"
139+
- Make sure you authorized the scopes in Admin Console (Step 2)
140+
- Wait 10-15 minutes for changes to propagate
141+
142+
### Error: "Domain-wide delegation is not enabled"
143+
- Complete Step 1 to enable delegation on the service account
144+
- Redeploy the application
145+
146+
### Still not working?
147+
1. Check Admin Console → Security → API Controls → Domain-wide delegation
148+
2. Verify Client ID matches: `115131457162383560161`
149+
3. Verify scopes are exactly: `https://www.googleapis.com/auth/chat.messages,https://www.googleapis.com/auth/chat.spaces`
150+
4. Check Cloud Run service account is `employee-portal-runtime@edvolution-admon.iam.gserviceaccount.com`
151+
152+
---
153+
154+
## Alternative: Chat Space Instead of DMs
155+
156+
If you prefer not to use domain-wide delegation, you can:
157+
158+
1. **Create a Chat Space** (e.g., "HR Approvals")
159+
2. **Add all managers/admins** to the space
160+
3. **Add the bot** to the space
161+
4. **Send notifications to the space** instead of DMs
162+
163+
This way:
164+
- ✅ No domain-wide delegation needed
165+
- ✅ All approvers see all requests
166+
- ✅ Transparent approval process
167+
- ❌ Less private (everyone sees everyone's requests)
168+
169+
---
170+
171+
## Resources
172+
173+
- [Domain-Wide Delegation Guide](https://developers.google.com/identity/protocols/oauth2/service-account#delegatingauthority)
174+
- [Google Chat API - User Authentication](https://developers.google.com/workspace/chat/authenticate-authorize-chat-user)
175+
- [OAuth 2.0 Scopes for Google APIs](https://developers.google.com/identity/protocols/oauth2/scopes#chat)

FRD.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1551,7 +1551,7 @@ Each audit log must include:
15511551
| GOOGLE_API_KEY | No | Gemini AI API key | AIza... |
15521552
| WORKSPACE_DOMAIN | Yes | Google Workspace domain | company.com |
15531553
| WORKSPACE_ADMIN_EMAIL | Yes | Workspace admin email | admin@company.com |
1554-
| ADMIN_USERS | Yes | Comma-separated admin emails | admin@company.com,hr@company.com |
1554+
| ADMIN_USERS | Yes | Comma-separated admin emails | dirk@edvolution.io,mgonzalez@edvolution.io,gabriela@edvolution.io |
15551555
| FLASK_SECRET_KEY | Yes | Flask session secret | random-secret-key-here |
15561556
| FLASK_ENV | No | Environment (production/development) | production |
15571557
| ENABLE_CHAT_NOTIFICATIONS | No | Enable Google Chat notifications | true |

GOOGLE_CHAT_SETUP.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,69 @@ Add these scopes to your Google OAuth consent screen:
331331
- Check Chat API is enabled
332332
- Ensure proper OAuth scopes are granted
333333

334+
### Approval notifications not received
335+
336+
**IMPORTANT LIMITATION:** Google Chat bots using service account authentication **cannot proactively send DM messages** to users. This is a Google Chat API restriction.
337+
338+
**What this means:**
339+
- ❌ The bot cannot send approval cards automatically when requests are created
340+
- ✅ The bot CAN respond to commands like `pending`, `help`, `status`
341+
- ✅ Users will receive **email notifications** for approvals
342+
- ✅ Users can check pending approvals by messaging the bot with `pending`
343+
344+
**Recommended workflow:**
345+
1. Employee creates time-off request
346+
2. Manager receives **email notification**
347+
3. Manager can either:
348+
- Approve via web portal
349+
- Message the bot with `pending` to see all pending approvals
350+
- Click email link to go directly to the request
351+
352+
If you still want to troubleshoot Chat functionality:
353+
354+
1. **Check if Chat notifications are enabled:**
355+
```bash
356+
# In .env file
357+
ENABLE_CHAT_NOTIFICATIONS=true
358+
```
359+
360+
2. **Verify the bot has been added to a DM with the user:**
361+
- Open Google Chat
362+
- Search for "Employee Portal Approvals" (or your bot name)
363+
- Start a conversation with the bot
364+
- Send "help" to verify it responds
365+
366+
3. **Check Application Default Credentials:**
367+
The bot uses ADC (Application Default Credentials) to send messages, not user OAuth credentials.
368+
369+
For Cloud Run (production):
370+
- The service account is automatically used
371+
- No additional configuration needed
372+
373+
For local development:
374+
- Install gcloud CLI
375+
- Run: `gcloud auth application-default login`
376+
- This creates local ADC credentials
377+
378+
4. **Test the notification system:**
379+
```bash
380+
python3 test_chat_notification.py
381+
```
382+
Enter your email when prompted to test if messages are delivered.
383+
384+
5. **Check Cloud Run logs:**
385+
```bash
386+
gcloud logging read "resource.type=cloud_run_revision AND resource.labels.service_name=employee-portal" --limit 50 --format=json
387+
```
388+
Look for errors like:
389+
- "Failed to send approval card"
390+
- "Could not find existing DM space"
391+
- "Failed to create DM space"
392+
393+
6. **Verify the bot can create DM spaces:**
394+
The bot must have the `chat.bot` scope to create DM spaces and send messages.
395+
This is configured automatically when using Application Default Credentials.
396+
334397
## Next Steps
335398

336399
1. ✅ Implement Google Chat API client in NotificationService

0 commit comments

Comments
 (0)