Expose oauth2Scopes on Connector instead of AccessSource

The AccessSource.oauth2Scopes field duplicated knowledge that
naturally belongs on the Connector object that AccessSource
already exposes via its connector field. Move it to Connector so
every type that holds a connector (AccessSource, SCIMBridge, etc.)
can reach the scopes through the connector relationship.

AccessSourceRow now queries accessSource.connector { oauth2Scopes }
in its reconnect flow.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
This commit is contained in:
Aurélien Sibiril
2026-04-08 09:09:08 +02:00
parent 53d6ab09cb
commit ec42409219
3 changed files with 19 additions and 30 deletions

View File

@@ -44,8 +44,8 @@ const fragment = graphql`
connectorId
connector {
provider
oauth2Scopes
}
oauth2Scopes
connectionStatus
selectedOrganization
needsConfiguration
@@ -206,15 +206,15 @@ export function AccessSourceRow({ fKey, connectionId, organizationId }: Props) {
};
const handleReconnect = () => {
const provider = accessSource.connector?.provider;
if (!provider || !accessSource.connectorId) return;
const connector = accessSource.connector;
if (!connector || !accessSource.connectorId) return;
const baseURL = import.meta.env.VITE_API_URL || window.location.origin;
const url = new URL("/api/console/v1/connectors/initiate", baseURL);
url.searchParams.append("organization_id", organizationId);
url.searchParams.append("provider", provider);
url.searchParams.append("provider", connector.provider);
url.searchParams.append("connector_id", accessSource.connectorId);
for (const scope of accessSource.oauth2Scopes) {
for (const scope of connector.oauth2Scopes) {
url.searchParams.append("scope", scope);
}
url.searchParams.append(

View File

@@ -2184,6 +2184,7 @@ input ConnectorFilter {
type Connector {
id: ID!
provider: ConnectorProvider!
oauth2Scopes: [String!]! @goField(forceResolver: true)
createdAt: Datetime!
}
@@ -6804,7 +6805,6 @@ 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!

View File

@@ -522,30 +522,6 @@ 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)
@@ -1007,6 +983,15 @@ func (r *complianceFrameworkResolver) Framework(ctx context.Context, obj *types.
return types.NewFramework(framework), nil
}
// Oauth2Scopes is the resolver for the oauth2Scopes field.
func (r *connectorResolver) Oauth2Scopes(ctx context.Context, obj *types.Connector) ([]string, error) {
scopes := drivers.ProviderOAuth2Scopes(obj.Provider)
if scopes == nil {
return []string{}, nil
}
return scopes, nil
}
// Organization is the resolver for the organization field.
func (r *controlResolver) Organization(ctx context.Context, obj *types.Control) (*types.Organization, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGet); err != nil {
@@ -11880,6 +11865,9 @@ func (r *Resolver) ComplianceFramework() schema.ComplianceFrameworkResolver {
return &complianceFrameworkResolver{r}
}
// Connector returns schema.ConnectorResolver implementation.
func (r *Resolver) Connector() schema.ConnectorResolver { return &connectorResolver{r} }
// Control returns schema.ControlResolver implementation.
func (r *Resolver) Control() schema.ControlResolver { return &controlResolver{r} }
@@ -12227,6 +12215,7 @@ type auditLogEntryResolver struct{ *Resolver }
type auditLogEntryConnectionResolver struct{ *Resolver }
type complianceExternalURLResolver struct{ *Resolver }
type complianceFrameworkResolver struct{ *Resolver }
type connectorResolver struct{ *Resolver }
type controlResolver struct{ *Resolver }
type controlConnectionResolver struct{ *Resolver }
type customDomainResolver struct{ *Resolver }