Replace the binary profile ACTIVE/INACTIVE model with PENDING, ACTIVE, and DEACTIVATED so invited-but-not-yet-activated members remain assignable to assets, data, and risks instead of being treated like deactivated users. Add activated_at/deactivated_at timestamps and Mark* lifecycle helpers, and update every transition (create, invite/re-invite, activation, archive, SCIM, SAML, sessions, compliance-portal grant) to the new states. Expose a multi-state states[] filter across coredata, GraphQL, MCP, and the console owner pickers, which now request ACTIVE and PENDING members. A migration renames the membership_state enum, classifies existing inactive profiles as PENDING from recent invitation activity, and backfills the new timestamp columns. Signed-off-by: Émile Ré <emile@probo.com>
7424 lines
274 KiB
Go
7424 lines
274 KiB
Go
package mcp_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 mcpgen. DO NOT EDIT.
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
|
"go.gearno.de/kit/log"
|
|
"go.probo.inc/probo/pkg/accessreview"
|
|
"go.probo.inc/probo/pkg/complianceportal/management"
|
|
"go.probo.inc/probo/pkg/cookiebanner"
|
|
"go.probo.inc/probo/pkg/coredata"
|
|
"go.probo.inc/probo/pkg/gid"
|
|
"go.probo.inc/probo/pkg/iam"
|
|
"go.probo.inc/probo/pkg/mail"
|
|
"go.probo.inc/probo/pkg/page"
|
|
"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/authn"
|
|
"go.probo.inc/probo/pkg/server/api/authz"
|
|
"go.probo.inc/probo/pkg/server/api/mcp/v1/types"
|
|
"go.probo.inc/probo/pkg/thirdparty"
|
|
"go.probo.inc/probo/pkg/validator"
|
|
)
|
|
|
|
// ListOrganizationsTool handles the listOrganizations tool
|
|
// List all organizations the user has access to
|
|
func (r *Resolver) ListOrganizationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListOrganizationsInput) (*mcp.CallToolResult, types.ListOrganizationsOutput, error) {
|
|
user := authn.IdentityFromContext(ctx)
|
|
|
|
organizations, err := r.iamSvc.AccountService.ListOrganizations(ctx, user.ID)
|
|
if err != nil {
|
|
return nil, types.ListOrganizationsOutput{}, fmt.Errorf("failed to list organizations: %w", err)
|
|
}
|
|
|
|
result := types.ListOrganizationsOutput{
|
|
Organizations: make([]*types.Organization, 0, len(organizations)),
|
|
}
|
|
|
|
for _, org := range organizations {
|
|
result.Organizations = append(result.Organizations, types.NewOrganization(org))
|
|
}
|
|
|
|
return nil, result, nil
|
|
}
|
|
|
|
// ListThirdPartiesTool handles the listThirdParties tool
|
|
// List all thirdParties for the organization
|
|
func (r *Resolver) ListThirdPartiesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListThirdPartiesInput) (*mcp.CallToolResult, types.ListThirdPartiesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionThirdPartyList)
|
|
if err != nil {
|
|
return nil, types.ListThirdPartiesOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.ThirdPartyOrderField]{
|
|
Field: coredata.ThirdPartyOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.ThirdPartyOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
thirdPartyFilter := coredata.NewThirdPartyFilter(nil, input.Level, nil, nil, nil)
|
|
|
|
page, err := prb.ThirdParties.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor, thirdPartyFilter)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization thirdParties: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListThirdPartiesOutput(page), nil
|
|
}
|
|
|
|
// AddThirdPartyTool handles the addThirdParty tool
|
|
// Add a new thirdParty to the organization
|
|
func (r *Resolver) AddThirdPartyTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddThirdPartyInput) (*mcp.CallToolResult, types.AddThirdPartyOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionThirdPartyCreate)
|
|
if err != nil {
|
|
return nil, types.AddThirdPartyOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
var category *coredata.ThirdPartyCategory
|
|
|
|
if input.Category != nil {
|
|
cat := coredata.ThirdPartyCategory(*input.Category)
|
|
category = &cat
|
|
}
|
|
|
|
var countries coredata.CountryCodes
|
|
if len(input.Countries) > 0 {
|
|
countries = make(coredata.CountryCodes, len(input.Countries))
|
|
for i, c := range input.Countries {
|
|
countries[i] = coredata.CountryCode(c)
|
|
}
|
|
}
|
|
|
|
thirdParty, err := svc.ThirdParties.Create(
|
|
ctx, scope,
|
|
probo.CreateThirdPartyRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
Description: input.Description,
|
|
Category: category,
|
|
HeadquarterAddress: input.HeadquarterAddress,
|
|
LegalName: input.LegalName,
|
|
WebsiteURL: input.WebsiteURL,
|
|
PrivacyPolicyURL: input.PrivacyPolicyURL,
|
|
ServiceLevelAgreementURL: input.ServiceLevelAgreementURL,
|
|
DataProcessingAgreementURL: input.DataProcessingAgreementURL,
|
|
BusinessAssociateAgreementURL: input.BusinessAssociateAgreementURL,
|
|
SubprocessorsListURL: input.SubprocessorsListURL,
|
|
Certifications: input.Certifications,
|
|
Countries: countries,
|
|
BusinessOwnerID: input.BusinessOwnerID,
|
|
SecurityOwnerID: input.SecurityOwnerID,
|
|
StatusPageURL: input.StatusPageURL,
|
|
TermsOfServiceURL: input.TermsOfServiceURL,
|
|
SecurityPageURL: input.SecurityPageURL,
|
|
TrustPageURL: input.TrustPageURL,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddThirdPartyOutput{}, fmt.Errorf("failed to create thirdParty: %w", err)
|
|
}
|
|
|
|
return nil, types.NewAddThirdPartyOutput(thirdParty), nil
|
|
}
|
|
|
|
// UpdateThirdPartyTool handles the updateThirdParty tool
|
|
// Update an existing thirdParty
|
|
func (r *Resolver) UpdateThirdPartyTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateThirdPartyInput) (*mcp.CallToolResult, types.UpdateThirdPartyOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateThirdPartyOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
var description **string
|
|
if input.Description != nil {
|
|
description = &input.Description
|
|
}
|
|
|
|
var headquarterAddress **string
|
|
if input.HeadquarterAddress != nil {
|
|
headquarterAddress = &input.HeadquarterAddress
|
|
}
|
|
|
|
var legalName **string
|
|
if input.LegalName != nil {
|
|
legalName = &input.LegalName
|
|
}
|
|
|
|
var websiteURL **string
|
|
if input.WebsiteURL != nil {
|
|
websiteURL = &input.WebsiteURL
|
|
}
|
|
|
|
var privacyPolicyURL **string
|
|
if input.PrivacyPolicyURL != nil {
|
|
privacyPolicyURL = &input.PrivacyPolicyURL
|
|
}
|
|
|
|
var serviceLevelAgreementURL **string
|
|
if input.ServiceLevelAgreementURL != nil {
|
|
serviceLevelAgreementURL = &input.ServiceLevelAgreementURL
|
|
}
|
|
|
|
var dataProcessingAgreementURL **string
|
|
if input.DataProcessingAgreementURL != nil {
|
|
dataProcessingAgreementURL = &input.DataProcessingAgreementURL
|
|
}
|
|
|
|
var businessAssociateAgreementURL **string
|
|
if input.BusinessAssociateAgreementURL != nil {
|
|
businessAssociateAgreementURL = &input.BusinessAssociateAgreementURL
|
|
}
|
|
|
|
var subprocessorsListURL **string
|
|
if input.SubprocessorsListURL != nil {
|
|
subprocessorsListURL = &input.SubprocessorsListURL
|
|
}
|
|
|
|
var statusPageURL **string
|
|
if input.StatusPageURL != nil {
|
|
statusPageURL = &input.StatusPageURL
|
|
}
|
|
|
|
var termsOfServiceURL **string
|
|
if input.TermsOfServiceURL != nil {
|
|
termsOfServiceURL = &input.TermsOfServiceURL
|
|
}
|
|
|
|
var securityPageURL **string
|
|
if input.SecurityPageURL != nil {
|
|
securityPageURL = &input.SecurityPageURL
|
|
}
|
|
|
|
var trustPageURL **string
|
|
if input.TrustPageURL != nil {
|
|
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 category *coredata.ThirdPartyCategory
|
|
|
|
if input.Category != nil {
|
|
cat := coredata.ThirdPartyCategory(*input.Category)
|
|
category = &cat
|
|
}
|
|
|
|
var countries coredata.CountryCodes
|
|
if len(input.Countries) > 0 {
|
|
countries = make(coredata.CountryCodes, len(input.Countries))
|
|
for i, c := range input.Countries {
|
|
countries[i] = coredata.CountryCode(c)
|
|
}
|
|
}
|
|
|
|
thirdParty, err := svc.ThirdParties.Update(
|
|
ctx, scope,
|
|
probo.UpdateThirdPartyRequest{
|
|
ID: input.ID,
|
|
Name: input.Name,
|
|
Description: description,
|
|
Category: category,
|
|
HeadquarterAddress: headquarterAddress,
|
|
LegalName: legalName,
|
|
WebsiteURL: websiteURL,
|
|
PrivacyPolicyURL: privacyPolicyURL,
|
|
ServiceLevelAgreementURL: serviceLevelAgreementURL,
|
|
DataProcessingAgreementURL: dataProcessingAgreementURL,
|
|
BusinessAssociateAgreementURL: businessAssociateAgreementURL,
|
|
SubprocessorsListURL: subprocessorsListURL,
|
|
Certifications: input.Certifications,
|
|
Countries: countries,
|
|
BusinessOwnerID: businessOwnerID,
|
|
SecurityOwnerID: securityOwnerID,
|
|
StatusPageURL: statusPageURL,
|
|
TermsOfServiceURL: termsOfServiceURL,
|
|
SecurityPageURL: securityPageURL,
|
|
TrustPageURL: trustPageURL,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateThirdPartyOutput{}, fmt.Errorf("failed to update thirdParty: %w", err)
|
|
}
|
|
|
|
return nil, types.NewUpdateThirdPartyOutput(thirdParty), nil
|
|
}
|
|
|
|
func (r *Resolver) ListRisksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRisksInput) (*mcp.CallToolResult, types.ListRisksOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRiskList)
|
|
if err != nil {
|
|
return nil, types.ListRisksOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.RiskOrderField]{
|
|
Field: coredata.RiskOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.RiskOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
riskFilter := coredata.NewRiskFilter(nil)
|
|
if input.Filter != nil {
|
|
riskFilter = coredata.NewRiskFilter(input.Filter.Query)
|
|
}
|
|
|
|
page, err := prb.Risks.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor, riskFilter)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization risks: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListRisksOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskInput) (*mcp.CallToolResult, types.GetRiskOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskGet)
|
|
if err != nil {
|
|
return nil, types.GetRiskOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
risk, err := prb.Risks.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetRiskOutput{}, fmt.Errorf("failed to get risk: %w", err)
|
|
}
|
|
|
|
return nil, types.GetRiskOutput{
|
|
Risk: types.NewRisk(risk),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskInput) (*mcp.CallToolResult, types.AddRiskOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRiskCreate)
|
|
if err != nil {
|
|
return nil, types.AddRiskOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
risk, err := svc.Risks.Create(
|
|
ctx, scope,
|
|
probo.CreateRiskRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
Description: input.Description,
|
|
Category: input.Category,
|
|
Treatment: input.Treatment,
|
|
InherentLikelihood: input.InherentLikelihood,
|
|
InherentImpact: input.InherentImpact,
|
|
ResidualLikelihood: input.ResidualLikelihood,
|
|
ResidualImpact: input.ResidualImpact,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddRiskOutput{}, fmt.Errorf("failed to create risk: %w", err)
|
|
}
|
|
|
|
return nil, types.AddRiskOutput{
|
|
Risk: types.NewRisk(risk),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskInput) (*mcp.CallToolResult, types.UpdateRiskOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateRiskOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
risk, err := svc.Risks.Update(
|
|
ctx, scope,
|
|
probo.UpdateRiskRequest{
|
|
ID: input.ID,
|
|
Name: input.Name,
|
|
Description: UnwrapOmittable(input.Description),
|
|
Category: input.Category,
|
|
Treatment: input.Treatment,
|
|
OwnerID: UnwrapOmittable(input.OwnerID),
|
|
InherentLikelihood: input.InherentLikelihood,
|
|
InherentImpact: input.InherentImpact,
|
|
ResidualLikelihood: input.ResidualLikelihood,
|
|
ResidualImpact: input.ResidualImpact,
|
|
Note: input.Note,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateRiskOutput{}, fmt.Errorf("failed to update risk: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateRiskOutput{
|
|
Risk: types.NewRisk(risk),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListMeasuresTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasuresInput) (*mcp.CallToolResult, types.ListMeasuresOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionMeasureList)
|
|
if err != nil {
|
|
return nil, types.ListMeasuresOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.MeasureOrderField]{
|
|
Field: coredata.MeasureOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.MeasureOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
var measureFilter = coredata.NewMeasureFilter(nil, nil, nil)
|
|
if input.Filter != nil {
|
|
measureFilter = coredata.NewMeasureFilter(input.Filter.Query, input.Filter.State, input.Filter.Category)
|
|
}
|
|
|
|
page, err := prb.Measures.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor, measureFilter)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization measures: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListMeasuresOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetMeasureInput) (*mcp.CallToolResult, types.GetMeasureOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionMeasureGet)
|
|
if err != nil {
|
|
return nil, types.GetMeasureOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
measure, err := prb.Measures.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetMeasureOutput{}, fmt.Errorf("failed to get measure: %w", err)
|
|
}
|
|
|
|
return nil, types.GetMeasureOutput{
|
|
Measure: types.NewMeasure(measure),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddMeasureInput) (*mcp.CallToolResult, types.AddMeasureOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionMeasureCreate)
|
|
if err != nil {
|
|
return nil, types.AddMeasureOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
measure, err := svc.Measures.Create(
|
|
ctx, scope,
|
|
probo.CreateMeasureRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
Description: input.Description,
|
|
Category: input.Category,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddMeasureOutput{}, fmt.Errorf("failed to create measure: %w", err)
|
|
}
|
|
|
|
return nil, types.AddMeasureOutput{
|
|
Measure: types.NewMeasure(measure),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateMeasureInput) (*mcp.CallToolResult, types.UpdateMeasureOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionMeasureUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateMeasureOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
measure, err := svc.Measures.Update(
|
|
ctx, scope,
|
|
probo.UpdateMeasureRequest{
|
|
ID: input.ID,
|
|
Name: input.Name,
|
|
Description: UnwrapOmittable(input.Description),
|
|
Category: input.Category,
|
|
State: input.State,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateMeasureOutput{}, fmt.Errorf("failed to update measure: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateMeasureOutput{
|
|
Measure: types.NewMeasure(measure),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListFrameworksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListFrameworksInput) (*mcp.CallToolResult, types.ListFrameworksOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionFrameworkList)
|
|
if err != nil {
|
|
return nil, types.ListFrameworksOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.FrameworkOrderField]{
|
|
Field: coredata.FrameworkOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.FrameworkOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
page, err := prb.Frameworks.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization frameworks: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListFrameworksOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetFrameworkInput) (*mcp.CallToolResult, types.GetFrameworkOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionFrameworkGet)
|
|
if err != nil {
|
|
return nil, types.GetFrameworkOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
framework, err := prb.Frameworks.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetFrameworkOutput{}, fmt.Errorf("failed to get framework: %w", err)
|
|
}
|
|
|
|
return nil, types.GetFrameworkOutput{
|
|
Framework: types.NewFramework(framework),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddFrameworkInput) (*mcp.CallToolResult, types.AddFrameworkOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionFrameworkCreate)
|
|
if err != nil {
|
|
return nil, types.AddFrameworkOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
framework, err := svc.Frameworks.Create(
|
|
ctx, scope,
|
|
probo.CreateFrameworkRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
Description: input.Description,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddFrameworkOutput{}, fmt.Errorf("failed to create framework: %w", err)
|
|
}
|
|
|
|
return nil, types.AddFrameworkOutput{
|
|
Framework: types.NewFramework(framework),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateFrameworkInput) (*mcp.CallToolResult, types.UpdateFrameworkOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionFrameworkUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateFrameworkOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
framework, err := svc.Frameworks.Update(
|
|
ctx, scope,
|
|
probo.UpdateFrameworkRequest{
|
|
ID: input.ID,
|
|
Name: input.Name,
|
|
Description: UnwrapOmittable(input.Description),
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateFrameworkOutput{}, fmt.Errorf("failed to update framework: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateFrameworkOutput{
|
|
Framework: types.NewFramework(framework),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListAssetsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAssetsInput) (*mcp.CallToolResult, types.ListAssetsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionAssetList)
|
|
if err != nil {
|
|
return nil, types.ListAssetsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.AssetOrderField]{
|
|
Field: coredata.AssetOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.AssetOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
page, err := prb.Assets.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization assets: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListAssetsOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAssetInput) (*mcp.CallToolResult, types.GetAssetOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionAssetGet)
|
|
if err != nil {
|
|
return nil, types.GetAssetOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
asset, err := prb.Assets.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetAssetOutput{}, fmt.Errorf("failed to get asset: %w", err)
|
|
}
|
|
|
|
return nil, types.GetAssetOutput{
|
|
Asset: types.NewAsset(asset),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddAssetInput) (*mcp.CallToolResult, types.AddAssetOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionAssetCreate)
|
|
if err != nil {
|
|
return nil, types.AddAssetOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
asset, err := svc.Assets.Create(
|
|
ctx, scope,
|
|
probo.CreateAssetRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
Amount: input.Amount,
|
|
OwnerID: input.OwnerID,
|
|
AssetType: input.AssetType,
|
|
DataTypesStored: input.DataTypesStored,
|
|
ThirdPartyIDs: input.ThirdPartyIds,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddAssetOutput{}, fmt.Errorf("failed to create asset: %w", err)
|
|
}
|
|
|
|
return nil, types.AddAssetOutput{
|
|
Asset: types.NewAsset(asset),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateAssetInput) (*mcp.CallToolResult, types.UpdateAssetOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionAssetUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateAssetOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
asset, err := svc.Assets.Update(
|
|
ctx, scope,
|
|
probo.UpdateAssetRequest{
|
|
ID: input.ID,
|
|
Name: input.Name,
|
|
Amount: input.Amount,
|
|
OwnerID: input.OwnerID,
|
|
AssetType: input.AssetType,
|
|
DataTypesStored: input.DataTypesStored,
|
|
ThirdPartyIDs: input.ThirdPartyIds,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateAssetOutput{}, fmt.Errorf("failed to update asset: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateAssetOutput{
|
|
Asset: types.NewAsset(asset),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListDataTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDataInput) (*mcp.CallToolResult, types.ListDataOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionDatumList)
|
|
if err != nil {
|
|
return nil, types.ListDataOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.DatumOrderField]{
|
|
Field: coredata.DatumOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.DatumOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
page, err := prb.Data.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization data: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListDataOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetDatumTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDatumInput) (*mcp.CallToolResult, types.GetDatumOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDatumGet)
|
|
if err != nil {
|
|
return nil, types.GetDatumOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
datum, err := prb.Data.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetDatumOutput{}, fmt.Errorf("failed to get datum: %w", err)
|
|
}
|
|
|
|
return nil, types.GetDatumOutput{
|
|
Datum: types.NewDatum(datum),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddDatumTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddDatumInput) (*mcp.CallToolResult, types.AddDatumOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionDatumCreate)
|
|
if err != nil {
|
|
return nil, types.AddDatumOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
datum, err := svc.Data.Create(
|
|
ctx, scope,
|
|
probo.CreateDatumRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
DataClassification: input.DataClassification,
|
|
OwnerID: input.OwnerID,
|
|
ThirdPartyIDs: input.ThirdPartyIds,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddDatumOutput{}, fmt.Errorf("failed to create datum: %w", err)
|
|
}
|
|
|
|
return nil, types.AddDatumOutput{
|
|
Datum: types.NewDatum(datum),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateDatumTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateDatumInput) (*mcp.CallToolResult, types.UpdateDatumOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDatumUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateDatumOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
datum, err := svc.Data.Update(
|
|
ctx, scope,
|
|
probo.UpdateDatumRequest{
|
|
ID: input.ID,
|
|
Name: input.Name,
|
|
DataClassification: input.DataClassification,
|
|
OwnerID: input.OwnerID,
|
|
ThirdPartyIDs: input.ThirdPartyIds,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateDatumOutput{}, fmt.Errorf("failed to update datum: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateDatumOutput{
|
|
Datum: types.NewDatum(datum),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListFindingsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListFindingsInput) (*mcp.CallToolResult, types.ListFindingsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionFindingList)
|
|
if err != nil {
|
|
return nil, types.ListFindingsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.FindingOrderField]{
|
|
Field: coredata.FindingOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.FindingOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
findingFilter := coredata.NewFindingFilter(nil, nil, nil, nil)
|
|
if input.Filter != nil {
|
|
findingFilter = coredata.NewFindingFilter(
|
|
input.Filter.Kind,
|
|
input.Filter.Status,
|
|
input.Filter.Priority,
|
|
input.Filter.OwnerID,
|
|
)
|
|
}
|
|
|
|
page, err := prb.Findings.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor, findingFilter)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization findings: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListFindingsOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetFindingTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetFindingInput) (*mcp.CallToolResult, types.GetFindingOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionFindingGet)
|
|
if err != nil {
|
|
return nil, types.GetFindingOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
finding, err := prb.Findings.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetFindingOutput{}, fmt.Errorf("cannot get finding: %w", err)
|
|
}
|
|
|
|
return nil, types.GetFindingOutput{
|
|
Finding: types.NewFinding(finding),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddFindingTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddFindingInput) (*mcp.CallToolResult, types.AddFindingOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionFindingCreate)
|
|
if err != nil {
|
|
return nil, types.AddFindingOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
finding, err := svc.Findings.Create(
|
|
ctx, scope,
|
|
&probo.CreateFindingRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Kind: input.Kind,
|
|
Description: input.Description,
|
|
Source: input.Source,
|
|
IdentifiedOn: input.IdentifiedOn,
|
|
RootCause: input.RootCause,
|
|
CorrectiveAction: input.CorrectiveAction,
|
|
OwnerID: input.OwnerID,
|
|
DueDate: input.DueDate,
|
|
Status: input.Status,
|
|
Priority: input.Priority,
|
|
RiskID: input.RiskID,
|
|
EffectivenessCheck: input.EffectivenessCheck,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddFindingOutput{}, fmt.Errorf("failed to create finding: %w", err)
|
|
}
|
|
|
|
return nil, types.AddFindingOutput{
|
|
Finding: types.NewFinding(finding),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateFindingTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateFindingInput) (*mcp.CallToolResult, types.UpdateFindingOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionFindingUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateFindingOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
finding, err := svc.Findings.Update(
|
|
ctx, scope,
|
|
&probo.UpdateFindingRequest{
|
|
ID: input.ID,
|
|
Description: UnwrapOmittable(input.Description),
|
|
Source: UnwrapOmittable(input.Source),
|
|
IdentifiedOn: UnwrapOmittable(input.IdentifiedOn),
|
|
RootCause: UnwrapOmittable(input.RootCause),
|
|
CorrectiveAction: UnwrapOmittable(input.CorrectiveAction),
|
|
OwnerID: input.OwnerID,
|
|
DueDate: UnwrapOmittable(input.DueDate),
|
|
Status: input.Status,
|
|
Priority: input.Priority,
|
|
RiskID: UnwrapOmittable(input.RiskID),
|
|
EffectivenessCheck: UnwrapOmittable(input.EffectivenessCheck),
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateFindingOutput{}, fmt.Errorf("failed to update finding: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateFindingOutput{
|
|
Finding: types.NewFinding(finding),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListObligationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListObligationsInput) (*mcp.CallToolResult, types.ListObligationsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionObligationList)
|
|
if err != nil {
|
|
return nil, types.ListObligationsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.ObligationOrderField]{
|
|
Field: coredata.ObligationOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.ObligationOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
page, err := prb.Obligations.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization obligations: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListObligationsOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetObligationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetObligationInput) (*mcp.CallToolResult, types.GetObligationOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionObligationGet)
|
|
if err != nil {
|
|
return nil, types.GetObligationOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
obligation, err := prb.Obligations.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetObligationOutput{}, fmt.Errorf("failed to get obligation: %w", err)
|
|
}
|
|
|
|
return nil, types.GetObligationOutput{
|
|
Obligation: types.NewObligation(obligation),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddObligationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddObligationInput) (*mcp.CallToolResult, types.AddObligationOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionObligationCreate)
|
|
if err != nil {
|
|
return nil, types.AddObligationOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
obligation, err := svc.Obligations.Create(
|
|
ctx, scope,
|
|
&probo.CreateObligationRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Area: input.Area,
|
|
Source: input.Source,
|
|
Requirement: input.Requirement,
|
|
ActionsToBeImplemented: input.ActionsToBeImplemented,
|
|
Regulator: input.Regulator,
|
|
OwnerID: input.OwnerID,
|
|
LastReviewDate: input.LastReviewDate,
|
|
DueDate: input.DueDate,
|
|
Status: *input.Status,
|
|
Type: *input.Type,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddObligationOutput{}, fmt.Errorf("failed to create obligation: %w", err)
|
|
}
|
|
|
|
return nil, types.AddObligationOutput{
|
|
Obligation: types.NewObligation(obligation),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateObligationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateObligationInput) (*mcp.CallToolResult, types.UpdateObligationOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionObligationUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateObligationOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
obligation, err := svc.Obligations.Update(
|
|
ctx, scope,
|
|
&probo.UpdateObligationRequest{
|
|
ID: input.ID,
|
|
Area: UnwrapOmittable(input.Area),
|
|
Source: UnwrapOmittable(input.Source),
|
|
Requirement: UnwrapOmittable(input.Requirement),
|
|
ActionsToBeImplemented: UnwrapOmittable(input.ActionsToBeImplemented),
|
|
Regulator: UnwrapOmittable(input.Regulator),
|
|
OwnerID: input.OwnerID,
|
|
LastReviewDate: UnwrapOmittable(input.LastReviewDate),
|
|
DueDate: UnwrapOmittable(input.DueDate),
|
|
Status: input.Status,
|
|
Type: input.Type,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateObligationOutput{}, fmt.Errorf("failed to update obligation: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateObligationOutput{
|
|
Obligation: types.NewObligation(obligation),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListProcessingActivitiesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListProcessingActivitiesInput) (*mcp.CallToolResult, types.ListProcessingActivitiesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionProcessingActivityList)
|
|
if err != nil {
|
|
return nil, types.ListProcessingActivitiesOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.ProcessingActivityOrderField]{
|
|
Field: coredata.ProcessingActivityOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.ProcessingActivityOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
page, err := prb.ProcessingActivities.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization processing activities: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListProcessingActivitiesOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetProcessingActivityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetProcessingActivityInput) (*mcp.CallToolResult, types.GetProcessingActivityOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionProcessingActivityGet)
|
|
if err != nil {
|
|
return nil, types.GetProcessingActivityOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
processingActivity, err := prb.ProcessingActivities.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetProcessingActivityOutput{}, fmt.Errorf("failed to get processing activity: %w", err)
|
|
}
|
|
|
|
return nil, types.GetProcessingActivityOutput{
|
|
ProcessingActivity: types.NewProcessingActivity(processingActivity),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddProcessingActivityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddProcessingActivityInput) (*mcp.CallToolResult, types.AddProcessingActivityOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionProcessingActivityCreate)
|
|
if err != nil {
|
|
return nil, types.AddProcessingActivityOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
processingActivity, err := svc.ProcessingActivities.Create(
|
|
ctx, scope,
|
|
&probo.CreateProcessingActivityRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
Purpose: input.Purpose,
|
|
DataSubjectCategory: input.DataSubjectCategory,
|
|
PersonalDataCategory: input.PersonalDataCategory,
|
|
SpecialOrCriminalData: input.SpecialOrCriminalData,
|
|
ConsentEvidenceLink: input.ConsentEvidenceLink,
|
|
LawfulBasis: input.LawfulBasis,
|
|
Recipients: input.Recipients,
|
|
Location: input.Location,
|
|
InternationalTransfers: input.InternationalTransfers,
|
|
TransferSafeguard: input.TransferSafeguard,
|
|
RetentionPeriod: input.RetentionPeriod,
|
|
SecurityMeasures: input.SecurityMeasures,
|
|
DataProtectionImpactAssessmentNeeded: input.DataProtectionImpactAssessmentNeeded,
|
|
TransferImpactAssessmentNeeded: input.TransferImpactAssessmentNeeded,
|
|
LastReviewDate: input.LastReviewDate,
|
|
NextReviewDate: input.NextReviewDate,
|
|
Role: input.Role,
|
|
DataProtectionOfficerID: input.DataProtectionOfficerID,
|
|
ThirdPartyIDs: input.ThirdPartyIds,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddProcessingActivityOutput{}, fmt.Errorf("failed to create processing activity: %w", err)
|
|
}
|
|
|
|
return nil, types.AddProcessingActivityOutput{
|
|
ProcessingActivity: types.NewProcessingActivity(processingActivity),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateProcessingActivityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateProcessingActivityInput) (*mcp.CallToolResult, types.UpdateProcessingActivityOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionProcessingActivityUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateProcessingActivityOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
var thirdPartyIDs *[]gid.GID
|
|
if input.ThirdPartyIds != nil {
|
|
thirdPartyIDs = &input.ThirdPartyIds
|
|
}
|
|
|
|
processingActivity, err := svc.ProcessingActivities.Update(
|
|
ctx, scope,
|
|
&probo.UpdateProcessingActivityRequest{
|
|
ID: input.ID,
|
|
Name: input.Name,
|
|
Purpose: UnwrapOmittable(input.Purpose),
|
|
DataSubjectCategory: UnwrapOmittable(input.DataSubjectCategory),
|
|
PersonalDataCategory: UnwrapOmittable(input.PersonalDataCategory),
|
|
SpecialOrCriminalData: input.SpecialOrCriminalData,
|
|
ConsentEvidenceLink: UnwrapOmittable(input.ConsentEvidenceLink),
|
|
LawfulBasis: input.LawfulBasis,
|
|
Recipients: UnwrapOmittable(input.Recipients),
|
|
Location: UnwrapOmittable(input.Location),
|
|
InternationalTransfers: input.InternationalTransfers,
|
|
TransferSafeguard: UnwrapOmittable(input.TransferSafeguard),
|
|
RetentionPeriod: UnwrapOmittable(input.RetentionPeriod),
|
|
SecurityMeasures: UnwrapOmittable(input.SecurityMeasures),
|
|
DataProtectionImpactAssessmentNeeded: input.DataProtectionImpactAssessmentNeeded,
|
|
TransferImpactAssessmentNeeded: input.TransferImpactAssessmentNeeded,
|
|
LastReviewDate: UnwrapOmittable(input.LastReviewDate),
|
|
NextReviewDate: UnwrapOmittable(input.NextReviewDate),
|
|
Role: input.Role,
|
|
DataProtectionOfficerID: UnwrapOmittable(input.DataProtectionOfficerID),
|
|
ThirdPartyIDs: thirdPartyIDs,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateProcessingActivityOutput{}, fmt.Errorf("failed to update processing activity: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateProcessingActivityOutput{
|
|
ProcessingActivity: types.NewProcessingActivity(processingActivity),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteProcessingActivityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteProcessingActivityInput) (*mcp.CallToolResult, types.DeleteProcessingActivityOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionProcessingActivityDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteProcessingActivityOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.ProcessingActivities.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteProcessingActivityOutput{}, fmt.Errorf("failed to delete processing activity: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteProcessingActivityOutput{
|
|
DeletedProcessingActivityID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListDataProtectionImpactAssessmentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDataProtectionImpactAssessmentsInput) (*mcp.CallToolResult, types.ListDataProtectionImpactAssessmentsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionDataProtectionImpactAssessmentList)
|
|
if err != nil {
|
|
return nil, types.ListDataProtectionImpactAssessmentsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.DataProtectionImpactAssessmentOrderField]{
|
|
Field: coredata.DataProtectionImpactAssessmentOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.DataProtectionImpactAssessmentOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
page, err := prb.DataProtectionImpactAssessments.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization data protection impact assessments: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListDataProtectionImpactAssessmentsOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetDataProtectionImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDataProtectionImpactAssessmentInput) (*mcp.CallToolResult, types.GetDataProtectionImpactAssessmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDataProtectionImpactAssessmentGet)
|
|
if err != nil {
|
|
return nil, types.GetDataProtectionImpactAssessmentOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
dpia, err := prb.DataProtectionImpactAssessments.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetDataProtectionImpactAssessmentOutput{}, fmt.Errorf("failed to get data protection impact assessment: %w", err)
|
|
}
|
|
|
|
return nil, types.GetDataProtectionImpactAssessmentOutput{
|
|
DataProtectionImpactAssessment: types.NewDataProtectionImpactAssessment(dpia),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddDataProtectionImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddDataProtectionImpactAssessmentInput) (*mcp.CallToolResult, types.AddDataProtectionImpactAssessmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ProcessingActivityID, probo.ActionDataProtectionImpactAssessmentCreate)
|
|
if err != nil {
|
|
return nil, types.AddDataProtectionImpactAssessmentOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
dpia, err := svc.DataProtectionImpactAssessments.Create(
|
|
ctx, scope,
|
|
&probo.CreateDataProtectionImpactAssessmentRequest{
|
|
ProcessingActivityID: input.ProcessingActivityID,
|
|
Description: input.Description,
|
|
NecessityAndProportionality: input.NecessityAndProportionality,
|
|
PotentialRisk: input.PotentialRisk,
|
|
Mitigations: input.Mitigations,
|
|
ResidualRisk: input.ResidualRisk,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddDataProtectionImpactAssessmentOutput{}, fmt.Errorf("failed to create data protection impact assessment: %w", err)
|
|
}
|
|
|
|
return nil, types.AddDataProtectionImpactAssessmentOutput{
|
|
DataProtectionImpactAssessment: types.NewDataProtectionImpactAssessment(dpia),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateDataProtectionImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateDataProtectionImpactAssessmentInput) (*mcp.CallToolResult, types.UpdateDataProtectionImpactAssessmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDataProtectionImpactAssessmentUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateDataProtectionImpactAssessmentOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
dpia, err := svc.DataProtectionImpactAssessments.Update(
|
|
ctx, scope,
|
|
&probo.UpdateDataProtectionImpactAssessmentRequest{
|
|
ID: input.ID,
|
|
Description: UnwrapOmittable(input.Description),
|
|
NecessityAndProportionality: UnwrapOmittable(input.NecessityAndProportionality),
|
|
PotentialRisk: UnwrapOmittable(input.PotentialRisk),
|
|
Mitigations: UnwrapOmittable(input.Mitigations),
|
|
ResidualRisk: input.ResidualRisk,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateDataProtectionImpactAssessmentOutput{}, fmt.Errorf("failed to update data protection impact assessment: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateDataProtectionImpactAssessmentOutput{
|
|
DataProtectionImpactAssessment: types.NewDataProtectionImpactAssessment(dpia),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListTransferImpactAssessmentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTransferImpactAssessmentsInput) (*mcp.CallToolResult, types.ListTransferImpactAssessmentsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionTransferImpactAssessmentList)
|
|
if err != nil {
|
|
return nil, types.ListTransferImpactAssessmentsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.TransferImpactAssessmentOrderField]{
|
|
Field: coredata.TransferImpactAssessmentOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.TransferImpactAssessmentOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
page, err := prb.TransferImpactAssessments.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization transfer impact assessments: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListTransferImpactAssessmentsOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetTransferImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTransferImpactAssessmentInput) (*mcp.CallToolResult, types.GetTransferImpactAssessmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionTransferImpactAssessmentGet)
|
|
if err != nil {
|
|
return nil, types.GetTransferImpactAssessmentOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
tia, err := prb.TransferImpactAssessments.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetTransferImpactAssessmentOutput{}, fmt.Errorf("failed to get transfer impact assessment: %w", err)
|
|
}
|
|
|
|
return nil, types.GetTransferImpactAssessmentOutput{
|
|
TransferImpactAssessment: types.NewTransferImpactAssessment(tia),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddTransferImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTransferImpactAssessmentInput) (*mcp.CallToolResult, types.AddTransferImpactAssessmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ProcessingActivityID, probo.ActionTransferImpactAssessmentCreate)
|
|
if err != nil {
|
|
return nil, types.AddTransferImpactAssessmentOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
tia, err := svc.TransferImpactAssessments.Create(
|
|
ctx, scope,
|
|
&probo.CreateTransferImpactAssessmentRequest{
|
|
ProcessingActivityID: input.ProcessingActivityID,
|
|
DataSubjects: input.DataSubjects,
|
|
LegalMechanism: input.LegalMechanism,
|
|
Transfer: input.Transfer,
|
|
LocalLawRisk: input.LocalLawRisk,
|
|
SupplementaryMeasures: input.SupplementaryMeasures,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddTransferImpactAssessmentOutput{}, fmt.Errorf("failed to create transfer impact assessment: %w", err)
|
|
}
|
|
|
|
return nil, types.AddTransferImpactAssessmentOutput{
|
|
TransferImpactAssessment: types.NewTransferImpactAssessment(tia),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateTransferImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTransferImpactAssessmentInput) (*mcp.CallToolResult, types.UpdateTransferImpactAssessmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionTransferImpactAssessmentUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateTransferImpactAssessmentOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
tia, err := svc.TransferImpactAssessments.Update(
|
|
ctx, scope,
|
|
&probo.UpdateTransferImpactAssessmentRequest{
|
|
ID: input.ID,
|
|
DataSubjects: UnwrapOmittable(input.DataSubjects),
|
|
LegalMechanism: UnwrapOmittable(input.LegalMechanism),
|
|
Transfer: UnwrapOmittable(input.Transfer),
|
|
LocalLawRisk: UnwrapOmittable(input.LocalLawRisk),
|
|
SupplementaryMeasures: UnwrapOmittable(input.SupplementaryMeasures),
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateTransferImpactAssessmentOutput{}, fmt.Errorf("failed to update transfer impact assessment: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateTransferImpactAssessmentOutput{
|
|
TransferImpactAssessment: types.NewTransferImpactAssessment(tia),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteTransferImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTransferImpactAssessmentInput) (*mcp.CallToolResult, types.DeleteTransferImpactAssessmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionTransferImpactAssessmentDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteTransferImpactAssessmentOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.TransferImpactAssessments.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteTransferImpactAssessmentOutput{}, fmt.Errorf("failed to delete transfer impact assessment: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteTransferImpactAssessmentOutput{
|
|
DeletedTransferImpactAssessmentID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListAuditsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAuditsInput) (*mcp.CallToolResult, types.ListAuditsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionAuditList)
|
|
if err != nil {
|
|
return nil, types.ListAuditsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.AuditOrderField]{
|
|
Field: coredata.AuditOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.AuditOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
page, err := prb.Audits.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization audits: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListAuditsOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAuditInput) (*mcp.CallToolResult, types.GetAuditOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionAuditGet)
|
|
if err != nil {
|
|
return nil, types.GetAuditOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
audit, err := prb.Audits.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetAuditOutput{}, fmt.Errorf("cannot get audit: %w", err)
|
|
}
|
|
|
|
var file *coredata.File
|
|
if audit.ReportFileID != nil {
|
|
file, err = prb.Files.Get(ctx, scope, *audit.ReportFileID)
|
|
if err != nil {
|
|
return nil, types.GetAuditOutput{}, fmt.Errorf("cannot get audit report file: %w", err)
|
|
}
|
|
}
|
|
|
|
return nil, types.GetAuditOutput{
|
|
Audit: types.NewAudit(audit, file),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddAuditInput) (*mcp.CallToolResult, types.AddAuditOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionAuditCreate)
|
|
if err != nil {
|
|
return nil, types.AddAuditOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
audit, err := svc.Audits.Create(
|
|
ctx, scope,
|
|
&probo.CreateAuditRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
ValidFrom: input.ValidFrom,
|
|
ValidUntil: input.ValidUntil,
|
|
AuditStartDate: input.AuditStartDate,
|
|
AuditEndDate: input.AuditEndDate,
|
|
State: input.State,
|
|
FrameworkID: input.FrameworkID,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddAuditOutput{}, fmt.Errorf("failed to create audit: %w", err)
|
|
}
|
|
|
|
return nil, types.AddAuditOutput{
|
|
Audit: types.NewAudit(audit, nil),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateAuditInput) (*mcp.CallToolResult, types.UpdateAuditOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionAuditUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateAuditOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
audit, err := svc.Audits.Update(
|
|
ctx, scope,
|
|
&probo.UpdateAuditRequest{
|
|
ID: input.ID,
|
|
Name: UnwrapOmittable(input.Name),
|
|
ValidFrom: input.ValidFrom,
|
|
ValidUntil: input.ValidUntil,
|
|
AuditStartDate: input.AuditStartDate,
|
|
AuditEndDate: input.AuditEndDate,
|
|
State: input.State,
|
|
CompliancePortalVisibility: input.CompliancePortalVisibility,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateAuditOutput{}, fmt.Errorf("cannot update audit: %w", err)
|
|
}
|
|
|
|
var file *coredata.File
|
|
if audit.ReportFileID != nil {
|
|
file, err = svc.Files.Get(ctx, scope, *audit.ReportFileID)
|
|
if err != nil {
|
|
return nil, types.UpdateAuditOutput{}, fmt.Errorf("cannot get audit report file: %w", err)
|
|
}
|
|
}
|
|
|
|
return nil, types.UpdateAuditOutput{
|
|
Audit: types.NewAudit(audit, file),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListControlsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListControlsInput) (*mcp.CallToolResult, types.ListControlsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionControlList)
|
|
if err != nil {
|
|
return nil, types.ListControlsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.ControlOrderField]{
|
|
Field: coredata.ControlOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.ControlOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
var controlFilter = coredata.NewControlFilter(nil)
|
|
if input.Filter != nil {
|
|
controlFilter = coredata.NewControlFilter(input.Filter.Query)
|
|
}
|
|
|
|
var (
|
|
controlPage *page.Page[*coredata.Control, coredata.ControlOrderField]
|
|
)
|
|
|
|
if input.Filter != nil && input.Filter.FrameworkID != nil {
|
|
controlPage, err = prb.Controls.ListForFrameworkID(ctx, scope, *input.Filter.FrameworkID, cursor, controlFilter)
|
|
} else {
|
|
controlPage, err = prb.Controls.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor, controlFilter)
|
|
}
|
|
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization controls: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListControlsOutput(controlPage), nil
|
|
}
|
|
|
|
func (r *Resolver) GetControlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetControlInput) (*mcp.CallToolResult, types.GetControlOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionControlGet)
|
|
if err != nil {
|
|
return nil, types.GetControlOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
control, err := prb.Controls.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetControlOutput{}, fmt.Errorf("failed to get control: %w", err)
|
|
}
|
|
|
|
return nil, types.GetControlOutput{
|
|
Control: types.NewControl(control),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddControlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddControlInput) (*mcp.CallToolResult, types.AddControlOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.FrameworkID, probo.ActionControlCreate)
|
|
if err != nil {
|
|
return nil, types.AddControlOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
control, err := svc.Controls.Create(
|
|
ctx, scope,
|
|
probo.CreateControlRequest{
|
|
FrameworkID: input.FrameworkID,
|
|
Name: input.Name,
|
|
Description: input.Description,
|
|
SectionTitle: input.SectionTitle,
|
|
BestPractice: input.BestPractice,
|
|
MaturityLevel: coredata.ControlMaturityLevel(input.MaturityLevel),
|
|
NotImplementedJustification: input.NotImplementedJustification,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddControlOutput{}, fmt.Errorf("failed to create control: %w", err)
|
|
}
|
|
|
|
return nil, types.AddControlOutput{
|
|
Control: types.NewControl(control),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateControlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateControlInput) (*mcp.CallToolResult, types.UpdateControlOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionControlUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateControlOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
var maturityLevel *coredata.ControlMaturityLevel
|
|
|
|
if input.MaturityLevel != nil {
|
|
v := coredata.ControlMaturityLevel(*input.MaturityLevel)
|
|
maturityLevel = &v
|
|
}
|
|
|
|
control, err := svc.Controls.Update(
|
|
ctx, scope,
|
|
probo.UpdateControlRequest{
|
|
ID: input.ID,
|
|
Name: input.Name,
|
|
Description: UnwrapOmittable(input.Description),
|
|
SectionTitle: input.SectionTitle,
|
|
BestPractice: input.BestPractice,
|
|
MaturityLevel: maturityLevel,
|
|
NotImplementedJustification: UnwrapOmittable(input.NotImplementedJustification),
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateControlOutput{}, fmt.Errorf("failed to update control: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateControlOutput{
|
|
Control: types.NewControl(control),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) LinkControlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkControlInput) (*mcp.CallToolResult, types.LinkControlOutput, error) {
|
|
svc := r.proboSvc
|
|
|
|
switch input.ResourceID.EntityType() {
|
|
case coredata.MeasureEntityType:
|
|
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlMeasureMappingCreate)
|
|
if err != nil {
|
|
return nil, types.LinkControlOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Controls.CreateMeasureMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to measure: %w", err)
|
|
}
|
|
case coredata.DocumentEntityType:
|
|
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlDocumentMappingCreate)
|
|
if err != nil {
|
|
return nil, types.LinkControlOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Controls.CreateDocumentMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to document: %w", err)
|
|
}
|
|
case coredata.AuditEntityType:
|
|
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlAuditMappingCreate)
|
|
if err != nil {
|
|
return nil, types.LinkControlOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Controls.CreateAuditMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to audit: %w", err)
|
|
}
|
|
case coredata.ObligationEntityType:
|
|
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlObligationMappingCreate)
|
|
if err != nil {
|
|
return nil, types.LinkControlOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Controls.CreateObligationMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to obligation: %w", err)
|
|
}
|
|
default:
|
|
return nil, types.LinkControlOutput{}, fmt.Errorf("unsupported resource type for control linking: entity type %d", input.ResourceID.EntityType())
|
|
}
|
|
|
|
return nil, types.LinkControlOutput{}, nil
|
|
}
|
|
|
|
func (r *Resolver) UnlinkControlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkControlInput) (*mcp.CallToolResult, types.UnlinkControlOutput, error) {
|
|
svc := r.proboSvc
|
|
|
|
switch input.ResourceID.EntityType() {
|
|
case coredata.MeasureEntityType:
|
|
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlMeasureMappingDelete)
|
|
if err != nil {
|
|
return nil, types.UnlinkControlOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Controls.DeleteMeasureMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from measure: %w", err)
|
|
}
|
|
case coredata.DocumentEntityType:
|
|
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlDocumentMappingDelete)
|
|
if err != nil {
|
|
return nil, types.UnlinkControlOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Controls.DeleteDocumentMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from document: %w", err)
|
|
}
|
|
case coredata.AuditEntityType:
|
|
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlAuditMappingDelete)
|
|
if err != nil {
|
|
return nil, types.UnlinkControlOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Controls.DeleteAuditMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from audit: %w", err)
|
|
}
|
|
case coredata.ObligationEntityType:
|
|
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlObligationMappingDelete)
|
|
if err != nil {
|
|
return nil, types.UnlinkControlOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Controls.DeleteObligationMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from obligation: %w", err)
|
|
}
|
|
default:
|
|
return nil, types.UnlinkControlOutput{}, fmt.Errorf("unsupported resource type for control unlinking: entity type %d", input.ResourceID.EntityType())
|
|
}
|
|
|
|
return nil, types.UnlinkControlOutput{}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListControlObligationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListControlObligationsInput) (*mcp.CallToolResult, types.ListControlObligationsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlGet)
|
|
if err != nil {
|
|
return nil, types.ListControlObligationsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.ObligationOrderField]{
|
|
Field: coredata.ObligationOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.ObligationOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
obligationPage, err := prb.Obligations.ListForControlID(ctx, scope, input.ControlID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListControlObligationsOutput{}, fmt.Errorf("failed to list control obligations: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListControlObligationsOutput(obligationPage), nil
|
|
}
|
|
|
|
func (r *Resolver) ListControlMeasuresTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListControlMeasuresInput) (*mcp.CallToolResult, types.ListControlMeasuresOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlGet)
|
|
if err != nil {
|
|
return nil, types.ListControlMeasuresOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.MeasureOrderField]{
|
|
Field: coredata.MeasureOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.MeasureOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
measurePage, err := prb.Measures.ListForControlID(ctx, scope, input.ControlID, cursor, coredata.NewMeasureFilter(nil, nil, nil))
|
|
if err != nil {
|
|
return nil, types.ListControlMeasuresOutput{}, fmt.Errorf("failed to list control measures: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListControlMeasuresOutput(measurePage), nil
|
|
}
|
|
|
|
func (r *Resolver) ListControlDocumentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListControlDocumentsInput) (*mcp.CallToolResult, types.ListControlDocumentsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlGet)
|
|
if err != nil {
|
|
return nil, types.ListControlDocumentsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
|
|
Field: coredata.DocumentOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
docPage, err := prb.Documents.ListForControlID(ctx, scope, input.ControlID, cursor, coredata.NewDocumentFilter(nil))
|
|
if err != nil {
|
|
return nil, types.ListControlDocumentsOutput{}, fmt.Errorf("failed to list control documents: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListControlDocumentsOutput(docPage), nil
|
|
}
|
|
|
|
func (r *Resolver) ListControlAuditsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListControlAuditsInput) (*mcp.CallToolResult, types.ListControlAuditsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlGet)
|
|
if err != nil {
|
|
return nil, types.ListControlAuditsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.AuditOrderField]{
|
|
Field: coredata.AuditOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.AuditOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
auditPage, err := prb.Audits.ListForControlID(ctx, scope, input.ControlID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListControlAuditsOutput{}, fmt.Errorf("failed to list control audits: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListControlAuditsOutput(auditPage), nil
|
|
}
|
|
|
|
func (r *Resolver) ListRiskObligationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskObligationsInput) (*mcp.CallToolResult, types.ListRiskObligationsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskGet)
|
|
if err != nil {
|
|
return nil, types.ListRiskObligationsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.ObligationOrderField]{
|
|
Field: coredata.ObligationOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.ObligationOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
obligationPage, err := prb.Obligations.ListForRiskID(ctx, scope, input.RiskID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListRiskObligationsOutput{}, fmt.Errorf("failed to list risk obligations: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListRiskObligationsOutput(obligationPage), nil
|
|
}
|
|
|
|
func (r *Resolver) LinkRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkRiskInput) (*mcp.CallToolResult, types.LinkRiskOutput, error) {
|
|
svc := r.proboSvc
|
|
|
|
switch input.ResourceID.EntityType() {
|
|
case coredata.DocumentEntityType:
|
|
scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskDocumentMappingCreate)
|
|
if err != nil {
|
|
return nil, types.LinkRiskOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Risks.CreateDocumentMapping(ctx, scope, input.RiskID, input.ResourceID); err != nil {
|
|
return nil, types.LinkRiskOutput{}, fmt.Errorf("failed to link risk to document: %w", err)
|
|
}
|
|
case coredata.MeasureEntityType:
|
|
scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskMeasureMappingCreate)
|
|
if err != nil {
|
|
return nil, types.LinkRiskOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Risks.CreateMeasureMapping(ctx, scope, input.RiskID, input.ResourceID); err != nil {
|
|
return nil, types.LinkRiskOutput{}, fmt.Errorf("failed to link risk to measure: %w", err)
|
|
}
|
|
case coredata.ObligationEntityType:
|
|
scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskObligationMappingCreate)
|
|
if err != nil {
|
|
return nil, types.LinkRiskOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Risks.CreateObligationMapping(ctx, scope, input.RiskID, input.ResourceID); err != nil {
|
|
return nil, types.LinkRiskOutput{}, fmt.Errorf("failed to link risk to obligation: %w", err)
|
|
}
|
|
default:
|
|
return nil, types.LinkRiskOutput{}, fmt.Errorf("unsupported resource type for risk linking: entity type %d", input.ResourceID.EntityType())
|
|
}
|
|
|
|
return nil, types.LinkRiskOutput{}, nil
|
|
}
|
|
|
|
func (r *Resolver) UnlinkRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkRiskInput) (*mcp.CallToolResult, types.UnlinkRiskOutput, error) {
|
|
svc := r.proboSvc
|
|
|
|
switch input.ResourceID.EntityType() {
|
|
case coredata.DocumentEntityType:
|
|
scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskDocumentMappingDelete)
|
|
if err != nil {
|
|
return nil, types.UnlinkRiskOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Risks.DeleteDocumentMapping(ctx, scope, input.RiskID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkRiskOutput{}, fmt.Errorf("failed to unlink risk from document: %w", err)
|
|
}
|
|
case coredata.MeasureEntityType:
|
|
scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskMeasureMappingDelete)
|
|
if err != nil {
|
|
return nil, types.UnlinkRiskOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Risks.DeleteMeasureMapping(ctx, scope, input.RiskID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkRiskOutput{}, fmt.Errorf("failed to unlink risk from measure: %w", err)
|
|
}
|
|
case coredata.ObligationEntityType:
|
|
scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskObligationMappingDelete)
|
|
if err != nil {
|
|
return nil, types.UnlinkRiskOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Risks.DeleteObligationMapping(ctx, scope, input.RiskID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkRiskOutput{}, fmt.Errorf("failed to unlink risk from obligation: %w", err)
|
|
}
|
|
default:
|
|
return nil, types.UnlinkRiskOutput{}, fmt.Errorf("unsupported resource type for risk unlinking: entity type %d", input.ResourceID.EntityType())
|
|
}
|
|
|
|
return nil, types.UnlinkRiskOutput{}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListTasksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTasksInput) (*mcp.CallToolResult, types.ListTasksOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionTaskList)
|
|
if err != nil {
|
|
return nil, types.ListTasksOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.TaskOrderField]{
|
|
Field: coredata.TaskOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.TaskOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
page, err := prb.Tasks.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization tasks: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListTasksOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetTaskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTaskInput) (*mcp.CallToolResult, types.GetTaskOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionTaskGet)
|
|
if err != nil {
|
|
return nil, types.GetTaskOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
task, err := prb.Tasks.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetTaskOutput{}, fmt.Errorf("failed to get task: %w", err)
|
|
}
|
|
|
|
return nil, types.GetTaskOutput{
|
|
Task: types.NewTask(task),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddTaskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTaskInput) (*mcp.CallToolResult, types.AddTaskOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionTaskCreate)
|
|
if err != nil {
|
|
return nil, types.AddTaskOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
priority := coredata.TaskPriorityMedium
|
|
if input.Priority != nil {
|
|
priority = *input.Priority
|
|
}
|
|
|
|
task, err := svc.Tasks.Create(
|
|
ctx, scope,
|
|
probo.CreateTaskRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
MeasureID: input.MeasureID,
|
|
Name: input.Name,
|
|
Description: input.Description,
|
|
Priority: priority,
|
|
TimeEstimate: input.TimeEstimate,
|
|
Deadline: input.Deadline,
|
|
AssignedToID: input.AssignedToID,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddTaskOutput{}, fmt.Errorf("failed to create task: %w", err)
|
|
}
|
|
|
|
return nil, types.AddTaskOutput{
|
|
Task: types.NewTask(task),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateTaskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTaskInput) (*mcp.CallToolResult, types.UpdateTaskOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionTaskUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateTaskOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
task, err := svc.Tasks.Update(
|
|
ctx, scope,
|
|
probo.UpdateTaskRequest{
|
|
TaskID: input.ID,
|
|
Name: input.Name,
|
|
Description: UnwrapOmittable(input.Description),
|
|
State: input.State,
|
|
Priority: input.Priority,
|
|
Rank: input.Rank,
|
|
TimeEstimate: UnwrapOmittable(input.TimeEstimate),
|
|
Deadline: UnwrapOmittable(input.Deadline),
|
|
AssignedToID: UnwrapOmittable(input.AssignedToID),
|
|
MeasureID: UnwrapOmittable(input.MeasureID),
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateTaskOutput{}, fmt.Errorf("failed to update task: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateTaskOutput{
|
|
Task: types.NewTask(task),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AssignTaskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AssignTaskInput) (*mcp.CallToolResult, types.AssignTaskOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionTaskAssign)
|
|
if err != nil {
|
|
return nil, types.AssignTaskOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
task, err := svc.Tasks.Assign(ctx, scope, input.ID, input.AssignedToID)
|
|
if err != nil {
|
|
return nil, types.AssignTaskOutput{}, fmt.Errorf("failed to assign task: %w", err)
|
|
}
|
|
|
|
return nil, types.AssignTaskOutput{
|
|
Task: types.NewTask(task),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UnassignTaskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnassignTaskInput) (*mcp.CallToolResult, types.UnassignTaskOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionTaskUnassign)
|
|
if err != nil {
|
|
return nil, types.UnassignTaskOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
task, err := svc.Tasks.Unassign(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.UnassignTaskOutput{}, fmt.Errorf("failed to unassign task: %w", err)
|
|
}
|
|
|
|
return nil, types.UnassignTaskOutput{
|
|
Task: types.NewTask(task),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteTaskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTaskInput) (*mcp.CallToolResult, types.DeleteTaskOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionTaskDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteTaskOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.Tasks.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteTaskOutput{}, fmt.Errorf("failed to delete task: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteTaskOutput{
|
|
DeletedTaskID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListDocumentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentsInput) (*mcp.CallToolResult, types.ListDocumentsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionDocumentList)
|
|
if err != nil {
|
|
return nil, types.ListDocumentsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
|
|
Field: coredata.DocumentOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
documentFilter := coredata.NewDocumentFilter(nil).
|
|
WithStatus([]coredata.DocumentStatus{coredata.DocumentStatusActive})
|
|
|
|
if input.Filter != nil {
|
|
var query *string
|
|
if input.Filter.Query != nil && *input.Filter.Query != "" {
|
|
query = input.Filter.Query
|
|
}
|
|
|
|
documentFilter = coredata.NewDocumentFilter(query).
|
|
WithWriteModes(input.Filter.WriteModes).
|
|
WithDocumentTypes(input.Filter.DocumentTypes).
|
|
WithClassifications(input.Filter.Classifications).
|
|
WithStatus(input.Filter.Status)
|
|
|
|
if len(input.Filter.Status) == 0 {
|
|
documentFilter = documentFilter.WithStatus([]coredata.DocumentStatus{coredata.DocumentStatusActive})
|
|
}
|
|
}
|
|
|
|
docPage, err := prb.Documents.ListByOrganizationID(ctx, scope, input.OrganizationID, cursor, documentFilter)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization documents: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListDocumentsOutput(docPage), nil
|
|
}
|
|
|
|
func (r *Resolver) GetDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDocumentInput) (*mcp.CallToolResult, types.GetDocumentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentGet)
|
|
if err != nil {
|
|
return nil, types.GetDocumentOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
document, err := prb.Documents.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot get document: %w", err))
|
|
}
|
|
|
|
return nil, types.GetDocumentOutput{
|
|
Document: types.NewDocument(document),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddDocumentInput) (*mcp.CallToolResult, types.AddDocumentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionDocumentCreate)
|
|
if err != nil {
|
|
return nil, types.AddDocumentOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
var compliancePortalVisibility *coredata.CompliancePortalVisibility
|
|
if input.CompliancePortalVisibility != nil {
|
|
compliancePortalVisibility = input.CompliancePortalVisibility
|
|
}
|
|
|
|
contentJSON, err := markdownToProseMirrorJSON(input.Content)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot convert markdown to prosemirror: %w", err))
|
|
}
|
|
|
|
document, documentVersion, err := svc.Documents.Create(
|
|
ctx, scope,
|
|
probo.CreateDocumentRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Title: input.Title,
|
|
Content: contentJSON,
|
|
Classification: input.Classification,
|
|
DocumentType: input.DocumentType,
|
|
CompliancePortalVisibility: compliancePortalVisibility,
|
|
DefaultApproverIDs: input.DefaultApproverIds,
|
|
},
|
|
)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot create document: %w", err))
|
|
}
|
|
|
|
return nil, types.NewAddDocumentOutput(document, documentVersion), nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateDocumentInput) (*mcp.CallToolResult, types.UpdateDocumentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateDocumentOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
var defaultApproverIDs *[]gid.GID
|
|
if input.DefaultApproverIds != nil {
|
|
defaultApproverIDs = &input.DefaultApproverIds
|
|
}
|
|
|
|
var content *string
|
|
|
|
if input.Content != nil {
|
|
c, err := markdownToProseMirrorJSON(*input.Content)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot convert markdown to prosemirror: %w", err))
|
|
}
|
|
|
|
content = &c
|
|
}
|
|
|
|
document, documentVersion, _, err := svc.Documents.Update(
|
|
ctx, scope,
|
|
probo.UpdateDocumentRequest{
|
|
DocumentID: input.ID,
|
|
Title: input.Title,
|
|
Content: content,
|
|
Classification: input.Classification,
|
|
DocumentType: input.DocumentType,
|
|
CompliancePortalVisibility: input.CompliancePortalVisibility,
|
|
DefaultApproverIDs: defaultApproverIDs,
|
|
},
|
|
)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot update document: %w", err))
|
|
}
|
|
|
|
output := types.UpdateDocumentOutput{
|
|
Document: types.NewDocument(document),
|
|
}
|
|
|
|
if documentVersion != nil {
|
|
output.DocumentVersion = types.NewDocumentVersion(documentVersion)
|
|
}
|
|
|
|
return nil, output, nil
|
|
}
|
|
|
|
func (r *Resolver) ListDocumentVersionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentVersionsInput) (*mcp.CallToolResult, types.ListDocumentVersionsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.DocumentID, probo.ActionDocumentVersionList)
|
|
if err != nil {
|
|
return nil, types.ListDocumentVersionsOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.DocumentVersionOrderField]{
|
|
Field: coredata.DocumentVersionOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.DocumentVersionOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
svc := r.proboSvc
|
|
|
|
versionFilter := coredata.NewDocumentVersionFilter()
|
|
if input.Filter != nil && len(input.Filter.Statuses) > 0 {
|
|
versionFilter = versionFilter.WithStatuses(input.Filter.Statuses...)
|
|
}
|
|
|
|
versionPage, err := svc.Documents.ListVersions(ctx, scope, input.DocumentID, cursor, versionFilter)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list document versions: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListDocumentVersionsOutput(versionPage), nil
|
|
}
|
|
|
|
func (r *Resolver) GetDocumentVersionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDocumentVersionInput) (*mcp.CallToolResult, types.GetDocumentVersionOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentVersionGet)
|
|
if err != nil {
|
|
return nil, types.GetDocumentVersionOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
version, err := svc.Documents.GetVersion(ctx, scope, input.ID)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot get document version: %w", err))
|
|
}
|
|
|
|
return nil, types.GetDocumentVersionOutput{
|
|
DocumentVersion: types.NewDocumentVersion(version),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListDocumentVersionSignaturesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentVersionSignaturesInput) (*mcp.CallToolResult, types.ListDocumentVersionSignaturesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionSignatureList)
|
|
if err != nil {
|
|
return nil, types.ListDocumentVersionSignaturesOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.DocumentVersionSignatureOrderField]{
|
|
Field: coredata.DocumentVersionSignatureOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.DocumentVersionSignatureOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
var (
|
|
signatureStates []coredata.DocumentVersionSignatureState
|
|
activeContract *bool
|
|
profileState *coredata.ProfileState
|
|
)
|
|
|
|
if input.Filter != nil {
|
|
if input.Filter.States != nil {
|
|
signatureStates = input.Filter.States
|
|
}
|
|
|
|
if input.Filter.ActiveContract != nil {
|
|
activeContract = input.Filter.ActiveContract
|
|
}
|
|
|
|
if input.Filter.ProfileState != nil {
|
|
profileState = input.Filter.ProfileState
|
|
}
|
|
}
|
|
|
|
signatureFilter := coredata.NewDocumentVersionSignatureFilter(signatureStates, activeContract, profileState)
|
|
|
|
page, err := prb.Documents.ListSignatures(ctx, scope, input.DocumentVersionID, cursor, signatureFilter)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list document version signatures: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListDocumentVersionSignaturesOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetDocumentVersionSignatureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDocumentVersionSignatureInput) (*mcp.CallToolResult, types.GetDocumentVersionSignatureOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentVersionSignatureGet)
|
|
if err != nil {
|
|
return nil, types.GetDocumentVersionSignatureOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
signature, err := prb.Documents.GetVersionSignature(ctx, scope, input.ID)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot get document version signature: %w", err))
|
|
}
|
|
|
|
return nil, types.GetDocumentVersionSignatureOutput{
|
|
DocumentVersionSignature: types.NewDocumentVersionSignature(signature),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) RequestDocumentVersionSignatureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RequestDocumentVersionSignatureInput) (*mcp.CallToolResult, types.RequestDocumentVersionSignatureOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionSignatureRequest)
|
|
if err != nil {
|
|
return nil, types.RequestDocumentVersionSignatureOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
documentVersionSignature, err := svc.Documents.RequestSignature(
|
|
ctx, scope,
|
|
probo.RequestSignatureRequest{
|
|
DocumentVersionID: input.DocumentVersionID,
|
|
Signatory: input.SignatoryID,
|
|
},
|
|
)
|
|
if err != nil {
|
|
if _, ok := errors.AsType[*probo.ErrDocumentVersionNotCurrent](err); ok {
|
|
return nil, types.RequestDocumentVersionSignatureOutput{}, fmt.Errorf("cannot request signature: %w", err)
|
|
}
|
|
|
|
panic(fmt.Errorf("cannot request signature: %w", err))
|
|
}
|
|
|
|
return nil, types.RequestDocumentVersionSignatureOutput{
|
|
DocumentVersionSignature: types.NewDocumentVersionSignature(documentVersionSignature),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteDocumentInput) (*mcp.CallToolResult, types.DeleteDocumentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.DocumentID, probo.ActionDocumentDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteDocumentOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.Documents.SoftDelete(ctx, scope, input.DocumentID)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot soft delete document: %w", err))
|
|
}
|
|
|
|
return nil, types.DeleteDocumentOutput{
|
|
DeletedDocumentID: input.DocumentID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) CancelSignatureRequestTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CancelSignatureRequestInput) (*mcp.CallToolResult, types.CancelSignatureRequestOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.DocumentVersionSignatureID, probo.ActionDocumentVersionCancelSignature)
|
|
if err != nil {
|
|
return nil, types.CancelSignatureRequestOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.Documents.CancelSignatureRequest(ctx, scope, input.DocumentVersionSignatureID)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot cancel signature request: %w", err))
|
|
}
|
|
|
|
return nil, types.CancelSignatureRequestOutput{
|
|
DeletedDocumentVersionSignatureID: input.DocumentVersionSignatureID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskInput) (*mcp.CallToolResult, types.DeleteRiskOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteRiskOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.Risks.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteRiskOutput{}, fmt.Errorf("failed to delete risk: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteRiskOutput{
|
|
DeletedRiskID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteMeasureInput) (*mcp.CallToolResult, types.DeleteMeasureOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionMeasureDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteMeasureOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.Measures.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteMeasureOutput{}, fmt.Errorf("failed to delete measure: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteMeasureOutput{
|
|
DeletedMeasureID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListMeasureRisksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasureRisksInput) (*mcp.CallToolResult, types.ListMeasureRisksOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureGet)
|
|
if err != nil {
|
|
return nil, types.ListMeasureRisksOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.RiskOrderField]{
|
|
Field: coredata.RiskOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.RiskOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
riskPage, err := prb.Risks.ListForMeasureID(ctx, scope, input.MeasureID, cursor, coredata.NewRiskFilter(nil))
|
|
if err != nil {
|
|
return nil, types.ListMeasureRisksOutput{}, fmt.Errorf("failed to list measure risks: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListMeasureRisksOutput(riskPage), nil
|
|
}
|
|
|
|
func (r *Resolver) ListMeasureControlsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasureControlsInput) (*mcp.CallToolResult, types.ListMeasureControlsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureGet)
|
|
if err != nil {
|
|
return nil, types.ListMeasureControlsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.ControlOrderField]{
|
|
Field: coredata.ControlOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.ControlOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
controlPage, err := prb.Controls.ListForMeasureID(ctx, scope, input.MeasureID, cursor, coredata.NewControlFilter(nil))
|
|
if err != nil {
|
|
return nil, types.ListMeasureControlsOutput{}, fmt.Errorf("failed to list measure controls: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListMeasureControlsOutput(controlPage), nil
|
|
}
|
|
|
|
func (r *Resolver) ListMeasureTasksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasureTasksInput) (*mcp.CallToolResult, types.ListMeasureTasksOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureGet)
|
|
if err != nil {
|
|
return nil, types.ListMeasureTasksOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.TaskOrderField]{
|
|
Field: coredata.TaskOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.TaskOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
taskPage, err := prb.Tasks.ListForMeasureID(ctx, scope, input.MeasureID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListMeasureTasksOutput{}, fmt.Errorf("failed to list measure tasks: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListMeasureTasksOutput(taskPage), nil
|
|
}
|
|
|
|
func (r *Resolver) ListMeasureEvidencesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasureEvidencesInput) (*mcp.CallToolResult, types.ListMeasureEvidencesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureGet)
|
|
if err != nil {
|
|
return nil, types.ListMeasureEvidencesOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.EvidenceOrderField]{
|
|
Field: coredata.EvidenceOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
evidencePage, err := prb.Evidences.ListForMeasureID(ctx, scope, input.MeasureID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListMeasureEvidencesOutput{}, fmt.Errorf("failed to list measure evidences: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListMeasureEvidencesOutput(evidencePage), nil
|
|
}
|
|
|
|
func (r *Resolver) LinkMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkMeasureInput) (*mcp.CallToolResult, types.LinkMeasureOutput, error) {
|
|
svc := r.proboSvc
|
|
|
|
switch input.ResourceID.EntityType() {
|
|
case coredata.ControlEntityType:
|
|
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionControlMeasureMappingCreate)
|
|
if err != nil {
|
|
return nil, types.LinkMeasureOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Controls.CreateMeasureMapping(ctx, scope, input.ResourceID, input.MeasureID); err != nil {
|
|
return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to control: %w", err)
|
|
}
|
|
case coredata.RiskEntityType:
|
|
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionRiskMeasureMappingCreate)
|
|
if err != nil {
|
|
return nil, types.LinkMeasureOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Risks.CreateMeasureMapping(ctx, scope, input.ResourceID, input.MeasureID); err != nil {
|
|
return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to risk: %w", err)
|
|
}
|
|
case coredata.DocumentEntityType:
|
|
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureDocumentMappingCreate)
|
|
if err != nil {
|
|
return nil, types.LinkMeasureOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Measures.CreateDocumentMapping(ctx, scope, input.MeasureID, input.ResourceID); err != nil {
|
|
return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to document: %w", err)
|
|
}
|
|
case coredata.ThirdPartyEntityType:
|
|
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureThirdPartyMappingCreate)
|
|
if err != nil {
|
|
return nil, types.LinkMeasureOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Measures.CreateThirdPartyMapping(ctx, scope, input.MeasureID, input.ResourceID); err != nil {
|
|
return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to third party: %w", err)
|
|
}
|
|
default:
|
|
return nil, types.LinkMeasureOutput{}, fmt.Errorf("unsupported resource type for measure linking: entity type %d", input.ResourceID.EntityType())
|
|
}
|
|
|
|
return nil, types.LinkMeasureOutput{}, nil
|
|
}
|
|
|
|
func (r *Resolver) UnlinkMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkMeasureInput) (*mcp.CallToolResult, types.UnlinkMeasureOutput, error) {
|
|
svc := r.proboSvc
|
|
|
|
switch input.ResourceID.EntityType() {
|
|
case coredata.ControlEntityType:
|
|
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionControlMeasureMappingDelete)
|
|
if err != nil {
|
|
return nil, types.UnlinkMeasureOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Controls.DeleteMeasureMapping(ctx, scope, input.ResourceID, input.MeasureID); err != nil {
|
|
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from control: %w", err)
|
|
}
|
|
case coredata.RiskEntityType:
|
|
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionRiskMeasureMappingDelete)
|
|
if err != nil {
|
|
return nil, types.UnlinkMeasureOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Risks.DeleteMeasureMapping(ctx, scope, input.ResourceID, input.MeasureID); err != nil {
|
|
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from risk: %w", err)
|
|
}
|
|
case coredata.DocumentEntityType:
|
|
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureDocumentMappingDelete)
|
|
if err != nil {
|
|
return nil, types.UnlinkMeasureOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Measures.DeleteDocumentMapping(ctx, scope, input.MeasureID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from document: %w", err)
|
|
}
|
|
case coredata.ThirdPartyEntityType:
|
|
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureThirdPartyMappingDelete)
|
|
if err != nil {
|
|
return nil, types.UnlinkMeasureOutput{}, err
|
|
}
|
|
|
|
if _, _, err := svc.Measures.DeleteThirdPartyMapping(ctx, scope, input.MeasureID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from third party: %w", err)
|
|
}
|
|
default:
|
|
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("unsupported resource type for measure unlinking: entity type %d", input.ResourceID.EntityType())
|
|
}
|
|
|
|
return nil, types.UnlinkMeasureOutput{}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListUsersTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListUsersInput) (*mcp.CallToolResult, types.ListUsersOutput, error) {
|
|
if _, err := r.Authorize(ctx, input.OrganizationID, iam.ActionMembershipProfileList); err != nil {
|
|
return nil, types.ListUsersOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.MembershipProfileOrderField]{
|
|
Field: coredata.MembershipProfileOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.MembershipProfileOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
filter := coredata.NewMembershipProfileFilter(nil).WithMembership()
|
|
if input.Filter != nil {
|
|
filter = coredata.NewMembershipProfileFilter(input.Filter.ContractEnded).WithMembership()
|
|
|
|
if len(input.Filter.States) > 0 {
|
|
filter.WithStates(input.Filter.States...)
|
|
}
|
|
|
|
if input.Filter.State != nil {
|
|
filter.WithState(*input.Filter.State)
|
|
}
|
|
|
|
if input.Filter.Query != nil {
|
|
filter.WithQuery(input.Filter.Query)
|
|
}
|
|
|
|
if input.Filter.Role != nil {
|
|
filter.WithRole(*input.Filter.Role)
|
|
}
|
|
|
|
if input.Filter.Kind != nil {
|
|
kind := string(*input.Filter.Kind)
|
|
filter.WithKind(&kind)
|
|
}
|
|
}
|
|
|
|
pageResult, err := r.iamSvc.OrganizationService.ListProfiles(ctx, input.OrganizationID, cursor, filter)
|
|
if err != nil {
|
|
return nil, types.ListUsersOutput{}, fmt.Errorf("list users: %w", err)
|
|
}
|
|
|
|
users := make([]*types.Profile, 0, len(pageResult.Data))
|
|
for _, p := range pageResult.Data {
|
|
users = append(users, types.NewProfile(p))
|
|
}
|
|
|
|
var nextCursor *page.CursorKey
|
|
|
|
if len(pageResult.Data) > 0 && pageResult.Cursor != nil {
|
|
cursorKey := pageResult.Data[len(pageResult.Data)-1].CursorKey(pageResult.Cursor.OrderBy.Field)
|
|
nextCursor = &cursorKey
|
|
}
|
|
|
|
return nil, types.ListUsersOutput{
|
|
Users: users,
|
|
NextCursor: nextCursor,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) GetUserTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetUserInput) (*mcp.CallToolResult, types.GetUserOutput, error) {
|
|
profile, err := r.iamSvc.OrganizationService.GetProfile(ctx, input.ID)
|
|
if err != nil {
|
|
if _, ok := errors.AsType[*iam.ErrProfileNotFound](err); ok {
|
|
return nil, types.GetUserOutput{}, fmt.Errorf("user not found: %w", err)
|
|
}
|
|
|
|
return nil, types.GetUserOutput{}, fmt.Errorf("get user: %w", err)
|
|
}
|
|
|
|
if _, err := r.Authorize(ctx, profile.OrganizationID, iam.ActionMembershipProfileGet); err != nil {
|
|
return nil, types.GetUserOutput{}, err
|
|
}
|
|
|
|
return nil, types.GetUserOutput{User: types.NewProfile(profile)}, nil
|
|
}
|
|
|
|
func (r *Resolver) CreateUserTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateUserInput) (*mcp.CallToolResult, types.CreateUserOutput, error) {
|
|
scope, err := r.Authorize(
|
|
ctx,
|
|
input.OrganizationID,
|
|
iam.ActionMembershipProfileCreate,
|
|
authz.WithAttr("target_role", input.Role.String()),
|
|
)
|
|
if err != nil {
|
|
return nil, types.CreateUserOutput{}, err
|
|
}
|
|
|
|
var contractStart, contractEnd **time.Time
|
|
if input.ContractStartDate != nil {
|
|
contractStart = &input.ContractStartDate
|
|
}
|
|
|
|
if input.ContractEndDate != nil {
|
|
contractEnd = &input.ContractEndDate
|
|
}
|
|
|
|
profile, err := r.iamSvc.OrganizationService.CreateUser(ctx, scope, &iam.CreateUserRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
EmailAddress: input.EmailAddress,
|
|
Role: input.Role,
|
|
FullName: input.FullName,
|
|
AdditionalEmailAddresses: input.AdditionalEmailAddresses,
|
|
Kind: input.Kind,
|
|
Position: input.Position,
|
|
ContractStartDate: contractStart,
|
|
ContractEndDate: contractEnd,
|
|
})
|
|
if err != nil {
|
|
if _, ok := errors.AsType[*iam.ErrUserAlreadyExists](err); ok {
|
|
return nil, types.CreateUserOutput{}, fmt.Errorf("user with email already exists: %w", err)
|
|
}
|
|
|
|
return nil, types.CreateUserOutput{}, fmt.Errorf("create user: %w", err)
|
|
}
|
|
|
|
return nil, types.CreateUserOutput{User: types.NewProfile(profile)}, nil
|
|
}
|
|
|
|
func (r *Resolver) InviteUserTool(ctx context.Context, req *mcp.CallToolRequest, input *types.InviteUserInput) (*mcp.CallToolResult, types.InviteUserOutput, error) {
|
|
if _, err := r.Authorize(ctx, input.ProfileID, iam.ActionInvitationCreate); err != nil {
|
|
return nil, types.InviteUserOutput{}, err
|
|
}
|
|
|
|
invitation, err := r.iamSvc.OrganizationService.InviteUser(ctx, &iam.CreateInvitationRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
ProfileID: input.ProfileID,
|
|
})
|
|
if err != nil {
|
|
if _, ok := errors.AsType[*iam.ErrOrganizationNotFound](err); ok {
|
|
return nil, types.InviteUserOutput{}, fmt.Errorf("organization not found: %w", err)
|
|
}
|
|
|
|
if _, ok := errors.AsType[*iam.ErrUserAlreadyExists](err); ok {
|
|
return nil, types.InviteUserOutput{}, fmt.Errorf("user already in organization: %w", err)
|
|
}
|
|
|
|
return nil, types.InviteUserOutput{}, fmt.Errorf("invite user: %w", err)
|
|
}
|
|
|
|
return nil, types.InviteUserOutput{InvitationID: invitation.ID}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateUserTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateUserInput) (*mcp.CallToolResult, types.UpdateUserOutput, error) {
|
|
if _, err := r.Authorize(ctx, input.ID, iam.ActionMembershipProfileUpdate); err != nil {
|
|
return nil, types.UpdateUserOutput{}, err
|
|
}
|
|
|
|
var additionalEmails []mail.Addr
|
|
if input.AdditionalEmailAddresses != nil {
|
|
additionalEmails = *input.AdditionalEmailAddresses
|
|
}
|
|
|
|
var position *string
|
|
if p := UnwrapOmittable(input.Position); p != nil {
|
|
position = *p
|
|
}
|
|
|
|
var contractStart, contractEnd **time.Time
|
|
if p := UnwrapOmittable(input.ContractStartDate); p != nil {
|
|
contractStart = p
|
|
}
|
|
|
|
if p := UnwrapOmittable(input.ContractEndDate); p != nil {
|
|
contractEnd = p
|
|
}
|
|
|
|
profile, err := r.iamSvc.OrganizationService.UpdateUser(ctx, &iam.UpdateUserRequest{
|
|
ID: input.ID,
|
|
FullName: input.FullName,
|
|
AdditionalEmailAddresses: additionalEmails,
|
|
Kind: input.Kind,
|
|
Position: position,
|
|
ContractStartDate: contractStart,
|
|
ContractEndDate: contractEnd,
|
|
})
|
|
if err != nil {
|
|
return nil, types.UpdateUserOutput{}, fmt.Errorf("update user: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateUserOutput{User: types.NewProfile(profile)}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateMembershipTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateMembershipInput) (*mcp.CallToolResult, types.UpdateMembershipOutput, error) {
|
|
if _, err := r.Authorize(
|
|
ctx,
|
|
input.MembershipID,
|
|
iam.ActionMembershipUpdate,
|
|
authz.WithAttr("target_role", input.Role.String()),
|
|
); err != nil {
|
|
return nil, types.UpdateMembershipOutput{}, err
|
|
}
|
|
|
|
membership, err := r.iamSvc.OrganizationService.UpdateMembership(ctx, input.OrganizationID, input.MembershipID, input.Role)
|
|
if err != nil {
|
|
return nil, types.UpdateMembershipOutput{}, fmt.Errorf("update membership: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateMembershipOutput{
|
|
Membership: &types.Membership{
|
|
ID: membership.ID,
|
|
Role: membership.Role,
|
|
CreatedAt: membership.CreatedAt,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) RemoveUserTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RemoveUserInput) (*mcp.CallToolResult, types.RemoveUserOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ProfileID, iam.ActionMembershipDelete)
|
|
if err != nil {
|
|
return nil, types.RemoveUserOutput{}, err
|
|
}
|
|
|
|
err = r.iamSvc.OrganizationService.RemoveUser(ctx, scope, input.OrganizationID, input.ProfileID)
|
|
if err != nil {
|
|
if _, ok := errors.AsType[*iam.ErrUserManagedBySCIM](err); ok {
|
|
return nil, types.RemoveUserOutput{}, fmt.Errorf("user is managed by SCIM and cannot be removed: %w", err)
|
|
}
|
|
|
|
if _, ok := errors.AsType[*iam.ErrLastActiveOwner](err); ok {
|
|
return nil, types.RemoveUserOutput{}, fmt.Errorf("cannot remove last active owner: %w", err)
|
|
}
|
|
|
|
if _, ok := errors.AsType[*iam.ErrProfileInUse](err); ok {
|
|
return nil, types.RemoveUserOutput{}, fmt.Errorf("cannot remove person: referenced by other resources: %w", err)
|
|
}
|
|
|
|
return nil, types.RemoveUserOutput{}, fmt.Errorf("remove user: %w", err)
|
|
}
|
|
|
|
return nil, types.RemoveUserOutput{DeletedUserID: input.ProfileID}, nil
|
|
}
|
|
|
|
func (r *Resolver) ArchiveUserTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ArchiveUserInput) (*mcp.CallToolResult, types.ArchiveUserOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ProfileID, iam.ActionMembershipProfileDelete)
|
|
if err != nil {
|
|
return nil, types.ArchiveUserOutput{}, err
|
|
}
|
|
|
|
err = r.iamSvc.OrganizationService.ArchiveUser(ctx, scope, input.OrganizationID, input.ProfileID)
|
|
if err != nil {
|
|
if _, ok := errors.AsType[*iam.ErrUserManagedBySCIM](err); ok {
|
|
return nil, types.ArchiveUserOutput{}, fmt.Errorf("user is managed by SCIM and cannot be archived: %w", err)
|
|
}
|
|
|
|
if _, ok := errors.AsType[*iam.ErrLastActiveOwner](err); ok {
|
|
return nil, types.ArchiveUserOutput{}, fmt.Errorf("cannot archive last active owner: %w", err)
|
|
}
|
|
|
|
return nil, types.ArchiveUserOutput{}, fmt.Errorf("archive user: %w", err)
|
|
}
|
|
|
|
return nil, types.ArchiveUserOutput{ArchivedUserID: input.ProfileID}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteDataProtectionImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteDataProtectionImpactAssessmentInput) (*mcp.CallToolResult, types.DeleteDataProtectionImpactAssessmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDataProtectionImpactAssessmentDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteDataProtectionImpactAssessmentOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.DataProtectionImpactAssessments.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteDataProtectionImpactAssessmentOutput{}, fmt.Errorf("failed to delete data protection impact assessment: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteDataProtectionImpactAssessmentOutput{
|
|
DeletedDataProtectionImpactAssessmentID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListStatementsOfApplicabilityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListStatementsOfApplicabilityInput) (*mcp.CallToolResult, types.ListStatementsOfApplicabilityOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionStatementOfApplicabilityList)
|
|
if err != nil {
|
|
return nil, types.ListStatementsOfApplicabilityOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.StatementOfApplicabilityOrderField]{
|
|
Field: coredata.StatementOfApplicabilityOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.StatementOfApplicabilityOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
pg, err := prb.StatementsOfApplicability.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListStatementsOfApplicabilityOutput{}, fmt.Errorf("failed to list statements of applicability: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListStatementsOfApplicabilityOutput(pg), nil
|
|
}
|
|
|
|
func (r *Resolver) GetStatementOfApplicabilityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetStatementOfApplicabilityInput) (*mcp.CallToolResult, types.GetStatementOfApplicabilityOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionStatementOfApplicabilityGet)
|
|
if err != nil {
|
|
return nil, types.GetStatementOfApplicabilityOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
soa, err := prb.StatementsOfApplicability.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetStatementOfApplicabilityOutput{}, fmt.Errorf("failed to get statement of applicability: %w", err)
|
|
}
|
|
|
|
return nil, types.GetStatementOfApplicabilityOutput{
|
|
StatementOfApplicability: types.NewStatementOfApplicability(soa),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddStatementOfApplicabilityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddStatementOfApplicabilityInput) (*mcp.CallToolResult, types.AddStatementOfApplicabilityOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionStatementOfApplicabilityCreate)
|
|
if err != nil {
|
|
return nil, types.AddStatementOfApplicabilityOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
soa, err := svc.StatementsOfApplicability.Create(ctx, scope, probo.CreateStatementOfApplicabilityRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddStatementOfApplicabilityOutput{}, fmt.Errorf("failed to create statement of applicability: %w", err)
|
|
}
|
|
|
|
return nil, types.AddStatementOfApplicabilityOutput{
|
|
StatementOfApplicability: types.NewStatementOfApplicability(soa),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateStatementOfApplicabilityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateStatementOfApplicabilityInput) (*mcp.CallToolResult, types.UpdateStatementOfApplicabilityOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionStatementOfApplicabilityUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateStatementOfApplicabilityOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
soa, err := svc.StatementsOfApplicability.Update(ctx, scope, probo.UpdateStatementOfApplicabilityRequest{
|
|
StatementOfApplicabilityID: input.ID,
|
|
Name: input.Name,
|
|
})
|
|
if err != nil {
|
|
return nil, types.UpdateStatementOfApplicabilityOutput{}, fmt.Errorf("failed to update statement of applicability: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateStatementOfApplicabilityOutput{
|
|
StatementOfApplicability: types.NewStatementOfApplicability(soa),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteStatementOfApplicabilityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteStatementOfApplicabilityInput) (*mcp.CallToolResult, types.DeleteStatementOfApplicabilityOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionStatementOfApplicabilityDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteStatementOfApplicabilityOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.StatementsOfApplicability.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteStatementOfApplicabilityOutput{}, fmt.Errorf("failed to delete statement of applicability: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteStatementOfApplicabilityOutput{
|
|
DeletedStatementOfApplicabilityID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListApplicabilityStatementsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListApplicabilityStatementsInput) (*mcp.CallToolResult, types.ListApplicabilityStatementsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.StatementOfApplicabilityID, probo.ActionApplicabilityStatementList)
|
|
if err != nil {
|
|
return nil, types.ListApplicabilityStatementsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.ApplicabilityStatementOrderField]{
|
|
Field: coredata.ApplicabilityStatementOrderFieldControlSectionTitle,
|
|
Direction: page.OrderDirectionAsc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.ApplicabilityStatementOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
pg, err := prb.StatementsOfApplicability.ListApplicabilityStatements(ctx, scope, input.StatementOfApplicabilityID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListApplicabilityStatementsOutput{}, fmt.Errorf("failed to list applicability statements: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListApplicabilityStatementsOutput(pg), nil
|
|
}
|
|
|
|
func (r *Resolver) GetApplicabilityStatementTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetApplicabilityStatementInput) (*mcp.CallToolResult, types.GetApplicabilityStatementOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionApplicabilityStatementGet)
|
|
if err != nil {
|
|
return nil, types.GetApplicabilityStatementOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
stmt, err := prb.StatementsOfApplicability.GetApplicabilityStatement(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetApplicabilityStatementOutput{}, fmt.Errorf("failed to get applicability statement: %w", err)
|
|
}
|
|
|
|
return nil, types.GetApplicabilityStatementOutput{
|
|
ApplicabilityStatement: types.NewApplicabilityStatement(stmt),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddApplicabilityStatementTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddApplicabilityStatementInput) (*mcp.CallToolResult, types.AddApplicabilityStatementOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.StatementOfApplicabilityID, probo.ActionApplicabilityStatementCreate)
|
|
if err != nil {
|
|
return nil, types.AddApplicabilityStatementOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
stmt, err := svc.StatementsOfApplicability.CreateApplicabilityStatement(
|
|
ctx, scope,
|
|
input.StatementOfApplicabilityID,
|
|
input.ControlID,
|
|
input.Applicability,
|
|
input.Justification,
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddApplicabilityStatementOutput{}, fmt.Errorf("failed to create applicability statement: %w", err)
|
|
}
|
|
|
|
return nil, types.AddApplicabilityStatementOutput{
|
|
ApplicabilityStatement: types.NewApplicabilityStatement(stmt),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateApplicabilityStatementTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateApplicabilityStatementInput) (*mcp.CallToolResult, types.UpdateApplicabilityStatementOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionApplicabilityStatementUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateApplicabilityStatementOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
stmt, err := svc.StatementsOfApplicability.UpdateApplicabilityStatement(
|
|
ctx, scope,
|
|
input.ID,
|
|
input.Applicability,
|
|
input.Justification,
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateApplicabilityStatementOutput{}, fmt.Errorf("failed to update applicability statement: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateApplicabilityStatementOutput{
|
|
ApplicabilityStatement: types.NewApplicabilityStatement(stmt),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteApplicabilityStatementTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteApplicabilityStatementInput) (*mcp.CallToolResult, types.DeleteApplicabilityStatementOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionApplicabilityStatementDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteApplicabilityStatementOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.StatementsOfApplicability.DeleteApplicabilityStatement(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteApplicabilityStatementOutput{}, fmt.Errorf("failed to delete applicability statement: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteApplicabilityStatementOutput{
|
|
DeletedApplicabilityStatementID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
// ListThirdPartyRiskAssessmentsTool handles the listThirdPartyRiskAssessments tool
|
|
// List all risk assessments for a thirdParty
|
|
func (r *Resolver) ListThirdPartyRiskAssessmentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListThirdPartyRiskAssessmentsInput) (*mcp.CallToolResult, types.ListThirdPartyRiskAssessmentsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ThirdPartyID, probo.ActionThirdPartyRiskAssessmentList)
|
|
if err != nil {
|
|
return nil, types.ListThirdPartyRiskAssessmentsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.ThirdPartyRiskAssessmentOrderField]{
|
|
Field: coredata.ThirdPartyRiskAssessmentOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.ThirdPartyRiskAssessmentOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := prb.ThirdParties.ListRiskAssessments(ctx, scope, input.ThirdPartyID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListThirdPartyRiskAssessmentsOutput{}, fmt.Errorf("cannot list thirdParty risk assessments: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListThirdPartyRiskAssessmentsOutput(p), nil
|
|
}
|
|
|
|
// AddThirdPartyRiskAssessmentTool handles the addThirdPartyRiskAssessment tool
|
|
// Add a new risk assessment for a thirdParty
|
|
func (r *Resolver) AddThirdPartyRiskAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddThirdPartyRiskAssessmentInput) (*mcp.CallToolResult, types.AddThirdPartyRiskAssessmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ThirdPartyID, probo.ActionThirdPartyRiskAssessmentCreate)
|
|
if err != nil {
|
|
return nil, types.AddThirdPartyRiskAssessmentOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
assessment, err := prb.ThirdParties.CreateRiskAssessment(
|
|
ctx, scope,
|
|
probo.CreateThirdPartyRiskAssessmentRequest{
|
|
ThirdPartyID: input.ThirdPartyID,
|
|
ExpiresAt: input.ExpiresAt,
|
|
DataSensitivity: input.DataSensitivity,
|
|
BusinessImpact: input.BusinessImpact,
|
|
Notes: input.Notes,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddThirdPartyRiskAssessmentOutput{}, fmt.Errorf("failed to create thirdParty risk assessment: %w", err)
|
|
}
|
|
|
|
return nil, types.NewAddThirdPartyRiskAssessmentOutput(assessment), nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteThirdPartyTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteThirdPartyInput) (*mcp.CallToolResult, types.DeleteThirdPartyOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteThirdPartyOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.ThirdParties.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteThirdPartyOutput{}, fmt.Errorf("failed to delete thirdParty: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteThirdPartyOutput{
|
|
DeletedThirdPartyID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteFindingTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteFindingInput) (*mcp.CallToolResult, types.DeleteFindingOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionFindingDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteFindingOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.Findings.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteFindingOutput{}, fmt.Errorf("cannot delete finding: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteFindingOutput{
|
|
DeletedFindingID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) LinkFindingAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkFindingAuditInput) (*mcp.CallToolResult, types.LinkFindingAuditOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.FindingID, probo.ActionFindingAuditMappingCreate)
|
|
if err != nil {
|
|
return nil, types.LinkFindingAuditOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
finding, audit, err := svc.Findings.CreateAuditMapping(ctx, scope, input.FindingID, input.AuditID, input.ReferenceID)
|
|
if err != nil {
|
|
return nil, types.LinkFindingAuditOutput{}, fmt.Errorf("cannot link finding to audit: %w", err)
|
|
}
|
|
|
|
return nil, types.LinkFindingAuditOutput{
|
|
Finding: types.NewFinding(finding),
|
|
Audit: types.NewAudit(audit, nil),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UnlinkFindingAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkFindingAuditInput) (*mcp.CallToolResult, types.UnlinkFindingAuditOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.FindingID, probo.ActionFindingAuditMappingDelete)
|
|
if err != nil {
|
|
return nil, types.UnlinkFindingAuditOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
finding, audit, err := svc.Findings.DeleteAuditMapping(ctx, scope, input.FindingID, input.AuditID)
|
|
if err != nil {
|
|
return nil, types.UnlinkFindingAuditOutput{}, fmt.Errorf("cannot unlink finding from audit: %w", err)
|
|
}
|
|
|
|
return nil, types.UnlinkFindingAuditOutput{
|
|
DeletedFindingID: finding.ID,
|
|
DeletedAuditID: audit.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListFindingAuditsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListFindingAuditsInput) (*mcp.CallToolResult, types.ListFindingAuditsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.FindingID, probo.ActionFindingGet)
|
|
if err != nil {
|
|
return nil, types.ListFindingAuditsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.AuditOrderField]{
|
|
Field: coredata.AuditOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.AuditOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
auditPage, err := prb.Audits.ListForFindingID(ctx, scope, input.FindingID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListFindingAuditsOutput{}, fmt.Errorf("cannot list finding audits: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListFindingAuditsOutput(auditPage), nil
|
|
}
|
|
|
|
// ListAccessReviewCampaignsTool handles the listAccessReviewCampaigns tool
|
|
// List access review campaigns for an organization
|
|
func (r *Resolver) ListAccessReviewCampaignsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAccessReviewCampaignsInput) (*mcp.CallToolResult, types.ListAccessReviewCampaignsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, accessreview.ActionCampaignList)
|
|
if err != nil {
|
|
return nil, types.ListAccessReviewCampaignsOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.AccessReviewCampaignOrderField]{
|
|
Field: coredata.AccessReviewCampaignOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.AccessReviewCampaignOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := r.accessReview.ListCampaignsForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list access review campaigns: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListAccessReviewCampaignsOutput(p), nil
|
|
}
|
|
|
|
// ListAccessEntriesTool handles the listAccessEntries tool
|
|
// List access entries for a campaign or campaign source with optional filters
|
|
func (r *Resolver) ListAccessEntriesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAccessEntriesInput) (*mcp.CallToolResult, types.ListAccessEntriesOutput, error) {
|
|
if input.AccessReviewCampaignSourceID == nil && input.CampaignID == nil {
|
|
return nil, types.ListAccessEntriesOutput{}, fmt.Errorf("campaign_id or access_review_campaign_source_id is required")
|
|
}
|
|
|
|
var (
|
|
scope *coredata.Scope
|
|
campaignID gid.GID
|
|
sourceID *gid.GID
|
|
err error
|
|
)
|
|
|
|
if input.AccessReviewCampaignSourceID != nil {
|
|
scope, err = r.Authorize(ctx, *input.AccessReviewCampaignSourceID, accessreview.ActionEntryList)
|
|
if err != nil {
|
|
return nil, types.ListAccessEntriesOutput{}, err
|
|
}
|
|
|
|
campaignSource, err := r.accessReview.GetCampaignSource(ctx, scope, *input.AccessReviewCampaignSourceID)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot get campaign source: %w", err))
|
|
}
|
|
|
|
campaignID = campaignSource.AccessReviewCampaignID
|
|
sourceID = input.AccessReviewCampaignSourceID
|
|
} else {
|
|
scope, err = r.Authorize(ctx, *input.CampaignID, accessreview.ActionEntryList)
|
|
if err != nil {
|
|
return nil, types.ListAccessEntriesOutput{}, err
|
|
}
|
|
|
|
campaignID = *input.CampaignID
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.AccessReviewEntryOrderField]{
|
|
Field: coredata.AccessReviewEntryOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.AccessReviewEntryOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
var filter *coredata.AccessReviewEntryFilter
|
|
if input.Filter != nil {
|
|
filter = &coredata.AccessReviewEntryFilter{
|
|
Decision: input.Filter.Decision,
|
|
Flag: input.Filter.Flag,
|
|
IncrementalTag: input.Filter.IncrementalTag,
|
|
IsAdmin: input.Filter.IsAdmin,
|
|
Active: input.Filter.Active,
|
|
AuthMethod: input.Filter.AuthMethod,
|
|
AccountType: input.Filter.AccountType,
|
|
}
|
|
}
|
|
|
|
var p *page.Page[*coredata.AccessReviewEntry, coredata.AccessReviewEntryOrderField]
|
|
|
|
if sourceID != nil {
|
|
p, err = r.accessReview.ListEntriesForCampaignIDAndSourceID(
|
|
ctx,
|
|
scope,
|
|
campaignID,
|
|
*sourceID,
|
|
cursor,
|
|
filter,
|
|
)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list access entries: %w", err))
|
|
}
|
|
} else {
|
|
p, err = r.accessReview.ListEntriesForCampaignID(ctx, scope, campaignID, cursor, filter)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list access entries: %w", err))
|
|
}
|
|
}
|
|
|
|
return nil, types.NewListAccessEntriesOutput(p), nil
|
|
}
|
|
|
|
// GetAccessReviewStatisticsTool handles the getAccessReviewCampaignStatistics tool
|
|
// Get statistics for an access review campaign
|
|
func (r *Resolver) GetAccessReviewStatisticsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAccessReviewStatisticsInput) (*mcp.CallToolResult, types.GetAccessReviewStatisticsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignGet)
|
|
if err != nil {
|
|
return nil, types.GetAccessReviewStatisticsOutput{}, err
|
|
}
|
|
|
|
stats, err := r.accessReview.CampaignStatistics(ctx, scope, input.CampaignID)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot get campaign statistics: %w", err))
|
|
}
|
|
|
|
return nil, types.GetAccessReviewStatisticsOutput{
|
|
Statistics: types.NewAccessReviewStatistics(stats),
|
|
}, nil
|
|
}
|
|
|
|
// RecordAccessReviewEntryDecisionTool handles the recordAccessEntryDecision tool
|
|
// Record a decision on an access entry
|
|
func (r *Resolver) RecordAccessReviewEntryDecisionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RecordAccessReviewEntryDecisionInput) (*mcp.CallToolResult, types.RecordAccessReviewEntryDecisionOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.AccessReviewEntryID, accessreview.ActionEntryDecide)
|
|
if err != nil {
|
|
return nil, types.RecordAccessReviewEntryDecisionOutput{}, err
|
|
}
|
|
|
|
entry, err := r.accessReview.RecordDecision(
|
|
ctx,
|
|
scope,
|
|
accessreview.RecordAccessReviewEntryDecisionRequest{
|
|
EntryID: input.AccessReviewEntryID,
|
|
Decision: input.Decision,
|
|
DecisionNote: input.DecisionNote,
|
|
DecidedByID: &authn.IdentityFromContext(ctx).ID,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.RecordAccessReviewEntryDecisionOutput{}, fmt.Errorf("cannot record decision: %w", err)
|
|
}
|
|
|
|
return nil, types.RecordAccessReviewEntryDecisionOutput{
|
|
AccessEntry: types.NewAccessReviewEntry(entry),
|
|
}, nil
|
|
}
|
|
|
|
// RecordAccessReviewEntryDecisionsTool handles the recordAccessEntryDecisions tool
|
|
// Record decisions on multiple access entries in a single batch
|
|
func (r *Resolver) RecordAccessReviewEntryDecisionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RecordAccessReviewEntryDecisionsInput) (*mcp.CallToolResult, types.RecordAccessReviewEntryDecisionsOutput, error) {
|
|
if len(input.Decisions) == 0 {
|
|
return nil, types.RecordAccessReviewEntryDecisionsOutput{
|
|
AccessReviewEntries: []*types.AccessReviewEntry{},
|
|
}, nil
|
|
}
|
|
|
|
const maxBatchSize = 100
|
|
if len(input.Decisions) > maxBatchSize {
|
|
return nil, types.RecordAccessReviewEntryDecisionsOutput{}, fmt.Errorf("cannot record decisions: batch size %d exceeds maximum of %d", len(input.Decisions), maxBatchSize)
|
|
}
|
|
|
|
// Authorize each entry individually to prevent cross-org bypass.
|
|
for _, d := range input.Decisions {
|
|
if _, err := r.Authorize(ctx, d.AccessReviewEntryID, accessreview.ActionEntryDecide); err != nil {
|
|
return nil, types.RecordAccessReviewEntryDecisionsOutput{}, err
|
|
}
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.Decisions[0].AccessReviewEntryID)
|
|
|
|
identity := authn.IdentityFromContext(ctx)
|
|
if identity == nil {
|
|
return nil, types.RecordAccessReviewEntryDecisionsOutput{}, fmt.Errorf("no identity in context")
|
|
}
|
|
|
|
decidedByID := &identity.ID
|
|
|
|
decisions := make([]accessreview.RecordAccessReviewEntryDecisionRequest, len(input.Decisions))
|
|
for i, d := range input.Decisions {
|
|
decisions[i] = accessreview.RecordAccessReviewEntryDecisionRequest{
|
|
EntryID: d.AccessReviewEntryID,
|
|
Decision: d.Decision,
|
|
DecisionNote: d.DecisionNote,
|
|
DecidedByID: decidedByID,
|
|
}
|
|
}
|
|
|
|
entries, err := r.accessReview.RecordDecisions(ctx, scope, decisions)
|
|
if err != nil {
|
|
return nil, types.RecordAccessReviewEntryDecisionsOutput{}, fmt.Errorf("cannot record decisions: %w", err)
|
|
}
|
|
|
|
accessEntries := make([]*types.AccessReviewEntry, len(entries))
|
|
for i, e := range entries {
|
|
accessEntries[i] = types.NewAccessReviewEntry(e)
|
|
}
|
|
|
|
return nil, types.RecordAccessReviewEntryDecisionsOutput{
|
|
AccessReviewEntries: accessEntries,
|
|
}, nil
|
|
}
|
|
|
|
// CloseAccessReviewCampaignTool handles the closeAccessReviewCampaign tool
|
|
// Close an access review campaign
|
|
func (r *Resolver) CloseAccessReviewCampaignTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CloseAccessReviewCampaignInput) (*mcp.CallToolResult, types.CloseAccessReviewCampaignOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignClose)
|
|
if err != nil {
|
|
return nil, types.CloseAccessReviewCampaignOutput{}, err
|
|
}
|
|
|
|
campaign, err := r.accessReview.CloseCampaign(ctx, scope, input.CampaignID)
|
|
if err != nil {
|
|
return nil, types.CloseAccessReviewCampaignOutput{}, fmt.Errorf("cannot close campaign: %w", err)
|
|
}
|
|
|
|
return nil, types.CloseAccessReviewCampaignOutput{
|
|
Campaign: types.NewAccessReviewCampaign(campaign),
|
|
}, nil
|
|
}
|
|
|
|
// ListAccessReviewSourcesTool handles the listAccessSources tool
|
|
// List access sources for an organization
|
|
func (r *Resolver) ListAccessReviewSourcesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAccessReviewSourcesInput) (*mcp.CallToolResult, types.ListAccessReviewSourcesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, accessreview.ActionSourceList)
|
|
if err != nil {
|
|
return nil, types.ListAccessReviewSourcesOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.AccessReviewSourceOrderField]{
|
|
Field: coredata.AccessReviewSourceOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.AccessReviewSourceOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := r.accessReview.ListSourcesForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list access sources: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListAccessReviewSourcesOutput(p), nil
|
|
}
|
|
|
|
// CreateAccessReviewSourceTool handles the createAccessSource tool
|
|
// Create a new access source for an organization
|
|
func (r *Resolver) CreateAccessReviewSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateAccessReviewSourceInput) (*mcp.CallToolResult, types.CreateAccessReviewSourceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, accessreview.ActionSourceCreate)
|
|
if err != nil {
|
|
return nil, types.CreateAccessReviewSourceOutput{}, err
|
|
}
|
|
|
|
source, err := r.accessReview.CreateSource(ctx, scope, accessreview.CreateAccessReviewSourceRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
ConnectorID: input.ConnectorID,
|
|
Name: input.Name,
|
|
CsvData: input.CsvData,
|
|
})
|
|
if err != nil {
|
|
return nil, types.CreateAccessReviewSourceOutput{}, fmt.Errorf("cannot create access source: %w", err)
|
|
}
|
|
|
|
r.accessReview.AutoSelectDefaultOrganization(ctx, scope, source)
|
|
|
|
return nil, types.CreateAccessReviewSourceOutput{
|
|
AccessReviewSource: types.NewAccessReviewSource(source),
|
|
}, nil
|
|
}
|
|
|
|
// UpdateAccessReviewSourceTool handles the updateAccessSource tool
|
|
// Update an existing access source
|
|
func (r *Resolver) UpdateAccessReviewSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateAccessReviewSourceInput) (*mcp.CallToolResult, types.UpdateAccessReviewSourceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.AccessReviewSourceID, accessreview.ActionSourceUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateAccessReviewSourceOutput{}, err
|
|
}
|
|
|
|
updateReq := accessreview.UpdateAccessReviewSourceRequest{
|
|
AccessReviewSourceID: input.AccessReviewSourceID,
|
|
}
|
|
|
|
if input.Name != nil {
|
|
updateReq.Name = &input.Name
|
|
}
|
|
|
|
connectorSet := false
|
|
|
|
if rawConnectorID := UnwrapOmittable(input.ConnectorID); rawConnectorID != nil {
|
|
connectorSet = true
|
|
|
|
if *rawConnectorID != nil {
|
|
id, err := gid.ParseGID(**rawConnectorID)
|
|
if err != nil {
|
|
return nil, types.UpdateAccessReviewSourceOutput{}, fmt.Errorf("cannot parse connector_id: %w", err)
|
|
}
|
|
|
|
idPtr := &id
|
|
updateReq.ConnectorID = &idPtr
|
|
} else {
|
|
var nilGID *gid.GID
|
|
|
|
updateReq.ConnectorID = &nilGID
|
|
}
|
|
}
|
|
|
|
if rawCsvData := UnwrapOmittable(input.CsvData); rawCsvData != nil {
|
|
updateReq.CsvData = rawCsvData
|
|
}
|
|
|
|
source, err := r.accessReview.UpdateSource(ctx, scope, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateAccessReviewSourceOutput{}, fmt.Errorf("cannot update access source: %w", err)
|
|
}
|
|
|
|
// A connector was just (re)linked: default its org so the source is
|
|
// usable right away. Matches the GraphQL surface; skipped on name/CSV-only
|
|
// updates to avoid a needless provider round-trip.
|
|
if connectorSet {
|
|
r.accessReview.AutoSelectDefaultOrganization(ctx, scope, source)
|
|
}
|
|
|
|
return nil, types.UpdateAccessReviewSourceOutput{
|
|
AccessReviewSource: types.NewAccessReviewSource(source),
|
|
}, nil
|
|
}
|
|
|
|
// DeleteAccessReviewSourceTool handles the deleteAccessSource tool
|
|
// Delete an access source
|
|
func (r *Resolver) DeleteAccessReviewSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteAccessReviewSourceInput) (*mcp.CallToolResult, types.DeleteAccessReviewSourceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.AccessReviewSourceID, accessreview.ActionSourceDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteAccessReviewSourceOutput{}, err
|
|
}
|
|
|
|
if err := r.accessReview.DeleteSource(ctx, scope, input.AccessReviewSourceID); err != nil {
|
|
return nil, types.DeleteAccessReviewSourceOutput{}, fmt.Errorf("cannot delete access source: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteAccessReviewSourceOutput{
|
|
DeletedAccessReviewSourceID: input.AccessReviewSourceID,
|
|
}, nil
|
|
}
|
|
|
|
// CreateAccessReviewCampaignTool handles the createAccessReviewCampaign tool
|
|
// Create a new access review campaign for an organization
|
|
func (r *Resolver) CreateAccessReviewCampaignTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateAccessReviewCampaignInput) (*mcp.CallToolResult, types.CreateAccessReviewCampaignOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, accessreview.ActionCampaignCreate)
|
|
if err != nil {
|
|
return nil, types.CreateAccessReviewCampaignOutput{}, err
|
|
}
|
|
|
|
var description string
|
|
if input.Description != nil {
|
|
description = *input.Description
|
|
}
|
|
|
|
campaign, err := r.accessReview.CreateCampaign(ctx, scope, accessreview.CreateAccessReviewCampaignRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
Description: description,
|
|
AccessReviewSourceIDs: input.AccessReviewSourceIds,
|
|
})
|
|
if err != nil {
|
|
return nil, types.CreateAccessReviewCampaignOutput{}, fmt.Errorf("cannot create access review campaign: %w", err)
|
|
}
|
|
|
|
return nil, types.CreateAccessReviewCampaignOutput{
|
|
Campaign: types.NewAccessReviewCampaign(campaign),
|
|
}, nil
|
|
}
|
|
|
|
// UpdateAccessReviewCampaignTool handles the updateAccessReviewCampaign tool
|
|
// Update an existing access review campaign
|
|
func (r *Resolver) UpdateAccessReviewCampaignTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateAccessReviewCampaignInput) (*mcp.CallToolResult, types.UpdateAccessReviewCampaignOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateAccessReviewCampaignOutput{}, err
|
|
}
|
|
|
|
updateReq := accessreview.UpdateAccessReviewCampaignRequest{
|
|
CampaignID: input.CampaignID,
|
|
}
|
|
|
|
if input.Name != nil {
|
|
updateReq.Name = &input.Name
|
|
}
|
|
|
|
if input.Description != nil {
|
|
updateReq.Description = &input.Description
|
|
}
|
|
|
|
campaign, err := r.accessReview.UpdateCampaign(ctx, scope, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateAccessReviewCampaignOutput{}, fmt.Errorf("cannot update access review campaign: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateAccessReviewCampaignOutput{
|
|
Campaign: types.NewAccessReviewCampaign(campaign),
|
|
}, nil
|
|
}
|
|
|
|
// DeleteAccessReviewCampaignTool handles the deleteAccessReviewCampaign tool
|
|
// Delete an access review campaign
|
|
func (r *Resolver) DeleteAccessReviewCampaignTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteAccessReviewCampaignInput) (*mcp.CallToolResult, types.DeleteAccessReviewCampaignOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteAccessReviewCampaignOutput{}, err
|
|
}
|
|
|
|
if err := r.accessReview.DeleteCampaign(ctx, scope, input.CampaignID); err != nil {
|
|
return nil, types.DeleteAccessReviewCampaignOutput{}, fmt.Errorf("cannot delete access review campaign: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteAccessReviewCampaignOutput{
|
|
DeletedCampaignID: input.CampaignID,
|
|
}, nil
|
|
}
|
|
|
|
// StartAccessReviewCampaignTool handles the startAccessReviewCampaign tool
|
|
// Start an access review campaign
|
|
func (r *Resolver) StartAccessReviewCampaignTool(ctx context.Context, req *mcp.CallToolRequest, input *types.StartAccessReviewCampaignInput) (*mcp.CallToolResult, types.StartAccessReviewCampaignOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignStart)
|
|
if err != nil {
|
|
return nil, types.StartAccessReviewCampaignOutput{}, err
|
|
}
|
|
|
|
campaign, err := r.accessReview.StartCampaign(ctx, scope, input.CampaignID)
|
|
if err != nil {
|
|
return nil, types.StartAccessReviewCampaignOutput{}, fmt.Errorf("cannot start access review campaign: %w", err)
|
|
}
|
|
|
|
return nil, types.StartAccessReviewCampaignOutput{
|
|
Campaign: types.NewAccessReviewCampaign(campaign),
|
|
}, nil
|
|
}
|
|
|
|
// CancelAccessReviewCampaignTool handles the cancelAccessReviewCampaign tool
|
|
// Cancel an in-progress access review campaign
|
|
func (r *Resolver) CancelAccessReviewCampaignTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CancelAccessReviewCampaignInput) (*mcp.CallToolResult, types.CancelAccessReviewCampaignOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignCancel)
|
|
if err != nil {
|
|
return nil, types.CancelAccessReviewCampaignOutput{}, err
|
|
}
|
|
|
|
campaign, err := r.accessReview.CancelCampaign(ctx, scope, input.CampaignID)
|
|
if err != nil {
|
|
return nil, types.CancelAccessReviewCampaignOutput{}, fmt.Errorf("cannot cancel access review campaign: %w", err)
|
|
}
|
|
|
|
return nil, types.CancelAccessReviewCampaignOutput{
|
|
Campaign: types.NewAccessReviewCampaign(campaign),
|
|
}, nil
|
|
}
|
|
|
|
// AddAccessReviewCampaignSourceTool handles the addAccessReviewCampaignScopeSource tool
|
|
// Add an access source to an access review campaign's scope
|
|
func (r *Resolver) AddAccessReviewCampaignSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddAccessReviewCampaignSourceInput) (*mcp.CallToolResult, types.AddAccessReviewCampaignSourceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignAddSource)
|
|
if err != nil {
|
|
return nil, types.AddAccessReviewCampaignSourceOutput{}, err
|
|
}
|
|
|
|
campaign, err := r.accessReview.AddCampaignSource(ctx, scope, accessreview.AddCampaignSourceRequest{
|
|
CampaignID: input.CampaignID,
|
|
AccessReviewSourceID: input.AccessReviewSourceID,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddAccessReviewCampaignSourceOutput{}, fmt.Errorf("cannot add scope source to access review campaign: %w", err)
|
|
}
|
|
|
|
return nil, types.AddAccessReviewCampaignSourceOutput{
|
|
Campaign: types.NewAccessReviewCampaign(campaign),
|
|
}, nil
|
|
}
|
|
|
|
// RemoveAccessReviewCampaignSourceTool handles the removeAccessReviewCampaignScopeSource tool
|
|
// Remove an access source from an access review campaign's scope
|
|
func (r *Resolver) RemoveAccessReviewCampaignSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RemoveAccessReviewCampaignSourceInput) (*mcp.CallToolResult, types.RemoveAccessReviewCampaignSourceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignRemoveSource)
|
|
if err != nil {
|
|
return nil, types.RemoveAccessReviewCampaignSourceOutput{}, err
|
|
}
|
|
|
|
campaign, err := r.accessReview.RemoveCampaignSource(ctx, scope, accessreview.RemoveCampaignSourceRequest{
|
|
CampaignID: input.CampaignID,
|
|
AccessReviewSourceID: input.AccessReviewSourceID,
|
|
})
|
|
if err != nil {
|
|
return nil, types.RemoveAccessReviewCampaignSourceOutput{}, fmt.Errorf("cannot remove scope source from access review campaign: %w", err)
|
|
}
|
|
|
|
return nil, types.RemoveAccessReviewCampaignSourceOutput{
|
|
Campaign: types.NewAccessReviewCampaign(campaign),
|
|
}, nil
|
|
}
|
|
|
|
// FlagAccessReviewEntryTool handles the flagAccessEntry tool
|
|
// Flag an access entry during review
|
|
func (r *Resolver) FlagAccessReviewEntryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.FlagAccessReviewEntryInput) (*mcp.CallToolResult, types.FlagAccessReviewEntryOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.AccessReviewEntryID, accessreview.ActionEntryFlag)
|
|
if err != nil {
|
|
return nil, types.FlagAccessReviewEntryOutput{}, err
|
|
}
|
|
|
|
entry, err := r.accessReview.FlagEntry(ctx, scope, accessreview.FlagAccessReviewEntryRequest{
|
|
EntryID: input.AccessReviewEntryID,
|
|
Flags: input.Flags,
|
|
FlagReasons: input.FlagReasons,
|
|
})
|
|
if err != nil {
|
|
return nil, types.FlagAccessReviewEntryOutput{}, fmt.Errorf("cannot flag access entry: %w", err)
|
|
}
|
|
|
|
return nil, types.FlagAccessReviewEntryOutput{
|
|
AccessEntry: types.NewAccessReviewEntry(entry),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) GetAuditReportUrlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAuditReportUrlInput) (*mcp.CallToolResult, types.GetAuditReportUrlOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionReportGetReportUrl)
|
|
if err != nil {
|
|
return nil, types.GetAuditReportUrlOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
url, err := prb.Audits.GenerateReportURL(ctx, scope, input.ID, 15*time.Minute)
|
|
if err != nil {
|
|
return nil, types.GetAuditReportUrlOutput{}, fmt.Errorf("cannot generate audit report URL: %w", err)
|
|
}
|
|
|
|
return nil, types.GetAuditReportUrlOutput{
|
|
URL: *url,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ArchiveDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ArchiveDocumentInput) (*mcp.CallToolResult, types.ArchiveDocumentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentArchive)
|
|
if err != nil {
|
|
return nil, types.ArchiveDocumentOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
document, err := svc.Documents.Archive(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.ArchiveDocumentOutput{}, fmt.Errorf("cannot archive document: %w", err)
|
|
}
|
|
|
|
return nil, types.ArchiveDocumentOutput{
|
|
Document: types.NewDocument(document),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UnarchiveDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnarchiveDocumentInput) (*mcp.CallToolResult, types.UnarchiveDocumentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentUnarchive)
|
|
if err != nil {
|
|
return nil, types.UnarchiveDocumentOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
document, err := svc.Documents.Unarchive(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.UnarchiveDocumentOutput{}, fmt.Errorf("cannot unarchive document: %w", err)
|
|
}
|
|
|
|
return nil, types.UnarchiveDocumentOutput{
|
|
Document: types.NewDocument(document),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) GetOrganizationContextTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetOrganizationContextInput) (*mcp.CallToolResult, types.GetOrganizationContextOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionOrganizationContextGet)
|
|
if err != nil {
|
|
return nil, types.GetOrganizationContextOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
orgContext, err := prb.Organizations.GetContext(ctx, scope, input.OrganizationID)
|
|
if err != nil {
|
|
return nil, types.GetOrganizationContextOutput{}, fmt.Errorf("cannot get organization context: %w", err)
|
|
}
|
|
|
|
return nil, types.GetOrganizationContextOutput{
|
|
OrganizationContext: types.NewOrganizationContext(orgContext),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateOrganizationContextTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateOrganizationContextInput) (*mcp.CallToolResult, types.UpdateOrganizationContextOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionOrganizationContextUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateOrganizationContextOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
orgContext, err := prb.Organizations.UpdateContext(
|
|
ctx, scope,
|
|
probo.UpdateOrganizationContextRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Product: &input.Product,
|
|
Architecture: &input.Architecture,
|
|
Team: &input.Team,
|
|
Processes: &input.Processes,
|
|
Customers: &input.Customers,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateOrganizationContextOutput{}, fmt.Errorf("cannot update organization context: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateOrganizationContextOutput{
|
|
OrganizationContext: types.NewOrganizationContext(orgContext),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) GetAuditLogEntryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAuditLogEntryInput) (*mcp.CallToolResult, types.GetAuditLogEntryOutput, error) {
|
|
if _, err := r.Authorize(ctx, input.ID, iam.ActionAuditLogEntryGet); err != nil {
|
|
return nil, types.GetAuditLogEntryOutput{}, err
|
|
}
|
|
|
|
entry, err := r.iamSvc.OrganizationService.GetAuditLogEntry(ctx, input.ID)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot get audit log entry: %w", err))
|
|
}
|
|
|
|
return nil, types.GetAuditLogEntryOutput{
|
|
AuditLogEntry: types.NewAuditLogEntry(entry),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListAuditLogEntriesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAuditLogEntriesInput) (*mcp.CallToolResult, types.ListAuditLogEntriesOutput, error) {
|
|
if _, err := r.Authorize(ctx, input.OrganizationID, iam.ActionAuditLogEntryList); err != nil {
|
|
return nil, types.ListAuditLogEntriesOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.AuditLogEntryOrderField]{
|
|
Field: coredata.AuditLogEntryOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
filter := coredata.NewAuditLogEntryFilter()
|
|
|
|
if input.Filter != nil {
|
|
if input.Filter.Action != nil {
|
|
filter.WithAction(*input.Filter.Action)
|
|
}
|
|
|
|
if input.Filter.ActorID != nil {
|
|
filter.WithActorID(*input.Filter.ActorID)
|
|
}
|
|
|
|
if input.Filter.ResourceType != nil {
|
|
filter.WithResourceType(*input.Filter.ResourceType)
|
|
}
|
|
|
|
if input.Filter.ResourceID != nil {
|
|
filter.WithResourceID(*input.Filter.ResourceID)
|
|
}
|
|
}
|
|
|
|
p, err := r.iamSvc.OrganizationService.ListAuditLogEntries(ctx, input.OrganizationID, cursor, filter)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list audit log entries: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListAuditLogEntriesOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) ListMeasureDocumentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasureDocumentsInput) (*mcp.CallToolResult, types.ListMeasureDocumentsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureGet)
|
|
if err != nil {
|
|
return nil, types.ListMeasureDocumentsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
|
|
Field: coredata.DocumentOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
docPage, err := prb.Documents.ListForMeasureID(ctx, scope, input.MeasureID, cursor, coredata.NewDocumentFilter(nil))
|
|
if err != nil {
|
|
return nil, types.ListMeasureDocumentsOutput{}, fmt.Errorf("failed to list measure documents: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListMeasureDocumentsOutput(docPage), nil
|
|
}
|
|
|
|
func (r *Resolver) VoidDocumentVersionApprovalTool(ctx context.Context, req *mcp.CallToolRequest, input *types.VoidDocumentVersionApprovalInput) (*mcp.CallToolResult, types.VoidDocumentVersionApprovalOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionVoidApproval)
|
|
if err != nil {
|
|
return nil, types.VoidDocumentVersionApprovalOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
_, documentVersion, err := svc.DocumentApprovals.VoidApproval(ctx, scope, input.DocumentVersionID)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot void document version approval: %w", err))
|
|
}
|
|
|
|
return nil, types.VoidDocumentVersionApprovalOutput{
|
|
DocumentVersion: types.NewDocumentVersion(documentVersion),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteDocumentDraftTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteDocumentDraftInput) (*mcp.CallToolResult, types.DeleteDocumentDraftOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentDeleteDraft)
|
|
if err != nil {
|
|
return nil, types.DeleteDocumentDraftOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
document, err := svc.Documents.DeleteDraft(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteDocumentDraftOutput{}, fmt.Errorf("cannot delete document draft: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteDocumentDraftOutput{
|
|
Document: types.NewDocument(document),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) PublishStatementOfApplicabilityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishStatementOfApplicabilityInput) (*mcp.CallToolResult, types.PublishStatementOfApplicabilityOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionStatementOfApplicabilityPublish)
|
|
if err != nil {
|
|
return nil, types.PublishStatementOfApplicabilityOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishStatementOfApplicability(ctx, scope, input.ID, input.ApproverIds, input.Minor)
|
|
if err != nil {
|
|
return nil, types.PublishStatementOfApplicabilityOutput{}, fmt.Errorf("cannot publish statement of applicability: %w", err)
|
|
}
|
|
|
|
return nil, types.PublishStatementOfApplicabilityOutput{
|
|
DocumentID: document.ID,
|
|
DocumentVersionID: documentVersion.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListWebhookSubscriptionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListWebhookSubscriptionsInput) (*mcp.CallToolResult, types.ListWebhookSubscriptionsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionWebhookSubscriptionList)
|
|
if err != nil {
|
|
return nil, types.ListWebhookSubscriptionsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.WebhookSubscriptionOrderField]{
|
|
Field: coredata.WebhookSubscriptionOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.WebhookSubscriptionOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
page, err := prb.WebhookSubscriptions.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list webhook subscriptions: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListWebhookSubscriptionsOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetWebhookSubscriptionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetWebhookSubscriptionInput) (*mcp.CallToolResult, types.GetWebhookSubscriptionOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionWebhookSubscriptionGet)
|
|
if err != nil {
|
|
return nil, types.GetWebhookSubscriptionOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
subscription, err := prb.WebhookSubscriptions.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetWebhookSubscriptionOutput{}, fmt.Errorf("failed to get webhook subscription: %w", err)
|
|
}
|
|
|
|
return nil, types.GetWebhookSubscriptionOutput{
|
|
WebhookSubscription: types.NewWebhookSubscription(subscription),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) CreateWebhookSubscriptionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateWebhookSubscriptionInput) (*mcp.CallToolResult, types.CreateWebhookSubscriptionOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionWebhookSubscriptionCreate)
|
|
if err != nil {
|
|
return nil, types.CreateWebhookSubscriptionOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
subscription, err := prb.WebhookSubscriptions.Create(
|
|
ctx, scope,
|
|
probo.CreateWebhookSubscriptionRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
EndpointURL: input.EndpointURL,
|
|
SelectedEvents: input.SelectedEvents,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.CreateWebhookSubscriptionOutput{}, fmt.Errorf("failed to create webhook subscription: %w", err)
|
|
}
|
|
|
|
return nil, types.CreateWebhookSubscriptionOutput{
|
|
WebhookSubscription: types.NewWebhookSubscription(subscription),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateWebhookSubscriptionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateWebhookSubscriptionInput) (*mcp.CallToolResult, types.UpdateWebhookSubscriptionOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionWebhookSubscriptionUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateWebhookSubscriptionOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
subscription, err := prb.WebhookSubscriptions.Update(
|
|
ctx, scope,
|
|
probo.UpdateWebhookSubscriptionRequest{
|
|
WebhookSubscriptionID: input.ID,
|
|
EndpointURL: input.EndpointURL,
|
|
SelectedEvents: input.SelectedEvents,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateWebhookSubscriptionOutput{}, fmt.Errorf("failed to update webhook subscription: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateWebhookSubscriptionOutput{
|
|
WebhookSubscription: types.NewWebhookSubscription(subscription),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteWebhookSubscriptionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteWebhookSubscriptionInput) (*mcp.CallToolResult, types.DeleteWebhookSubscriptionOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionWebhookSubscriptionDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteWebhookSubscriptionOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
err = prb.WebhookSubscriptions.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteWebhookSubscriptionOutput{}, fmt.Errorf("failed to delete webhook subscription: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteWebhookSubscriptionOutput{
|
|
DeletedWebhookSubscriptionID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListWebhookEventsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListWebhookEventsInput) (*mcp.CallToolResult, types.ListWebhookEventsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.WebhookSubscriptionID, probo.ActionWebhookSubscriptionGet)
|
|
if err != nil {
|
|
return nil, types.ListWebhookEventsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.WebhookEventOrderField]{
|
|
Field: coredata.WebhookEventOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.WebhookEventOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
page, err := prb.WebhookSubscriptions.ListEventsForSubscriptionID(ctx, scope, input.WebhookSubscriptionID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list webhook events: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListWebhookEventsOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) ListDocumentVersionApprovalQuorumsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentVersionApprovalQuorumsInput) (*mcp.CallToolResult, types.ListDocumentVersionApprovalQuorumsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionApprovalList)
|
|
if err != nil {
|
|
return nil, types.ListDocumentVersionApprovalQuorumsOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.DocumentVersionApprovalQuorumOrderField]{
|
|
Field: coredata.DocumentVersionApprovalQuorumOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.DocumentVersionApprovalQuorumOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := svc.DocumentApprovals.ListQuorums(ctx, scope, input.DocumentVersionID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list approval quorums: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListDocumentVersionApprovalQuorumsOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) GetDocumentVersionApprovalQuorumTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDocumentVersionApprovalQuorumInput) (*mcp.CallToolResult, types.GetDocumentVersionApprovalQuorumOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentVersionApprovalList)
|
|
if err != nil {
|
|
return nil, types.GetDocumentVersionApprovalQuorumOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
quorum, err := svc.DocumentApprovals.GetQuorum(ctx, scope, input.ID)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot get approval quorum: %w", err))
|
|
}
|
|
|
|
return nil, types.GetDocumentVersionApprovalQuorumOutput{
|
|
ApprovalQuorum: types.NewDocumentVersionApprovalQuorum(quorum),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListDocumentVersionApprovalDecisionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentVersionApprovalDecisionsInput) (*mcp.CallToolResult, types.ListDocumentVersionApprovalDecisionsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.QuorumID, probo.ActionDocumentVersionApprovalList)
|
|
if err != nil {
|
|
return nil, types.ListDocumentVersionApprovalDecisionsOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.DocumentVersionApprovalDecisionOrderField]{
|
|
Field: coredata.DocumentVersionApprovalDecisionOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.DocumentVersionApprovalDecisionOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
var states []coredata.DocumentVersionApprovalDecisionState
|
|
if input.Filter != nil {
|
|
states = input.Filter.States
|
|
}
|
|
|
|
filter := coredata.NewDocumentVersionApprovalDecisionFilter(states)
|
|
|
|
p, err := svc.DocumentApprovals.ListDecisions(ctx, scope, input.QuorumID, cursor, filter)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list approval decisions: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListDocumentVersionApprovalDecisionsOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) GetDocumentVersionApprovalDecisionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDocumentVersionApprovalDecisionInput) (*mcp.CallToolResult, types.GetDocumentVersionApprovalDecisionOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentVersionApprovalList)
|
|
if err != nil {
|
|
return nil, types.GetDocumentVersionApprovalDecisionOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
decision, err := svc.DocumentApprovals.GetDecision(ctx, scope, input.ID)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot get approval decision: %w", err))
|
|
}
|
|
|
|
return nil, types.GetDocumentVersionApprovalDecisionOutput{
|
|
ApprovalDecision: types.NewDocumentVersionApprovalDecision(decision),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) PublishDataListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishDataListInput) (*mcp.CallToolResult, types.PublishDataListOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionDatumPublish)
|
|
if err != nil {
|
|
return nil, types.PublishDataListOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishDataList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
|
|
if err != nil {
|
|
return nil, types.PublishDataListOutput{}, fmt.Errorf("cannot publish data list: %w", err)
|
|
}
|
|
|
|
return nil, types.PublishDataListOutput{
|
|
DocumentID: document.ID,
|
|
DocumentVersionID: documentVersion.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) PublishAssetListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishAssetListInput) (*mcp.CallToolResult, types.PublishAssetListOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionAssetPublish)
|
|
if err != nil {
|
|
return nil, types.PublishAssetListOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishAssetList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
|
|
if err != nil {
|
|
return nil, types.PublishAssetListOutput{}, fmt.Errorf("cannot publish asset list: %w", err)
|
|
}
|
|
|
|
return nil, types.PublishAssetListOutput{
|
|
DocumentID: document.ID,
|
|
DocumentVersionID: documentVersion.ID,
|
|
}, nil
|
|
}
|
|
|
|
// ListThirdPartyContactsTool handles the listThirdPartyContacts tool
|
|
// List all contacts for a thirdParty
|
|
func (r *Resolver) ListThirdPartyContactsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListThirdPartyContactsInput) (*mcp.CallToolResult, types.ListThirdPartyContactsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ThirdPartyID, probo.ActionThirdPartyContactList)
|
|
if err != nil {
|
|
return nil, types.ListThirdPartyContactsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.ThirdPartyContactOrderField]{
|
|
Field: coredata.ThirdPartyContactOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.ThirdPartyContactOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := prb.ThirdPartyContacts.List(ctx, scope, input.ThirdPartyID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListThirdPartyContactsOutput{}, fmt.Errorf("cannot list thirdParty contacts: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListThirdPartyContactsOutput(p), nil
|
|
}
|
|
|
|
// AddThirdPartyContactTool handles the addThirdPartyContact tool
|
|
// Add a new contact to a thirdParty
|
|
func (r *Resolver) AddThirdPartyContactTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddThirdPartyContactInput) (*mcp.CallToolResult, types.AddThirdPartyContactOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ThirdPartyID, probo.ActionThirdPartyContactCreate)
|
|
if err != nil {
|
|
return nil, types.AddThirdPartyContactOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
emailAddr, err := mail.ParseAddr(input.Email)
|
|
if err != nil {
|
|
return nil, types.AddThirdPartyContactOutput{}, fmt.Errorf("invalid email address: %w", err)
|
|
}
|
|
|
|
thirdPartyContact, err := prb.ThirdPartyContacts.Create(ctx, scope, probo.CreateThirdPartyContactRequest{
|
|
ThirdPartyID: input.ThirdPartyID,
|
|
FullName: &input.FullName,
|
|
Email: &emailAddr,
|
|
Phone: &input.Phone,
|
|
Role: &input.Role,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddThirdPartyContactOutput{}, fmt.Errorf("cannot create thirdParty contact: %w", err)
|
|
}
|
|
|
|
return nil, types.AddThirdPartyContactOutput{
|
|
ThirdPartyContact: types.NewThirdPartyContact(thirdPartyContact),
|
|
}, nil
|
|
}
|
|
|
|
// UpdateThirdPartyContactTool handles the updateThirdPartyContact tool
|
|
// Update an existing thirdParty contact
|
|
func (r *Resolver) UpdateThirdPartyContactTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateThirdPartyContactInput) (*mcp.CallToolResult, types.UpdateThirdPartyContactOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyContactUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateThirdPartyContactOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
updateReq := probo.UpdateThirdPartyContactRequest{
|
|
ID: input.ID,
|
|
}
|
|
|
|
if input.FullName != nil {
|
|
updateReq.FullName = &input.FullName
|
|
}
|
|
|
|
if input.Email != nil {
|
|
emailAddr, err := mail.ParseAddr(*input.Email)
|
|
if err != nil {
|
|
return nil, types.UpdateThirdPartyContactOutput{}, fmt.Errorf("invalid email address: %w", err)
|
|
}
|
|
|
|
emailPtr := &emailAddr
|
|
updateReq.Email = &emailPtr
|
|
}
|
|
|
|
if input.Phone != nil {
|
|
updateReq.Phone = &input.Phone
|
|
}
|
|
|
|
if input.Role != nil {
|
|
updateReq.Role = &input.Role
|
|
}
|
|
|
|
thirdPartyContact, err := prb.ThirdPartyContacts.Update(ctx, scope, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateThirdPartyContactOutput{}, fmt.Errorf("cannot update thirdParty contact: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateThirdPartyContactOutput{
|
|
ThirdPartyContact: types.NewThirdPartyContact(thirdPartyContact),
|
|
}, nil
|
|
}
|
|
|
|
// DeleteThirdPartyContactTool handles the deleteThirdPartyContact tool
|
|
// Delete a thirdParty contact
|
|
func (r *Resolver) DeleteThirdPartyContactTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteThirdPartyContactInput) (*mcp.CallToolResult, types.DeleteThirdPartyContactOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyContactDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteThirdPartyContactOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
err = prb.ThirdPartyContacts.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteThirdPartyContactOutput{}, fmt.Errorf("cannot delete thirdParty contact: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteThirdPartyContactOutput{
|
|
DeletedThirdPartyContactID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
// ListThirdPartyServicesTool handles the listThirdPartyServices tool
|
|
// List all services for a thirdParty
|
|
func (r *Resolver) ListThirdPartyServicesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListThirdPartyServicesInput) (*mcp.CallToolResult, types.ListThirdPartyServicesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ThirdPartyID, probo.ActionThirdPartyServiceList)
|
|
if err != nil {
|
|
return nil, types.ListThirdPartyServicesOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.ThirdPartyServiceOrderField]{
|
|
Field: coredata.ThirdPartyServiceOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.ThirdPartyServiceOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := prb.ThirdPartyServices.List(ctx, scope, input.ThirdPartyID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListThirdPartyServicesOutput{}, fmt.Errorf("cannot list thirdParty services: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListThirdPartyServicesOutput(p), nil
|
|
}
|
|
|
|
// AddThirdPartyServiceTool handles the addThirdPartyService tool
|
|
// Add a new service to a thirdParty
|
|
func (r *Resolver) AddThirdPartyServiceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddThirdPartyServiceInput) (*mcp.CallToolResult, types.AddThirdPartyServiceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ThirdPartyID, probo.ActionThirdPartyServiceCreate)
|
|
if err != nil {
|
|
return nil, types.AddThirdPartyServiceOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
thirdPartyService, err := prb.ThirdPartyServices.Create(ctx, scope, probo.CreateThirdPartyServiceRequest{
|
|
ThirdPartyID: input.ThirdPartyID,
|
|
Name: input.Name,
|
|
Description: input.Description,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddThirdPartyServiceOutput{}, fmt.Errorf("cannot create thirdParty service: %w", err)
|
|
}
|
|
|
|
return nil, types.AddThirdPartyServiceOutput{
|
|
ThirdPartyService: types.NewThirdPartyService(thirdPartyService),
|
|
}, nil
|
|
}
|
|
|
|
// UpdateThirdPartyServiceTool handles the updateThirdPartyService tool
|
|
// Update an existing thirdParty service
|
|
func (r *Resolver) UpdateThirdPartyServiceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateThirdPartyServiceInput) (*mcp.CallToolResult, types.UpdateThirdPartyServiceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyServiceUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateThirdPartyServiceOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
updateReq := probo.UpdateThirdPartyServiceRequest{
|
|
ID: input.ID,
|
|
}
|
|
|
|
if input.Name != nil {
|
|
updateReq.Name = input.Name
|
|
}
|
|
|
|
if input.Description != nil {
|
|
updateReq.Description = &input.Description
|
|
}
|
|
|
|
thirdPartyService, err := prb.ThirdPartyServices.Update(ctx, scope, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateThirdPartyServiceOutput{}, fmt.Errorf("cannot update thirdParty service: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateThirdPartyServiceOutput{
|
|
ThirdPartyService: types.NewThirdPartyService(thirdPartyService),
|
|
}, nil
|
|
}
|
|
|
|
// DeleteThirdPartyServiceTool handles the deleteThirdPartyService tool
|
|
// Delete a thirdParty service
|
|
func (r *Resolver) DeleteThirdPartyServiceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteThirdPartyServiceInput) (*mcp.CallToolResult, types.DeleteThirdPartyServiceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyServiceDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteThirdPartyServiceOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
err = prb.ThirdPartyServices.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteThirdPartyServiceOutput{}, fmt.Errorf("cannot delete thirdParty service: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteThirdPartyServiceOutput{
|
|
DeletedThirdPartyServiceID: input.ID,
|
|
}, nil
|
|
}
|
|
func (r *Resolver) DeleteAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteAssetInput) (*mcp.CallToolResult, types.DeleteAssetOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionAssetDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteAssetOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.Assets.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteAssetOutput{}, fmt.Errorf("failed to delete asset: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteAssetOutput{
|
|
DeletedAssetID: input.ID,
|
|
}, nil
|
|
}
|
|
func (r *Resolver) DeleteDatumTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteDatumInput) (*mcp.CallToolResult, types.DeleteDatumOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionDatumDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteDatumOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.Data.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteDatumOutput{}, fmt.Errorf("failed to delete datum: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteDatumOutput{
|
|
DeletedDatumID: input.ID,
|
|
}, nil
|
|
}
|
|
func (r *Resolver) DeleteObligationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteObligationInput) (*mcp.CallToolResult, types.DeleteObligationOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionObligationDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteObligationOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.Obligations.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteObligationOutput{}, fmt.Errorf("failed to delete obligation: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteObligationOutput{
|
|
DeletedObligationID: input.ID,
|
|
}, nil
|
|
}
|
|
func (r *Resolver) DeleteAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteAuditInput) (*mcp.CallToolResult, types.DeleteAuditOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionAuditDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteAuditOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.Audits.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteAuditOutput{}, fmt.Errorf("failed to delete audit: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteAuditOutput{
|
|
DeletedAuditID: input.ID,
|
|
}, nil
|
|
}
|
|
func (r *Resolver) ListRightsRequestsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRightsRequestsInput) (*mcp.CallToolResult, types.ListRightsRequestsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRightsRequestList)
|
|
if err != nil {
|
|
return nil, types.ListRightsRequestsOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
pageOrderBy := page.OrderBy[coredata.RightsRequestOrderField]{
|
|
Field: coredata.RightsRequestOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.RightsRequestOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
page, err := prb.RightsRequests.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization rights requests: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListRightsRequestsOutput(page), nil
|
|
}
|
|
func (r *Resolver) GetRightsRequestTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRightsRequestInput) (*mcp.CallToolResult, types.GetRightsRequestOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRightsRequestGet)
|
|
if err != nil {
|
|
return nil, types.GetRightsRequestOutput{}, err
|
|
}
|
|
|
|
prb := r.proboSvc
|
|
|
|
rightsRequest, err := prb.RightsRequests.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetRightsRequestOutput{}, fmt.Errorf("failed to get rights request: %w", err)
|
|
}
|
|
|
|
return nil, types.GetRightsRequestOutput{
|
|
RightsRequest: types.NewRightsRequest(rightsRequest),
|
|
}, nil
|
|
}
|
|
func (r *Resolver) AddRightsRequestTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRightsRequestInput) (*mcp.CallToolResult, types.AddRightsRequestOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRightsRequestCreate)
|
|
if err != nil {
|
|
return nil, types.AddRightsRequestOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
rightsRequest, err := svc.RightsRequests.Create(
|
|
ctx, scope,
|
|
&probo.CreateRightsRequestRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
RequestType: &input.RequestType,
|
|
RequestState: &input.RequestState,
|
|
DataSubject: &input.DataSubject,
|
|
Contact: input.Contact,
|
|
Details: input.Details,
|
|
Deadline: input.Deadline,
|
|
ActionTaken: input.ActionTaken,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddRightsRequestOutput{}, fmt.Errorf("failed to create rights request: %w", err)
|
|
}
|
|
|
|
return nil, types.AddRightsRequestOutput{
|
|
RightsRequest: types.NewRightsRequest(rightsRequest),
|
|
}, nil
|
|
}
|
|
func (r *Resolver) UpdateRightsRequestTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRightsRequestInput) (*mcp.CallToolResult, types.UpdateRightsRequestOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRightsRequestUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateRightsRequestOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
var dataSubject **string
|
|
if input.DataSubject != nil {
|
|
dataSubject = &input.DataSubject
|
|
}
|
|
|
|
rightsRequest, err := svc.RightsRequests.Update(
|
|
ctx, scope,
|
|
&probo.UpdateRightsRequestRequest{
|
|
ID: input.ID,
|
|
RequestType: input.RequestType,
|
|
RequestState: input.RequestState,
|
|
DataSubject: dataSubject,
|
|
Contact: UnwrapOmittable(input.Contact),
|
|
Details: UnwrapOmittable(input.Details),
|
|
Deadline: UnwrapOmittable(input.Deadline),
|
|
ActionTaken: UnwrapOmittable(input.ActionTaken),
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateRightsRequestOutput{}, fmt.Errorf("failed to update rights request: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateRightsRequestOutput{
|
|
RightsRequest: types.NewRightsRequest(rightsRequest),
|
|
}, nil
|
|
}
|
|
func (r *Resolver) DeleteRightsRequestTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRightsRequestInput) (*mcp.CallToolResult, types.DeleteRightsRequestOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRightsRequestDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteRightsRequestOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
err = svc.RightsRequests.Delete(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteRightsRequestOutput{}, fmt.Errorf("failed to delete rights request: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteRightsRequestOutput{
|
|
DeletedRightsRequestID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
// GetCompliancePortalTool handles the getCompliancePortal tool
|
|
// Get the compliance portal for an organization
|
|
func (r *Resolver) GetCompliancePortalTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetCompliancePortalInput) (*mcp.CallToolResult, types.GetCompliancePortalOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, management.ActionCompliancePortalGet)
|
|
if err != nil {
|
|
return nil, types.GetCompliancePortalOutput{}, err
|
|
}
|
|
|
|
prb := r.management
|
|
|
|
compliancePortal, err := prb.GetByOrganizationID(ctx, scope, input.OrganizationID)
|
|
if err != nil {
|
|
return nil, types.GetCompliancePortalOutput{}, fmt.Errorf("cannot get compliance portal: %w", err)
|
|
}
|
|
|
|
tc := types.NewCompliancePortal(compliancePortal)
|
|
|
|
if compliancePortal.LogoFileID != nil {
|
|
logo, err := r.loadFile(ctx, scope, *compliancePortal.LogoFileID)
|
|
if err != nil {
|
|
return nil, types.GetCompliancePortalOutput{}, err
|
|
}
|
|
|
|
tc.Logo = logo
|
|
}
|
|
|
|
if compliancePortal.DarkLogoFileID != nil {
|
|
darkLogo, err := r.loadFile(ctx, scope, *compliancePortal.DarkLogoFileID)
|
|
if err != nil {
|
|
return nil, types.GetCompliancePortalOutput{}, err
|
|
}
|
|
|
|
tc.DarkLogo = darkLogo
|
|
}
|
|
|
|
if compliancePortal.NonDisclosureAgreementFileID != nil {
|
|
nda, err := r.loadFile(ctx, scope, *compliancePortal.NonDisclosureAgreementFileID)
|
|
if err != nil {
|
|
return nil, types.GetCompliancePortalOutput{}, err
|
|
}
|
|
|
|
tc.Nda = nda
|
|
}
|
|
|
|
return nil, types.GetCompliancePortalOutput{CompliancePortal: tc}, nil
|
|
}
|
|
|
|
// UpdateCompliancePortalTool handles the updateCompliancePortal tool
|
|
// Update the compliance portal settings
|
|
func (r *Resolver) UpdateCompliancePortalTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCompliancePortalInput) (*mcp.CallToolResult, types.UpdateCompliancePortalOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.ActionCompliancePortalUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateCompliancePortalOutput{}, err
|
|
}
|
|
|
|
prb := r.management
|
|
|
|
updateReq := &management.UpdateRequest{
|
|
ID: input.CompliancePortalID,
|
|
}
|
|
|
|
if active := UnwrapOmittable(input.Active); active != nil {
|
|
updateReq.Active = *active
|
|
}
|
|
|
|
if sei := UnwrapOmittable(input.SearchEngineIndexing); sei != nil {
|
|
updateReq.SearchEngineIndexing = *sei
|
|
}
|
|
|
|
updateReq.Description = UnwrapOmittable(input.Description)
|
|
updateReq.WebsiteURL = UnwrapOmittable(input.WebsiteURL)
|
|
updateReq.Email = UnwrapOmittable(input.Email)
|
|
updateReq.HeadquarterAddress = UnwrapOmittable(input.HeadquarterAddress)
|
|
|
|
if entityName := UnwrapOmittable(input.EntityName); entityName != nil {
|
|
updateReq.EntityName = *entityName
|
|
}
|
|
|
|
compliancePortal, _, err := prb.Update(ctx, scope, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateCompliancePortalOutput{}, fmt.Errorf("cannot update compliance portal: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateCompliancePortalOutput{CompliancePortal: types.NewCompliancePortal(compliancePortal)}, nil
|
|
}
|
|
|
|
// ListCompliancePortalReferencesTool handles the listCompliancePortalReferences tool
|
|
// List all references for a compliance portal
|
|
func (r *Resolver) ListCompliancePortalReferencesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCompliancePortalReferencesInput) (*mcp.CallToolResult, types.ListCompliancePortalReferencesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.ActionCompliancePortalReferenceList)
|
|
if err != nil {
|
|
return nil, types.ListCompliancePortalReferencesOutput{}, err
|
|
}
|
|
|
|
prb := r.management
|
|
|
|
pageOrderBy := page.OrderBy[coredata.CompliancePortalReferenceOrderField]{
|
|
Field: coredata.CompliancePortalReferenceOrderFieldRank,
|
|
Direction: page.OrderDirectionAsc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.CompliancePortalReferenceOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := prb.ListReferences(ctx, scope, input.CompliancePortalID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListCompliancePortalReferencesOutput{}, fmt.Errorf("cannot list compliance portal references: %w", err)
|
|
}
|
|
|
|
refs := make([]*types.CompliancePortalReference, 0, len(p.Data))
|
|
for _, reference := range p.Data {
|
|
ref := types.NewCompliancePortalReference(reference)
|
|
|
|
logo, err := r.loadFile(ctx, scope, reference.LogoFileID)
|
|
if err != nil {
|
|
return nil, types.ListCompliancePortalReferencesOutput{}, err
|
|
}
|
|
|
|
ref.Logo = logo
|
|
|
|
refs = append(refs, ref)
|
|
}
|
|
|
|
return nil, types.NewListCompliancePortalReferencesOutput(refs, p), nil
|
|
}
|
|
|
|
// AddCompliancePortalReferenceTool handles the addCompliancePortalReference tool
|
|
// Add a new reference to the compliance portal
|
|
func (r *Resolver) AddCompliancePortalReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddCompliancePortalReferenceInput) (*mcp.CallToolResult, types.AddCompliancePortalReferenceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.ActionCompliancePortalReferenceCreate)
|
|
if err != nil {
|
|
return nil, types.AddCompliancePortalReferenceOutput{}, err
|
|
}
|
|
|
|
prb := r.management
|
|
|
|
var websiteURL string
|
|
if input.WebsiteURL != nil {
|
|
websiteURL = *input.WebsiteURL
|
|
}
|
|
|
|
reference, err := prb.CreateReference(
|
|
ctx, scope,
|
|
&management.CreateReferenceRequest{
|
|
CompliancePortalID: input.CompliancePortalID,
|
|
Name: input.Name,
|
|
Description: input.Description,
|
|
WebsiteURL: websiteURL,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddCompliancePortalReferenceOutput{}, fmt.Errorf("cannot add compliance portal reference: %w", err)
|
|
}
|
|
|
|
return nil, types.AddCompliancePortalReferenceOutput{CompliancePortalReference: types.NewCompliancePortalReference(reference)}, nil
|
|
}
|
|
|
|
// UpdateCompliancePortalReferenceTool handles the updateCompliancePortalReference tool
|
|
// Update a compliance portal reference
|
|
func (r *Resolver) UpdateCompliancePortalReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCompliancePortalReferenceInput) (*mcp.CallToolResult, types.UpdateCompliancePortalReferenceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, management.ActionCompliancePortalReferenceUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateCompliancePortalReferenceOutput{}, err
|
|
}
|
|
|
|
prb := r.management
|
|
|
|
updateRefReq := &management.UpdateReferenceRequest{
|
|
ID: input.ID,
|
|
Description: UnwrapOmittable(input.Description),
|
|
}
|
|
|
|
if name := UnwrapOmittable(input.Name); name != nil {
|
|
updateRefReq.Name = *name
|
|
}
|
|
|
|
if websiteURL := UnwrapOmittable(input.WebsiteURL); websiteURL != nil {
|
|
updateRefReq.WebsiteURL = *websiteURL
|
|
}
|
|
|
|
if rank := UnwrapOmittable(input.Rank); rank != nil {
|
|
updateRefReq.Rank = *rank
|
|
}
|
|
|
|
reference, err := prb.UpdateReference(ctx, scope, updateRefReq)
|
|
if err != nil {
|
|
return nil, types.UpdateCompliancePortalReferenceOutput{}, fmt.Errorf("cannot update compliance portal reference: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateCompliancePortalReferenceOutput{CompliancePortalReference: types.NewCompliancePortalReference(reference)}, nil
|
|
}
|
|
|
|
// DeleteCompliancePortalReferenceTool handles the deleteCompliancePortalReference tool
|
|
// Delete a compliance portal reference
|
|
func (r *Resolver) DeleteCompliancePortalReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCompliancePortalReferenceInput) (*mcp.CallToolResult, types.DeleteCompliancePortalReferenceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, management.ActionCompliancePortalReferenceDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteCompliancePortalReferenceOutput{}, err
|
|
}
|
|
|
|
prb := r.management
|
|
|
|
err = prb.DeleteReference(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteCompliancePortalReferenceOutput{}, fmt.Errorf("cannot delete compliance portal reference: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteCompliancePortalReferenceOutput{DeletedCompliancePortalReferenceID: input.ID}, nil
|
|
}
|
|
|
|
// ListCompliancePortalFilesTool handles the listCompliancePortalFiles tool
|
|
// List all files for the compliance portal
|
|
func (r *Resolver) ListCompliancePortalFilesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCompliancePortalFilesInput) (*mcp.CallToolResult, types.ListCompliancePortalFilesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, management.ActionCompliancePortalFileList)
|
|
if err != nil {
|
|
return nil, types.ListCompliancePortalFilesOutput{}, err
|
|
}
|
|
|
|
prb := r.management
|
|
|
|
pageOrderBy := page.OrderBy[coredata.CompliancePortalFileOrderField]{
|
|
Field: coredata.CompliancePortalFileOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.CompliancePortalFileOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
filter := coredata.NewCompliancePortalFileFilter()
|
|
|
|
p, err := prb.ListFilesForOrganizationID(ctx, scope, input.OrganizationID, cursor, filter)
|
|
if err != nil {
|
|
return nil, types.ListCompliancePortalFilesOutput{}, fmt.Errorf("cannot list compliance portal files: %w", err)
|
|
}
|
|
|
|
files := make([]*types.CompliancePortalFile, 0, len(p.Data))
|
|
for _, f := range p.Data {
|
|
file, err := r.loadFile(ctx, scope, f.FileID)
|
|
if err != nil {
|
|
return nil, types.ListCompliancePortalFilesOutput{}, err
|
|
}
|
|
|
|
files = append(files, types.NewCompliancePortalFile(f, file))
|
|
}
|
|
|
|
return nil, types.NewListCompliancePortalFilesOutput(files, p), nil
|
|
}
|
|
|
|
// DeleteCompliancePortalFileTool handles the deleteCompliancePortalFile tool
|
|
// Delete a compliance portal file
|
|
func (r *Resolver) DeleteCompliancePortalFileTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCompliancePortalFileInput) (*mcp.CallToolResult, types.DeleteCompliancePortalFileOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, management.ActionCompliancePortalFileDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteCompliancePortalFileOutput{}, err
|
|
}
|
|
|
|
prb := r.management
|
|
|
|
err = prb.DeleteFile(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteCompliancePortalFileOutput{}, fmt.Errorf("cannot delete compliance portal file: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteCompliancePortalFileOutput{DeletedCompliancePortalFileID: input.ID}, nil
|
|
}
|
|
|
|
// ListComplianceCustomLinksTool handles the listComplianceCustomLinks tool
|
|
// List all custom links for a compliance portal
|
|
func (r *Resolver) ListComplianceCustomLinksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListComplianceCustomLinksInput) (*mcp.CallToolResult, types.ListComplianceCustomLinksOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.ActionComplianceCustomLinkList)
|
|
if err != nil {
|
|
return nil, types.ListComplianceCustomLinksOutput{}, err
|
|
}
|
|
|
|
prb := r.management
|
|
|
|
pageOrderBy := page.OrderBy[coredata.ComplianceCustomLinkOrderField]{
|
|
Field: coredata.ComplianceCustomLinkOrderFieldRank,
|
|
Direction: page.OrderDirectionAsc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.ComplianceCustomLinkOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := prb.ListCustomLinks(ctx, scope, input.CompliancePortalID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListComplianceCustomLinksOutput{}, fmt.Errorf("cannot list compliance custom links: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListComplianceCustomLinksOutput(p), nil
|
|
}
|
|
|
|
// AddComplianceCustomLinkTool handles the addComplianceCustomLink tool
|
|
// Add a new custom link to the compliance portal
|
|
func (r *Resolver) AddComplianceCustomLinkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddComplianceCustomLinkInput) (*mcp.CallToolResult, types.AddComplianceCustomLinkOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.ActionComplianceCustomLinkCreate)
|
|
if err != nil {
|
|
return nil, types.AddComplianceCustomLinkOutput{}, err
|
|
}
|
|
|
|
prb := r.management
|
|
|
|
item, err := prb.CreateCustomLink(
|
|
ctx, scope,
|
|
&management.CreateCustomLinkRequest{
|
|
CompliancePortalID: input.CompliancePortalID,
|
|
Name: input.Name,
|
|
URL: input.URL,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddComplianceCustomLinkOutput{}, fmt.Errorf("cannot add compliance custom link: %w", err)
|
|
}
|
|
|
|
return nil, types.AddComplianceCustomLinkOutput{ComplianceCustomLink: types.NewComplianceCustomLink(item)}, nil
|
|
}
|
|
|
|
// UpdateComplianceCustomLinkTool handles the updateComplianceCustomLink tool
|
|
// Update a compliance custom link
|
|
func (r *Resolver) UpdateComplianceCustomLinkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateComplianceCustomLinkInput) (*mcp.CallToolResult, types.UpdateComplianceCustomLinkOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, management.ActionComplianceCustomLinkUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateComplianceCustomLinkOutput{}, err
|
|
}
|
|
|
|
prb := r.management
|
|
|
|
updateURLReq := &management.UpdateCustomLinkRequest{
|
|
ID: input.ID,
|
|
}
|
|
|
|
if name := UnwrapOmittable(input.Name); name != nil && *name != nil {
|
|
updateURLReq.Name = **name
|
|
}
|
|
|
|
if u := UnwrapOmittable(input.URL); u != nil && *u != nil {
|
|
updateURLReq.URL = **u
|
|
}
|
|
|
|
if rank := UnwrapOmittable(input.Rank); rank != nil {
|
|
updateURLReq.Rank = *rank
|
|
}
|
|
|
|
item, err := prb.UpdateCustomLink(ctx, scope, updateURLReq)
|
|
if err != nil {
|
|
return nil, types.UpdateComplianceCustomLinkOutput{}, fmt.Errorf("cannot update compliance custom link: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateComplianceCustomLinkOutput{ComplianceCustomLink: types.NewComplianceCustomLink(item)}, nil
|
|
}
|
|
|
|
// DeleteComplianceCustomLinkTool handles the deleteComplianceCustomLink tool
|
|
// Delete a compliance custom link
|
|
func (r *Resolver) DeleteComplianceCustomLinkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteComplianceCustomLinkInput) (*mcp.CallToolResult, types.DeleteComplianceCustomLinkOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, management.ActionComplianceCustomLinkDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteComplianceCustomLinkOutput{}, err
|
|
}
|
|
|
|
prb := r.management
|
|
|
|
err = prb.DeleteCustomLink(
|
|
ctx, scope,
|
|
&management.DeleteCustomLinkRequest{
|
|
ID: input.ID,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.DeleteComplianceCustomLinkOutput{}, fmt.Errorf("cannot delete compliance custom link: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteComplianceCustomLinkOutput{DeletedComplianceCustomLinkID: input.ID}, nil
|
|
}
|
|
|
|
// CreateCustomDomainTool handles the createCustomDomain tool
|
|
// Create a custom domain for a compliance page
|
|
func (r *Resolver) CreateCustomDomainTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateCustomDomainInput) (*mcp.CallToolResult, types.CreateCustomDomainOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.ActionCustomDomainCreate)
|
|
if err != nil {
|
|
return nil, types.CreateCustomDomainOutput{}, err
|
|
}
|
|
|
|
domain, err := r.management.AddCustomDomain(
|
|
ctx, scope,
|
|
input.CompliancePortalID,
|
|
input.Domain,
|
|
)
|
|
if err != nil {
|
|
return nil, types.CreateCustomDomainOutput{}, fmt.Errorf("cannot create custom domain: %w", err)
|
|
}
|
|
|
|
var cert *coredata.Certificate
|
|
if domain.CertificateID != nil {
|
|
cert, err = r.certManager.Get(ctx, scope, *domain.CertificateID)
|
|
if err != nil {
|
|
return nil, types.CreateCustomDomainOutput{}, fmt.Errorf("cannot load certificate: %w", err)
|
|
}
|
|
}
|
|
|
|
return nil, types.CreateCustomDomainOutput{CustomDomain: types.NewCustomDomain(domain, cert)}, nil
|
|
}
|
|
|
|
// DeleteCustomDomainTool handles the deleteCustomDomain tool
|
|
// Delete the custom domain of a compliance page
|
|
func (r *Resolver) DeleteCustomDomainTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCustomDomainInput) (*mcp.CallToolResult, types.DeleteCustomDomainOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.ActionCustomDomainDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteCustomDomainOutput{}, err
|
|
}
|
|
|
|
compliancePage, err := r.management.Get(ctx, scope, input.CompliancePortalID)
|
|
if err != nil {
|
|
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot load compliance page: %w", err)
|
|
}
|
|
|
|
if compliancePage.CustomDomainID == nil {
|
|
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("compliance page has no custom domain")
|
|
}
|
|
|
|
domain, err := r.management.GetDomain(ctx, scope, *compliancePage.CustomDomainID)
|
|
if err != nil {
|
|
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot get custom domain: %w", err)
|
|
}
|
|
|
|
var cert *coredata.Certificate
|
|
if domain.CertificateID != nil {
|
|
cert, err = r.certManager.Get(ctx, scope, *domain.CertificateID)
|
|
if err != nil {
|
|
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot load certificate: %w", err)
|
|
}
|
|
}
|
|
|
|
deletedDomain := types.NewCustomDomain(domain, cert)
|
|
|
|
if err := r.management.RemoveCustomDomain(ctx, scope, domain.ID); err != nil {
|
|
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot delete custom domain: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteCustomDomainOutput{DeletedCustomDomain: deletedDomain}, nil
|
|
}
|
|
|
|
func (r *Resolver) VetThirdPartyTool(ctx context.Context, req *mcp.CallToolRequest, input *types.VetThirdPartyInput) (*mcp.CallToolResult, types.VetThirdPartyOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyVet)
|
|
if err != nil {
|
|
return nil, types.VetThirdPartyOutput{}, err
|
|
}
|
|
|
|
svc := r.thirdPartySvc
|
|
|
|
thirdParty, err := svc.Vet(
|
|
ctx, scope,
|
|
thirdparty.VetRequest{
|
|
ID: input.ID,
|
|
WebsiteURL: input.WebsiteURL,
|
|
Procedure: input.Procedure,
|
|
},
|
|
)
|
|
if err != nil {
|
|
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
|
|
return nil, types.VetThirdPartyOutput{}, validationErrors
|
|
}
|
|
|
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
|
return nil, types.VetThirdPartyOutput{}, fmt.Errorf("resource not found")
|
|
}
|
|
|
|
if errors.Is(err, thirdparty.ErrVettingDisabled) {
|
|
return nil, types.VetThirdPartyOutput{}, fmt.Errorf("vetting is not configured")
|
|
}
|
|
|
|
if errors.Is(err, thirdparty.ErrVettingInProgress) {
|
|
return nil, types.VetThirdPartyOutput{}, fmt.Errorf("vetting is already in progress")
|
|
}
|
|
|
|
r.logger.ErrorCtx(ctx, "cannot vet thirdParty", log.Error(err))
|
|
|
|
return nil, types.VetThirdPartyOutput{}, fmt.Errorf("internal server error")
|
|
}
|
|
|
|
return nil, types.VetThirdPartyOutput{
|
|
ThirdParty: types.NewThirdParty(thirdParty),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) PublishFindingListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishFindingListInput) (*mcp.CallToolResult, types.PublishFindingListOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionFindingPublish)
|
|
if err != nil {
|
|
return nil, types.PublishFindingListOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishFindingList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
|
|
if err != nil {
|
|
return nil, types.PublishFindingListOutput{}, fmt.Errorf("cannot publish finding list: %w", err)
|
|
}
|
|
|
|
return nil, types.PublishFindingListOutput{
|
|
DocumentID: document.ID,
|
|
DocumentVersionID: documentVersion.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) PublishObligationListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishObligationListInput) (*mcp.CallToolResult, types.PublishObligationListOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionObligationPublish)
|
|
if err != nil {
|
|
return nil, types.PublishObligationListOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishObligationList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
|
|
if err != nil {
|
|
return nil, types.PublishObligationListOutput{}, fmt.Errorf("cannot publish obligation list: %w", err)
|
|
}
|
|
|
|
return nil, types.PublishObligationListOutput{
|
|
DocumentID: document.ID,
|
|
DocumentVersionID: documentVersion.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) PublishProcessingActivityListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishProcessingActivityListInput) (*mcp.CallToolResult, types.PublishProcessingActivityListOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionProcessingActivityPublish)
|
|
if err != nil {
|
|
return nil, types.PublishProcessingActivityListOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishProcessingActivityList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
|
|
if err != nil {
|
|
return nil, types.PublishProcessingActivityListOutput{}, fmt.Errorf("cannot publish processing activity list: %w", err)
|
|
}
|
|
|
|
return nil, types.PublishProcessingActivityListOutput{
|
|
DocumentID: document.ID,
|
|
DocumentVersionID: documentVersion.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) PublishDataProtectionImpactAssessmentListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishDataProtectionImpactAssessmentListInput) (*mcp.CallToolResult, types.PublishDataProtectionImpactAssessmentListOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionDataProtectionImpactAssessmentPublish)
|
|
if err != nil {
|
|
return nil, types.PublishDataProtectionImpactAssessmentListOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishDataProtectionImpactAssessmentList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
|
|
if err != nil {
|
|
return nil, types.PublishDataProtectionImpactAssessmentListOutput{}, fmt.Errorf("cannot publish DPIA list: %w", err)
|
|
}
|
|
|
|
return nil, types.PublishDataProtectionImpactAssessmentListOutput{
|
|
DocumentID: document.ID,
|
|
DocumentVersionID: documentVersion.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) PublishTransferImpactAssessmentListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishTransferImpactAssessmentListInput) (*mcp.CallToolResult, types.PublishTransferImpactAssessmentListOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionTransferImpactAssessmentPublish)
|
|
if err != nil {
|
|
return nil, types.PublishTransferImpactAssessmentListOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishTransferImpactAssessmentList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
|
|
if err != nil {
|
|
return nil, types.PublishTransferImpactAssessmentListOutput{}, fmt.Errorf("cannot publish TIA list: %w", err)
|
|
}
|
|
|
|
return nil, types.PublishTransferImpactAssessmentListOutput{
|
|
DocumentID: document.ID,
|
|
DocumentVersionID: documentVersion.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) PublishThirdPartyListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishThirdPartyListInput) (*mcp.CallToolResult, types.PublishThirdPartyListOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionThirdPartyPublish)
|
|
if err != nil {
|
|
return nil, types.PublishThirdPartyListOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishThirdPartyList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
|
|
if err != nil {
|
|
return nil, types.PublishThirdPartyListOutput{}, fmt.Errorf("cannot publish thirdParty list: %w", err)
|
|
}
|
|
|
|
return nil, types.PublishThirdPartyListOutput{
|
|
DocumentID: document.ID,
|
|
DocumentVersionID: documentVersion.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListCookieBannersTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCookieBannersInput) (*mcp.CallToolResult, types.ListCookieBannersOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionCookieBannerList)
|
|
if err != nil {
|
|
return nil, types.ListCookieBannersOutput{}, err
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.CookieBannerOrderField]{Field: coredata.CookieBannerOrderFieldCreatedAt, Direction: page.OrderDirectionDesc})
|
|
|
|
banners, err := r.cookieBanner.ListCookieBannersForOrganization(ctx, scope, input.OrganizationID, cursor, coredata.NewCookieBannerFilter(nil))
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list cookie banners: %w", err))
|
|
}
|
|
|
|
p := page.NewPage(banners, cursor)
|
|
|
|
return nil, types.NewListCookieBannersOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) GetCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetCookieBannerInput) (*mcp.CallToolResult, types.GetCookieBannerOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerGet)
|
|
if err != nil {
|
|
return nil, types.GetCookieBannerOutput{}, err
|
|
}
|
|
|
|
banner, err := r.cookieBanner.GetCookieBanner(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetCookieBannerOutput{}, fmt.Errorf("cannot get cookie banner: %w", err)
|
|
}
|
|
|
|
return nil, types.GetCookieBannerOutput{CookieBanner: types.NewCookieBanner(banner)}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddCookieBannerInput) (*mcp.CallToolResult, types.AddCookieBannerOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionCookieBannerCreate)
|
|
if err != nil {
|
|
return nil, types.AddCookieBannerOutput{}, err
|
|
}
|
|
|
|
banner, err := r.cookieBanner.CreateCookieBanner(ctx, scope, cookiebanner.CreateCookieBannerRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
Origin: input.Origin,
|
|
PrivacyPolicyURL: input.PrivacyPolicyURL,
|
|
CookiePolicyURL: input.CookiePolicyURL,
|
|
ConsentExpiryDays: input.ConsentExpiryDays,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddCookieBannerOutput{}, fmt.Errorf("cannot create cookie banner: %w", err)
|
|
}
|
|
|
|
return nil, types.AddCookieBannerOutput{CookieBanner: types.NewCookieBanner(banner)}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCookieBannerInput) (*mcp.CallToolResult, types.UpdateCookieBannerOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateCookieBannerOutput{}, err
|
|
}
|
|
|
|
updateReq := cookiebanner.UpdateCookieBannerRequest{CookieBannerID: input.ID}
|
|
if v := UnwrapOmittable(input.Name); v != nil && *v != nil {
|
|
updateReq.Name = *v
|
|
}
|
|
|
|
if v := UnwrapOmittable(input.PrivacyPolicyURL); v != nil && *v != nil {
|
|
updateReq.PrivacyPolicyURL = *v
|
|
}
|
|
|
|
if v := UnwrapOmittable(input.CookiePolicyURL); v != nil && *v != nil {
|
|
updateReq.CookiePolicyURL = *v
|
|
}
|
|
|
|
if v := UnwrapOmittable(input.ConsentExpiryDays); v != nil && *v != nil {
|
|
updateReq.ConsentExpiryDays = *v
|
|
}
|
|
|
|
if v := UnwrapOmittable(input.DefaultLanguage); v != nil && *v != nil {
|
|
updateReq.DefaultLanguage = *v
|
|
}
|
|
|
|
banner, err := r.cookieBanner.UpdateCookieBanner(ctx, scope, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateCookieBannerOutput{}, fmt.Errorf("cannot update cookie banner: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateCookieBannerOutput{CookieBanner: types.NewCookieBanner(banner)}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCookieBannerInput) (*mcp.CallToolResult, types.DeleteCookieBannerOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteCookieBannerOutput{}, err
|
|
}
|
|
|
|
if err := r.cookieBanner.DeleteCookieBanner(ctx, scope, input.ID); err != nil {
|
|
return nil, types.DeleteCookieBannerOutput{}, fmt.Errorf("cannot delete cookie banner: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteCookieBannerOutput{DeletedID: input.ID}, nil
|
|
}
|
|
|
|
func (r *Resolver) ActivateCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ActivateCookieBannerInput) (*mcp.CallToolResult, types.ActivateCookieBannerOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerActivate)
|
|
if err != nil {
|
|
return nil, types.ActivateCookieBannerOutput{}, err
|
|
}
|
|
|
|
banner, err := r.cookieBanner.ActivateCookieBanner(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.ActivateCookieBannerOutput{}, fmt.Errorf("cannot activate cookie banner: %w", err)
|
|
}
|
|
|
|
return nil, types.ActivateCookieBannerOutput{CookieBanner: types.NewCookieBanner(banner)}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeactivateCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeactivateCookieBannerInput) (*mcp.CallToolResult, types.DeactivateCookieBannerOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerDeactivate)
|
|
if err != nil {
|
|
return nil, types.DeactivateCookieBannerOutput{}, err
|
|
}
|
|
|
|
banner, err := r.cookieBanner.DeactivateCookieBanner(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeactivateCookieBannerOutput{}, fmt.Errorf("cannot deactivate cookie banner: %w", err)
|
|
}
|
|
|
|
return nil, types.DeactivateCookieBannerOutput{CookieBanner: types.NewCookieBanner(banner)}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListCookieCategoriesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCookieCategoriesInput) (*mcp.CallToolResult, types.ListCookieCategoriesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieCategoryList)
|
|
if err != nil {
|
|
return nil, types.ListCookieCategoriesOutput{}, err
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.CookieCategoryOrderField]{Field: coredata.CookieCategoryOrderFieldRank, Direction: page.OrderDirectionAsc})
|
|
|
|
categories, err := r.cookieBanner.ListCategoriesForBanner(ctx, scope, input.CookieBannerID, cursor, coredata.NewCookieCategoryFilter(new(coredata.CookieCategoryKindUncategorised)))
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list cookie categories: %w", err))
|
|
}
|
|
|
|
p := page.NewPage(categories, cursor)
|
|
|
|
return nil, types.NewListCookieCategoriesOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) GetCookieCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetCookieCategoryInput) (*mcp.CallToolResult, types.GetCookieCategoryOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieCategoryGet)
|
|
if err != nil {
|
|
return nil, types.GetCookieCategoryOutput{}, err
|
|
}
|
|
|
|
category, err := r.cookieBanner.GetCookieCategory(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetCookieCategoryOutput{}, fmt.Errorf("cannot get cookie category: %w", err)
|
|
}
|
|
|
|
return nil, types.GetCookieCategoryOutput{CookieCategory: types.NewCookieCategory(category)}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddCookieCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddCookieCategoryInput) (*mcp.CallToolResult, types.AddCookieCategoryOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieCategoryCreate)
|
|
if err != nil {
|
|
return nil, types.AddCookieCategoryOutput{}, err
|
|
}
|
|
|
|
category, err := r.cookieBanner.CreateCookieCategory(ctx, scope, cookiebanner.CreateCookieCategoryRequest{
|
|
CookieBannerID: input.CookieBannerID,
|
|
Name: input.Name,
|
|
Slug: input.Slug,
|
|
Description: input.Description,
|
|
Rank: input.Rank,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddCookieCategoryOutput{}, fmt.Errorf("cannot create cookie category: %w", err)
|
|
}
|
|
|
|
return nil, types.AddCookieCategoryOutput{CookieCategory: types.NewCookieCategory(category)}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateCookieCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCookieCategoryInput) (*mcp.CallToolResult, types.UpdateCookieCategoryOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieCategoryUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateCookieCategoryOutput{}, err
|
|
}
|
|
|
|
updateReq := cookiebanner.UpdateCookieCategoryRequest{CookieCategoryID: input.ID}
|
|
if v := UnwrapOmittable(input.Name); v != nil && *v != nil {
|
|
updateReq.Name = *v
|
|
}
|
|
|
|
if v := UnwrapOmittable(input.Slug); v != nil && *v != nil {
|
|
updateReq.Slug = *v
|
|
}
|
|
|
|
if v := UnwrapOmittable(input.Description); v != nil && *v != nil {
|
|
updateReq.Description = *v
|
|
}
|
|
|
|
category, err := r.cookieBanner.UpdateCookieCategory(ctx, scope, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateCookieCategoryOutput{}, fmt.Errorf("cannot update cookie category: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateCookieCategoryOutput{CookieCategory: types.NewCookieCategory(category)}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteCookieCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCookieCategoryInput) (*mcp.CallToolResult, types.DeleteCookieCategoryOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieCategoryDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteCookieCategoryOutput{}, err
|
|
}
|
|
|
|
if err := r.cookieBanner.DeleteCookieCategory(ctx, scope, input.ID); err != nil {
|
|
return nil, types.DeleteCookieCategoryOutput{}, fmt.Errorf("cannot delete cookie category: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteCookieCategoryOutput{DeletedID: input.ID}, nil
|
|
}
|
|
|
|
func (r *Resolver) ReorderCookieCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ReorderCookieCategoryInput) (*mcp.CallToolResult, types.ReorderCookieCategoryOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieCategoryUpdate)
|
|
if err != nil {
|
|
return nil, types.ReorderCookieCategoryOutput{}, err
|
|
}
|
|
|
|
_, err = r.cookieBanner.ReorderCookieCategory(ctx, scope, cookiebanner.ReorderCookieCategoryRequest{
|
|
CookieCategoryID: input.ID,
|
|
Rank: input.Rank,
|
|
})
|
|
if err != nil {
|
|
return nil, types.ReorderCookieCategoryOutput{}, fmt.Errorf("cannot reorder cookie category: %w", err)
|
|
}
|
|
|
|
category, err := r.cookieBanner.GetCookieCategory(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.ReorderCookieCategoryOutput{}, fmt.Errorf("cannot get cookie category: %w", err)
|
|
}
|
|
|
|
return nil, types.ReorderCookieCategoryOutput{CookieCategory: types.NewCookieCategory(category)}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListTrackerPatternsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrackerPatternsInput) (*mcp.CallToolResult, types.ListTrackerPatternsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerPatternList)
|
|
if err != nil {
|
|
return nil, types.ListTrackerPatternsOutput{}, err
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.TrackerPatternOrderField]{Field: coredata.TrackerPatternOrderFieldCreatedAt, Direction: page.OrderDirectionAsc})
|
|
|
|
patterns, err := r.cookieBanner.ListTrackerPatternsForCategory(ctx, scope, input.CookieCategoryID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list tracker patterns: %w", err))
|
|
}
|
|
|
|
p := page.NewPage(patterns, cursor)
|
|
|
|
return nil, types.NewListTrackerPatternsOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) GetTrackerPatternTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTrackerPatternInput) (*mcp.CallToolResult, types.GetTrackerPatternOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerPatternGet)
|
|
if err != nil {
|
|
return nil, types.GetTrackerPatternOutput{}, err
|
|
}
|
|
|
|
pattern, err := r.cookieBanner.GetTrackerPattern(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetTrackerPatternOutput{}, fmt.Errorf("cannot get tracker pattern: %w", err)
|
|
}
|
|
|
|
return nil, types.GetTrackerPatternOutput{TrackerPattern: types.NewTrackerPattern(pattern)}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddTrackerPatternTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTrackerPatternInput) (*mcp.CallToolResult, types.AddTrackerPatternOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerPatternCreate)
|
|
if err != nil {
|
|
return nil, types.AddTrackerPatternOutput{}, err
|
|
}
|
|
|
|
pattern, err := r.cookieBanner.CreateTrackerPattern(ctx, scope, cookiebanner.CreateTrackerPatternRequest{
|
|
CookieCategoryID: input.CookieCategoryID,
|
|
TrackerType: coredata.TrackerType(input.TrackerType),
|
|
Pattern: input.Pattern,
|
|
MatchType: coredata.TrackerPatternMatchType(input.MatchType),
|
|
DisplayName: input.DisplayName,
|
|
MaxAgeSeconds: input.MaxAgeSeconds,
|
|
Description: input.Description,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddTrackerPatternOutput{}, fmt.Errorf("cannot create tracker pattern: %w", err)
|
|
}
|
|
|
|
return nil, types.AddTrackerPatternOutput{TrackerPattern: types.NewTrackerPattern(pattern)}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateTrackerPatternTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrackerPatternInput) (*mcp.CallToolResult, types.UpdateTrackerPatternOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerPatternUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateTrackerPatternOutput{}, err
|
|
}
|
|
|
|
updateReq := cookiebanner.UpdateTrackerPatternRequest{TrackerPatternID: input.ID}
|
|
if input.MaxAgeSeconds.IsSet() {
|
|
val, _ := input.MaxAgeSeconds.Value()
|
|
updateReq.MaxAgeSeconds = &val
|
|
}
|
|
|
|
if v := UnwrapOmittable(input.Description); v != nil && *v != nil {
|
|
updateReq.Description = *v
|
|
}
|
|
|
|
if v := UnwrapOmittable(input.Excluded); v != nil && *v != nil {
|
|
updateReq.Excluded = *v
|
|
}
|
|
|
|
pattern, err := r.cookieBanner.UpdateTrackerPattern(ctx, scope, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateTrackerPatternOutput{}, fmt.Errorf("cannot update tracker pattern: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateTrackerPatternOutput{TrackerPattern: types.NewTrackerPattern(pattern)}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteTrackerPatternTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTrackerPatternInput) (*mcp.CallToolResult, types.DeleteTrackerPatternOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerPatternDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteTrackerPatternOutput{}, err
|
|
}
|
|
|
|
if err := r.cookieBanner.DeleteTrackerPattern(ctx, scope, input.ID); err != nil {
|
|
return nil, types.DeleteTrackerPatternOutput{}, fmt.Errorf("cannot delete tracker pattern: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteTrackerPatternOutput{DeletedID: input.ID}, nil
|
|
}
|
|
|
|
func (r *Resolver) MoveTrackerPatternToCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.MoveTrackerPatternToCategoryInput) (*mcp.CallToolResult, types.MoveTrackerPatternToCategoryOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.TrackerPatternID, probo.ActionTrackerPatternUpdate)
|
|
if err != nil {
|
|
return nil, types.MoveTrackerPatternToCategoryOutput{}, err
|
|
}
|
|
|
|
if _, err := r.Authorize(ctx, input.TargetCookieCategoryID, probo.ActionCookieCategoryUpdate); err != nil {
|
|
return nil, types.MoveTrackerPatternToCategoryOutput{}, err
|
|
}
|
|
|
|
result, err := r.cookieBanner.MoveTrackerPatternToCategory(ctx, scope, cookiebanner.MoveTrackerPatternToCategoryRequest{
|
|
TrackerPatternID: input.TrackerPatternID,
|
|
TargetCookieCategoryID: input.TargetCookieCategoryID,
|
|
})
|
|
if err != nil {
|
|
return nil, types.MoveTrackerPatternToCategoryOutput{}, fmt.Errorf("cannot move tracker pattern: %w", err)
|
|
}
|
|
|
|
return nil, types.MoveTrackerPatternToCategoryOutput{TrackerPattern: types.NewTrackerPattern(result.TrackerPattern)}, nil
|
|
}
|
|
|
|
func (r *Resolver) PublishCookieBannerVersionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishCookieBannerVersionInput) (*mcp.CallToolResult, types.PublishCookieBannerVersionOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerVersionPublish)
|
|
if err != nil {
|
|
return nil, types.PublishCookieBannerVersionOutput{}, err
|
|
}
|
|
|
|
version, err := r.cookieBanner.PublishCookieBannerVersion(ctx, scope, input.CookieBannerID)
|
|
if err != nil {
|
|
return nil, types.PublishCookieBannerVersionOutput{}, fmt.Errorf("cannot publish cookie banner version: %w", err)
|
|
}
|
|
|
|
return nil, types.PublishCookieBannerVersionOutput{CookieBannerVersion: types.NewCookieBannerVersion(version)}, nil
|
|
}
|
|
|
|
func (r *Resolver) RegenerateCookieBannerTrackerPolicyTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RegenerateCookieBannerTrackerPolicyInput) (*mcp.CallToolResult, types.RegenerateCookieBannerTrackerPolicyOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerRegeneratePolicy)
|
|
if err != nil {
|
|
return nil, types.RegenerateCookieBannerTrackerPolicyOutput{}, err
|
|
}
|
|
|
|
banner, err := r.cookieBanner.RegenerateTrackerPolicy(ctx, scope, input.CookieBannerID)
|
|
if err != nil {
|
|
return nil, types.RegenerateCookieBannerTrackerPolicyOutput{}, fmt.Errorf("cannot regenerate cookie banner tracker policy: %w", err)
|
|
}
|
|
|
|
return nil, types.RegenerateCookieBannerTrackerPolicyOutput{CookieBanner: types.NewCookieBanner(banner)}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListCookieBannerVersionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCookieBannerVersionsInput) (*mcp.CallToolResult, types.ListCookieBannerVersionsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerVersionList)
|
|
if err != nil {
|
|
return nil, types.ListCookieBannerVersionsOutput{}, err
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.CookieBannerVersionOrderField]{Field: coredata.CookieBannerVersionOrderFieldCreatedAt, Direction: page.OrderDirectionDesc})
|
|
|
|
versions, err := r.cookieBanner.ListCookieBannerVersionsForBanner(ctx, scope, input.CookieBannerID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list cookie banner versions: %w", err))
|
|
}
|
|
|
|
p := page.NewPage(versions, cursor)
|
|
|
|
return nil, types.NewListCookieBannerVersionsOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) UpsertCookieBannerTranslationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpsertCookieBannerTranslationInput) (*mcp.CallToolResult, types.UpsertCookieBannerTranslationOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerUpdate)
|
|
if err != nil {
|
|
return nil, types.UpsertCookieBannerTranslationOutput{}, err
|
|
}
|
|
|
|
translation, err := r.cookieBanner.UpsertCookieBannerTranslation(ctx, scope, cookiebanner.UpsertCookieBannerTranslationRequest{
|
|
CookieBannerID: input.CookieBannerID,
|
|
Language: input.Language,
|
|
Translations: json.RawMessage(input.Translations),
|
|
})
|
|
if err != nil {
|
|
return nil, types.UpsertCookieBannerTranslationOutput{}, fmt.Errorf("cannot upsert cookie banner translation: %w", err)
|
|
}
|
|
|
|
return nil, types.UpsertCookieBannerTranslationOutput{CookieBannerTranslation: types.NewCookieBannerTranslation(translation)}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListCookieConsentRecordsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCookieConsentRecordsInput) (*mcp.CallToolResult, types.ListCookieConsentRecordsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieConsentRecordList)
|
|
if err != nil {
|
|
return nil, types.ListCookieConsentRecordsOutput{}, err
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.CookieConsentRecordOrderField]{Field: coredata.CookieConsentRecordOrderFieldCreatedAt, Direction: page.OrderDirectionDesc})
|
|
|
|
var action *coredata.CookieConsentAction
|
|
|
|
if input.Action != nil {
|
|
a := coredata.CookieConsentAction(*input.Action)
|
|
action = &a
|
|
}
|
|
|
|
filter := coredata.NewCookieConsentRecordFilter(action, input.VisitorID, input.Version)
|
|
|
|
records, err := r.cookieBanner.ListCookieConsentRecordsForBanner(ctx, scope, input.CookieBannerID, cursor, filter)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list cookie consent records: %w", err))
|
|
}
|
|
|
|
p := page.NewPage(records, cursor)
|
|
|
|
return nil, types.NewListCookieConsentRecordsOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) GetCookieConsentRecordTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetCookieConsentRecordInput) (*mcp.CallToolResult, types.GetCookieConsentRecordOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieConsentRecordList)
|
|
if err != nil {
|
|
return nil, types.GetCookieConsentRecordOutput{}, err
|
|
}
|
|
|
|
record, err := r.cookieBanner.GetCookieConsentRecord(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetCookieConsentRecordOutput{}, fmt.Errorf("cannot get cookie consent record: %w", err)
|
|
}
|
|
|
|
return nil, types.GetCookieConsentRecordOutput{CookieConsentRecord: types.NewCookieConsentRecord(record)}, nil
|
|
}
|
|
|
|
func (r *Resolver) PublishRiskListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishRiskListInput) (*mcp.CallToolResult, types.PublishRiskListOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRiskPublish)
|
|
if err != nil {
|
|
return nil, types.PublishRiskListOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishRiskList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
|
|
if err != nil {
|
|
return nil, types.PublishRiskListOutput{}, fmt.Errorf("cannot publish risk list: %w", err)
|
|
}
|
|
|
|
return nil, types.PublishRiskListOutput{
|
|
DocumentID: document.ID,
|
|
DocumentVersionID: documentVersion.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) GetSCIMConfigurationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetSCIMConfigurationInput) (*mcp.CallToolResult, types.GetSCIMConfigurationOutput, error) {
|
|
if _, err := r.Authorize(ctx, input.OrganizationID, iam.ActionSCIMConfigurationGet); err != nil {
|
|
return nil, types.GetSCIMConfigurationOutput{}, err
|
|
}
|
|
|
|
config, err := r.iamSvc.OrganizationService.GetSCIMConfiguration(ctx, input.OrganizationID)
|
|
if err != nil {
|
|
if _, ok := errors.AsType[*iam.ErrNoSCIMConfigurationFound](err); ok {
|
|
return nil, types.GetSCIMConfigurationOutput{}, fmt.Errorf("SCIM configuration not found")
|
|
}
|
|
|
|
panic(fmt.Errorf("cannot get SCIM configuration: %w", err))
|
|
}
|
|
|
|
return nil, types.GetSCIMConfigurationOutput{ScimConfiguration: types.NewSCIMConfiguration(config)}, nil
|
|
}
|
|
|
|
func (r *Resolver) CreateSCIMConfigurationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateSCIMConfigurationInput) (*mcp.CallToolResult, types.CreateSCIMConfigurationOutput, error) {
|
|
if _, err := r.Authorize(ctx, input.OrganizationID, iam.ActionSCIMConfigurationCreate); err != nil {
|
|
return nil, types.CreateSCIMConfigurationOutput{}, err
|
|
}
|
|
|
|
config, token, err := r.iamSvc.OrganizationService.CreateSCIMConfiguration(ctx, input.OrganizationID)
|
|
if err != nil {
|
|
return nil, types.CreateSCIMConfigurationOutput{}, fmt.Errorf("cannot create SCIM configuration: %w", err)
|
|
}
|
|
|
|
output := types.CreateSCIMConfigurationOutput{
|
|
ScimConfiguration: types.NewSCIMConfiguration(config),
|
|
Token: token,
|
|
}
|
|
|
|
if input.ConnectorID != nil {
|
|
bridge, err := r.iamSvc.OrganizationService.CreateSCIMBridge(ctx, input.OrganizationID, config.ID, *input.ConnectorID)
|
|
if err != nil {
|
|
return nil, types.CreateSCIMConfigurationOutput{}, fmt.Errorf("cannot create SCIM bridge: %w", err)
|
|
}
|
|
|
|
output.ScimBridge = types.NewSCIMBridge(bridge)
|
|
}
|
|
|
|
return nil, output, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteSCIMConfigurationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteSCIMConfigurationInput) (*mcp.CallToolResult, types.DeleteSCIMConfigurationOutput, error) {
|
|
if _, err := r.Authorize(ctx, input.OrganizationID, iam.ActionSCIMConfigurationDelete); err != nil {
|
|
return nil, types.DeleteSCIMConfigurationOutput{}, err
|
|
}
|
|
|
|
err := r.iamSvc.OrganizationService.DeleteSCIMConfiguration(ctx, input.OrganizationID, input.ScimConfigurationID)
|
|
if err != nil {
|
|
return nil, types.DeleteSCIMConfigurationOutput{}, fmt.Errorf("cannot delete SCIM configuration: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteSCIMConfigurationOutput{DeletedScimConfigurationID: input.ScimConfigurationID}, nil
|
|
}
|
|
|
|
func (r *Resolver) RegenerateSCIMTokenTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RegenerateSCIMTokenInput) (*mcp.CallToolResult, types.RegenerateSCIMTokenOutput, error) {
|
|
if _, err := r.Authorize(ctx, input.ScimConfigurationID, iam.ActionSCIMConfigurationUpdate); err != nil {
|
|
return nil, types.RegenerateSCIMTokenOutput{}, err
|
|
}
|
|
|
|
config, token, err := r.iamSvc.OrganizationService.RegenerateSCIMToken(ctx, input.OrganizationID, input.ScimConfigurationID)
|
|
if err != nil {
|
|
return nil, types.RegenerateSCIMTokenOutput{}, fmt.Errorf("cannot regenerate SCIM token: %w", err)
|
|
}
|
|
|
|
return nil, types.RegenerateSCIMTokenOutput{
|
|
ScimConfiguration: types.NewSCIMConfiguration(config),
|
|
Token: token,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) GetSCIMBridgeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetSCIMBridgeInput) (*mcp.CallToolResult, types.GetSCIMBridgeOutput, error) {
|
|
if _, err := r.Authorize(ctx, input.ID, iam.ActionSCIMBridgeGet); err != nil {
|
|
return nil, types.GetSCIMBridgeOutput{}, err
|
|
}
|
|
|
|
bridge, err := r.iamSvc.OrganizationService.GetSCIMBridgeByID(ctx, input.ID)
|
|
if err != nil {
|
|
if _, ok := errors.AsType[*iam.ErrSCIMBridgeNotFound](err); ok {
|
|
return nil, types.GetSCIMBridgeOutput{}, fmt.Errorf("SCIM bridge %s not found", input.ID)
|
|
}
|
|
|
|
panic(fmt.Errorf("cannot get SCIM bridge: %w", err))
|
|
}
|
|
|
|
return nil, types.GetSCIMBridgeOutput{ScimBridge: types.NewSCIMBridge(bridge)}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateSCIMBridgeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateSCIMBridgeInput) (*mcp.CallToolResult, types.UpdateSCIMBridgeOutput, error) {
|
|
if _, err := r.Authorize(ctx, input.ScimBridgeID, iam.ActionSCIMBridgeUpdate); err != nil {
|
|
return nil, types.UpdateSCIMBridgeOutput{}, err
|
|
}
|
|
|
|
bridge, err := r.iamSvc.OrganizationService.UpdateSCIMBridge(ctx, input.OrganizationID, input.ScimBridgeID, input.ExcludedUserNames)
|
|
if err != nil {
|
|
return nil, types.UpdateSCIMBridgeOutput{}, fmt.Errorf("cannot update SCIM bridge: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateSCIMBridgeOutput{ScimBridge: types.NewSCIMBridge(bridge)}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListSCIMEventsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListSCIMEventsInput) (*mcp.CallToolResult, types.ListSCIMEventsOutput, error) {
|
|
if _, err := r.Authorize(ctx, input.ScimConfigurationID, iam.ActionSCIMEventList); err != nil {
|
|
return nil, types.ListSCIMEventsOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.SCIMEventOrderField]{
|
|
Field: coredata.SCIMEventOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.SCIMEventOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := r.iamSvc.OrganizationService.ListSCIMEventsByConfigID(ctx, input.ScimConfigurationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list SCIM events: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListSCIMEventsOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) PublishDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishDocumentInput) (*mcp.CallToolResult, types.PublishDocumentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.DocumentID, probo.ActionDocumentVersionPublish)
|
|
if err != nil {
|
|
return nil, types.PublishDocumentOutput{}, err
|
|
}
|
|
|
|
svc := r.proboSvc
|
|
|
|
result, err := svc.Documents.PublishVersionWithDefaultApprovers(ctx, scope, probo.PublishDocumentRequest{
|
|
DocumentID: input.DocumentID,
|
|
Minor: input.Minor,
|
|
Changelog: input.Changelog,
|
|
})
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot publish document: %w", err))
|
|
}
|
|
|
|
output := types.PublishDocumentOutput{
|
|
Document: types.NewDocument(result.Document),
|
|
DocumentVersion: types.NewDocumentVersion(result.Version),
|
|
}
|
|
|
|
if result.Quorum != nil {
|
|
output.ApprovalQuorum = types.NewDocumentVersionApprovalQuorum(result.Quorum)
|
|
}
|
|
|
|
return nil, output, nil
|
|
}
|
|
|
|
func (r *Resolver) ListTrackerResourcesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrackerResourcesInput) (*mcp.CallToolResult, types.ListTrackerResourcesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerResourceList)
|
|
if err != nil {
|
|
return nil, types.ListTrackerResourcesOutput{}, err
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.TrackerResourceOrderField]{Field: coredata.TrackerResourceOrderFieldCreatedAt, Direction: page.OrderDirectionAsc})
|
|
|
|
resources, err := r.cookieBanner.ListTrackerResourcesForCategory(ctx, scope, input.CookieCategoryID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list tracker resources: %w", err))
|
|
}
|
|
|
|
p := page.NewPage(resources, cursor)
|
|
|
|
return nil, types.NewListTrackerResourcesOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) GetTrackerResourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTrackerResourceInput) (*mcp.CallToolResult, types.GetTrackerResourceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerResourceGet)
|
|
if err != nil {
|
|
return nil, types.GetTrackerResourceOutput{}, err
|
|
}
|
|
|
|
resource, err := r.cookieBanner.GetTrackerResource(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetTrackerResourceOutput{}, fmt.Errorf("cannot get tracker resource: %w", err)
|
|
}
|
|
|
|
return nil, types.GetTrackerResourceOutput{TrackerResource: types.NewTrackerResource(resource)}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddTrackerResourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTrackerResourceInput) (*mcp.CallToolResult, types.AddTrackerResourceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerResourceCreate)
|
|
if err != nil {
|
|
return nil, types.AddTrackerResourceOutput{}, err
|
|
}
|
|
|
|
description := ""
|
|
if input.Description != nil {
|
|
description = *input.Description
|
|
}
|
|
|
|
resource, err := r.cookieBanner.CreateTrackerResource(ctx, scope, cookiebanner.CreateTrackerResourceRequest{
|
|
CookieCategoryID: input.CookieCategoryID,
|
|
ResourceType: coredata.TrackerResourceType(input.ResourceType),
|
|
Origin: input.Origin,
|
|
Path: input.Path,
|
|
DisplayName: input.DisplayName,
|
|
Description: description,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddTrackerResourceOutput{}, fmt.Errorf("cannot create tracker resource: %w", err)
|
|
}
|
|
|
|
return nil, types.AddTrackerResourceOutput{TrackerResource: types.NewTrackerResource(resource)}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateTrackerResourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrackerResourceInput) (*mcp.CallToolResult, types.UpdateTrackerResourceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerResourceUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateTrackerResourceOutput{}, err
|
|
}
|
|
|
|
updateReq := cookiebanner.UpdateTrackerResourceRequest{TrackerResourceID: input.ID}
|
|
if v := UnwrapOmittable(input.DisplayName); v != nil && *v != nil {
|
|
updateReq.DisplayName = *v
|
|
}
|
|
|
|
if v := UnwrapOmittable(input.Description); v != nil && *v != nil {
|
|
updateReq.Description = *v
|
|
}
|
|
|
|
if v := UnwrapOmittable(input.Excluded); v != nil && *v != nil {
|
|
updateReq.Excluded = *v
|
|
}
|
|
|
|
resource, err := r.cookieBanner.UpdateTrackerResource(ctx, scope, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateTrackerResourceOutput{}, fmt.Errorf("cannot update tracker resource: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateTrackerResourceOutput{TrackerResource: types.NewTrackerResource(resource)}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteTrackerResourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTrackerResourceInput) (*mcp.CallToolResult, types.DeleteTrackerResourceOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerResourceDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteTrackerResourceOutput{}, err
|
|
}
|
|
|
|
if err := r.cookieBanner.DeleteTrackerResource(ctx, scope, input.ID); err != nil {
|
|
return nil, types.DeleteTrackerResourceOutput{}, fmt.Errorf("cannot delete tracker resource: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteTrackerResourceOutput{DeletedID: input.ID}, nil
|
|
}
|
|
|
|
func (r *Resolver) MoveTrackerResourceToCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.MoveTrackerResourceToCategoryInput) (*mcp.CallToolResult, types.MoveTrackerResourceToCategoryOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.TrackerResourceID, probo.ActionTrackerResourceUpdate)
|
|
if err != nil {
|
|
return nil, types.MoveTrackerResourceToCategoryOutput{}, err
|
|
}
|
|
|
|
if _, err := r.Authorize(ctx, input.TargetCookieCategoryID, probo.ActionCookieCategoryUpdate); err != nil {
|
|
return nil, types.MoveTrackerResourceToCategoryOutput{}, err
|
|
}
|
|
|
|
result, err := r.cookieBanner.MoveTrackerResourceToCategory(ctx, scope, cookiebanner.MoveTrackerResourceToCategoryRequest{
|
|
TrackerResourceID: input.TrackerResourceID,
|
|
TargetCookieCategoryID: input.TargetCookieCategoryID,
|
|
})
|
|
if err != nil {
|
|
return nil, types.MoveTrackerResourceToCategoryOutput{}, fmt.Errorf("cannot move tracker resource: %w", err)
|
|
}
|
|
|
|
return nil, types.MoveTrackerResourceToCategoryOutput{TrackerResource: types.NewTrackerResource(result.TrackerResource)}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListChildThirdPartiesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListChildThirdPartiesInput) (*mcp.CallToolResult, types.ListChildThirdPartiesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ParentThirdPartyID, probo.ActionThirdPartyRelationList)
|
|
if err != nil {
|
|
return nil, types.ListChildThirdPartiesOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.ThirdPartyOrderField]{
|
|
Field: coredata.ThirdPartyOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.ThirdPartyOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
page, err := r.proboSvc.ThirdParties.ListForParentThirdPartyID(ctx, scope, input.ParentThirdPartyID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list child third parties: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListChildThirdPartiesOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) ListRiskAssessmentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentsInput) (*mcp.CallToolResult, types.ListRiskAssessmentsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRiskAssessmentList)
|
|
if err != nil {
|
|
return nil, types.ListRiskAssessmentsOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.RiskAssessmentOrderField]{
|
|
Field: coredata.RiskAssessmentOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.RiskAssessmentOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := r.riskManagement.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list risk assessments: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListRiskAssessmentsOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) GetRiskAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentInput) (*mcp.CallToolResult, types.GetRiskAssessmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentGet)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentOutput{}, err
|
|
}
|
|
|
|
ra, err := r.riskManagement.Get(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentOutput{}, fmt.Errorf("failed to get risk assessment: %w", err)
|
|
}
|
|
|
|
return nil, types.GetRiskAssessmentOutput{
|
|
RiskAssessment: types.NewRiskAssessment(ra),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddRiskAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskAssessmentInput) (*mcp.CallToolResult, types.AddRiskAssessmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRiskAssessmentCreate)
|
|
if err != nil {
|
|
return nil, types.AddRiskAssessmentOutput{}, err
|
|
}
|
|
|
|
ra, err := r.riskManagement.Create(ctx, scope, riskmanagement.CreateRiskAssessmentRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
Description: input.Description,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddRiskAssessmentOutput{}, fmt.Errorf("failed to create risk assessment: %w", err)
|
|
}
|
|
|
|
return nil, types.AddRiskAssessmentOutput{
|
|
RiskAssessment: types.NewRiskAssessment(ra),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateRiskAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskAssessmentInput) (*mcp.CallToolResult, types.UpdateRiskAssessmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateRiskAssessmentOutput{}, err
|
|
}
|
|
|
|
ra, err := r.riskManagement.Update(ctx, scope, riskmanagement.UpdateRiskAssessmentRequest{
|
|
ID: input.ID,
|
|
Name: input.Name,
|
|
Description: UnwrapOmittable(input.Description),
|
|
})
|
|
if err != nil {
|
|
return nil, types.UpdateRiskAssessmentOutput{}, fmt.Errorf("failed to update risk assessment: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateRiskAssessmentOutput{
|
|
RiskAssessment: types.NewRiskAssessment(ra),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteRiskAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskAssessmentInput) (*mcp.CallToolResult, types.DeleteRiskAssessmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteRiskAssessmentOutput{}, err
|
|
}
|
|
|
|
if err := r.riskManagement.Delete(ctx, scope, input.ID); err != nil {
|
|
return nil, types.DeleteRiskAssessmentOutput{}, fmt.Errorf("failed to delete risk assessment: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteRiskAssessmentOutput{
|
|
DeletedRiskAssessmentID: input.ID,
|
|
}, nil
|
|
}
|
|
func (r *Resolver) ListRiskAssessmentScopesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentScopesInput) (*mcp.CallToolResult, types.ListRiskAssessmentScopesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentID, probo.ActionRiskAssessmentScopeList)
|
|
if err != nil {
|
|
return nil, types.ListRiskAssessmentScopesOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.RiskAssessmentScopeOrderField]{
|
|
Field: coredata.RiskAssessmentScopeOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.RiskAssessmentScopeOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := r.riskManagement.ListScopesForRiskAssessmentID(ctx, scope, input.RiskAssessmentID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list risk assessment scopes: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListRiskAssessmentScopesOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) GetRiskAssessmentScopeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentScopeInput) (*mcp.CallToolResult, types.GetRiskAssessmentScopeOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentScopeGet)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentScopeOutput{}, err
|
|
}
|
|
|
|
s, err := r.riskManagement.GetScope(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentScopeOutput{}, fmt.Errorf("failed to get risk assessment scope: %w", err)
|
|
}
|
|
|
|
return nil, types.GetRiskAssessmentScopeOutput{
|
|
RiskAssessmentScope: types.NewRiskAssessmentScope(s),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddRiskAssessmentScopeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskAssessmentScopeInput) (*mcp.CallToolResult, types.AddRiskAssessmentScopeOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentID, probo.ActionRiskAssessmentScopeCreate)
|
|
if err != nil {
|
|
return nil, types.AddRiskAssessmentScopeOutput{}, err
|
|
}
|
|
|
|
s, err := r.riskManagement.CreateScope(ctx, scope, riskmanagement.CreateRiskAssessmentScopeRequest{
|
|
RiskAssessmentID: input.RiskAssessmentID,
|
|
Name: input.Name,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddRiskAssessmentScopeOutput{}, fmt.Errorf("failed to create risk assessment scope: %w", err)
|
|
}
|
|
|
|
return nil, types.AddRiskAssessmentScopeOutput{
|
|
RiskAssessmentScope: types.NewRiskAssessmentScope(s),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateRiskAssessmentScopeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskAssessmentScopeInput) (*mcp.CallToolResult, types.UpdateRiskAssessmentScopeOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentScopeUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateRiskAssessmentScopeOutput{}, err
|
|
}
|
|
|
|
s, err := r.riskManagement.UpdateScope(ctx, scope, riskmanagement.UpdateRiskAssessmentScopeRequest{
|
|
ID: input.ID,
|
|
Name: input.Name,
|
|
})
|
|
if err != nil {
|
|
return nil, types.UpdateRiskAssessmentScopeOutput{}, fmt.Errorf("failed to update risk assessment scope: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateRiskAssessmentScopeOutput{
|
|
RiskAssessmentScope: types.NewRiskAssessmentScope(s),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteRiskAssessmentScopeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskAssessmentScopeInput) (*mcp.CallToolResult, types.DeleteRiskAssessmentScopeOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentScopeDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteRiskAssessmentScopeOutput{}, err
|
|
}
|
|
|
|
if err := r.riskManagement.DeleteScope(ctx, scope, input.ID); err != nil {
|
|
return nil, types.DeleteRiskAssessmentScopeOutput{}, fmt.Errorf("failed to delete risk assessment scope: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteRiskAssessmentScopeOutput{
|
|
DeletedRiskAssessmentScopeID: input.ID,
|
|
}, nil
|
|
}
|
|
func (r *Resolver) ListRiskAssessmentNodesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentNodesInput) (*mcp.CallToolResult, types.ListRiskAssessmentNodesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentNodeList)
|
|
if err != nil {
|
|
return nil, types.ListRiskAssessmentNodesOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.RiskAssessmentNodeOrderField]{
|
|
Field: coredata.RiskAssessmentNodeOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.RiskAssessmentNodeOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := r.riskManagement.ListNodesForScopeID(ctx, scope, input.RiskAssessmentScopeID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list risk assessment nodes: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListRiskAssessmentNodesOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) GetRiskAssessmentNodeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentNodeInput) (*mcp.CallToolResult, types.GetRiskAssessmentNodeOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentNodeGet)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentNodeOutput{}, err
|
|
}
|
|
|
|
n, err := r.riskManagement.GetNode(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentNodeOutput{}, fmt.Errorf("failed to get risk assessment node: %w", err)
|
|
}
|
|
|
|
return nil, types.GetRiskAssessmentNodeOutput{
|
|
RiskAssessmentNode: types.NewRiskAssessmentNode(n),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddRiskAssessmentNodeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskAssessmentNodeInput) (*mcp.CallToolResult, types.AddRiskAssessmentNodeOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentNodeCreate)
|
|
if err != nil {
|
|
return nil, types.AddRiskAssessmentNodeOutput{}, err
|
|
}
|
|
|
|
n, err := r.riskManagement.CreateNode(ctx, scope, riskmanagement.CreateRiskAssessmentNodeRequest{
|
|
RiskAssessmentScopeID: input.RiskAssessmentScopeID,
|
|
BoundaryID: input.BoundaryID,
|
|
NodeType: input.NodeType,
|
|
Name: input.Name,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddRiskAssessmentNodeOutput{}, fmt.Errorf("failed to create risk assessment node: %w", err)
|
|
}
|
|
|
|
return nil, types.AddRiskAssessmentNodeOutput{
|
|
RiskAssessmentNode: types.NewRiskAssessmentNode(n),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateRiskAssessmentNodeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskAssessmentNodeInput) (*mcp.CallToolResult, types.UpdateRiskAssessmentNodeOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentNodeUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateRiskAssessmentNodeOutput{}, err
|
|
}
|
|
|
|
var boundaryID **gid.GID
|
|
if input.BoundaryID != nil {
|
|
boundaryID = &input.BoundaryID
|
|
}
|
|
|
|
n, err := r.riskManagement.UpdateNode(ctx, scope, riskmanagement.UpdateRiskAssessmentNodeRequest{
|
|
ID: input.ID,
|
|
BoundaryID: boundaryID,
|
|
NodeType: input.NodeType,
|
|
Name: input.Name,
|
|
})
|
|
if err != nil {
|
|
return nil, types.UpdateRiskAssessmentNodeOutput{}, fmt.Errorf("failed to update risk assessment node: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateRiskAssessmentNodeOutput{
|
|
RiskAssessmentNode: types.NewRiskAssessmentNode(n),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteRiskAssessmentNodeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskAssessmentNodeInput) (*mcp.CallToolResult, types.DeleteRiskAssessmentNodeOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentNodeDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteRiskAssessmentNodeOutput{}, err
|
|
}
|
|
|
|
if err := r.riskManagement.DeleteNode(ctx, scope, input.ID); err != nil {
|
|
return nil, types.DeleteRiskAssessmentNodeOutput{}, fmt.Errorf("failed to delete risk assessment node: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteRiskAssessmentNodeOutput{
|
|
DeletedRiskAssessmentNodeID: input.ID,
|
|
}, nil
|
|
}
|
|
func (r *Resolver) ListRiskAssessmentProcessesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentProcessesInput) (*mcp.CallToolResult, types.ListRiskAssessmentProcessesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentProcessList)
|
|
if err != nil {
|
|
return nil, types.ListRiskAssessmentProcessesOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.RiskAssessmentProcessOrderField]{
|
|
Field: coredata.RiskAssessmentProcessOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.RiskAssessmentProcessOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := r.riskManagement.ListProcessesForScopeID(ctx, scope, input.RiskAssessmentScopeID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list risk assessment processes: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListRiskAssessmentProcessesOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) GetRiskAssessmentProcessTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentProcessInput) (*mcp.CallToolResult, types.GetRiskAssessmentProcessOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentProcessGet)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentProcessOutput{}, err
|
|
}
|
|
|
|
p, err := r.riskManagement.GetProcess(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentProcessOutput{}, fmt.Errorf("failed to get risk assessment process: %w", err)
|
|
}
|
|
|
|
return nil, types.GetRiskAssessmentProcessOutput{
|
|
RiskAssessmentProcess: types.NewRiskAssessmentProcess(p),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddRiskAssessmentProcessTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskAssessmentProcessInput) (*mcp.CallToolResult, types.AddRiskAssessmentProcessOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentProcessCreate)
|
|
if err != nil {
|
|
return nil, types.AddRiskAssessmentProcessOutput{}, err
|
|
}
|
|
|
|
p, err := r.riskManagement.CreateProcess(ctx, scope, riskmanagement.CreateRiskAssessmentProcessRequest{
|
|
RiskAssessmentScopeID: input.RiskAssessmentScopeID,
|
|
SourceNodeID: input.SourceNodeID,
|
|
TargetNodeID: input.TargetNodeID,
|
|
Name: input.Name,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddRiskAssessmentProcessOutput{}, fmt.Errorf("failed to create risk assessment process: %w", err)
|
|
}
|
|
|
|
return nil, types.AddRiskAssessmentProcessOutput{
|
|
RiskAssessmentProcess: types.NewRiskAssessmentProcess(p),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateRiskAssessmentProcessTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskAssessmentProcessInput) (*mcp.CallToolResult, types.UpdateRiskAssessmentProcessOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentProcessUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateRiskAssessmentProcessOutput{}, err
|
|
}
|
|
|
|
p, err := r.riskManagement.UpdateProcess(ctx, scope, riskmanagement.UpdateRiskAssessmentProcessRequest{
|
|
ID: input.ID,
|
|
SourceNodeID: input.SourceNodeID,
|
|
TargetNodeID: input.TargetNodeID,
|
|
Name: input.Name,
|
|
})
|
|
if err != nil {
|
|
return nil, types.UpdateRiskAssessmentProcessOutput{}, fmt.Errorf("failed to update risk assessment process: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateRiskAssessmentProcessOutput{
|
|
RiskAssessmentProcess: types.NewRiskAssessmentProcess(p),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteRiskAssessmentProcessTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskAssessmentProcessInput) (*mcp.CallToolResult, types.DeleteRiskAssessmentProcessOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentProcessDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteRiskAssessmentProcessOutput{}, err
|
|
}
|
|
|
|
if err := r.riskManagement.DeleteProcess(ctx, scope, input.ID); err != nil {
|
|
return nil, types.DeleteRiskAssessmentProcessOutput{}, fmt.Errorf("failed to delete risk assessment process: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteRiskAssessmentProcessOutput{
|
|
DeletedRiskAssessmentProcessID: input.ID,
|
|
}, nil
|
|
}
|
|
func (r *Resolver) ListRiskAssessmentThreatsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentThreatsInput) (*mcp.CallToolResult, types.ListRiskAssessmentThreatsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentThreatList)
|
|
if err != nil {
|
|
return nil, types.ListRiskAssessmentThreatsOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.RiskAssessmentThreatOrderField]{
|
|
Field: coredata.RiskAssessmentThreatOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.RiskAssessmentThreatOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := r.riskManagement.ListThreatsForScopeID(ctx, scope, input.RiskAssessmentScopeID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list risk assessment threats: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListRiskAssessmentThreatsOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) GetRiskAssessmentThreatTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentThreatInput) (*mcp.CallToolResult, types.GetRiskAssessmentThreatOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentThreatGet)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentThreatOutput{}, err
|
|
}
|
|
|
|
t, err := r.riskManagement.GetThreat(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentThreatOutput{}, fmt.Errorf("failed to get risk assessment threat: %w", err)
|
|
}
|
|
|
|
return nil, types.GetRiskAssessmentThreatOutput{
|
|
RiskAssessmentThreat: types.NewRiskAssessmentThreat(t),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddRiskAssessmentThreatTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskAssessmentThreatInput) (*mcp.CallToolResult, types.AddRiskAssessmentThreatOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentThreatCreate)
|
|
if err != nil {
|
|
return nil, types.AddRiskAssessmentThreatOutput{}, err
|
|
}
|
|
|
|
t, err := r.riskManagement.CreateThreat(ctx, scope, riskmanagement.CreateRiskAssessmentThreatRequest{
|
|
RiskAssessmentScopeID: input.RiskAssessmentScopeID,
|
|
ProcessID: input.ProcessID,
|
|
Name: input.Name,
|
|
Category: input.Category,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddRiskAssessmentThreatOutput{}, fmt.Errorf("failed to create risk assessment threat: %w", err)
|
|
}
|
|
|
|
return nil, types.AddRiskAssessmentThreatOutput{
|
|
RiskAssessmentThreat: types.NewRiskAssessmentThreat(t),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateRiskAssessmentThreatTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskAssessmentThreatInput) (*mcp.CallToolResult, types.UpdateRiskAssessmentThreatOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentThreatUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateRiskAssessmentThreatOutput{}, err
|
|
}
|
|
|
|
t, err := r.riskManagement.UpdateThreat(ctx, scope, riskmanagement.UpdateRiskAssessmentThreatRequest{
|
|
ID: input.ID,
|
|
ProcessID: input.ProcessID,
|
|
Name: input.Name,
|
|
Category: input.Category,
|
|
})
|
|
if err != nil {
|
|
return nil, types.UpdateRiskAssessmentThreatOutput{}, fmt.Errorf("failed to update risk assessment threat: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateRiskAssessmentThreatOutput{
|
|
RiskAssessmentThreat: types.NewRiskAssessmentThreat(t),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteRiskAssessmentThreatTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskAssessmentThreatInput) (*mcp.CallToolResult, types.DeleteRiskAssessmentThreatOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentThreatDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteRiskAssessmentThreatOutput{}, err
|
|
}
|
|
|
|
if err := r.riskManagement.DeleteThreat(ctx, scope, input.ID); err != nil {
|
|
return nil, types.DeleteRiskAssessmentThreatOutput{}, fmt.Errorf("failed to delete risk assessment threat: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteRiskAssessmentThreatOutput{
|
|
DeletedRiskAssessmentThreatID: input.ID,
|
|
}, nil
|
|
}
|
|
func (r *Resolver) ListRiskAssessmentScenariosTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentScenariosInput) (*mcp.CallToolResult, types.ListRiskAssessmentScenariosOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentScenarioList)
|
|
if err != nil {
|
|
return nil, types.ListRiskAssessmentScenariosOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.RiskAssessmentScenarioOrderField]{
|
|
Field: coredata.RiskAssessmentScenarioOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.RiskAssessmentScenarioOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := r.riskManagement.ListScenariosForScopeID(ctx, scope, input.RiskAssessmentScopeID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list risk assessment scenarios: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListRiskAssessmentScenariosOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) GetRiskAssessmentScenarioTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentScenarioInput) (*mcp.CallToolResult, types.GetRiskAssessmentScenarioOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentScenarioGet)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentScenarioOutput{}, err
|
|
}
|
|
|
|
s, err := r.riskManagement.GetScenario(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentScenarioOutput{}, fmt.Errorf("failed to get risk assessment scenario: %w", err)
|
|
}
|
|
|
|
return nil, types.GetRiskAssessmentScenarioOutput{
|
|
RiskAssessmentScenario: types.NewRiskAssessmentScenario(s),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddRiskAssessmentScenarioTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskAssessmentScenarioInput) (*mcp.CallToolResult, types.AddRiskAssessmentScenarioOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentScenarioCreate)
|
|
if err != nil {
|
|
return nil, types.AddRiskAssessmentScenarioOutput{}, err
|
|
}
|
|
|
|
s, err := r.riskManagement.CreateScenario(ctx, scope, riskmanagement.CreateRiskAssessmentScenarioRequest{
|
|
RiskAssessmentScopeID: input.RiskAssessmentScopeID,
|
|
Name: input.Name,
|
|
Description: input.Description,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddRiskAssessmentScenarioOutput{}, fmt.Errorf("failed to create risk assessment scenario: %w", err)
|
|
}
|
|
|
|
return nil, types.AddRiskAssessmentScenarioOutput{
|
|
RiskAssessmentScenario: types.NewRiskAssessmentScenario(s),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateRiskAssessmentScenarioTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskAssessmentScenarioInput) (*mcp.CallToolResult, types.UpdateRiskAssessmentScenarioOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentScenarioUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateRiskAssessmentScenarioOutput{}, err
|
|
}
|
|
|
|
s, err := r.riskManagement.UpdateScenario(ctx, scope, riskmanagement.UpdateRiskAssessmentScenarioRequest{
|
|
ID: input.ID,
|
|
Name: input.Name,
|
|
Description: UnwrapOmittable(input.Description),
|
|
})
|
|
if err != nil {
|
|
return nil, types.UpdateRiskAssessmentScenarioOutput{}, fmt.Errorf("failed to update risk assessment scenario: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateRiskAssessmentScenarioOutput{
|
|
RiskAssessmentScenario: types.NewRiskAssessmentScenario(s),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteRiskAssessmentScenarioTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskAssessmentScenarioInput) (*mcp.CallToolResult, types.DeleteRiskAssessmentScenarioOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentScenarioDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteRiskAssessmentScenarioOutput{}, err
|
|
}
|
|
|
|
if err := r.riskManagement.DeleteScenario(ctx, scope, input.ID); err != nil {
|
|
return nil, types.DeleteRiskAssessmentScenarioOutput{}, fmt.Errorf("failed to delete risk assessment scenario: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteRiskAssessmentScenarioOutput{
|
|
DeletedRiskAssessmentScenarioID: input.ID,
|
|
}, nil
|
|
}
|
|
func (r *Resolver) LinkRiskAssessmentScenarioThreatTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkRiskAssessmentScenarioThreatInput) (*mcp.CallToolResult, types.LinkRiskAssessmentScenarioThreatOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentScenarioID, probo.ActionRiskAssessmentScenarioThreatLink)
|
|
if err != nil {
|
|
return nil, types.LinkRiskAssessmentScenarioThreatOutput{}, err
|
|
}
|
|
|
|
err = r.riskManagement.LinkScenarioThreat(ctx, scope, riskmanagement.LinkRiskAssessmentScenarioThreatRequest{
|
|
RiskAssessmentScenarioID: input.RiskAssessmentScenarioID,
|
|
ThreatID: input.ThreatID,
|
|
})
|
|
if err != nil {
|
|
return nil, types.LinkRiskAssessmentScenarioThreatOutput{}, fmt.Errorf("failed to link scenario threat: %w", err)
|
|
}
|
|
|
|
return nil, types.LinkRiskAssessmentScenarioThreatOutput{}, nil
|
|
}
|
|
|
|
func (r *Resolver) UnlinkRiskAssessmentScenarioThreatTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkRiskAssessmentScenarioThreatInput) (*mcp.CallToolResult, types.UnlinkRiskAssessmentScenarioThreatOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentScenarioID, probo.ActionRiskAssessmentScenarioThreatUnlink)
|
|
if err != nil {
|
|
return nil, types.UnlinkRiskAssessmentScenarioThreatOutput{}, err
|
|
}
|
|
|
|
if err := r.riskManagement.UnlinkScenarioThreat(
|
|
ctx,
|
|
scope,
|
|
riskmanagement.UnlinkRiskAssessmentScenarioThreatRequest{
|
|
RiskAssessmentScenarioID: input.RiskAssessmentScenarioID,
|
|
ThreatID: input.ThreatID,
|
|
},
|
|
); err != nil {
|
|
return nil, types.UnlinkRiskAssessmentScenarioThreatOutput{}, fmt.Errorf("failed to unlink scenario threat: %w", err)
|
|
}
|
|
|
|
return nil, types.UnlinkRiskAssessmentScenarioThreatOutput{}, nil
|
|
}
|
|
|
|
func (r *Resolver) LinkRiskAssessmentScenarioRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkRiskAssessmentScenarioRiskInput) (*mcp.CallToolResult, types.LinkRiskAssessmentScenarioRiskOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentScenarioID, probo.ActionRiskAssessmentScenarioRiskLink)
|
|
if err != nil {
|
|
return nil, types.LinkRiskAssessmentScenarioRiskOutput{}, err
|
|
}
|
|
|
|
if err := r.riskManagement.LinkScenarioRisk(
|
|
ctx,
|
|
scope,
|
|
riskmanagement.LinkRiskAssessmentScenarioRiskRequest{
|
|
RiskAssessmentScenarioID: input.RiskAssessmentScenarioID,
|
|
RiskID: input.RiskID,
|
|
},
|
|
); err != nil {
|
|
return nil, types.LinkRiskAssessmentScenarioRiskOutput{}, fmt.Errorf("failed to link scenario risk: %w", err)
|
|
}
|
|
|
|
return nil, types.LinkRiskAssessmentScenarioRiskOutput{}, nil
|
|
}
|
|
|
|
func (r *Resolver) UnlinkRiskAssessmentScenarioRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkRiskAssessmentScenarioRiskInput) (*mcp.CallToolResult, types.UnlinkRiskAssessmentScenarioRiskOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentScenarioID, probo.ActionRiskAssessmentScenarioRiskUnlink)
|
|
if err != nil {
|
|
return nil, types.UnlinkRiskAssessmentScenarioRiskOutput{}, err
|
|
}
|
|
|
|
if err := r.riskManagement.UnlinkScenarioRisk(
|
|
ctx,
|
|
scope,
|
|
riskmanagement.UnlinkRiskAssessmentScenarioRiskRequest{
|
|
RiskAssessmentScenarioID: input.RiskAssessmentScenarioID,
|
|
RiskID: input.RiskID,
|
|
},
|
|
); err != nil {
|
|
return nil, types.UnlinkRiskAssessmentScenarioRiskOutput{}, fmt.Errorf("failed to unlink scenario risk: %w", err)
|
|
}
|
|
|
|
return nil, types.UnlinkRiskAssessmentScenarioRiskOutput{}, nil
|
|
}
|
|
|
|
func (r *Resolver) GetRiskAssessmentScopeMermaidChartTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentScopeMermaidChartInput) (*mcp.CallToolResult, types.GetRiskAssessmentScopeMermaidChartOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentScopeGet)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentScopeMermaidChartOutput{}, err
|
|
}
|
|
|
|
chart, err := r.riskManagement.BuildScopeMermaidChart(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentScopeMermaidChartOutput{}, fmt.Errorf("failed to build mermaid chart: %w", err)
|
|
}
|
|
|
|
return nil, types.GetRiskAssessmentScopeMermaidChartOutput{
|
|
MermaidChart: chart,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListRiskAssessmentBoundariesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentBoundariesInput) (*mcp.CallToolResult, types.ListRiskAssessmentBoundariesOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentBoundaryList)
|
|
if err != nil {
|
|
return nil, types.ListRiskAssessmentBoundariesOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.RiskAssessmentBoundaryOrderField]{
|
|
Field: coredata.RiskAssessmentBoundaryOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.RiskAssessmentBoundaryOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := r.riskManagement.ListBoundariesForScopeID(ctx, scope, input.RiskAssessmentScopeID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list risk assessment boundaries: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListRiskAssessmentBoundariesOutput(p), nil
|
|
}
|
|
|
|
func (r *Resolver) GetRiskAssessmentBoundaryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentBoundaryInput) (*mcp.CallToolResult, types.GetRiskAssessmentBoundaryOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentBoundaryGet)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentBoundaryOutput{}, err
|
|
}
|
|
|
|
b, err := r.riskManagement.GetBoundary(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetRiskAssessmentBoundaryOutput{}, fmt.Errorf("failed to get risk assessment boundary: %w", err)
|
|
}
|
|
|
|
return nil, types.GetRiskAssessmentBoundaryOutput{
|
|
RiskAssessmentBoundary: types.NewRiskAssessmentBoundary(b),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddRiskAssessmentBoundaryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskAssessmentBoundaryInput) (*mcp.CallToolResult, types.AddRiskAssessmentBoundaryOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentBoundaryCreate)
|
|
if err != nil {
|
|
return nil, types.AddRiskAssessmentBoundaryOutput{}, err
|
|
}
|
|
|
|
b, err := r.riskManagement.CreateBoundary(ctx, scope, riskmanagement.CreateRiskAssessmentBoundaryRequest{
|
|
RiskAssessmentScopeID: input.RiskAssessmentScopeID,
|
|
ParentBoundaryID: input.ParentBoundaryID,
|
|
Name: input.Name,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddRiskAssessmentBoundaryOutput{}, fmt.Errorf("failed to create risk assessment boundary: %w", err)
|
|
}
|
|
|
|
return nil, types.AddRiskAssessmentBoundaryOutput{
|
|
RiskAssessmentBoundary: types.NewRiskAssessmentBoundary(b),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) UpdateRiskAssessmentBoundaryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskAssessmentBoundaryInput) (*mcp.CallToolResult, types.UpdateRiskAssessmentBoundaryOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentBoundaryUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateRiskAssessmentBoundaryOutput{}, err
|
|
}
|
|
|
|
var parentBoundaryID **gid.GID
|
|
if input.ParentBoundaryID != nil {
|
|
parentBoundaryID = &input.ParentBoundaryID
|
|
}
|
|
|
|
b, err := r.riskManagement.UpdateBoundary(ctx, scope, riskmanagement.UpdateRiskAssessmentBoundaryRequest{
|
|
ID: input.ID,
|
|
ParentBoundaryID: parentBoundaryID,
|
|
Name: input.Name,
|
|
})
|
|
if err != nil {
|
|
return nil, types.UpdateRiskAssessmentBoundaryOutput{}, fmt.Errorf("failed to update risk assessment boundary: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateRiskAssessmentBoundaryOutput{
|
|
RiskAssessmentBoundary: types.NewRiskAssessmentBoundary(b),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteRiskAssessmentBoundaryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskAssessmentBoundaryInput) (*mcp.CallToolResult, types.DeleteRiskAssessmentBoundaryOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentBoundaryDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteRiskAssessmentBoundaryOutput{}, err
|
|
}
|
|
|
|
if err := r.riskManagement.DeleteBoundary(ctx, scope, input.ID); err != nil {
|
|
return nil, types.DeleteRiskAssessmentBoundaryOutput{}, fmt.Errorf("failed to delete risk assessment boundary: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteRiskAssessmentBoundaryOutput{
|
|
DeletedRiskAssessmentBoundaryID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) SetResourceAliasTool(ctx context.Context, req *mcp.CallToolRequest, input *types.SetResourceAliasInput) (*mcp.CallToolResult, types.SetResourceAliasOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ResourceID, resourcealias.ActionAliasSet)
|
|
if err != nil {
|
|
return nil, types.SetResourceAliasOutput{}, err
|
|
}
|
|
|
|
alias, err := r.resourceAlias.Create(
|
|
ctx,
|
|
scope,
|
|
resourcealias.CreateRequest{
|
|
ResourceID: input.ResourceID,
|
|
Alias: input.Alias,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.SetResourceAliasOutput{}, fmt.Errorf("cannot set resource alias: %w", err)
|
|
}
|
|
|
|
return nil, types.SetResourceAliasOutput{
|
|
ResourceAlias: types.NewResourceAlias(input.ResourceID, alias),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) RemoveResourceAliasTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RemoveResourceAliasInput) (*mcp.CallToolResult, types.RemoveResourceAliasOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ResourceID, resourcealias.ActionAliasRemove)
|
|
if err != nil {
|
|
return nil, types.RemoveResourceAliasOutput{}, err
|
|
}
|
|
|
|
err = r.resourceAlias.Remove(ctx, scope, input.ResourceID)
|
|
if err != nil {
|
|
return nil, types.RemoveResourceAliasOutput{}, fmt.Errorf("cannot remove resource alias: %w", err)
|
|
}
|
|
|
|
return nil, types.RemoveResourceAliasOutput{
|
|
DeletedResourceID: input.ResourceID,
|
|
}, nil
|
|
}
|
|
|
|
// ListCommitmentGroupsTool handles the listCommitmentGroups tool
|
|
// List all commitment groups for a trust center
|
|
func (r *Resolver) ListCommitmentGroupsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCommitmentGroupsInput) (*mcp.CallToolResult, types.ListCommitmentGroupsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.TrustCenterID, management.ActionCompliancePortalCommitmentGroupList)
|
|
if err != nil {
|
|
return nil, types.ListCommitmentGroupsOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.CompliancePortalCommitmentGroupOrderField]{
|
|
Field: coredata.CompliancePortalCommitmentGroupOrderFieldRank,
|
|
Direction: page.OrderDirectionAsc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.CompliancePortalCommitmentGroupOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := r.management.ListCommitmentGroups(ctx, scope, input.TrustCenterID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListCommitmentGroupsOutput{}, fmt.Errorf("cannot list commitment groups: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListCommitmentGroupsOutput(p), nil
|
|
}
|
|
|
|
// AddCommitmentGroupTool handles the addCommitmentGroup tool
|
|
// Add a new commitment group to a trust center
|
|
func (r *Resolver) AddCommitmentGroupTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddCommitmentGroupInput) (*mcp.CallToolResult, types.AddCommitmentGroupOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.TrustCenterID, management.ActionCompliancePortalCommitmentGroupCreate)
|
|
if err != nil {
|
|
return nil, types.AddCommitmentGroupOutput{}, err
|
|
}
|
|
|
|
group, err := r.management.CreateCommitmentGroup(
|
|
ctx, scope,
|
|
&management.CreateCompliancePortalCommitmentGroupRequest{
|
|
CompliancePortalID: input.TrustCenterID,
|
|
Title: input.Title,
|
|
Description: input.Description,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddCommitmentGroupOutput{}, fmt.Errorf("cannot add commitment group: %w", err)
|
|
}
|
|
|
|
return nil, types.AddCommitmentGroupOutput{CommitmentGroup: types.NewCommitmentGroup(group)}, nil
|
|
}
|
|
|
|
// UpdateCommitmentGroupTool handles the updateCommitmentGroup tool
|
|
// Update an existing commitment group
|
|
func (r *Resolver) UpdateCommitmentGroupTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCommitmentGroupInput) (*mcp.CallToolResult, types.UpdateCommitmentGroupOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, management.ActionCompliancePortalCommitmentGroupUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateCommitmentGroupOutput{}, err
|
|
}
|
|
|
|
updateReq := &management.UpdateCompliancePortalCommitmentGroupRequest{
|
|
ID: input.ID,
|
|
}
|
|
|
|
if title := UnwrapOmittable(input.Title); title != nil {
|
|
updateReq.Title = *title
|
|
}
|
|
|
|
if description := UnwrapOmittable(input.Description); description != nil {
|
|
updateReq.Description = *description
|
|
}
|
|
|
|
if rank := UnwrapOmittable(input.Rank); rank != nil {
|
|
updateReq.Rank = *rank
|
|
}
|
|
|
|
group, err := r.management.UpdateCommitmentGroup(ctx, scope, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateCommitmentGroupOutput{}, fmt.Errorf("cannot update commitment group: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateCommitmentGroupOutput{CommitmentGroup: types.NewCommitmentGroup(group)}, nil
|
|
}
|
|
|
|
// DeleteCommitmentGroupTool handles the deleteCommitmentGroup tool
|
|
// Delete a commitment group
|
|
func (r *Resolver) DeleteCommitmentGroupTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCommitmentGroupInput) (*mcp.CallToolResult, types.DeleteCommitmentGroupOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, management.ActionCompliancePortalCommitmentGroupDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteCommitmentGroupOutput{}, err
|
|
}
|
|
|
|
err = r.management.DeleteCommitmentGroup(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteCommitmentGroupOutput{}, fmt.Errorf("cannot delete commitment group: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteCommitmentGroupOutput{DeletedCommitmentGroupID: input.ID}, nil
|
|
}
|
|
|
|
// ListCommitmentsTool handles the listCommitments tool
|
|
// List all commitments in a commitment group
|
|
func (r *Resolver) ListCommitmentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCommitmentsInput) (*mcp.CallToolResult, types.ListCommitmentsOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.GroupID, management.ActionCompliancePortalCommitmentList)
|
|
if err != nil {
|
|
return nil, types.ListCommitmentsOutput{}, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.CompliancePortalCommitmentOrderField]{
|
|
Field: coredata.CompliancePortalCommitmentOrderFieldRank,
|
|
Direction: page.OrderDirectionAsc,
|
|
}
|
|
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.CompliancePortalCommitmentOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := r.management.ListCommitments(ctx, scope, input.GroupID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListCommitmentsOutput{}, fmt.Errorf("cannot list commitments: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListCommitmentsOutput(p), nil
|
|
}
|
|
|
|
// AddCommitmentTool handles the addCommitment tool
|
|
// Add a new commitment to a commitment group
|
|
func (r *Resolver) AddCommitmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddCommitmentInput) (*mcp.CallToolResult, types.AddCommitmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.GroupID, management.ActionCompliancePortalCommitmentCreate)
|
|
if err != nil {
|
|
return nil, types.AddCommitmentOutput{}, err
|
|
}
|
|
|
|
commitment, err := r.management.CreateCommitment(
|
|
ctx, scope,
|
|
&management.CreateCompliancePortalCommitmentRequest{
|
|
GroupID: input.GroupID,
|
|
Icon: input.Icon,
|
|
Eyebrow: input.Eyebrow,
|
|
Title: input.Title,
|
|
Description: input.Description,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddCommitmentOutput{}, fmt.Errorf("cannot add commitment: %w", err)
|
|
}
|
|
|
|
return nil, types.AddCommitmentOutput{Commitment: types.NewCommitment(commitment)}, nil
|
|
}
|
|
|
|
// UpdateCommitmentTool handles the updateCommitment tool
|
|
// Update an existing commitment
|
|
func (r *Resolver) UpdateCommitmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCommitmentInput) (*mcp.CallToolResult, types.UpdateCommitmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, management.ActionCompliancePortalCommitmentUpdate)
|
|
if err != nil {
|
|
return nil, types.UpdateCommitmentOutput{}, err
|
|
}
|
|
|
|
updateReq := &management.UpdateCompliancePortalCommitmentRequest{
|
|
ID: input.ID,
|
|
}
|
|
|
|
if icon := UnwrapOmittable(input.Icon); icon != nil {
|
|
updateReq.Icon = *icon
|
|
}
|
|
|
|
if eyebrow := UnwrapOmittable(input.Eyebrow); eyebrow != nil {
|
|
updateReq.Eyebrow = *eyebrow
|
|
}
|
|
|
|
if title := UnwrapOmittable(input.Title); title != nil {
|
|
updateReq.Title = *title
|
|
}
|
|
|
|
if description := UnwrapOmittable(input.Description); description != nil {
|
|
updateReq.Description = *description
|
|
}
|
|
|
|
if rank := UnwrapOmittable(input.Rank); rank != nil {
|
|
updateReq.Rank = *rank
|
|
}
|
|
|
|
commitment, err := r.management.UpdateCommitment(ctx, scope, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateCommitmentOutput{}, fmt.Errorf("cannot update commitment: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateCommitmentOutput{Commitment: types.NewCommitment(commitment)}, nil
|
|
}
|
|
|
|
// DeleteCommitmentTool handles the deleteCommitment tool
|
|
// Delete a commitment
|
|
func (r *Resolver) DeleteCommitmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCommitmentInput) (*mcp.CallToolResult, types.DeleteCommitmentOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.ID, management.ActionCompliancePortalCommitmentDelete)
|
|
if err != nil {
|
|
return nil, types.DeleteCommitmentOutput{}, err
|
|
}
|
|
|
|
err = r.management.DeleteCommitment(ctx, scope, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteCommitmentOutput{}, fmt.Errorf("cannot delete commitment: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteCommitmentOutput{DeletedCommitmentID: input.ID}, nil
|
|
}
|
|
|
|
func (r *Resolver) RequestAuditLogExportTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RequestAuditLogExportInput) (*mcp.CallToolResult, types.RequestAuditLogExportOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, iam.ActionAuditLogExport)
|
|
if err != nil {
|
|
return nil, types.RequestAuditLogExportOutput{}, err
|
|
}
|
|
|
|
identity := authn.IdentityFromContext(ctx)
|
|
|
|
logExport, err := r.iamSvc.OrganizationService.RequestLogExport(
|
|
ctx,
|
|
scope,
|
|
iam.RequestLogExportRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Type: coredata.ExportJobTypeAuditLog,
|
|
FromTime: input.FromTime,
|
|
ToTime: input.ToTime,
|
|
RecipientEmail: identity.EmailAddress,
|
|
RecipientName: identity.FullName,
|
|
},
|
|
)
|
|
if err != nil {
|
|
if _, ok := errors.AsType[*iam.ErrInvalidLogExportTimeRange](err); ok {
|
|
return nil, types.RequestAuditLogExportOutput{}, err
|
|
}
|
|
|
|
return nil, types.RequestAuditLogExportOutput{}, fmt.Errorf("cannot request audit log export: %w", err)
|
|
}
|
|
|
|
return nil, types.RequestAuditLogExportOutput{
|
|
ExportJobID: logExport.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) RequestSCIMEventExportTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RequestSCIMEventExportInput) (*mcp.CallToolResult, types.RequestSCIMEventExportOutput, error) {
|
|
scope, err := r.Authorize(ctx, input.OrganizationID, iam.ActionSCIMEventExport)
|
|
if err != nil {
|
|
return nil, types.RequestSCIMEventExportOutput{}, err
|
|
}
|
|
|
|
identity := authn.IdentityFromContext(ctx)
|
|
|
|
logExport, err := r.iamSvc.OrganizationService.RequestLogExport(
|
|
ctx,
|
|
scope,
|
|
iam.RequestLogExportRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Type: coredata.ExportJobTypeSCIMEvent,
|
|
FromTime: input.FromTime,
|
|
ToTime: input.ToTime,
|
|
RecipientEmail: identity.EmailAddress,
|
|
RecipientName: identity.FullName,
|
|
},
|
|
)
|
|
if err != nil {
|
|
if _, ok := errors.AsType[*iam.ErrInvalidLogExportTimeRange](err); ok {
|
|
return nil, types.RequestSCIMEventExportOutput{}, err
|
|
}
|
|
|
|
return nil, types.RequestSCIMEventExportOutput{}, fmt.Errorf("cannot request SCIM event export: %w", err)
|
|
}
|
|
|
|
return nil, types.RequestSCIMEventExportOutput{
|
|
ExportJobID: logExport.ID,
|
|
}, nil
|
|
}
|