Replace third-party owners with administrators
Some checks failed
github / Analyze (go) (push) Has been cancelled
github / Analyze (actions) (push) Has been cancelled
github / Analyze (javascript-typescript) (push) Has been cancelled
make / build-apps (push) Has been cancelled
make / probod binary (darwin/amd64) (push) Has been cancelled
make / probod binary (freebsd/amd64) (push) Has been cancelled
make / probod binary (linux/amd64) (push) Has been cancelled
make / probod binary (openbsd/amd64) (push) Has been cancelled
make / probod binary (windows/amd64) (push) Has been cancelled
make / probod binary (darwin/arm64) (push) Has been cancelled
make / probod binary (freebsd/arm64) (push) Has been cancelled
make / probod binary (linux/arm64) (push) Has been cancelled
make / probod binary (openbsd/arm64) (push) Has been cancelled
make / probo-agent (darwin/amd64) (push) Has been cancelled
make / probo-agent (freebsd/amd64) (push) Has been cancelled
make / probo-agent (linux/amd64) (push) Has been cancelled
make / probo-agent (windows/amd64) (push) Has been cancelled
make / probo-agent (darwin/arm64) (push) Has been cancelled
make / probo-agent (freebsd/arm64) (push) Has been cancelled
make / probo-agent (linux/arm64) (push) Has been cancelled
make / probo-agent (windows/arm64) (push) Has been cancelled
make / docker (amd64) (push) Has been cancelled
make / docker (arm64) (push) Has been cancelled
make / snapshot-scan (push) Has been cancelled
make / build-probod (push) Has been cancelled
make / build-probo-agent (push) Has been cancelled
make / lint-go (push) Has been cancelled
make / lint-js (push) Has been cancelled
make / lint-swift (push) Has been cancelled
make / lint-shell (push) Has been cancelled
make / test (push) Has been cancelled
make / test-e2e (push) Has been cancelled
trufflehog / scan (push) Has been cancelled
Some checks failed
github / Analyze (go) (push) Has been cancelled
github / Analyze (actions) (push) Has been cancelled
github / Analyze (javascript-typescript) (push) Has been cancelled
make / build-apps (push) Has been cancelled
make / probod binary (darwin/amd64) (push) Has been cancelled
make / probod binary (freebsd/amd64) (push) Has been cancelled
make / probod binary (linux/amd64) (push) Has been cancelled
make / probod binary (openbsd/amd64) (push) Has been cancelled
make / probod binary (windows/amd64) (push) Has been cancelled
make / probod binary (darwin/arm64) (push) Has been cancelled
make / probod binary (freebsd/arm64) (push) Has been cancelled
make / probod binary (linux/arm64) (push) Has been cancelled
make / probod binary (openbsd/arm64) (push) Has been cancelled
make / probo-agent (darwin/amd64) (push) Has been cancelled
make / probo-agent (freebsd/amd64) (push) Has been cancelled
make / probo-agent (linux/amd64) (push) Has been cancelled
make / probo-agent (windows/amd64) (push) Has been cancelled
make / probo-agent (darwin/arm64) (push) Has been cancelled
make / probo-agent (freebsd/arm64) (push) Has been cancelled
make / probo-agent (linux/arm64) (push) Has been cancelled
make / probo-agent (windows/arm64) (push) Has been cancelled
make / docker (amd64) (push) Has been cancelled
make / docker (arm64) (push) Has been cancelled
make / snapshot-scan (push) Has been cancelled
make / build-probod (push) Has been cancelled
make / build-probo-agent (push) Has been cancelled
make / lint-go (push) Has been cancelled
make / lint-js (push) Has been cancelled
make / lint-swift (push) Has been cancelled
make / lint-shell (push) Has been cancelled
make / test (push) Has been cancelled
make / test-e2e (push) Has been cancelled
trufflehog / scan (push) Has been cancelled
Migrate business and security owners into a shared administrators list across GraphQL, MCP, CLI, n8n, and the console. Signed-off-by: Sacha Al Himdani <sacha@probo.com>
This commit is contained in:
@@ -58,21 +58,22 @@ type (
|
||||
}
|
||||
|
||||
Loaders struct {
|
||||
Organization *dataloadgen.Loader[gid.GID, *coredata.Organization]
|
||||
Framework *dataloadgen.Loader[gid.GID, *coredata.Framework]
|
||||
Control *dataloadgen.Loader[gid.GID, *coredata.Control]
|
||||
ThirdParty *dataloadgen.Loader[gid.GID, *coredata.ThirdParty]
|
||||
Document *dataloadgen.Loader[gid.GID, *coredata.Document]
|
||||
Profile *dataloadgen.Loader[gid.GID, *coredata.MembershipProfile]
|
||||
Risk *dataloadgen.Loader[gid.GID, *coredata.Risk]
|
||||
Measure *dataloadgen.Loader[gid.GID, *coredata.Measure]
|
||||
Task *dataloadgen.Loader[gid.GID, *coredata.Task]
|
||||
File *dataloadgen.Loader[gid.GID, *coredata.File]
|
||||
CookieBanner *dataloadgen.Loader[gid.GID, *coredata.CookieBanner]
|
||||
CookieCategory *dataloadgen.Loader[gid.GID, *coredata.CookieCategory]
|
||||
CommonTrackerPattern *dataloadgen.Loader[gid.GID, *coredata.CommonTrackerPattern]
|
||||
CommonThirdParty *dataloadgen.Loader[gid.GID, *coredata.CommonThirdParty]
|
||||
Authorize *dataloadgen.Loader[AuthorizeKey, AuthorizeResult]
|
||||
Organization *dataloadgen.Loader[gid.GID, *coredata.Organization]
|
||||
Framework *dataloadgen.Loader[gid.GID, *coredata.Framework]
|
||||
Control *dataloadgen.Loader[gid.GID, *coredata.Control]
|
||||
ThirdParty *dataloadgen.Loader[gid.GID, *coredata.ThirdParty]
|
||||
Document *dataloadgen.Loader[gid.GID, *coredata.Document]
|
||||
Profile *dataloadgen.Loader[gid.GID, *coredata.MembershipProfile]
|
||||
Risk *dataloadgen.Loader[gid.GID, *coredata.Risk]
|
||||
Measure *dataloadgen.Loader[gid.GID, *coredata.Measure]
|
||||
Task *dataloadgen.Loader[gid.GID, *coredata.Task]
|
||||
File *dataloadgen.Loader[gid.GID, *coredata.File]
|
||||
CookieBanner *dataloadgen.Loader[gid.GID, *coredata.CookieBanner]
|
||||
CookieCategory *dataloadgen.Loader[gid.GID, *coredata.CookieCategory]
|
||||
CommonTrackerPattern *dataloadgen.Loader[gid.GID, *coredata.CommonTrackerPattern]
|
||||
CommonThirdParty *dataloadgen.Loader[gid.GID, *coredata.CommonThirdParty]
|
||||
ThirdPartyAdministratorIDs *dataloadgen.Loader[gid.GID, []gid.GID]
|
||||
Authorize *dataloadgen.Loader[AuthorizeKey, AuthorizeResult]
|
||||
}
|
||||
|
||||
batchFetcher struct {
|
||||
@@ -109,20 +110,21 @@ func NewMiddleware(proboSvc *probo.Service, iamSvc *iam.Service, cookieBannerSvc
|
||||
|
||||
func (f *batchFetcher) newLoaders() *Loaders {
|
||||
return &Loaders{
|
||||
Organization: dataloadgen.NewMappedLoader(f.fetchOrganizations),
|
||||
Framework: dataloadgen.NewMappedLoader(f.fetchFrameworks),
|
||||
Control: dataloadgen.NewMappedLoader(f.fetchControls),
|
||||
ThirdParty: dataloadgen.NewMappedLoader(f.fetchThirdParties),
|
||||
Document: dataloadgen.NewMappedLoader(f.fetchDocuments),
|
||||
Profile: dataloadgen.NewMappedLoader(f.fetchProfiles),
|
||||
Risk: dataloadgen.NewMappedLoader(f.fetchRisks),
|
||||
Measure: dataloadgen.NewMappedLoader(f.fetchMeasures),
|
||||
Task: dataloadgen.NewMappedLoader(f.fetchTasks),
|
||||
File: dataloadgen.NewMappedLoader(f.fetchFiles),
|
||||
CookieBanner: dataloadgen.NewMappedLoader(f.fetchCookieBanners),
|
||||
CookieCategory: dataloadgen.NewMappedLoader(f.fetchCookieCategories),
|
||||
CommonTrackerPattern: dataloadgen.NewMappedLoader(f.fetchCommonTrackerPatterns),
|
||||
CommonThirdParty: dataloadgen.NewMappedLoader(f.fetchCommonThirdParties),
|
||||
Organization: dataloadgen.NewMappedLoader(f.fetchOrganizations),
|
||||
Framework: dataloadgen.NewMappedLoader(f.fetchFrameworks),
|
||||
Control: dataloadgen.NewMappedLoader(f.fetchControls),
|
||||
ThirdParty: dataloadgen.NewMappedLoader(f.fetchThirdParties),
|
||||
Document: dataloadgen.NewMappedLoader(f.fetchDocuments),
|
||||
Profile: dataloadgen.NewMappedLoader(f.fetchProfiles),
|
||||
Risk: dataloadgen.NewMappedLoader(f.fetchRisks),
|
||||
Measure: dataloadgen.NewMappedLoader(f.fetchMeasures),
|
||||
Task: dataloadgen.NewMappedLoader(f.fetchTasks),
|
||||
File: dataloadgen.NewMappedLoader(f.fetchFiles),
|
||||
CookieBanner: dataloadgen.NewMappedLoader(f.fetchCookieBanners),
|
||||
CookieCategory: dataloadgen.NewMappedLoader(f.fetchCookieCategories),
|
||||
CommonTrackerPattern: dataloadgen.NewMappedLoader(f.fetchCommonTrackerPatterns),
|
||||
CommonThirdParty: dataloadgen.NewMappedLoader(f.fetchCommonThirdParties),
|
||||
ThirdPartyAdministratorIDs: dataloadgen.NewMappedLoader(f.fetchThirdPartyAdministratorIDs),
|
||||
Authorize: dataloadgen.NewMappedLoader(
|
||||
f.fetchAuthorizes,
|
||||
dataloadgen.WithoutCache(),
|
||||
@@ -350,6 +352,26 @@ func (f *batchFetcher) fetchCommonThirdParties(ctx context.Context, keys []gid.G
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (f *batchFetcher) fetchThirdPartyAdministratorIDs(ctx context.Context, keys []gid.GID) (map[gid.GID][]gid.GID, error) {
|
||||
scope := coredata.NewScopeFromObjectID(keys[0])
|
||||
|
||||
administratorIDsByThirdPartyID, err := f.probo.ThirdParties.MapAdministratorIDsForThirdPartyIDs(ctx, scope, keys)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot batch load third party administrator ids: %w", err)
|
||||
}
|
||||
|
||||
result := make(map[gid.GID][]gid.GID, len(keys))
|
||||
for _, id := range keys {
|
||||
if ids, ok := administratorIDsByThirdPartyID[id]; ok {
|
||||
result[id] = ids
|
||||
} else {
|
||||
result[id] = []gid.GID{}
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// fetchAuthorizes evaluates the batch with a single AuthorizeMulti call and
|
||||
// surfaces per-key denials via dataloadgen.MappedFetchError. When
|
||||
// AuthorizeMulti cannot evaluate the batch as a whole (e.g. mixed
|
||||
|
||||
@@ -285,8 +285,7 @@ type ThirdParty implements Node {
|
||||
filter: MeasureFilter
|
||||
): MeasureConnection! @goField(forceResolver: true)
|
||||
|
||||
businessOwner: Profile @goField(forceResolver: true)
|
||||
securityOwner: Profile @goField(forceResolver: true)
|
||||
administrators: [Profile!]! @goField(forceResolver: true)
|
||||
|
||||
statusPageUrl: String
|
||||
termsOfServiceUrl: String
|
||||
@@ -540,8 +539,7 @@ input CreateThirdPartyInput {
|
||||
trustPageUrl: String
|
||||
statusPageUrl: String
|
||||
termsOfServiceUrl: String
|
||||
businessOwnerId: ID
|
||||
securityOwnerId: ID
|
||||
administratorIds: [ID!]
|
||||
parentThirdPartyId: ID
|
||||
}
|
||||
|
||||
@@ -564,8 +562,7 @@ input UpdateThirdPartyInput {
|
||||
countries: [CountryCode!]
|
||||
securityPageUrl: String @goField(omittable: true)
|
||||
trustPageUrl: String @goField(omittable: true)
|
||||
businessOwnerId: ID @goField(omittable: true)
|
||||
securityOwnerId: ID @goField(omittable: true)
|
||||
administratorIds: [ID!]
|
||||
showOnCompliancePortal: Boolean
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/vikstrous/dataloadgen"
|
||||
"go.gearno.de/kit/log"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/iam"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/probo"
|
||||
@@ -58,8 +59,7 @@ func (r *mutationResolver) CreateThirdParty(ctx context.Context, input types.Cre
|
||||
Certifications: input.Certifications,
|
||||
SecurityPageURL: input.SecurityPageURL,
|
||||
TrustPageURL: input.TrustPageURL,
|
||||
BusinessOwnerID: input.BusinessOwnerID,
|
||||
SecurityOwnerID: input.SecurityOwnerID,
|
||||
AdministratorIDs: input.AdministratorIds,
|
||||
Countries: input.Countries,
|
||||
ParentThirdPartyID: input.ParentThirdPartyID,
|
||||
},
|
||||
@@ -120,6 +120,11 @@ func (r *mutationResolver) UpdateThirdParty(ctx context.Context, input types.Upd
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var administratorIDs *[]gid.GID
|
||||
if input.AdministratorIds != nil {
|
||||
administratorIDs = &input.AdministratorIds
|
||||
}
|
||||
|
||||
thirdParty, err := r.probo.ThirdParties.Update(
|
||||
ctx, scope,
|
||||
probo.UpdateThirdPartyRequest{
|
||||
@@ -140,8 +145,7 @@ func (r *mutationResolver) UpdateThirdParty(ctx context.Context, input types.Upd
|
||||
WebsiteURL: gqlutils.UnwrapOmittable(input.WebsiteURL),
|
||||
Category: input.Category,
|
||||
Certifications: input.Certifications,
|
||||
BusinessOwnerID: gqlutils.UnwrapOmittable(input.BusinessOwnerID),
|
||||
SecurityOwnerID: gqlutils.UnwrapOmittable(input.SecurityOwnerID),
|
||||
AdministratorIDs: administratorIDs,
|
||||
ShowOnCompliancePortal: input.ShowOnCompliancePortal,
|
||||
Countries: input.Countries,
|
||||
},
|
||||
@@ -855,56 +859,45 @@ func (r *thirdPartyResolver) Measures(ctx context.Context, obj *types.ThirdParty
|
||||
return types.NewMeasureConnection(page, r, obj.ID, measureFilter), nil
|
||||
}
|
||||
|
||||
// BusinessOwner is the resolver for the businessOwner field.
|
||||
func (r *thirdPartyResolver) BusinessOwner(ctx context.Context, obj *types.ThirdParty) (*types.Profile, error) {
|
||||
if obj.BusinessOwner == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if _, err := r.authorize(ctx, obj.BusinessOwner.ID, iam.ActionMembershipProfileGet); err != nil {
|
||||
// Administrators is the resolver for the administrators field.
|
||||
func (r *thirdPartyResolver) Administrators(ctx context.Context, obj *types.ThirdParty) ([]*types.Profile, error) {
|
||||
if _, err := r.authorize(ctx, obj.ID, probo.ActionThirdPartyGet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
loaders := dataloader.FromContext(ctx)
|
||||
|
||||
businessOwner, err := loaders.Profile.Load(ctx, obj.BusinessOwner.ID)
|
||||
administratorIDs, err := loaders.ThirdPartyAdministratorIDs.Load(ctx, obj.ID)
|
||||
if err != nil {
|
||||
if errors.Is(err, coredata.ErrResourceNotFound) || errors.Is(err, dataloadgen.ErrNotFound) {
|
||||
return nil, gqlutils.NotFound(ctx, err)
|
||||
}
|
||||
|
||||
r.logger.ErrorCtx(ctx, "cannot get business owner", log.Error(err))
|
||||
|
||||
r.logger.ErrorCtx(ctx, "cannot get third party administrator ids", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return types.NewProfile(businessOwner), nil
|
||||
}
|
||||
|
||||
// SecurityOwner is the resolver for the securityOwner field.
|
||||
func (r *thirdPartyResolver) SecurityOwner(ctx context.Context, obj *types.ThirdParty) (*types.Profile, error) {
|
||||
if obj.SecurityOwner == nil {
|
||||
return nil, nil
|
||||
if len(administratorIDs) == 0 {
|
||||
return []*types.Profile{}, nil
|
||||
}
|
||||
|
||||
if _, err := r.authorize(ctx, obj.SecurityOwner.ID, iam.ActionMembershipProfileGet); err != nil {
|
||||
if _, err := r.batchAuthorize(ctx, iam.ActionMembershipProfileGet, administratorIDs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
loaders := dataloader.FromContext(ctx)
|
||||
|
||||
securityOwner, err := loaders.Profile.Load(ctx, obj.SecurityOwner.ID)
|
||||
profiles, err := loaders.Profile.LoadAll(ctx, administratorIDs)
|
||||
if err != nil {
|
||||
if errors.Is(err, coredata.ErrResourceNotFound) || errors.Is(err, dataloadgen.ErrNotFound) {
|
||||
return nil, gqlutils.NotFound(ctx, err)
|
||||
}
|
||||
|
||||
r.logger.ErrorCtx(ctx, "cannot get security owner", log.Error(err))
|
||||
r.logger.ErrorCtx(ctx, "cannot get third party administrators", log.Error(err))
|
||||
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return types.NewProfile(securityOwner), nil
|
||||
result := make([]*types.Profile, len(profiles))
|
||||
for i, p := range profiles {
|
||||
result[i] = types.NewProfile(p)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ParentThirdParty is the resolver for the parentThirdParty field.
|
||||
|
||||
@@ -98,18 +98,6 @@ func NewThirdParty(v *coredata.ThirdParty) *ThirdParty {
|
||||
CreatedAt: v.CreatedAt,
|
||||
}
|
||||
|
||||
if v.BusinessOwnerID != nil {
|
||||
object.BusinessOwner = &Profile{
|
||||
ID: *v.BusinessOwnerID,
|
||||
}
|
||||
}
|
||||
|
||||
if v.SecurityOwnerID != nil {
|
||||
object.SecurityOwner = &Profile{
|
||||
ID: *v.SecurityOwnerID,
|
||||
}
|
||||
}
|
||||
|
||||
if v.ParentThirdPartyID != nil {
|
||||
object.ParentThirdParty = &ThirdParty{
|
||||
ID: *v.ParentThirdPartyID,
|
||||
|
||||
@@ -90,7 +90,17 @@ func (r *Resolver) ListThirdPartiesTool(ctx context.Context, req *mcp.CallToolRe
|
||||
panic(fmt.Errorf("cannot list organization thirdParties: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.NewListThirdPartiesOutput(page), nil
|
||||
thirdPartyIDs := make([]gid.GID, len(page.Data))
|
||||
for i, tp := range page.Data {
|
||||
thirdPartyIDs[i] = tp.ID
|
||||
}
|
||||
|
||||
administratorIDsByThirdPartyID, err := prb.ThirdParties.MapAdministratorIDsForThirdPartyIDs(ctx, scope, thirdPartyIDs)
|
||||
if err != nil {
|
||||
return nil, types.ListThirdPartiesOutput{}, fmt.Errorf("cannot load third party administrators: %w", err)
|
||||
}
|
||||
|
||||
return nil, types.NewListThirdPartiesOutput(page, administratorIDsByThirdPartyID), nil
|
||||
}
|
||||
|
||||
// AddThirdPartyTool handles the addThirdParty tool
|
||||
@@ -135,8 +145,7 @@ func (r *Resolver) AddThirdPartyTool(ctx context.Context, req *mcp.CallToolReque
|
||||
SubprocessorsListURL: input.SubprocessorsListURL,
|
||||
Certifications: input.Certifications,
|
||||
Countries: countries,
|
||||
BusinessOwnerID: input.BusinessOwnerID,
|
||||
SecurityOwnerID: input.SecurityOwnerID,
|
||||
AdministratorIDs: input.AdministratorIds,
|
||||
StatusPageURL: input.StatusPageURL,
|
||||
TermsOfServiceURL: input.TermsOfServiceURL,
|
||||
SecurityPageURL: input.SecurityPageURL,
|
||||
@@ -147,7 +156,7 @@ func (r *Resolver) AddThirdPartyTool(ctx context.Context, req *mcp.CallToolReque
|
||||
return nil, types.AddThirdPartyOutput{}, fmt.Errorf("failed to create thirdParty: %w", err)
|
||||
}
|
||||
|
||||
return nil, types.NewAddThirdPartyOutput(thirdParty), nil
|
||||
return nil, types.NewAddThirdPartyOutput(thirdParty, input.AdministratorIds), nil
|
||||
}
|
||||
|
||||
// UpdateThirdPartyTool handles the updateThirdParty tool
|
||||
@@ -225,14 +234,9 @@ func (r *Resolver) UpdateThirdPartyTool(ctx context.Context, req *mcp.CallToolRe
|
||||
trustPageURL = &input.TrustPageURL
|
||||
}
|
||||
|
||||
var businessOwnerID **gid.GID
|
||||
if input.BusinessOwnerID != nil {
|
||||
businessOwnerID = &input.BusinessOwnerID
|
||||
}
|
||||
|
||||
var securityOwnerID **gid.GID
|
||||
if input.SecurityOwnerID != nil {
|
||||
securityOwnerID = &input.SecurityOwnerID
|
||||
var administratorIDs *[]gid.GID
|
||||
if input.AdministratorIds != nil {
|
||||
administratorIDs = &input.AdministratorIds
|
||||
}
|
||||
|
||||
var category *coredata.ThirdPartyCategory
|
||||
@@ -267,8 +271,7 @@ func (r *Resolver) UpdateThirdPartyTool(ctx context.Context, req *mcp.CallToolRe
|
||||
SubprocessorsListURL: subprocessorsListURL,
|
||||
Certifications: input.Certifications,
|
||||
Countries: countries,
|
||||
BusinessOwnerID: businessOwnerID,
|
||||
SecurityOwnerID: securityOwnerID,
|
||||
AdministratorIDs: administratorIDs,
|
||||
StatusPageURL: statusPageURL,
|
||||
TermsOfServiceURL: termsOfServiceURL,
|
||||
SecurityPageURL: securityPageURL,
|
||||
@@ -279,7 +282,12 @@ func (r *Resolver) UpdateThirdPartyTool(ctx context.Context, req *mcp.CallToolRe
|
||||
return nil, types.UpdateThirdPartyOutput{}, fmt.Errorf("failed to update thirdParty: %w", err)
|
||||
}
|
||||
|
||||
return nil, types.NewUpdateThirdPartyOutput(thirdParty), nil
|
||||
administratorIDsByThirdPartyID, err := svc.ThirdParties.MapAdministratorIDsForThirdPartyIDs(ctx, scope, []gid.GID{thirdParty.ID})
|
||||
if err != nil {
|
||||
return nil, types.UpdateThirdPartyOutput{}, fmt.Errorf("cannot load third party administrators: %w", err)
|
||||
}
|
||||
|
||||
return nil, types.NewUpdateThirdPartyOutput(thirdParty, administratorIDsByThirdPartyID[thirdParty.ID]), nil
|
||||
}
|
||||
|
||||
func (r *Resolver) ListRisksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRisksInput) (*mcp.CallToolResult, types.ListRisksOutput, error) {
|
||||
@@ -5414,8 +5422,13 @@ func (r *Resolver) VetThirdPartyTool(ctx context.Context, req *mcp.CallToolReque
|
||||
return nil, types.VetThirdPartyOutput{}, fmt.Errorf("internal server error")
|
||||
}
|
||||
|
||||
administratorIDsByThirdPartyID, err := r.proboSvc.ThirdParties.MapAdministratorIDsForThirdPartyIDs(ctx, scope, []gid.GID{thirdParty.ID})
|
||||
if err != nil {
|
||||
return nil, types.VetThirdPartyOutput{}, fmt.Errorf("cannot load third party administrators: %w", err)
|
||||
}
|
||||
|
||||
return nil, types.VetThirdPartyOutput{
|
||||
ThirdParty: types.NewThirdParty(thirdParty),
|
||||
ThirdParty: types.NewThirdParty(thirdParty, administratorIDsByThirdPartyID[thirdParty.ID]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -6318,7 +6331,17 @@ func (r *Resolver) ListChildThirdPartiesTool(ctx context.Context, req *mcp.CallT
|
||||
panic(fmt.Errorf("cannot list child third parties: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.NewListChildThirdPartiesOutput(page), nil
|
||||
thirdPartyIDs := make([]gid.GID, len(page.Data))
|
||||
for i, tp := range page.Data {
|
||||
thirdPartyIDs[i] = tp.ID
|
||||
}
|
||||
|
||||
administratorIDsByThirdPartyID, err := r.proboSvc.ThirdParties.MapAdministratorIDsForThirdPartyIDs(ctx, scope, thirdPartyIDs)
|
||||
if err != nil {
|
||||
return nil, types.ListChildThirdPartiesOutput{}, fmt.Errorf("cannot load third party administrators: %w", err)
|
||||
}
|
||||
|
||||
return nil, types.NewListChildThirdPartiesOutput(page, administratorIDsByThirdPartyID), nil
|
||||
}
|
||||
|
||||
func (r *Resolver) ListRiskAssessmentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentsInput) (*mcp.CallToolResult, types.ListRiskAssessmentsOutput, error) {
|
||||
@@ -7658,8 +7681,13 @@ func (r *Resolver) GetThirdPartyTool(ctx context.Context, req *mcp.CallToolReque
|
||||
return nil, types.GetThirdPartyOutput{}, fmt.Errorf("cannot get third party: %w", err)
|
||||
}
|
||||
|
||||
administratorIDsByThirdPartyID, err := r.proboSvc.ThirdParties.MapAdministratorIDsForThirdPartyIDs(ctx, scope, []gid.GID{thirdParty.ID})
|
||||
if err != nil {
|
||||
return nil, types.GetThirdPartyOutput{}, fmt.Errorf("cannot load third party administrators: %w", err)
|
||||
}
|
||||
|
||||
return nil, types.GetThirdPartyOutput{
|
||||
ThirdParty: types.NewThirdParty(thirdParty),
|
||||
ThirdParty: types.NewThirdParty(thirdParty, administratorIDsByThirdPartyID[thirdParty.ID]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -825,16 +825,11 @@ components:
|
||||
items:
|
||||
type: string
|
||||
description: Countries or regions (ISO 3166-1 alpha-2 country codes, EU, or GLOBAL)
|
||||
business_owner_id:
|
||||
anyOf:
|
||||
- $ref: "#/components/schemas/GID"
|
||||
- type: "null"
|
||||
description: Business owner ID
|
||||
security_owner_id:
|
||||
anyOf:
|
||||
- $ref: "#/components/schemas/GID"
|
||||
- type: "null"
|
||||
description: Security owner ID
|
||||
administrator_ids:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Administrator profile IDs
|
||||
status_page_url:
|
||||
type:
|
||||
- string
|
||||
@@ -1051,12 +1046,11 @@ components:
|
||||
items:
|
||||
type: string
|
||||
description: Countries or regions (ISO 3166-1 alpha-2 country codes, EU, or GLOBAL)
|
||||
business_owner_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Business owner ID
|
||||
security_owner_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Security owner ID
|
||||
administrator_ids:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Administrator profile IDs
|
||||
status_page_url:
|
||||
type: string
|
||||
description: Status page URL
|
||||
@@ -1152,12 +1146,11 @@ components:
|
||||
items:
|
||||
type: string
|
||||
description: Countries or regions (ISO 3166-1 alpha-2 country codes, EU, or GLOBAL)
|
||||
business_owner_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Business owner ID
|
||||
security_owner_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Security owner ID
|
||||
administrator_ids:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Administrator profile IDs
|
||||
status_page_url:
|
||||
type: string
|
||||
description: Status page URL
|
||||
|
||||
@@ -22,6 +22,7 @@ package types
|
||||
|
||||
import (
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
@@ -64,12 +65,16 @@ func NewAddThirdPartyRiskAssessmentOutput(v *coredata.ThirdPartyRiskAssessment)
|
||||
}
|
||||
}
|
||||
|
||||
func NewThirdParty(v *coredata.ThirdParty) *ThirdParty {
|
||||
func NewThirdParty(v *coredata.ThirdParty, administratorIDs []gid.GID) *ThirdParty {
|
||||
countries := make([]string, len(v.Countries))
|
||||
for i, c := range v.Countries {
|
||||
countries[i] = string(c)
|
||||
}
|
||||
|
||||
if administratorIDs == nil {
|
||||
administratorIDs = []gid.GID{}
|
||||
}
|
||||
|
||||
return &ThirdParty{
|
||||
ID: v.ID,
|
||||
OrganizationID: v.OrganizationID,
|
||||
@@ -86,8 +91,7 @@ func NewThirdParty(v *coredata.ThirdParty) *ThirdParty {
|
||||
SubprocessorsListURL: v.SubprocessorsListURL,
|
||||
Certifications: v.Certifications,
|
||||
Countries: countries,
|
||||
BusinessOwnerID: v.BusinessOwnerID,
|
||||
SecurityOwnerID: v.SecurityOwnerID,
|
||||
AdministratorIds: administratorIDs,
|
||||
StatusPageURL: v.StatusPageURL,
|
||||
TermsOfServiceURL: v.TermsOfServiceURL,
|
||||
SecurityPageURL: v.SecurityPageURL,
|
||||
@@ -98,10 +102,13 @@ func NewThirdParty(v *coredata.ThirdParty) *ThirdParty {
|
||||
}
|
||||
}
|
||||
|
||||
func NewListThirdPartiesOutput(thirdPartyPage *page.Page[*coredata.ThirdParty, coredata.ThirdPartyOrderField]) ListThirdPartiesOutput {
|
||||
func NewListThirdPartiesOutput(
|
||||
thirdPartyPage *page.Page[*coredata.ThirdParty, coredata.ThirdPartyOrderField],
|
||||
administratorIDsByThirdPartyID map[gid.GID][]gid.GID,
|
||||
) ListThirdPartiesOutput {
|
||||
thirdParties := make([]*ThirdParty, 0, len(thirdPartyPage.Data))
|
||||
for _, v := range thirdPartyPage.Data {
|
||||
thirdParties = append(thirdParties, NewThirdParty(v))
|
||||
thirdParties = append(thirdParties, NewThirdParty(v, administratorIDsByThirdPartyID[v.ID]))
|
||||
}
|
||||
|
||||
var nextCursor *page.CursorKey
|
||||
@@ -117,10 +124,13 @@ func NewListThirdPartiesOutput(thirdPartyPage *page.Page[*coredata.ThirdParty, c
|
||||
}
|
||||
}
|
||||
|
||||
func NewListChildThirdPartiesOutput(thirdPartyPage *page.Page[*coredata.ThirdParty, coredata.ThirdPartyOrderField]) ListChildThirdPartiesOutput {
|
||||
func NewListChildThirdPartiesOutput(
|
||||
thirdPartyPage *page.Page[*coredata.ThirdParty, coredata.ThirdPartyOrderField],
|
||||
administratorIDsByThirdPartyID map[gid.GID][]gid.GID,
|
||||
) ListChildThirdPartiesOutput {
|
||||
thirdParties := make([]*ThirdParty, 0, len(thirdPartyPage.Data))
|
||||
for _, v := range thirdPartyPage.Data {
|
||||
thirdParties = append(thirdParties, NewThirdParty(v))
|
||||
thirdParties = append(thirdParties, NewThirdParty(v, administratorIDsByThirdPartyID[v.ID]))
|
||||
}
|
||||
|
||||
var nextCursor *page.CursorKey
|
||||
@@ -136,15 +146,15 @@ func NewListChildThirdPartiesOutput(thirdPartyPage *page.Page[*coredata.ThirdPar
|
||||
}
|
||||
}
|
||||
|
||||
func NewAddThirdPartyOutput(v *coredata.ThirdParty) AddThirdPartyOutput {
|
||||
func NewAddThirdPartyOutput(v *coredata.ThirdParty, administratorIDs []gid.GID) AddThirdPartyOutput {
|
||||
return AddThirdPartyOutput{
|
||||
ThirdParty: NewThirdParty(v),
|
||||
ThirdParty: NewThirdParty(v, administratorIDs),
|
||||
}
|
||||
}
|
||||
|
||||
func NewUpdateThirdPartyOutput(v *coredata.ThirdParty) UpdateThirdPartyOutput {
|
||||
func NewUpdateThirdPartyOutput(v *coredata.ThirdParty, administratorIDs []gid.GID) UpdateThirdPartyOutput {
|
||||
return UpdateThirdPartyOutput{
|
||||
ThirdParty: NewThirdParty(v),
|
||||
ThirdParty: NewThirdParty(v, administratorIDs),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user