From 231f7d153ea6429fee2588460fc999a92440a718 Mon Sep 17 00:00:00 2001 From: Bryan Frimin Date: Mon, 22 Jun 2026 10:59:04 +0200 Subject: [PATCH] Replace trust center alias with resource alias in console API Drop the setTrustCenterAlias and removeTrustCenterAlias mutations and the alias field on Audit in favor of generic setResourceAlias and removeResourceAlias mutations backed by the resourcealias service. Signed-off-by: Bryan Frimin --- pkg/server/api/console/v1/audit_resolvers.go | 16 --- .../api/console/v1/document_resolvers.go | 5 +- pkg/server/api/console/v1/gqlgen.yaml | 4 +- .../api/console/v1/graphql/audit.graphql | 1 - .../console/v1/graphql/resource_alias.graphql | 30 ++++++ .../console/v1/graphql/trust_center.graphql | 29 ----- pkg/server/api/console/v1/graphql_handler.go | 3 + pkg/server/api/console/v1/resolver.go | 4 + .../console/v1/resource_alias_resolvers.go | 71 ++++++++++++ .../api/console/v1/trust_center_resolvers.go | 101 +----------------- ...rust_center_alias.go => resource_alias.go} | 16 ++- 11 files changed, 123 insertions(+), 157 deletions(-) create mode 100644 pkg/server/api/console/v1/graphql/resource_alias.graphql create mode 100644 pkg/server/api/console/v1/resource_alias_resolvers.go rename pkg/server/api/console/v1/types/{trust_center_alias.go => resource_alias.go} (70%) diff --git a/pkg/server/api/console/v1/audit_resolvers.go b/pkg/server/api/console/v1/audit_resolvers.go index 848333e51..1fae3fb8c 100644 --- a/pkg/server/api/console/v1/audit_resolvers.go +++ b/pkg/server/api/console/v1/audit_resolvers.go @@ -173,22 +173,6 @@ func (r *auditResolver) Findings(ctx context.Context, obj *types.Audit, first *i return types.NewFindingConnection(p, r, obj.ID, filter), nil } -// Alias is the resolver for the alias field. -func (r *auditResolver) Alias(ctx context.Context, obj *types.Audit) (*string, error) { - scope, err := r.authorize(ctx, obj.ID, probo.ActionAuditGet) - if err != nil { - return nil, err - } - - alias, err := r.probo.TrustCenterAliases.GetByResourceID(ctx, scope, obj.ID) - if err != nil { - r.logger.ErrorCtx(ctx, "cannot get audit alias", log.Error(err)) - return nil, gqlutils.Internal(ctx) - } - - return alias, nil -} - // Permission is the resolver for the permission field. func (r *auditResolver) Permission(ctx context.Context, obj *types.Audit, action string) (bool, error) { return r.Resolver.Permission(ctx, obj, action) diff --git a/pkg/server/api/console/v1/document_resolvers.go b/pkg/server/api/console/v1/document_resolvers.go index 2958295c8..3398debe5 100644 --- a/pkg/server/api/console/v1/document_resolvers.go +++ b/pkg/server/api/console/v1/document_resolvers.go @@ -19,6 +19,7 @@ import ( "go.probo.inc/probo/pkg/iam" "go.probo.inc/probo/pkg/page" "go.probo.inc/probo/pkg/probo" + "go.probo.inc/probo/pkg/resourcealias" "go.probo.inc/probo/pkg/server/api/authn" "go.probo.inc/probo/pkg/server/api/console/v1/dataloader" "go.probo.inc/probo/pkg/server/api/console/v1/schema" @@ -29,12 +30,12 @@ import ( // Alias is the resolver for the alias field. func (r *documentResolver) Alias(ctx context.Context, obj *types.Document) (*string, error) { - scope, err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet) + scope, err := r.authorize(ctx, obj.ID, resourcealias.ActionAliasGet) if err != nil { return nil, err } - return r.probo.TrustCenterAliases.GetByResourceID(ctx, scope, obj.ID) + return r.resourceAlias.GetByResourceID(ctx, scope, obj.ID) } // Organization is the resolver for the organization field. diff --git a/pkg/server/api/console/v1/gqlgen.yaml b/pkg/server/api/console/v1/gqlgen.yaml index e2f5e7d9a..55c2144f6 100644 --- a/pkg/server/api/console/v1/gqlgen.yaml +++ b/pkg/server/api/console/v1/gqlgen.yaml @@ -41,6 +41,6 @@ models: EmailAddr: model: - "go.probo.inc/probo/pkg/server/gqlutils/types/mail.AddrScalar" - TrustCenterAlias: + ResourceAlias: model: - - "go.probo.inc/probo/pkg/server/api/console/v1/types.TrustCenterAlias" + - "go.probo.inc/probo/pkg/server/api/console/v1/types.ResourceAlias" diff --git a/pkg/server/api/console/v1/graphql/audit.graphql b/pkg/server/api/console/v1/graphql/audit.graphql index 25f414d41..ad49a3000 100644 --- a/pkg/server/api/console/v1/graphql/audit.graphql +++ b/pkg/server/api/console/v1/graphql/audit.graphql @@ -173,7 +173,6 @@ type Audit implements Node { ): FindingConnection @goField(forceResolver: true) trustCenterVisibility: TrustCenterVisibility! - alias: String @goField(forceResolver: true) createdAt: Datetime! updatedAt: Datetime! diff --git a/pkg/server/api/console/v1/graphql/resource_alias.graphql b/pkg/server/api/console/v1/graphql/resource_alias.graphql new file mode 100644 index 000000000..a9c43f001 --- /dev/null +++ b/pkg/server/api/console/v1/graphql/resource_alias.graphql @@ -0,0 +1,30 @@ +type ResourceAlias { + resourceId: ID! + alias: String! +} + +input SetResourceAliasInput { + resourceId: ID! + alias: String! +} + +input RemoveResourceAliasInput { + resourceId: ID! +} + +type SetResourceAliasPayload { + resourceAlias: ResourceAlias! +} + +type RemoveResourceAliasPayload { + deletedResourceId: ID! +} + +extend type Mutation { + setResourceAlias( + input: SetResourceAliasInput! + ): SetResourceAliasPayload! + removeResourceAlias( + input: RemoveResourceAliasInput! + ): RemoveResourceAliasPayload! +} diff --git a/pkg/server/api/console/v1/graphql/trust_center.graphql b/pkg/server/api/console/v1/graphql/trust_center.graphql index 2b24a5213..6d8d06738 100644 --- a/pkg/server/api/console/v1/graphql/trust_center.graphql +++ b/pkg/server/api/console/v1/graphql/trust_center.graphql @@ -550,12 +550,6 @@ extend type Mutation { deleteCustomDomain( input: DeleteCustomDomainInput! ): DeleteCustomDomainPayload! - setTrustCenterAlias( - input: SetTrustCenterAliasInput! - ): SetTrustCenterAliasPayload! - removeTrustCenterAlias( - input: RemoveTrustCenterAliasInput! - ): RemoveTrustCenterAliasPayload! } input UpdateTrustCenterInput { @@ -765,26 +759,3 @@ type CreateCustomDomainPayload { type DeleteCustomDomainPayload { deletedCustomDomainId: ID! } - -input SetTrustCenterAliasInput { - resourceId: ID! - alias: String! -} - -input RemoveTrustCenterAliasInput { - resourceId: ID! -} - -type TrustCenterAlias { - resourceId: ID! - alias: String! - organization: Organization! @goField(forceResolver: true) -} - -type SetTrustCenterAliasPayload { - alias: TrustCenterAlias! -} - -type RemoveTrustCenterAliasPayload { - deletedResourceId: ID! -} diff --git a/pkg/server/api/console/v1/graphql_handler.go b/pkg/server/api/console/v1/graphql_handler.go index 89d9ab36b..1b293f55b 100644 --- a/pkg/server/api/console/v1/graphql_handler.go +++ b/pkg/server/api/console/v1/graphql_handler.go @@ -29,6 +29,7 @@ import ( "go.probo.inc/probo/pkg/iam" "go.probo.inc/probo/pkg/mailman" "go.probo.inc/probo/pkg/probo" + "go.probo.inc/probo/pkg/resourcealias" "go.probo.inc/probo/pkg/riskmanagement" "go.probo.inc/probo/pkg/server/api/authz" "go.probo.inc/probo/pkg/server/api/console/v1/dataloader" @@ -40,6 +41,7 @@ import ( func NewGraphQLHandler( iamSvc *iam.Service, proboSvc *probo.Service, + resourceAliasSvc *resourcealias.Service, esignSvc *esign.Service, accessReviewSvc *accessreview.Service, agentRunSvc *agentrun.Service, @@ -59,6 +61,7 @@ func NewGraphQLHandler( authorize: dataloader.NewAuthorizeFunc(logger), batchAuthorize: authz.NewBatchAuthorizeFunc(iamSvc, logger), probo: proboSvc, + resourceAlias: resourceAliasSvc, iam: iamSvc, esign: esignSvc, accessReview: accessReviewSvc, diff --git a/pkg/server/api/console/v1/resolver.go b/pkg/server/api/console/v1/resolver.go index 238760e44..dc81621b9 100644 --- a/pkg/server/api/console/v1/resolver.go +++ b/pkg/server/api/console/v1/resolver.go @@ -39,6 +39,7 @@ import ( "go.probo.inc/probo/pkg/iam" "go.probo.inc/probo/pkg/mailman" "go.probo.inc/probo/pkg/probo" + "go.probo.inc/probo/pkg/resourcealias" "go.probo.inc/probo/pkg/riskmanagement" "go.probo.inc/probo/pkg/saferedirect" "go.probo.inc/probo/pkg/securecookie" @@ -54,6 +55,7 @@ type ( authorize authz.AuthorizeFunc batchAuthorize authz.BatchAuthorizeFunc probo *probo.Service + resourceAlias *resourcealias.Service iam *iam.Service esign *esign.Service accessReview *accessreview.Service @@ -74,6 +76,7 @@ type ( func NewMux( logger *log.Logger, proboSvc *probo.Service, + resourceAliasSvc *resourcealias.Service, iamSvc *iam.Service, esignSvc *esign.Service, accessReviewSvc *accessreview.Service, @@ -97,6 +100,7 @@ func NewMux( graphqlHandler := NewGraphQLHandler( iamSvc, proboSvc, + resourceAliasSvc, esignSvc, accessReviewSvc, agentRunSvc, diff --git a/pkg/server/api/console/v1/resource_alias_resolvers.go b/pkg/server/api/console/v1/resource_alias_resolvers.go new file mode 100644 index 000000000..7135eafd3 --- /dev/null +++ b/pkg/server/api/console/v1/resource_alias_resolvers.go @@ -0,0 +1,71 @@ +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" + + "go.gearno.de/kit/log" + "go.probo.inc/probo/pkg/coredata" + "go.probo.inc/probo/pkg/resourcealias" + "go.probo.inc/probo/pkg/server/api/console/v1/types" + "go.probo.inc/probo/pkg/server/gqlutils" + "go.probo.inc/probo/pkg/validator" +) + +// SetResourceAlias is the resolver for the setResourceAlias field. +func (r *mutationResolver) SetResourceAlias(ctx context.Context, input types.SetResourceAliasInput) (*types.SetResourceAliasPayload, error) { + scope, err := r.authorize(ctx, input.ResourceID, resourcealias.ActionAliasSet) + if err != nil { + return nil, err + } + + alias, err := r.resourceAlias.Create( + ctx, + scope, + resourcealias.CreateRequest{ + ResourceID: input.ResourceID, + Alias: input.Alias, + }, + ) + if err != nil { + if errors.Is(err, coredata.ErrResourceAlreadyExists) { + return nil, gqlutils.Conflict(ctx, err) + } + + if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok { + return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors) + } + + r.logger.ErrorCtx(ctx, "cannot set resource alias", log.Error(err)) + + return nil, gqlutils.Internal(ctx) + } + + return &types.SetResourceAliasPayload{ + ResourceAlias: types.NewResourceAlias(input.ResourceID, alias), + }, nil +} + +// RemoveResourceAlias is the resolver for the removeResourceAlias field. +func (r *mutationResolver) RemoveResourceAlias(ctx context.Context, input types.RemoveResourceAliasInput) (*types.RemoveResourceAliasPayload, error) { + scope, err := r.authorize(ctx, input.ResourceID, resourcealias.ActionAliasRemove) + if err != nil { + return nil, err + } + + err = r.resourceAlias.Remove(ctx, scope, input.ResourceID) + if err != nil { + r.logger.ErrorCtx(ctx, "cannot remove resource alias", log.Error(err)) + + return nil, gqlutils.Internal(ctx) + } + + return &types.RemoveResourceAliasPayload{ + DeletedResourceID: input.ResourceID, + }, nil +} diff --git a/pkg/server/api/console/v1/trust_center_resolvers.go b/pkg/server/api/console/v1/trust_center_resolvers.go index abd867340..7bad7a961 100644 --- a/pkg/server/api/console/v1/trust_center_resolvers.go +++ b/pkg/server/api/console/v1/trust_center_resolvers.go @@ -16,6 +16,7 @@ import ( "go.probo.inc/probo/pkg/iam" "go.probo.inc/probo/pkg/page" "go.probo.inc/probo/pkg/probo" + "go.probo.inc/probo/pkg/resourcealias" "go.probo.inc/probo/pkg/server/api/console/v1/dataloader" "go.probo.inc/probo/pkg/server/api/console/v1/schema" "go.probo.inc/probo/pkg/server/api/console/v1/types" @@ -688,75 +689,6 @@ func (r *mutationResolver) DeleteCustomDomain(ctx context.Context, input types.D }, nil } -// SetTrustCenterAlias is the resolver for the setTrustCenterAlias field. -func (r *mutationResolver) SetTrustCenterAlias(ctx context.Context, input types.SetTrustCenterAliasInput) (*types.SetTrustCenterAliasPayload, error) { - scope, err := r.authorize(ctx, input.ResourceID, probo.ActionTrustCenterAliasSet) - if err != nil { - return nil, err - } - - alias, err := r.probo.TrustCenterAliases.Create( - ctx, - scope, - probo.CreateTrustCenterAliasRequest{ - ResourceID: input.ResourceID, - Alias: input.Alias, - }, - ) - if err != nil { - if errors.Is(err, coredata.ErrResourceAlreadyExists) { - return nil, gqlutils.Conflict(ctx, err) - } - - if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok { - return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors) - } - - if _, ok := errors.AsType[*probo.ErrTrustCenterAliasAuditReportMissing](err); ok { - return nil, gqlutils.Invalid(ctx, err) - } - - if _, ok := errors.AsType[*probo.ErrTrustCenterAliasResourceInvalid](err); ok { - return nil, gqlutils.Invalid(ctx, err) - } - - r.logger.ErrorCtx(ctx, "cannot set trust center alias", log.Error(err)) - - return nil, gqlutils.Internal(ctx) - } - - return &types.SetTrustCenterAliasPayload{ - Alias: types.NewTrustCenterAlias(input.ResourceID, alias), - }, nil -} - -// RemoveTrustCenterAlias is the resolver for the removeTrustCenterAlias field. -func (r *mutationResolver) RemoveTrustCenterAlias(ctx context.Context, input types.RemoveTrustCenterAliasInput) (*types.RemoveTrustCenterAliasPayload, error) { - scope, err := r.authorize(ctx, input.ResourceID, probo.ActionTrustCenterAliasRemove) - if err != nil { - return nil, err - } - - _, err = r.probo.TrustCenterAliases.Remove(ctx, scope, input.ResourceID) - if err != nil { - if _, ok := errors.AsType[*probo.ErrTrustCenterAliasAuditReportMissing](err); ok { - return nil, gqlutils.Invalid(ctx, err) - } - - if _, ok := errors.AsType[*probo.ErrTrustCenterAliasResourceInvalid](err); ok { - return nil, gqlutils.Invalid(ctx, err) - } - - r.logger.ErrorCtx(ctx, "cannot remove trust center alias", log.Error(err)) - - return nil, gqlutils.Internal(ctx) - } - - return &types.RemoveTrustCenterAliasPayload{ - DeletedResourceID: input.ResourceID, - }, nil -} - // Logo is the resolver for the logo field. func (r *trustCenterResolver) Logo(ctx context.Context, obj *types.TrustCenter) (*types.File, error) { if _, err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterGet); err != nil { @@ -1085,27 +1017,6 @@ func (r *trustCenterAccessResolver) Permission(ctx context.Context, obj *types.T return r.Resolver.Permission(ctx, obj, action) } -// Organization is the resolver for the organization field. -func (r *trustCenterAliasResolver) Organization(ctx context.Context, obj *types.TrustCenterAlias) (*types.Organization, error) { - scope, err := r.authorize(ctx, obj.OrganizationID, probo.ActionOrganizationGet) - if err != nil { - return nil, err - } - - organization, err := r.probo.Organizations.Get(ctx, scope, obj.OrganizationID) - if err != nil { - if errors.Is(err, coredata.ErrResourceNotFound) { - return nil, gqlutils.NotFound(ctx, err) - } - - r.logger.ErrorCtx(ctx, "cannot get organization", log.Error(err)) - - return nil, gqlutils.Internal(ctx) - } - - return types.NewOrganization(organization), nil -} - // Document is the resolver for the document field. func (r *trustCenterDocumentAccessResolver) Document(ctx context.Context, obj *types.TrustCenterDocumentAccess) (*types.Document, error) { scope, err := r.authorize(ctx, obj.ID, probo.ActionDocumentGet) @@ -1229,12 +1140,12 @@ func (r *trustCenterFileResolver) File(ctx context.Context, obj *types.TrustCent // Alias is the resolver for the alias field. func (r *trustCenterFileResolver) Alias(ctx context.Context, obj *types.TrustCenterFile) (*string, error) { - scope, err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterFileGet) + scope, err := r.authorize(ctx, obj.ID, resourcealias.ActionAliasGet) if err != nil { return nil, err } - return r.probo.TrustCenterAliases.GetByResourceID(ctx, scope, obj.ID) + return r.resourceAlias.GetByResourceID(ctx, scope, obj.ID) } // Organization is the resolver for the organization field. @@ -1336,11 +1247,6 @@ func (r *Resolver) TrustCenterAccess() schema.TrustCenterAccessResolver { return &trustCenterAccessResolver{r} } -// TrustCenterAlias returns schema.TrustCenterAliasResolver implementation. -func (r *Resolver) TrustCenterAlias() schema.TrustCenterAliasResolver { - return &trustCenterAliasResolver{r} -} - // TrustCenterDocumentAccess returns schema.TrustCenterDocumentAccessResolver implementation. func (r *Resolver) TrustCenterDocumentAccess() schema.TrustCenterDocumentAccessResolver { return &trustCenterDocumentAccessResolver{r} @@ -1376,7 +1282,6 @@ type complianceFrameworkResolver struct{ *Resolver } type customDomainResolver struct{ *Resolver } type trustCenterResolver struct{ *Resolver } type trustCenterAccessResolver struct{ *Resolver } -type trustCenterAliasResolver struct{ *Resolver } type trustCenterDocumentAccessResolver struct{ *Resolver } type trustCenterDocumentAccessConnectionResolver struct{ *Resolver } type trustCenterFileResolver struct{ *Resolver } diff --git a/pkg/server/api/console/v1/types/trust_center_alias.go b/pkg/server/api/console/v1/types/resource_alias.go similarity index 70% rename from pkg/server/api/console/v1/types/trust_center_alias.go rename to pkg/server/api/console/v1/types/resource_alias.go index 8a298b2c4..0404dc488 100644 --- a/pkg/server/api/console/v1/types/trust_center_alias.go +++ b/pkg/server/api/console/v1/types/resource_alias.go @@ -19,16 +19,14 @@ import ( "go.probo.inc/probo/pkg/gid" ) -type TrustCenterAlias struct { - ResourceID gid.GID `json:"resourceId"` - Alias string `json:"alias"` - OrganizationID gid.GID `json:"-"` +type ResourceAlias struct { + ResourceID gid.GID `json:"resourceId"` + Alias string `json:"alias"` } -func NewTrustCenterAlias(resourceID gid.GID, alias *coredata.TrustCenterAlias) *TrustCenterAlias { - return &TrustCenterAlias{ - ResourceID: resourceID, - Alias: alias.Alias, - OrganizationID: alias.OrganizationID, +func NewResourceAlias(resourceID gid.GID, alias *coredata.ResourceAlias) *ResourceAlias { + return &ResourceAlias{ + ResourceID: resourceID, + Alias: alias.Alias, } }