Link connector docs in the Add Source dialog
The access review Add Source dialog listed each connector with no path to its setup documentation. Connectors that have a published docs page on probo.com now surface a "Documentation" link on the card, opening the page in a new tab; connectors without a page show nothing extra. The link is data-driven from the connector registry: a new DocumentationURL on the provider Registration, populated for the 12 documented providers via a single accessReviewDocsURL helper, is surfaced as a nullable documentationUrl on ConnectorProviderInfo and rendered by the console only when present. This keeps the registry the single source of truth and adds no client-side provider map. The links resolve once the probo.com access-review docs pages are deployed; until then they 404, so deploy the docs alongside this change. Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
This commit is contained in:
@@ -29,6 +29,7 @@ import {
|
|||||||
DialogContent,
|
DialogContent,
|
||||||
DialogFooter,
|
DialogFooter,
|
||||||
DropdownItem,
|
DropdownItem,
|
||||||
|
IconArrowLink,
|
||||||
Input,
|
Input,
|
||||||
ThirdPartyLogo,
|
ThirdPartyLogo,
|
||||||
useDialogRef,
|
useDialogRef,
|
||||||
@@ -51,6 +52,7 @@ export const addAccessReviewSourceDialogConnectorProviderInfoFragment = graphql`
|
|||||||
fragment AddAccessReviewSourceDialogConnectorProviderInfoFragment on ConnectorProviderInfo @relay(plural: true) {
|
fragment AddAccessReviewSourceDialogConnectorProviderInfoFragment on ConnectorProviderInfo @relay(plural: true) {
|
||||||
provider
|
provider
|
||||||
displayName
|
displayName
|
||||||
|
documentationUrl
|
||||||
oauthConfigured
|
oauthConfigured
|
||||||
apiKeySupported
|
apiKeySupported
|
||||||
apiKeyManaged
|
apiKeyManaged
|
||||||
@@ -160,6 +162,17 @@ export function AddAccessReviewSourceDialog({
|
|||||||
<ThirdPartyLogo thirdParty={info.provider} tint className="size-6 shrink-0" />
|
<ThirdPartyLogo thirdParty={info.provider} tint className="size-6 shrink-0" />
|
||||||
<div className="mr-auto">
|
<div className="mr-auto">
|
||||||
<h3 className="font-medium">{info.displayName}</h3>
|
<h3 className="font-medium">{info.displayName}</h3>
|
||||||
|
{info.documentationUrl && (
|
||||||
|
<a
|
||||||
|
href={info.documentationUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center gap-1 text-xs text-txt-tertiary underline hover:no-underline"
|
||||||
|
>
|
||||||
|
{__("Documentation")}
|
||||||
|
<IconArrowLink size={12} />
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{isConnected
|
{isConnected
|
||||||
? (
|
? (
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ func TestAccessReviewDrivers(t *testing.T) {
|
|||||||
accessReviewDrivers {
|
accessReviewDrivers {
|
||||||
provider
|
provider
|
||||||
displayName
|
displayName
|
||||||
|
documentationUrl
|
||||||
oauthConfigured
|
oauthConfigured
|
||||||
apiKeySupported
|
apiKeySupported
|
||||||
clientCredentialsSupported
|
clientCredentialsSupported
|
||||||
@@ -51,11 +52,12 @@ func TestAccessReviewDrivers(t *testing.T) {
|
|||||||
|
|
||||||
var result struct {
|
var result struct {
|
||||||
AccessReviewDrivers []struct {
|
AccessReviewDrivers []struct {
|
||||||
Provider string `json:"provider"`
|
Provider string `json:"provider"`
|
||||||
DisplayName string `json:"displayName"`
|
DisplayName string `json:"displayName"`
|
||||||
OauthConfigured bool `json:"oauthConfigured"`
|
DocumentationURL *string `json:"documentationUrl"`
|
||||||
APIKeySupported bool `json:"apiKeySupported"`
|
OauthConfigured bool `json:"oauthConfigured"`
|
||||||
ClientCredentialsSupported bool `json:"clientCredentialsSupported"`
|
APIKeySupported bool `json:"apiKeySupported"`
|
||||||
|
ClientCredentialsSupported bool `json:"clientCredentialsSupported"`
|
||||||
ExtraSettings []struct {
|
ExtraSettings []struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Label string `json:"label"`
|
Label string `json:"label"`
|
||||||
@@ -69,17 +71,29 @@ func TestAccessReviewDrivers(t *testing.T) {
|
|||||||
assert.NotEmpty(t, result.AccessReviewDrivers)
|
assert.NotEmpty(t, result.AccessReviewDrivers)
|
||||||
|
|
||||||
providerNames := make(map[string]bool)
|
providerNames := make(map[string]bool)
|
||||||
|
docURLByProvider := make(map[string]*string)
|
||||||
|
|
||||||
for _, info := range result.AccessReviewDrivers {
|
for _, info := range result.AccessReviewDrivers {
|
||||||
assert.NotEmpty(t, info.Provider)
|
assert.NotEmpty(t, info.Provider)
|
||||||
assert.NotEmpty(t, info.DisplayName)
|
assert.NotEmpty(t, info.DisplayName)
|
||||||
assert.NotNil(t, info.ExtraSettings)
|
assert.NotNil(t, info.ExtraSettings)
|
||||||
providerNames[info.Provider] = true
|
providerNames[info.Provider] = true
|
||||||
|
docURLByProvider[info.Provider] = info.DocumentationURL
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.True(t, providerNames["BREX"], "expected BREX provider to be present")
|
assert.True(t, providerNames["BREX"], "expected BREX provider to be present")
|
||||||
assert.True(t, providerNames["HUBSPOT"], "expected HUBSPOT provider to be present")
|
assert.True(t, providerNames["HUBSPOT"], "expected HUBSPOT provider to be present")
|
||||||
|
|
||||||
|
// A documented provider exposes its probo.com docs URL; an undocumented one
|
||||||
|
// exposes null. See pkg/connector/provider/docs.go.
|
||||||
|
require.Contains(t, docURLByProvider, "ANTHROPIC")
|
||||||
|
|
||||||
|
if url := docURLByProvider["ANTHROPIC"]; assert.NotNil(t, url) {
|
||||||
|
assert.Equal(t, "https://www.probo.com/docs/product/access-review/anthropic", *url)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Nil(t, docURLByProvider["BREX"], "BREX has no doc page, documentationUrl must be null")
|
||||||
|
|
||||||
t.Run("viewer can list access review drivers", func(t *testing.T) {
|
t.Run("viewer can list access review drivers", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
viewer := testutil.NewClientInOrg(t, testutil.RoleViewer, owner)
|
viewer := testutil.NewClientInOrg(t, testutil.RoleViewer, owner)
|
||||||
|
|||||||
@@ -31,9 +31,10 @@ import (
|
|||||||
|
|
||||||
func anthropicRegistration() *Registration {
|
func anthropicRegistration() *Registration {
|
||||||
return &Registration{
|
return &Registration{
|
||||||
Provider: coredata.ConnectorProviderAnthropic,
|
Provider: coredata.ConnectorProviderAnthropic,
|
||||||
DisplayName: "Anthropic",
|
DisplayName: "Anthropic",
|
||||||
SupportsAPIKey: true,
|
DocumentationURL: accessReviewDocsURL("anthropic"),
|
||||||
|
SupportsAPIKey: true,
|
||||||
// Anthropic's Admin API authenticates with the admin key in the
|
// Anthropic's Admin API authenticates with the admin key in the
|
||||||
// x-api-key header; it rejects Authorization: Bearer and returns
|
// x-api-key header; it rejects Authorization: Bearer and returns
|
||||||
// 400 when both headers are present. APIKeyHeader makes the
|
// 400 when both headers are present. APIKeyHeader makes the
|
||||||
|
|||||||
@@ -31,9 +31,10 @@ import (
|
|||||||
|
|
||||||
func apolloRegistration() *Registration {
|
func apolloRegistration() *Registration {
|
||||||
return &Registration{
|
return &Registration{
|
||||||
Provider: coredata.ConnectorProviderApollo,
|
Provider: coredata.ConnectorProviderApollo,
|
||||||
DisplayName: "Apollo.io",
|
DisplayName: "Apollo.io",
|
||||||
SupportsAPIKey: true,
|
DocumentationURL: accessReviewDocsURL("apollo"),
|
||||||
|
SupportsAPIKey: true,
|
||||||
// Apollo's REST API authenticates with a master API key in the
|
// Apollo's REST API authenticates with a master API key in the
|
||||||
// x-api-key header; it rejects Authorization: Bearer (and, since
|
// x-api-key header; it rejects Authorization: Bearer (and, since
|
||||||
// Sept 2024, query/body key params). APIKeyHeader makes the
|
// Sept 2024, query/body key params). APIKeyHeader makes the
|
||||||
|
|||||||
@@ -31,10 +31,11 @@ import (
|
|||||||
|
|
||||||
func cloudflareRegistration() *Registration {
|
func cloudflareRegistration() *Registration {
|
||||||
return &Registration{
|
return &Registration{
|
||||||
Provider: coredata.ConnectorProviderCloudflare,
|
Provider: coredata.ConnectorProviderCloudflare,
|
||||||
DisplayName: "Cloudflare",
|
DisplayName: "Cloudflare",
|
||||||
ProbeURL: "https://api.cloudflare.com/client/v4/user/tokens/verify",
|
DocumentationURL: accessReviewDocsURL("cloudflare"),
|
||||||
SupportsAPIKey: true,
|
ProbeURL: "https://api.cloudflare.com/client/v4/user/tokens/verify",
|
||||||
|
SupportsAPIKey: true,
|
||||||
NewDriver: func(_ context.Context, c *http.Client, _ *coredata.Connector, _ *log.Logger) (drivers.Driver, error) {
|
NewDriver: func(_ context.Context, c *http.Client, _ *coredata.Connector, _ *log.Logger) (drivers.Driver, error) {
|
||||||
return drivers.NewCloudflareDriver(c), nil
|
return drivers.NewCloudflareDriver(c), nil
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -32,8 +32,9 @@ import (
|
|||||||
|
|
||||||
func crispRegistration() *Registration {
|
func crispRegistration() *Registration {
|
||||||
return &Registration{
|
return &Registration{
|
||||||
Provider: coredata.ConnectorProviderCrisp,
|
Provider: coredata.ConnectorProviderCrisp,
|
||||||
DisplayName: "Crisp",
|
DisplayName: "Crisp",
|
||||||
|
DocumentationURL: accessReviewDocsURL("crisp"),
|
||||||
// Model B: the plugin token is Probo's own Crisp Marketplace plugin
|
// Model B: the plugin token is Probo's own Crisp Marketplace plugin
|
||||||
// credential, held server-side in bootstrap config, not pasted by
|
// credential, held server-side in bootstrap config, not pasted by
|
||||||
// the customer. ManagedAPIKey injects it at connect time; the
|
// the customer. ManagedAPIKey injects it at connect time; the
|
||||||
|
|||||||
@@ -33,9 +33,10 @@ const cursorMembersEndpoint = "https://api.cursor.com/teams/members"
|
|||||||
|
|
||||||
func cursorRegistration() *Registration {
|
func cursorRegistration() *Registration {
|
||||||
return &Registration{
|
return &Registration{
|
||||||
Provider: coredata.ConnectorProviderCursor,
|
Provider: coredata.ConnectorProviderCursor,
|
||||||
DisplayName: "Cursor",
|
DisplayName: "Cursor",
|
||||||
SupportsAPIKey: true,
|
DocumentationURL: accessReviewDocsURL("cursor"),
|
||||||
|
SupportsAPIKey: true,
|
||||||
// Cursor's Admin API has no third-party OAuth2 flow; it
|
// Cursor's Admin API has no third-party OAuth2 flow; it
|
||||||
// authenticates with a team admin key (key_...) presented as the
|
// authenticates with a team admin key (key_...) presented as the
|
||||||
// HTTP Basic auth username with an empty password ("-u <key>:")
|
// HTTP Basic auth username with an empty password ("-u <key>:")
|
||||||
|
|||||||
@@ -31,9 +31,10 @@ import (
|
|||||||
|
|
||||||
func deepgramRegistration() *Registration {
|
func deepgramRegistration() *Registration {
|
||||||
return &Registration{
|
return &Registration{
|
||||||
Provider: coredata.ConnectorProviderDeepgram,
|
Provider: coredata.ConnectorProviderDeepgram,
|
||||||
DisplayName: "Deepgram",
|
DisplayName: "Deepgram",
|
||||||
SupportsAPIKey: true,
|
DocumentationURL: accessReviewDocsURL("deepgram"),
|
||||||
|
SupportsAPIKey: true,
|
||||||
// Deepgram authenticates with an API key under the `Token` scheme
|
// Deepgram authenticates with an API key under the `Token` scheme
|
||||||
// (`Authorization: Token <key>`), not Bearer. APIKeyAuthScheme makes
|
// (`Authorization: Token <key>`), not Bearer. APIKeyAuthScheme makes
|
||||||
// the APIKeyConnection use that scheme. There is no third-party
|
// the APIKeyConnection use that scheme. There is no third-party
|
||||||
|
|||||||
33
pkg/connector/provider/docs.go
Normal file
33
pkg/connector/provider/docs.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
package provider
|
||||||
|
|
||||||
|
// accessReviewDocsBaseURL is the public probo.com docs root for access-review
|
||||||
|
// connectors; each documented provider's page lives at this base + its slug.
|
||||||
|
const accessReviewDocsBaseURL = "https://www.probo.com/docs/product/access-review/"
|
||||||
|
|
||||||
|
// accessReviewDocsURL builds the public documentation URL for an access-review
|
||||||
|
// connector from its page slug (e.g. "anthropic"). The slug is passed explicitly
|
||||||
|
// by each registration rather than derived from the provider enum, so an enum
|
||||||
|
// containing an underscore (e.g. BETTER_STACK) cannot produce a wrong URL.
|
||||||
|
func accessReviewDocsURL(slug string) string {
|
||||||
|
return accessReviewDocsBaseURL + slug
|
||||||
|
}
|
||||||
@@ -31,10 +31,11 @@ import (
|
|||||||
|
|
||||||
func openaiRegistration() *Registration {
|
func openaiRegistration() *Registration {
|
||||||
return &Registration{
|
return &Registration{
|
||||||
Provider: coredata.ConnectorProviderOpenAI,
|
Provider: coredata.ConnectorProviderOpenAI,
|
||||||
DisplayName: "OpenAI",
|
DisplayName: "OpenAI",
|
||||||
ProbeURL: "https://api.openai.com/v1/models",
|
DocumentationURL: accessReviewDocsURL("openai"),
|
||||||
SupportsAPIKey: true,
|
ProbeURL: "https://api.openai.com/v1/models",
|
||||||
|
SupportsAPIKey: true,
|
||||||
NewDriver: func(_ context.Context, c *http.Client, _ *coredata.Connector, _ *log.Logger) (drivers.Driver, error) {
|
NewDriver: func(_ context.Context, c *http.Client, _ *coredata.Connector, _ *log.Logger) (drivers.Driver, error) {
|
||||||
return drivers.NewOpenAIDriver(c), nil
|
return drivers.NewOpenAIDriver(c), nil
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -31,9 +31,10 @@ import (
|
|||||||
|
|
||||||
func openrouterRegistration() *Registration {
|
func openrouterRegistration() *Registration {
|
||||||
return &Registration{
|
return &Registration{
|
||||||
Provider: coredata.ConnectorProviderOpenRouter,
|
Provider: coredata.ConnectorProviderOpenRouter,
|
||||||
DisplayName: "OpenRouter",
|
DisplayName: "OpenRouter",
|
||||||
SupportsAPIKey: true,
|
DocumentationURL: accessReviewDocsURL("openrouter"),
|
||||||
|
SupportsAPIKey: true,
|
||||||
// OpenRouter authenticates with an organization management
|
// OpenRouter authenticates with an organization management
|
||||||
// (provisioning) API key presented as Authorization: Bearer, the
|
// (provisioning) API key presented as Authorization: Bearer, the
|
||||||
// default APIKeyConnection scheme. The key is bound to one
|
// default APIKeyConnection scheme. The key is bound to one
|
||||||
|
|||||||
@@ -31,9 +31,10 @@ import (
|
|||||||
|
|
||||||
func railwayRegistration() *Registration {
|
func railwayRegistration() *Registration {
|
||||||
return &Registration{
|
return &Registration{
|
||||||
Provider: coredata.ConnectorProviderRailway,
|
Provider: coredata.ConnectorProviderRailway,
|
||||||
DisplayName: "Railway",
|
DisplayName: "Railway",
|
||||||
SupportsAPIKey: true,
|
DocumentationURL: accessReviewDocsURL("railway"),
|
||||||
|
SupportsAPIKey: true,
|
||||||
// Railway authenticates with an account API token as Authorization:
|
// Railway authenticates with an account API token as Authorization:
|
||||||
// Bearer. A single GraphQL call resolves the account's workspaces and
|
// Bearer. A single GraphQL call resolves the account's workspaces and
|
||||||
// their members, so there is nothing to pick (Pattern 3). Railway
|
// their members, so there is nothing to pick (Pattern 3). Railway
|
||||||
|
|||||||
@@ -31,10 +31,11 @@ import (
|
|||||||
|
|
||||||
func resendRegistration() *Registration {
|
func resendRegistration() *Registration {
|
||||||
return &Registration{
|
return &Registration{
|
||||||
Provider: coredata.ConnectorProviderResend,
|
Provider: coredata.ConnectorProviderResend,
|
||||||
DisplayName: "Resend",
|
DisplayName: "Resend",
|
||||||
ProbeURL: "https://api.resend.com/domains",
|
DocumentationURL: accessReviewDocsURL("resend"),
|
||||||
SupportsAPIKey: true,
|
ProbeURL: "https://api.resend.com/domains",
|
||||||
|
SupportsAPIKey: true,
|
||||||
NewDriver: func(_ context.Context, c *http.Client, _ *coredata.Connector, _ *log.Logger) (drivers.Driver, error) {
|
NewDriver: func(_ context.Context, c *http.Client, _ *coredata.Connector, _ *log.Logger) (drivers.Driver, error) {
|
||||||
return drivers.NewResendDriver(c), nil
|
return drivers.NewResendDriver(c), nil
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -32,9 +32,10 @@ import (
|
|||||||
|
|
||||||
func scalewayRegistration() *Registration {
|
func scalewayRegistration() *Registration {
|
||||||
return &Registration{
|
return &Registration{
|
||||||
Provider: coredata.ConnectorProviderScaleway,
|
Provider: coredata.ConnectorProviderScaleway,
|
||||||
DisplayName: "Scaleway",
|
DisplayName: "Scaleway",
|
||||||
SupportsAPIKey: true,
|
DocumentationURL: accessReviewDocsURL("scaleway"),
|
||||||
|
SupportsAPIKey: true,
|
||||||
// Scaleway authenticates with the secret key in the X-Auth-Token header
|
// Scaleway authenticates with the secret key in the X-Auth-Token header
|
||||||
// rather than Authorization: Bearer. APIKeyHeader makes the
|
// rather than Authorization: Bearer. APIKeyHeader makes the
|
||||||
// APIKeyConnection send that header and omit Authorization. The key is
|
// APIKeyConnection send that header and omit Authorization. The key is
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ type Registration struct {
|
|||||||
// Identity.
|
// Identity.
|
||||||
Provider coredata.ConnectorProvider
|
Provider coredata.ConnectorProvider
|
||||||
DisplayName string
|
DisplayName string
|
||||||
|
// DocumentationURL is the public probo.com docs page for connecting this
|
||||||
|
// provider as an access source. Empty for providers with no doc page yet;
|
||||||
|
// surfaced (nullable) on ConnectorProviderInfo so the console renders a link.
|
||||||
|
DocumentationURL string
|
||||||
|
|
||||||
// OAuth2 metadata.
|
// OAuth2 metadata.
|
||||||
AuthURL string
|
AuthURL string
|
||||||
|
|||||||
@@ -31,9 +31,10 @@ import (
|
|||||||
|
|
||||||
func yousignRegistration() *Registration {
|
func yousignRegistration() *Registration {
|
||||||
return &Registration{
|
return &Registration{
|
||||||
Provider: coredata.ConnectorProviderYousign,
|
Provider: coredata.ConnectorProviderYousign,
|
||||||
DisplayName: "Yousign",
|
DisplayName: "Yousign",
|
||||||
SupportsAPIKey: true,
|
DocumentationURL: accessReviewDocsURL("yousign"),
|
||||||
|
SupportsAPIKey: true,
|
||||||
// Yousign authenticates with an API key as Authorization: Bearer. The
|
// Yousign authenticates with an API key as Authorization: Bearer. The
|
||||||
// key is bound to one organization, so GET /v3/users returns everyone
|
// key is bound to one organization, so GET /v3/users returns everyone
|
||||||
// with nothing to pick (Pattern 3). The connector targets Yousign
|
// with nothing to pick (Pattern 3). The connector targets Yousign
|
||||||
|
|||||||
@@ -607,9 +607,15 @@ func (r *queryResolver) AccessReviewDrivers(ctx context.Context) ([]*types.Conne
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var documentationURL *string
|
||||||
|
if reg.DocumentationURL != "" {
|
||||||
|
documentationURL = new(reg.DocumentationURL)
|
||||||
|
}
|
||||||
|
|
||||||
infos = append(infos, &types.ConnectorProviderInfo{
|
infos = append(infos, &types.ConnectorProviderInfo{
|
||||||
Provider: provider,
|
Provider: provider,
|
||||||
DisplayName: reg.DisplayName,
|
DisplayName: reg.DisplayName,
|
||||||
|
DocumentationURL: documentationURL,
|
||||||
OauthConfigured: oauthConfigured,
|
OauthConfigured: oauthConfigured,
|
||||||
APIKeySupported: apiKeySupported,
|
APIKeySupported: apiKeySupported,
|
||||||
APIKeyManaged: apiKeyManaged,
|
APIKeyManaged: apiKeyManaged,
|
||||||
|
|||||||
@@ -104,6 +104,11 @@ enum ConnectorProvider
|
|||||||
type ConnectorProviderInfo {
|
type ConnectorProviderInfo {
|
||||||
provider: ConnectorProvider!
|
provider: ConnectorProvider!
|
||||||
displayName: String!
|
displayName: String!
|
||||||
|
"""
|
||||||
|
documentationUrl is the public probo.com docs page for connecting this
|
||||||
|
provider as an access source, or null when no doc page exists yet.
|
||||||
|
"""
|
||||||
|
documentationUrl: String
|
||||||
oauthConfigured: Boolean!
|
oauthConfigured: Boolean!
|
||||||
apiKeySupported: Boolean!
|
apiKeySupported: Boolean!
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user