Add Google Calendar integration via Supabase Edge Functions
- Create new create-google-meet-event edge function - Use service account authentication (no OAuth needed) - Add google_service_account_json field to platform_settings - Add admin UI for service account JSON configuration - Include test connection button in Integrasi tab - Add comprehensive setup documentation - Keep n8n workflows as alternative option Features: - Direct Google Calendar API integration - JWT authentication with service account - Auto-create Google Meet links - No external dependencies needed - Simple configuration via admin panel 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
187
n8n-workflows/README.md
Normal file
187
n8n-workflows/README.md
Normal file
@@ -0,0 +1,187 @@
|
||||
# n8n Workflows for Access Hub
|
||||
|
||||
## Workflows
|
||||
|
||||
### 1. Create Google Meet Event (Simple)
|
||||
**File:** `create-google-meet-event.json`
|
||||
|
||||
A simple 3-node workflow that:
|
||||
1. Receives webhook POST from Supabase Edge Function
|
||||
2. Creates event in Google Calendar using Google Calendar node
|
||||
3. Returns the meet link
|
||||
|
||||
**Best for:** Quick setup with minimal configuration
|
||||
|
||||
---
|
||||
|
||||
### 2. Create Google Meet Event (Advanced)
|
||||
**File:** `create-google-meet-event-advanced.json`
|
||||
|
||||
An advanced workflow with more control:
|
||||
1. Receives webhook POST from Supabase Edge Function
|
||||
2. Prepares event data with Code node (custom formatting)
|
||||
3. Creates event using Google Calendar API directly
|
||||
4. Returns the meet link
|
||||
|
||||
**Best for:** More customization, error handling, and control
|
||||
|
||||
---
|
||||
|
||||
## Import Instructions
|
||||
|
||||
### Option 1: Import from File
|
||||
1. In n8n, click **+ Import from File**
|
||||
2. Select the JSON file
|
||||
3. Click **Import**
|
||||
|
||||
### Option 2: Copy-Paste
|
||||
1. In n8n, click **+ New Workflow**
|
||||
2. Click **...** (menu) → **Import from URL**
|
||||
3. Paste the JSON content
|
||||
4. Click **Import**
|
||||
|
||||
---
|
||||
|
||||
## Setup Instructions
|
||||
|
||||
### 1. Configure Webhook
|
||||
- **Path**: `create-meet` (already set)
|
||||
- **Method**: POST
|
||||
- **Production URL**: Will be auto-generated when you activate the workflow
|
||||
|
||||
### 2. Configure Google Calendar Credentials
|
||||
|
||||
#### For Simple Workflow:
|
||||
1. Click on the **Google Calendar** node
|
||||
2. Click **Create New Credential**
|
||||
3. Select **Service Account** authentication
|
||||
4. Paste the entire JSON content from your service account file
|
||||
5. Give it a name: "Google Calendar (Service Account)"
|
||||
6. Click **Create**
|
||||
|
||||
#### For Advanced Workflow:
|
||||
1. Click on the **Google Calendar API** node
|
||||
2. Click **Create New Credential**
|
||||
3. Select **Service Account** authentication for Google API
|
||||
4. Paste the service account JSON
|
||||
5. Give it a name: "Google Calendar API (Service Account)"
|
||||
6. Click **Create**
|
||||
|
||||
### 3. Activate Workflow
|
||||
1. Click **Active** toggle in top right
|
||||
2. n8n will generate your webhook URL
|
||||
3. Your webhook URL will be: `https://api.backoffice.biz.id/webhook-test/create-meet`
|
||||
|
||||
---
|
||||
|
||||
## Test the Workflow
|
||||
|
||||
### Manual Test with Curl:
|
||||
```bash
|
||||
curl -X POST https://api.backoffice.biz.id/webhook-test/create-meet \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"slot_id": "test-123",
|
||||
"date": "2025-12-25",
|
||||
"start_time": "14:00:00",
|
||||
"end_time": "15:00:00",
|
||||
"client_name": "Test Client",
|
||||
"client_email": "test@example.com",
|
||||
"topic": "Test Topic",
|
||||
"notes": "Test notes",
|
||||
"calendar_id": "your-email@gmail.com",
|
||||
"brand_name": "Your Brand",
|
||||
"test_mode": true
|
||||
}'
|
||||
```
|
||||
|
||||
### Expected Response:
|
||||
```json
|
||||
{
|
||||
"meet_link": "https://meet.google.com/abc-defg-hij",
|
||||
"event_id": "event-id-from-google-calendar",
|
||||
"html_link": "https://www.google.com/calendar/event?eid=..."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Workflow Variables
|
||||
|
||||
The webhook receives these fields from your Supabase Edge Function:
|
||||
|
||||
| Field | Description | Example |
|
||||
|-------|-------------|---------|
|
||||
| `slot_id` | Unique slot identifier | `uuid-here` |
|
||||
| `date` | Event date (YYYY-MM-DD) | `2025-12-25` |
|
||||
| `start_time` | Start time (HH:MM:SS) | `14:00:00` |
|
||||
| `end_time` | End time (HH:MM:SS) | `15:00:00` |
|
||||
| `client_name` | Client's full name | `John Doe` |
|
||||
| `client_email` | Client's email | `john@example.com` |
|
||||
| `topic` | Consultation topic | `Business Consulting` |
|
||||
| `notes` | Additional notes | `Discuss project roadmap` |
|
||||
| `calendar_id` | Google Calendar ID | `your-email@gmail.com` |
|
||||
| `brand_name` | Your brand name | `Access Hub` |
|
||||
| `test_mode` | Test mode flag | `true` |
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Error: 403 Forbidden
|
||||
- Make sure calendar is shared with service account email
|
||||
- Service account email format: `xxx@project-id.iam.gserviceaccount.com`
|
||||
- Calendar permissions: "Make changes to events"
|
||||
|
||||
### Error: 401 Unauthorized
|
||||
- Check service account JSON is correct
|
||||
- Verify Calendar API is enabled in Google Cloud Console
|
||||
|
||||
### Error: 400 Invalid
|
||||
- Check date format (YYYY-MM-DD)
|
||||
- Check time format (HH:MM:SS)
|
||||
- Verify calendar ID is correct
|
||||
|
||||
### Webhook not triggering
|
||||
- Make sure workflow is **Active**
|
||||
- Check webhook URL matches: `/webhook-test/create-meet`
|
||||
- Verify webhook method is **POST** not GET
|
||||
|
||||
---
|
||||
|
||||
## Calendar ID
|
||||
|
||||
To find your Calendar ID:
|
||||
1. Go to Google Calendar Settings
|
||||
2. Scroll to **Integrate calendar**
|
||||
3. Copy the **Calendar ID**
|
||||
4. For primary calendar: your Gmail address
|
||||
|
||||
---
|
||||
|
||||
## Production vs Test
|
||||
|
||||
- **Test Mode**: Uses `/webhook-test/` path
|
||||
- **Production**: Uses `/webhook/` path
|
||||
- Toggle in Admin Settings → Integrasi → Mode Test n8n
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Import workflow JSON
|
||||
2. Set up Google Calendar credentials with service account
|
||||
3. Activate workflow
|
||||
4. Test with curl command above
|
||||
5. Check your Google Calendar for the event
|
||||
6. Verify meet link is returned
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
If you need help:
|
||||
- Check n8n workflow execution logs
|
||||
- Check Google Calendar API logs
|
||||
- Verify service account permissions
|
||||
- Check calendar sharing settings
|
||||
127
n8n-workflows/create-google-meet-event-advanced.json
Normal file
127
n8n-workflows/create-google-meet-event-advanced.json
Normal file
@@ -0,0 +1,127 @@
|
||||
{
|
||||
"name": "Create Google Meet Event - Access Hub (Advanced)",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"httpMethod": "POST",
|
||||
"path": "create-meet",
|
||||
"responseMode": "responseNode",
|
||||
"options": {}
|
||||
},
|
||||
"id": "webhook-trigger",
|
||||
"name": "Webhook",
|
||||
"type": "n8n-nodes-base.webhook",
|
||||
"typeVersion": 1.1,
|
||||
"position": [250, 300],
|
||||
"webhookId": "create-meet-webhook"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const items = $input.all();\nconst data = items[0].json;\n\n// Parse date and time\nconst startDate = new Date(`${data.date}T${data.start_time}`);\nconst endDate = new Date(`${data.date}T${data.end_time}`);\n\n// Format for Google Calendar API (ISO 8601 with timezone)\nconst startTime = startDate.toISOString();\nconst endTime = endDate.toISOString();\n\n// Build event data\nconst eventData = {\n calendarId: data.calendar_id,\n summary: `Konsultasi: ${data.topic} - ${data.client_name}`,\n description: `Client: ${data.client_email}\\n\\nNotes: ${data.notes || '-'}\\n\\nSlot ID: ${data.slot_id}\\nBrand: ${data.brand_name || 'Access Hub'}`,\n start: {\n dateTime: startTime,\n timeZone: 'Asia/Jakarta'\n },\n end: {\n dateTime: endTime,\n timeZone: 'Asia/Jakarta'\n },\n attendees: [\n { email: data.client_email }\n ],\n conferenceData: {\n createRequest: {\n requestId: data.slot_id,\n conferenceSolutionKey: { type: 'hangoutsMeet' }\n }\n },\n sendUpdates: 'all',\n guestsCanInviteOthers: false,\n guestsCanModify: false,\n guestsCanSeeOtherGuests: false\n};\n\nreturn [{ json: eventData }];"
|
||||
},
|
||||
"id": "prepare-event-data",
|
||||
"name": "Prepare Event Data",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [470, 300]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"authentication": "serviceAccount",
|
||||
"resource": "calendar",
|
||||
"operation": "insert",
|
||||
"calendarId": "={{ $json.calendarId }}",
|
||||
"body": "={{ { summary: $json.summary, description: $json.description, start: $json.start, end: $json.end, attendees: $json.attendees, conferenceData: $json.conferenceData, sendUpdates: $json.sendUpdates, guestsCanInviteOthers: $json.guestsCanInviteOthers, guestsCanModify: $json.guestsCanModify, guestsCanSeeOtherGuests: $json.guestsCanSeeOtherGuests } }}",
|
||||
"options": {
|
||||
"conferenceDataVersion": 1
|
||||
}
|
||||
},
|
||||
"id": "google-calendar-api",
|
||||
"name": "Google Calendar API",
|
||||
"type": "n8n-nodes-base.googleApi",
|
||||
"typeVersion": 1,
|
||||
"position": [690, 300],
|
||||
"credentials": {
|
||||
"googleApi": {
|
||||
"id": "REPLACE_WITH_YOUR_CREDENTIAL_ID",
|
||||
"name": "Google Calendar API (Service Account)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"respondWith": "json",
|
||||
"responseBody": "={{ { \"meet_link\": $json.hangoutLink, \"event_id\": $json.id, \"html_link\": $json.htmlLink } }}"
|
||||
},
|
||||
"id": "respond-to-webhook",
|
||||
"name": "Respond to Webhook",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"typeVersion": 1.1,
|
||||
"position": [910, 300]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{
|
||||
"id": "error-handler",
|
||||
"name": "error",
|
||||
"value": "={{ $json.error?.message || 'Unknown error' }}",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"id": "error-handler",
|
||||
"name": "Error Handler",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 3.4,
|
||||
"position": [910, 480]
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
"Webhook": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Prepare Event Data",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Prepare Event Data": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Google Calendar API",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Google Calendar API": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Respond to Webhook",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"pinData": {},
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"staticData": null,
|
||||
"tags": ["access-hub", "calendar", "meet"],
|
||||
"triggerCount": 1,
|
||||
"updatedAt": "2025-12-23T00:00:00.000Z",
|
||||
"versionId": "1"
|
||||
}
|
||||
89
n8n-workflows/create-google-meet-event.json
Normal file
89
n8n-workflows/create-google-meet-event.json
Normal file
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"name": "Create Google Meet Event - Access Hub",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"httpMethod": "POST",
|
||||
"path": "create-meet",
|
||||
"responseMode": "responseNode",
|
||||
"options": {}
|
||||
},
|
||||
"id": "webhook-trigger",
|
||||
"name": "Webhook",
|
||||
"type": "n8n-nodes-base.webhook",
|
||||
"typeVersion": 1.1,
|
||||
"position": [250, 300],
|
||||
"webhookId": "create-meet-webhook"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"operation": "create",
|
||||
"calendarId": "={{ $json.calendar_id }}",
|
||||
"title": "=Konsultasi: {{ $json.topic }} - {{ $json.client_name }}",
|
||||
"description": "=Client: {{ $json.client_email }}\n\nNotes: {{ $json.notes }}\n\nSlot ID: {{ $json.slot_id }}",
|
||||
"location": "Google Meet",
|
||||
"attendees": "={{ $json.client_email }}",
|
||||
"startsAt": "={{ $json.date }}T{{ $json.start_time }}",
|
||||
"endsAt": "={{ $json.date }}T{{ $json.end_time }}",
|
||||
"sendUpdates": "all",
|
||||
"conferenceDataVersion": 1,
|
||||
"options": {}
|
||||
},
|
||||
"id": "google-calendar",
|
||||
"name": "Google Calendar",
|
||||
"type": "n8n-nodes-base.googleCalendar",
|
||||
"typeVersion": 2,
|
||||
"position": [470, 300],
|
||||
"credentials": {
|
||||
"googleCalendarApi": {
|
||||
"id": "REPLACE_WITH_YOUR_CREDENTIAL_ID",
|
||||
"name": "Google Calendar account (Service Account)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"respondWith": "json",
|
||||
"responseBody": "={{ { \"meet_link\": $json.hangoutLink, \"event_id\": $json.id, \"html_link\": $json.htmlLink } }}"
|
||||
},
|
||||
"id": "respond-to-webhook",
|
||||
"name": "Respond to Webhook",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"typeVersion": 1.1,
|
||||
"position": [690, 300]
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
"Webhook": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Google Calendar",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Google Calendar": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Respond to Webhook",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"pinData": {},
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"staticData": null,
|
||||
"tags": [],
|
||||
"triggerCount": 1,
|
||||
"updatedAt": "2025-12-23T00:00:00.000Z",
|
||||
"versionId": "1"
|
||||
}
|
||||
Reference in New Issue
Block a user