Expose campaign sources as first-class nodes, paginate fetch attempts instead of denormalized status fields, and bind entries to their campaign snapshot. Update GraphQL, MCP, CLI, console, and e2e coverage to match. Signed-off-by: Bryan Frimin <bryan@probo.com>
621 lines
20 KiB
Go
621 lines
20 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.AccessReviewCampaignSourceEntityType:
|
|
action = accessreview.ActionCampaignGet
|
|
loadNode = func(ctx context.Context, scope *coredata.Scope, id gid.GID) (types.Node, error) {
|
|
campaignSource, err := r.accessReview.GetCampaignSource(ctx, scope, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return types.NewAccessReviewCampaignSource(campaignSource), 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 }
|