Expose OAuth2 scopes via GraphQL fields
Add per-context fields so the frontend can read scopes from the type that owns each connection: - ConnectorProviderInfo.oauth2Scopes: access review providers - AccessSource.oauth2Scopes: access review reconnect flow - Organization.slackOAuth2Scopes (console): compliance page Slack - Organization.googleWorkspaceOAuth2Scopes (connect): SCIM bridge Resolvers delegate to the constants declared in each owning Go module. The Google Workspace field lives on Organization, not on SCIMConfiguration, so the Connect button can read it before any SCIM configuration exists. Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
This commit is contained in:
@@ -250,6 +250,7 @@ type Organization implements Node {
|
||||
): SAMLConfigurationConnection @goField(forceResolver: true)
|
||||
|
||||
scimConfiguration: SCIMConfiguration @goField(forceResolver: true)
|
||||
googleWorkspaceOAuth2Scopes: [String!]! @goField(forceResolver: true)
|
||||
|
||||
auditLogEntries(
|
||||
first: Int
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/iam"
|
||||
"go.probo.inc/probo/pkg/iam/scim/bridge/provider/googleworkspace"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/server/api/authn"
|
||||
@@ -1333,6 +1334,11 @@ func (r *organizationResolver) ScimConfiguration(ctx context.Context, obj *types
|
||||
return types.NewSCIMConfiguration(config), nil
|
||||
}
|
||||
|
||||
// GoogleWorkspaceOAuth2Scopes is the resolver for the googleWorkspaceOAuth2Scopes field.
|
||||
func (r *organizationResolver) GoogleWorkspaceOAuth2Scopes(ctx context.Context, obj *types.Organization) ([]string, error) {
|
||||
return googleworkspace.OAuth2Scopes, nil
|
||||
}
|
||||
|
||||
// AuditLogEntries is the resolver for the auditLogEntries field.
|
||||
func (r *organizationResolver) AuditLogEntries(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AuditLogEntryOrderBy, filter *types.AuditLogEntryFilter) (*types.AuditLogEntryConnection, error) {
|
||||
if err := r.authorize(ctx, obj.ID, iam.ActionAuditLogEntryList); err != nil {
|
||||
|
||||
@@ -1908,6 +1908,7 @@ type Organization implements Node {
|
||||
last: Int
|
||||
before: CursorKey
|
||||
): SlackConnectionConnection! @goField(forceResolver: true)
|
||||
slackOAuth2Scopes: [String!]! @goField(forceResolver: true)
|
||||
connectors(filter: ConnectorFilter): [Connector!]! @goField(forceResolver: true)
|
||||
connectorProviderInfos: [ConnectorProviderInfo!]! @goField(forceResolver: true)
|
||||
|
||||
@@ -2166,6 +2167,7 @@ type ConnectorProviderInfo {
|
||||
oauthConfigured: Boolean!
|
||||
apiKeySupported: Boolean!
|
||||
clientCredentialsSupported: Boolean!
|
||||
oauth2Scopes: [String!]!
|
||||
extraSettings: [ConnectorProviderSettingInfo!]!
|
||||
}
|
||||
|
||||
@@ -6802,6 +6804,7 @@ type AccessSource implements Node {
|
||||
needsConfiguration: Boolean! @goField(forceResolver: true)
|
||||
connectionStatus: AccessSourceConnectionStatus! @goField(forceResolver: true)
|
||||
selectedOrganization: String @goField(forceResolver: true)
|
||||
oauth2Scopes: [String!]! @goField(forceResolver: true)
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/vikstrous/dataloadgen"
|
||||
"go.gearno.de/kit/log"
|
||||
"go.probo.inc/probo/pkg/accessreview"
|
||||
"go.probo.inc/probo/pkg/accessreview/drivers"
|
||||
"go.probo.inc/probo/pkg/connector"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
@@ -31,6 +32,7 @@ import (
|
||||
"go.probo.inc/probo/pkg/server/api/console/v1/types"
|
||||
"go.probo.inc/probo/pkg/server/gqlutils"
|
||||
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
|
||||
"go.probo.inc/probo/pkg/slack"
|
||||
"go.probo.inc/probo/pkg/validator"
|
||||
)
|
||||
|
||||
@@ -520,6 +522,30 @@ func (r *accessSourceResolver) SelectedOrganization(ctx context.Context, obj *ty
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Oauth2Scopes is the resolver for the oauth2Scopes field.
|
||||
func (r *accessSourceResolver) Oauth2Scopes(ctx context.Context, obj *types.AccessSource) ([]string, error) {
|
||||
if obj.ConnectorID == nil {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
prb := r.ProboService(ctx, obj.ID.TenantID())
|
||||
|
||||
dbConnector, err := prb.Connectors.Get(ctx, *obj.ConnectorID)
|
||||
if err != nil {
|
||||
if errors.Is(err, coredata.ErrResourceNotFound) {
|
||||
return []string{}, nil
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot get connector for oauth2 scopes", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
scopes := drivers.ProviderOAuth2Scopes(dbConnector.Provider)
|
||||
if scopes == nil {
|
||||
return []string{}, nil
|
||||
}
|
||||
return scopes, nil
|
||||
}
|
||||
|
||||
// Permission is the resolver for the permission field.
|
||||
func (r *accessSourceResolver) Permission(ctx context.Context, obj *types.AccessSource, action string) (bool, error) {
|
||||
return r.Resolver.Permission(ctx, obj, action)
|
||||
@@ -8280,6 +8306,11 @@ func (r *organizationResolver) SlackConnections(ctx context.Context, obj *types.
|
||||
return types.NewSlackConnectionConnection(page), nil
|
||||
}
|
||||
|
||||
// SlackOAuth2Scopes is the resolver for the slackOAuth2Scopes field.
|
||||
func (r *organizationResolver) SlackOAuth2Scopes(ctx context.Context, obj *types.Organization) ([]string, error) {
|
||||
return slack.OAuth2Scopes, nil
|
||||
}
|
||||
|
||||
// Connectors is the resolver for the connectors field.
|
||||
func (r *organizationResolver) Connectors(ctx context.Context, obj *types.Organization, filter *types.ConnectorFilter) ([]*types.Connector, error) {
|
||||
if err := r.authorize(ctx, obj.ID, probo.ActionConnectorList); err != nil {
|
||||
@@ -8320,12 +8351,17 @@ func (r *organizationResolver) ConnectorProviderInfos(ctx context.Context, obj *
|
||||
var infos []*types.ConnectorProviderInfo
|
||||
for _, provider := range coredata.ConnectorProviders() {
|
||||
_, oauthErr := r.connectorRegistry.Get(string(provider))
|
||||
scopes := drivers.ProviderOAuth2Scopes(provider)
|
||||
if scopes == nil {
|
||||
scopes = []string{}
|
||||
}
|
||||
info := &types.ConnectorProviderInfo{
|
||||
Provider: provider,
|
||||
DisplayName: providerDisplayName(provider),
|
||||
OauthConfigured: oauthErr == nil,
|
||||
APIKeySupported: providerSupportsAPIKey(provider),
|
||||
ClientCredentialsSupported: providerSupportsClientCredentials(provider),
|
||||
Oauth2Scopes: scopes,
|
||||
ExtraSettings: providerExtraSettings(provider),
|
||||
}
|
||||
infos = append(infos, info)
|
||||
|
||||
Reference in New Issue
Block a user