mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
Fix issue with credential selector, remove bigquery and ad support
This commit is contained in:
@@ -10,6 +10,8 @@ import { FAQ } from '@/components/ui/faq'
|
||||
|
||||
Google service accounts with domain-wide delegation let your workflows access Google APIs on behalf of users in your Google Workspace domain — without requiring each user to complete an OAuth consent flow. This is ideal for automated workflows that need to send emails, read spreadsheets, or manage files across your organization.
|
||||
|
||||
For example, you could build a workflow that iterates through a list of employees, impersonates each one to read their Google Docs, and uploads the contents to a shared knowledge base — all without requiring any of those users to sign in.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before adding a service account to Sim, you need to configure it in the Google Cloud Console and Google Workspace Admin Console.
|
||||
@@ -120,13 +122,11 @@ The table below lists every Google service that supports service account authent
|
||||
<tr><td>Google Forms</td><td>Google Forms API, Google Drive API</td><td><code>{'https://www.googleapis.com/auth/drive'}</code><br/><code>{'https://www.googleapis.com/auth/forms.body'}</code><br/><code>{'https://www.googleapis.com/auth/forms.responses.readonly'}</code></td></tr>
|
||||
<tr><td>Google Calendar</td><td>Google Calendar API</td><td><code>{'https://www.googleapis.com/auth/calendar'}</code></td></tr>
|
||||
<tr><td>Google Contacts</td><td>People API</td><td><code>{'https://www.googleapis.com/auth/contacts'}</code></td></tr>
|
||||
<tr><td>Google Ads</td><td>Google Ads API</td><td><code>{'https://www.googleapis.com/auth/adwords'}</code></td></tr>
|
||||
<tr><td>BigQuery</td><td>BigQuery API</td><td><code>{'https://www.googleapis.com/auth/bigquery'}</code></td></tr>
|
||||
<tr><td>Google Tasks</td><td>Tasks API</td><td><code>{'https://www.googleapis.com/auth/tasks'}</code></td></tr>
|
||||
<tr><td>Google Vault</td><td>Vault API, Cloud Storage API</td><td><code>{'https://www.googleapis.com/auth/ediscovery'}</code><br/><code>{'https://www.googleapis.com/auth/devstorage.read_only'}</code></td></tr>
|
||||
<tr><td>Google Groups</td><td>Admin SDK API</td><td><code>{'https://www.googleapis.com/auth/admin.directory.group'}</code><br/><code>{'https://www.googleapis.com/auth/admin.directory.group.member'}</code></td></tr>
|
||||
<tr><td>Google Meet</td><td>Google Meet API</td><td><code>{'https://www.googleapis.com/auth/meetings.space.created'}</code><br/><code>{'https://www.googleapis.com/auth/meetings.space.readonly'}</code></td></tr>
|
||||
<tr><td>Vertex AI</td><td>Vertex AI API</td><td><code>{'https://www.googleapis.com/auth/cloud-platform'}</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ function toCredentialResponse(
|
||||
displayName: string,
|
||||
providerId: string,
|
||||
updatedAt: Date,
|
||||
scope: string | null
|
||||
scope: string | null,
|
||||
credentialType: 'oauth' | 'service_account' = 'oauth'
|
||||
) {
|
||||
const storedScope = scope?.trim()
|
||||
// Some providers (e.g. Box) don't return scopes in their token response,
|
||||
@@ -55,6 +56,7 @@ function toCredentialResponse(
|
||||
id,
|
||||
name: displayName,
|
||||
provider: providerId,
|
||||
type: credentialType,
|
||||
lastUsed: updatedAt.toISOString(),
|
||||
isDefault: featureType === 'default',
|
||||
scopes,
|
||||
@@ -197,7 +199,8 @@ export async function GET(request: NextRequest) {
|
||||
platformCredential.displayName,
|
||||
platformCredential.providerId || 'google-service-account',
|
||||
platformCredential.updatedAt,
|
||||
null
|
||||
null,
|
||||
'service_account'
|
||||
),
|
||||
],
|
||||
},
|
||||
@@ -322,7 +325,8 @@ export async function GET(request: NextRequest) {
|
||||
sa.displayName,
|
||||
sa.providerId || saProviderId,
|
||||
sa.updatedAt,
|
||||
null
|
||||
null,
|
||||
'service_account'
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -98,8 +98,10 @@ export function CredentialSelector({
|
||||
)
|
||||
const provider = effectiveProviderId
|
||||
|
||||
const isTriggerMode = subBlock.mode === 'trigger'
|
||||
|
||||
const {
|
||||
data: credentials = [],
|
||||
data: rawCredentials = [],
|
||||
isFetching: credentialsLoading,
|
||||
refetch: refetchCredentials,
|
||||
} = useOAuthCredentials(effectiveProviderId, {
|
||||
@@ -108,13 +110,21 @@ export function CredentialSelector({
|
||||
workflowId: activeWorkflowId || undefined,
|
||||
})
|
||||
|
||||
const credentials = useMemo(
|
||||
() =>
|
||||
isTriggerMode
|
||||
? rawCredentials.filter((cred) => cred.type !== 'service_account')
|
||||
: rawCredentials,
|
||||
[rawCredentials, isTriggerMode]
|
||||
)
|
||||
|
||||
const selectedCredential = useMemo(
|
||||
() => credentials.find((cred) => cred.id === selectedId),
|
||||
[credentials, selectedId]
|
||||
)
|
||||
|
||||
const isServiceAccount = useMemo(
|
||||
() => selectedCredential?.provider?.endsWith('-service-account') ?? false,
|
||||
() => selectedCredential?.type === 'service_account',
|
||||
[selectedCredential]
|
||||
)
|
||||
|
||||
|
||||
@@ -100,6 +100,12 @@ export function useEditorSubblockLayout(
|
||||
const effectiveAdvanced = displayAdvancedMode
|
||||
const canonicalModeOverrides = blockData?.canonicalModes
|
||||
|
||||
// Expose canonical mode overrides to condition functions so they can
|
||||
// react to basic/advanced credential toggles (e.g. SERVICE_ACCOUNT_SUBBLOCKS).
|
||||
if (canonicalModeOverrides) {
|
||||
rawValues.__canonicalModes = canonicalModeOverrides
|
||||
}
|
||||
|
||||
const visibleSubBlocks = (config.subBlocks || []).filter((block) => {
|
||||
if (block.hidden) return false
|
||||
|
||||
|
||||
@@ -20,13 +20,29 @@ export const SERVICE_ACCOUNT_SUBBLOCKS: SubBlockConfig[] = [
|
||||
title: 'Is Service Account',
|
||||
type: 'short-input',
|
||||
hidden: true,
|
||||
mode: 'both',
|
||||
},
|
||||
{
|
||||
id: 'impersonateUserEmail',
|
||||
title: 'Impersonated Account',
|
||||
type: 'short-input',
|
||||
placeholder: 'Email to impersonate (for service accounts)',
|
||||
condition: { field: 'isServiceAccount', value: 'true' },
|
||||
paramVisibility: 'user-only',
|
||||
condition: (values) => {
|
||||
// In tool-input context (agent tools), __canonicalModes and isServiceAccount
|
||||
// are absent — always show so users can configure impersonation.
|
||||
const hasBlockEditorContext =
|
||||
values?.__canonicalModes !== undefined || values?.isServiceAccount !== undefined
|
||||
if (!hasBlockEditorContext) {
|
||||
return { field: 'isServiceAccount', value: 'does-not-match', not: true }
|
||||
}
|
||||
const modes = values.__canonicalModes as Record<string, string> | undefined
|
||||
if (modes?.oauthCredential === 'advanced') {
|
||||
return { field: 'isServiceAccount', value: 'does-not-match', not: true }
|
||||
}
|
||||
return { field: 'isServiceAccount', value: 'true' }
|
||||
},
|
||||
mode: 'both',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@@ -168,7 +168,6 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
'https://www.googleapis.com/auth/userinfo.profile',
|
||||
'https://www.googleapis.com/auth/adwords',
|
||||
],
|
||||
serviceAccountProviderId: 'google-service-account',
|
||||
},
|
||||
'google-bigquery': {
|
||||
name: 'Google BigQuery',
|
||||
@@ -258,7 +257,6 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
'https://www.googleapis.com/auth/userinfo.profile',
|
||||
'https://www.googleapis.com/auth/cloud-platform',
|
||||
],
|
||||
serviceAccountProviderId: 'google-service-account',
|
||||
},
|
||||
},
|
||||
defaultService: 'gmail',
|
||||
|
||||
@@ -136,6 +136,7 @@ export interface Credential {
|
||||
id: string
|
||||
name: string
|
||||
provider: OAuthProvider
|
||||
type?: 'oauth' | 'service_account'
|
||||
serviceId?: string
|
||||
lastUsed?: string
|
||||
isDefault?: boolean
|
||||
|
||||
Reference in New Issue
Block a user