Decouple each campaign from the live access-review sources it was started with by introducing a per-campaign source snapshot table (access_review_campaign_sources). The snapshot captures the source name, category, and connector at start time, so a review remains coherent even after the underlying source is edited or deleted. Fetch tracking becomes an append-only log (access_review_campaign_source_fetch_attempts) that preserves every attempt with its own status and error rather than overwriting a single row. Rename the shared access-review tables and enums to use a consistent access_review_ prefix throughout: access_entries → access_review_entries access_sources → access_review_sources access_source_category → access_review_source_category access_entry_* → access_review_entry_* The same rename propagates to every coredata type, service, GraphQL schema, MCP specification, CLI command, frontend component, and e2e test. The accessreview package gains dedicated actions.go and policies.go files for its own IAM policy set, mirroring the agentrun package pattern. Signed-off-by: Bryan Frimin <bryan@probo.com>
611 lines
19 KiB
Go
611 lines
19 KiB
Go
package console_v1
|
|
|
|
// This file will be automatically regenerated based on the schema, any resolver
|
|
// implementations
|
|
// will be copied through when generating and any unknown code will be moved to the end.
|
|
// Code generated by github.com/99designs/gqlgen version v0.17.90
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"slices"
|
|
"strings"
|
|
|
|
"go.gearno.de/kit/log"
|
|
"go.probo.inc/probo/pkg/accessreview"
|
|
"go.probo.inc/probo/pkg/agentrun"
|
|
"go.probo.inc/probo/pkg/coredata"
|
|
"go.probo.inc/probo/pkg/gid"
|
|
"go.probo.inc/probo/pkg/iam"
|
|
"go.probo.inc/probo/pkg/probo"
|
|
"go.probo.inc/probo/pkg/server/api/authn"
|
|
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
|
|
"go.probo.inc/probo/pkg/server/api/console/v1/types"
|
|
"go.probo.inc/probo/pkg/server/gqlutils"
|
|
)
|
|
|
|
// Node is the resolver for the node field.
|
|
func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error) {
|
|
var (
|
|
loadNode func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error)
|
|
action string
|
|
)
|
|
|
|
switch id.EntityType() {
|
|
case coredata.OrganizationEntityType:
|
|
action = iam.ActionOrganizationGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
organization, err := r.probo.Organizations.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewOrganization(organization), nil
|
|
}
|
|
case coredata.ThirdPartyEntityType:
|
|
action = probo.ActionThirdPartyGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
thirdParty, err := r.probo.ThirdParties.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewThirdParty(thirdParty), nil
|
|
}
|
|
case coredata.FrameworkEntityType:
|
|
action = probo.ActionFrameworkGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
framework, err := r.probo.Frameworks.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewFramework(framework), nil
|
|
}
|
|
case coredata.MeasureEntityType:
|
|
action = probo.ActionMeasureGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
measure, err := r.probo.Measures.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewMeasure(measure), nil
|
|
}
|
|
case coredata.TaskEntityType:
|
|
action = probo.ActionTaskGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
task, err := r.probo.Tasks.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewTask(task), nil
|
|
}
|
|
case coredata.EvidenceEntityType:
|
|
action = probo.ActionEvidenceList
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
evidence, err := r.probo.Evidences.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewEvidence(evidence), nil
|
|
}
|
|
case coredata.DocumentEntityType:
|
|
action = probo.ActionDocumentGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
document, err := r.probo.Documents.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewDocument(document), nil
|
|
}
|
|
case coredata.ControlEntityType:
|
|
action = probo.ActionControlList
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
control, err := r.probo.Controls.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewControl(control), nil
|
|
}
|
|
case coredata.RiskEntityType:
|
|
action = probo.ActionRiskGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
risk, err := r.probo.Risks.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewRisk(risk), nil
|
|
}
|
|
case coredata.RiskAssessmentEntityType:
|
|
action = probo.ActionRiskAssessmentGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
ra, err := r.riskManagement.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewRiskAssessment(ra), nil
|
|
}
|
|
case coredata.RiskAssessmentNodeEntityType:
|
|
action = probo.ActionRiskAssessmentNodeGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
n, err := r.riskManagement.GetNode(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewRiskAssessmentNode(n), nil
|
|
}
|
|
case coredata.RiskAssessmentProcessEntityType:
|
|
action = probo.ActionRiskAssessmentProcessGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
p, err := r.riskManagement.GetProcess(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewRiskAssessmentProcess(p), nil
|
|
}
|
|
case coredata.RiskAssessmentThreatEntityType:
|
|
action = probo.ActionRiskAssessmentThreatGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
t, err := r.riskManagement.GetThreat(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewRiskAssessmentThreat(t), nil
|
|
}
|
|
case coredata.RiskAssessmentScopeEntityType:
|
|
action = probo.ActionRiskAssessmentScopeGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
s, err := r.riskManagement.GetScope(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewRiskAssessmentScope(s), nil
|
|
}
|
|
case coredata.RiskAssessmentBoundaryEntityType:
|
|
action = probo.ActionRiskAssessmentBoundaryGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
b, err := r.riskManagement.GetBoundary(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewRiskAssessmentBoundary(b), nil
|
|
}
|
|
case coredata.RiskAssessmentScenarioEntityType:
|
|
action = probo.ActionRiskAssessmentScenarioGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
s, err := r.riskManagement.GetScenario(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewRiskAssessmentScenario(s), nil
|
|
}
|
|
case coredata.ThirdPartyComplianceReportEntityType:
|
|
action = probo.ActionThirdPartyComplianceReportGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
thirdPartyComplianceReport, err := r.probo.ThirdPartyComplianceReports.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewThirdPartyComplianceReport(thirdPartyComplianceReport), nil
|
|
}
|
|
case coredata.ThirdPartyContactEntityType:
|
|
action = probo.ActionThirdPartyContactGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
thirdPartyContact, err := r.probo.ThirdPartyContacts.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewThirdPartyContact(thirdPartyContact), nil
|
|
}
|
|
case coredata.ThirdPartyServiceEntityType:
|
|
action = probo.ActionThirdPartyServiceGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
thirdPartyService, err := r.probo.ThirdPartyServices.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewThirdPartyService(thirdPartyService), nil
|
|
}
|
|
case coredata.DocumentVersionEntityType:
|
|
action = probo.ActionDocumentVersionList
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
documentVersion, err := r.probo.Documents.GetVersion(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewDocumentVersion(documentVersion), nil
|
|
}
|
|
case coredata.DocumentVersionSignatureEntityType:
|
|
action = probo.ActionDocumentVersionSignatureList
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
documentVersionSignature, err := r.probo.Documents.GetVersionSignature(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewDocumentVersionSignature(documentVersionSignature), nil
|
|
}
|
|
case coredata.AssetEntityType:
|
|
action = probo.ActionAssetList
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
asset, err := r.probo.Assets.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewAsset(asset), nil
|
|
}
|
|
case coredata.DatumEntityType:
|
|
action = probo.ActionDatumList
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
datum, err := r.probo.Data.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewDatum(datum), nil
|
|
}
|
|
case coredata.AuditEntityType:
|
|
action = probo.ActionAuditList
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
audit, err := r.probo.Audits.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewAudit(audit), nil
|
|
}
|
|
case coredata.FindingEntityType:
|
|
action = probo.ActionFindingList
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
finding, err := r.probo.Findings.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewFinding(finding), nil
|
|
}
|
|
case coredata.ObligationEntityType:
|
|
action = probo.ActionObligationList
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
obligation, err := r.probo.Obligations.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewObligation(obligation), nil
|
|
}
|
|
case coredata.ProcessingActivityEntityType:
|
|
action = probo.ActionProcessingActivityList
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
processingActivity, err := r.probo.ProcessingActivities.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewProcessingActivity(processingActivity), nil
|
|
}
|
|
case coredata.DataProtectionImpactAssessmentEntityType:
|
|
// TODO: add action
|
|
// action = probo.ActionDataProtectionImpactAssessmentGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
dpia, err := r.probo.DataProtectionImpactAssessments.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewDataProtectionImpactAssessment(dpia), nil
|
|
}
|
|
case coredata.TransferImpactAssessmentEntityType:
|
|
// TODO: add action
|
|
//action = probo.ActionTransferImpactAssessmentGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
tia, err := r.probo.TransferImpactAssessments.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewTransferImpactAssessment(tia), nil
|
|
}
|
|
case coredata.TrustCenterEntityType:
|
|
action = probo.ActionTrustCenterGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
trustCenter, err := r.probo.TrustCenters.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewTrustCenter(trustCenter), nil
|
|
}
|
|
case coredata.TrustCenterAccessEntityType:
|
|
action = probo.ActionTrustCenterAccessGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
trustCenterAccess, err := r.probo.TrustCenterAccesses.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewTrustCenterAccess(trustCenterAccess), nil
|
|
}
|
|
case coredata.RightsRequestEntityType:
|
|
action = probo.ActionRightsRequestGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
rightsRequest, err := r.probo.RightsRequests.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewRightsRequest(rightsRequest), nil
|
|
}
|
|
case coredata.StatementOfApplicabilityEntityType:
|
|
action = probo.ActionStatementOfApplicabilityGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
statementOfApplicability, err := r.probo.StatementsOfApplicability.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewStatementOfApplicability(statementOfApplicability), nil
|
|
}
|
|
case coredata.WebhookSubscriptionEntityType:
|
|
action = probo.ActionWebhookSubscriptionGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
wc, err := r.probo.WebhookSubscriptions.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewWebhookSubscription(wc), nil
|
|
}
|
|
case coredata.AgentRunEntityType:
|
|
action = agentrun.ActionAgentRunGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
run, err := r.agentRun.Get(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewAgentRun(run), nil
|
|
}
|
|
case coredata.AccessReviewCampaignEntityType:
|
|
action = accessreview.ActionCampaignGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
campaign, err := r.accessReview.GetCampaign(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewAccessReviewCampaign(campaign), nil
|
|
}
|
|
case coredata.AccessReviewSourceEntityType:
|
|
action = accessreview.ActionSourceGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
source, err := r.accessReview.GetSource(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewAccessReviewSource(source), nil
|
|
}
|
|
case coredata.AccessReviewEntryEntityType:
|
|
action = accessreview.ActionEntryGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
entry, err := r.accessReview.GetEntry(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewAccessReviewEntry(entry), nil
|
|
}
|
|
case coredata.CookieBannerEntityType:
|
|
action = probo.ActionCookieBannerGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
banner, err := r.cookieBanner.GetCookieBanner(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewCookieBanner(banner), nil
|
|
}
|
|
case coredata.CookieCategoryEntityType:
|
|
action = probo.ActionCookieCategoryGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
category, err := r.cookieBanner.GetCookieCategory(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewCookieCategory(category), nil
|
|
}
|
|
case coredata.CookieConsentRecordEntityType:
|
|
action = probo.ActionCookieConsentRecordList
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
record, err := r.cookieBanner.GetCookieConsentRecord(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewCookieConsentRecord(record), nil
|
|
}
|
|
case coredata.TrackerPatternEntityType:
|
|
action = probo.ActionTrackerPatternGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
pattern, err := r.cookieBanner.GetTrackerPattern(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewTrackerPatternNode(pattern), nil
|
|
}
|
|
case coredata.CookieBannerVersionEntityType:
|
|
action = probo.ActionCookieBannerVersionGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
version, err := r.cookieBanner.GetCookieBannerVersion(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &types.CookieBannerVersion{
|
|
ID: version.ID,
|
|
Version: version.Version,
|
|
State: string(version.State),
|
|
CreatedAt: version.CreatedAt,
|
|
UpdatedAt: version.UpdatedAt,
|
|
}, nil
|
|
}
|
|
default:
|
|
}
|
|
|
|
scope, err := r.authorize(ctx, id, action)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
node, err := loadNode(ctx, scope, id)
|
|
if err != nil {
|
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
|
|
r.logger.ErrorCtx(ctx, "cannot load node", log.Error(err))
|
|
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return node, nil
|
|
}
|
|
|
|
// Viewer is the resolver for the viewer field.
|
|
func (r *queryResolver) Viewer(ctx context.Context) (*types.Viewer, error) {
|
|
identity := authn.IdentityFromContext(ctx)
|
|
|
|
session := authn.SessionFromContext(ctx)
|
|
apiKey := authn.APIKeyFromContext(ctx)
|
|
|
|
var viewerID gid.GID
|
|
if session != nil {
|
|
viewerID = session.ID
|
|
} else if apiKey != nil {
|
|
viewerID = apiKey.ID
|
|
} else {
|
|
viewerID = identity.ID
|
|
}
|
|
|
|
return &types.Viewer{ID: viewerID}, nil
|
|
}
|
|
|
|
// CommonThirdParties is the resolver for the commonThirdParties field.
|
|
func (r *queryResolver) CommonThirdParties(ctx context.Context, name string) ([]*types.CommonThirdParty, error) {
|
|
identity := authn.IdentityFromContext(ctx)
|
|
|
|
if _, err := r.authorize(ctx, identity.ID, probo.ActionCommonThirdPartyList); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
parties, err := r.thirdParty.Search(ctx, name)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot search common third parties", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
result := make([]*types.CommonThirdParty, len(parties))
|
|
for i, p := range parties {
|
|
result[i] = types.NewCommonThirdParty(p)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// AccessReviewDrivers is the resolver for the accessReviewDrivers field.
|
|
func (r *queryResolver) AccessReviewDrivers(ctx context.Context) ([]*types.ConnectorProviderInfo, error) {
|
|
identity := authn.IdentityFromContext(ctx)
|
|
|
|
if _, err := r.authorize(ctx, identity.ID, probo.ActionAccessReviewDriverCatalogList); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
registrations := r.providerRegistry.All()
|
|
infos := make([]*types.ConnectorProviderInfo, 0, len(registrations))
|
|
|
|
for _, reg := range registrations {
|
|
if reg == nil || reg.NewDriver == nil {
|
|
continue
|
|
}
|
|
|
|
provider := reg.Provider
|
|
_, oauthErr := r.connectorRegistry.Get(string(provider))
|
|
oauthConfigured := oauthErr == nil
|
|
apiKeySupported := reg.SupportsAPIKey
|
|
clientCredentialsSupported := reg.SupportsClientCredentials
|
|
|
|
// Skip providers that cannot be connected in this deployment: no
|
|
// OAuth client credentials configured and no key-based fallback
|
|
// (API key or client credentials) supported.
|
|
if !oauthConfigured && !apiKeySupported && !clientCredentialsSupported {
|
|
continue
|
|
}
|
|
|
|
scopes := r.providerRegistry.ProviderOAuth2Scopes(provider)
|
|
if scopes == nil {
|
|
scopes = []string{}
|
|
}
|
|
|
|
extraSettings := make([]*types.ConnectorProviderSettingInfo, 0, len(reg.ExtraSettings))
|
|
for _, setting := range reg.ExtraSettings {
|
|
extraSettings = append(
|
|
extraSettings,
|
|
&types.ConnectorProviderSettingInfo{
|
|
Key: setting.Key,
|
|
Label: setting.Label,
|
|
Required: setting.Required,
|
|
},
|
|
)
|
|
}
|
|
|
|
infos = append(infos, &types.ConnectorProviderInfo{
|
|
Provider: provider,
|
|
DisplayName: reg.DisplayName,
|
|
OauthConfigured: oauthConfigured,
|
|
APIKeySupported: apiKeySupported,
|
|
ClientCredentialsSupported: clientCredentialsSupported,
|
|
Oauth2Scopes: scopes,
|
|
ExtraSettings: extraSettings,
|
|
})
|
|
}
|
|
|
|
slices.SortFunc(
|
|
infos,
|
|
func(a, b *types.ConnectorProviderInfo) int {
|
|
return strings.Compare(a.DisplayName, b.DisplayName)
|
|
},
|
|
)
|
|
|
|
return infos, nil
|
|
}
|
|
|
|
// Mutation returns schema.MutationResolver implementation.
|
|
func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver{r} }
|
|
|
|
// Query returns schema.QueryResolver implementation.
|
|
func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
|
|
|
|
type mutationResolver struct{ *Resolver }
|
|
type queryResolver struct{ *Resolver }
|