Replace the old PDF/snapshot-based exports for processing activities, Data Protection Impact Assessments and Transfer Impact Assessments with the publish document system. Includes GraphQL mutations, MCP tools, CLI commands, n8n operations, frontend publish dialogs, e2e tests, and prosemirror register templates that mirror the previous PDF layouts. Each register lives as a generated DocumentTypeRegister document on the organization, reused across publishes (the major version bumps on every republish). Approvers can be passed in to create a draft pending approval; otherwise the version is published immediately. The frontend ProcessingActivities page exposes a Publish dropdown per register and a Document link button per active tab, pre-fills the previous default approvers, and navigates to the published document on success. Remove snapshot mode entirely from these three entities: drop snapshotId and sourceId from GraphQL schemas, types, filters, resolvers, MCP spec, frontend routes and pages; remove SnapshotsTypeProcessingActivities from the snapshot registry and delete the ProcessingActivities.Snapshot, ProcessingActivitySnapshotter interface and *.InsertProcessingActivitySnapshots methods. The snapshot_id columns remain in the database but are now filtered out with snapshot_id IS NULL. Add Get/Upsert/Clear GeneratedDocumentID methods on each entity type (ProcessingActivity, DataProtectionImpactAssessment, TransferImpactAssessment) backed by new columns in the generated_documents table, matching the Finding/Obligation pattern. Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
4843 lines
182 KiB
Go
4843 lines
182 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"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
|
"go.probo.inc/probo/pkg/accessreview"
|
|
"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/server/api/authn"
|
|
"go.probo.inc/probo/pkg/server/api/mcp/v1/types"
|
|
)
|
|
|
|
// 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
|
|
}
|
|
|
|
// ListVendorsTool handles the listVendors tool
|
|
// List all vendors for the organization
|
|
func (r *Resolver) ListVendorsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListVendorsInput) (*mcp.CallToolResult, types.ListVendorsOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionVendorList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
pageOrderBy := page.OrderBy[coredata.VendorOrderField]{
|
|
Field: coredata.VendorOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.VendorOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
noSnapshot := (*gid.GID)(nil)
|
|
vendorFilter := coredata.NewVendorFilter(&noSnapshot, nil)
|
|
if input.Filter != nil {
|
|
vendorFilter = coredata.NewVendorFilter(&input.Filter.SnapshotID, nil)
|
|
}
|
|
|
|
page, err := prb.Vendors.ListForOrganizationID(ctx, input.OrganizationID, cursor, vendorFilter)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization vendors: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListVendorsOutput(page), nil
|
|
}
|
|
|
|
// AddVendorTool handles the addVendor tool
|
|
// Add a new vendor to the organization
|
|
func (r *Resolver) AddVendorTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddVendorInput) (*mcp.CallToolResult, types.AddVendorOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionVendorCreate)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
var category *coredata.VendorCategory
|
|
if input.Category != nil {
|
|
cat := coredata.VendorCategory(*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)
|
|
}
|
|
}
|
|
|
|
vendor, err := svc.Vendors.Create(
|
|
ctx,
|
|
probo.CreateVendorRequest{
|
|
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.AddVendorOutput{}, fmt.Errorf("failed to create vendor: %w", err)
|
|
}
|
|
|
|
return nil, types.NewAddVendorOutput(vendor), nil
|
|
}
|
|
|
|
// UpdateVendorTool handles the updateVendor tool
|
|
// Update an existing vendor
|
|
func (r *Resolver) UpdateVendorTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateVendorInput) (*mcp.CallToolResult, types.UpdateVendorOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionVendorUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
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.VendorCategory
|
|
if input.Category != nil {
|
|
cat := coredata.VendorCategory(*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)
|
|
}
|
|
}
|
|
|
|
vendor, err := svc.Vendors.Update(
|
|
ctx,
|
|
probo.UpdateVendorRequest{
|
|
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.UpdateVendorOutput{}, fmt.Errorf("failed to update vendor: %w", err)
|
|
}
|
|
|
|
return nil, types.NewUpdateVendorOutput(vendor), nil
|
|
}
|
|
|
|
func (r *Resolver) ListRisksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRisksInput) (*mcp.CallToolResult, types.ListRisksOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionRiskList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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)
|
|
|
|
noSnapshot := (*gid.GID)(nil)
|
|
riskFilter := coredata.NewRiskFilter(nil, &noSnapshot)
|
|
if input.Filter != nil {
|
|
riskFilter = coredata.NewRiskFilter(input.Filter.Query, &input.Filter.SnapshotID)
|
|
}
|
|
|
|
page, err := prb.Risks.ListForOrganizationID(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionRiskGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
risk, err := prb.Risks.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionRiskCreate)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
risk, err := svc.Risks.Create(
|
|
ctx,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionRiskUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
risk, err := svc.Risks.Update(
|
|
ctx,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionMeasureList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionMeasureGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
measure, err := prb.Measures.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionMeasureCreate)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
measure, err := svc.Measures.Create(
|
|
ctx,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionMeasureUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
measure, err := svc.Measures.Update(
|
|
ctx,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionFrameworkList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionFrameworkGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
framework, err := prb.Frameworks.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionFrameworkCreate)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
framework, err := svc.Frameworks.Create(
|
|
ctx,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionFrameworkUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
framework, err := svc.Frameworks.Update(
|
|
ctx,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAssetList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionAssetGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
asset, err := prb.Assets.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAssetCreate)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
asset, err := svc.Assets.Create(
|
|
ctx,
|
|
probo.CreateAssetRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
Amount: input.Amount,
|
|
OwnerID: input.OwnerID,
|
|
AssetType: input.AssetType,
|
|
DataTypesStored: input.DataTypesStored,
|
|
VendorIDs: input.VendorIds,
|
|
},
|
|
)
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionAssetUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
asset, err := svc.Assets.Update(
|
|
ctx,
|
|
probo.UpdateAssetRequest{
|
|
ID: input.ID,
|
|
Name: input.Name,
|
|
Amount: input.Amount,
|
|
OwnerID: input.OwnerID,
|
|
AssetType: input.AssetType,
|
|
DataTypesStored: input.DataTypesStored,
|
|
VendorIDs: input.VendorIds,
|
|
},
|
|
)
|
|
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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDatumList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDatumGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
datum, err := prb.Data.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDatumCreate)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
datum, err := svc.Data.Create(
|
|
ctx,
|
|
probo.CreateDatumRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
DataClassification: input.DataClassification,
|
|
OwnerID: input.OwnerID,
|
|
VendorIDs: input.VendorIds,
|
|
},
|
|
)
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDatumUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
datum, err := svc.Data.Update(
|
|
ctx,
|
|
probo.UpdateDatumRequest{
|
|
ID: input.ID,
|
|
Name: input.Name,
|
|
DataClassification: input.DataClassification,
|
|
OwnerID: input.OwnerID,
|
|
VendorIDs: input.VendorIds,
|
|
},
|
|
)
|
|
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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionFindingList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionFindingGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
finding, err := prb.Findings.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionFindingCreate)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
finding, err := svc.Findings.Create(
|
|
ctx,
|
|
&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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionFindingUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
finding, err := svc.Findings.Update(
|
|
ctx,
|
|
&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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionObligationList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionObligationGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
obligation, err := prb.Obligations.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionObligationCreate)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
obligation, err := svc.Obligations.Create(
|
|
ctx,
|
|
&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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionObligationUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
obligation, err := svc.Obligations.Update(
|
|
ctx,
|
|
&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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionProcessingActivityList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionProcessingActivityGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
processingActivity, err := prb.ProcessingActivities.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionProcessingActivityCreate)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
processingActivity, err := svc.ProcessingActivities.Create(
|
|
ctx,
|
|
&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,
|
|
VendorIDs: input.VendorIds,
|
|
},
|
|
)
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionProcessingActivityUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
var vendorIDs *[]gid.GID
|
|
if input.VendorIds != nil {
|
|
vendorIDs = &input.VendorIds
|
|
}
|
|
|
|
processingActivity, err := svc.ProcessingActivities.Update(
|
|
ctx,
|
|
&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),
|
|
VendorIDs: vendorIDs,
|
|
},
|
|
)
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionProcessingActivityDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.ProcessingActivities.Delete(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDataProtectionImpactAssessmentList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDataProtectionImpactAssessmentGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
dpia, err := prb.DataProtectionImpactAssessments.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ProcessingActivityID, probo.ActionDataProtectionImpactAssessmentCreate)
|
|
|
|
svc := r.ProboService(ctx, input.ProcessingActivityID)
|
|
|
|
dpia, err := svc.DataProtectionImpactAssessments.Create(
|
|
ctx,
|
|
&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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDataProtectionImpactAssessmentUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
dpia, err := svc.DataProtectionImpactAssessments.Update(
|
|
ctx,
|
|
&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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionTransferImpactAssessmentList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionTransferImpactAssessmentGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
tia, err := prb.TransferImpactAssessments.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ProcessingActivityID, probo.ActionTransferImpactAssessmentCreate)
|
|
|
|
svc := r.ProboService(ctx, input.ProcessingActivityID)
|
|
|
|
tia, err := svc.TransferImpactAssessments.Create(
|
|
ctx,
|
|
&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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionTransferImpactAssessmentUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
tia, err := svc.TransferImpactAssessments.Update(
|
|
ctx,
|
|
&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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionTransferImpactAssessmentDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.TransferImpactAssessments.Delete(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAuditList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionAuditGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
audit, err := prb.Audits.Get(ctx, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetAuditOutput{}, fmt.Errorf("cannot get audit: %w", err)
|
|
}
|
|
|
|
var report *coredata.Report
|
|
if audit.ReportID != nil {
|
|
report, err = prb.Reports.Get(ctx, *audit.ReportID)
|
|
if err != nil {
|
|
return nil, types.GetAuditOutput{}, fmt.Errorf("cannot get audit report: %w", err)
|
|
}
|
|
}
|
|
|
|
return nil, types.GetAuditOutput{
|
|
Audit: types.NewAudit(audit, report),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) AddAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddAuditInput) (*mcp.CallToolResult, types.AddAuditOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAuditCreate)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
audit, err := svc.Audits.Create(
|
|
ctx,
|
|
&probo.CreateAuditRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
ValidFrom: input.ValidFrom,
|
|
ValidUntil: input.ValidUntil,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionAuditUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
audit, err := svc.Audits.Update(
|
|
ctx,
|
|
&probo.UpdateAuditRequest{
|
|
ID: input.ID,
|
|
Name: UnwrapOmittable(input.Name),
|
|
ValidFrom: input.ValidFrom,
|
|
ValidUntil: input.ValidUntil,
|
|
State: input.State,
|
|
TrustCenterVisibility: input.TrustCenterVisibility,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.UpdateAuditOutput{}, fmt.Errorf("cannot update audit: %w", err)
|
|
}
|
|
|
|
var report *coredata.Report
|
|
if audit.ReportID != nil {
|
|
report, err = svc.Reports.Get(ctx, *audit.ReportID)
|
|
if err != nil {
|
|
return nil, types.UpdateAuditOutput{}, fmt.Errorf("cannot get audit report: %w", err)
|
|
}
|
|
}
|
|
|
|
return nil, types.UpdateAuditOutput{
|
|
Audit: types.NewAudit(audit, report),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListControlsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListControlsInput) (*mcp.CallToolResult, types.ListControlsOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionControlList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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]
|
|
var err error
|
|
|
|
if input.Filter != nil && input.Filter.FrameworkID != nil {
|
|
controlPage, err = prb.Controls.ListForFrameworkID(ctx, *input.Filter.FrameworkID, cursor, controlFilter)
|
|
} else {
|
|
controlPage, err = prb.Controls.ListForOrganizationID(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionControlGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
control, err := prb.Controls.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.FrameworkID, probo.ActionControlCreate)
|
|
|
|
svc := r.ProboService(ctx, input.FrameworkID)
|
|
|
|
control, err := svc.Controls.Create(
|
|
ctx,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionControlUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
var maturityLevel *coredata.ControlMaturityLevel
|
|
if input.MaturityLevel != nil {
|
|
v := coredata.ControlMaturityLevel(*input.MaturityLevel)
|
|
maturityLevel = &v
|
|
}
|
|
|
|
control, err := svc.Controls.Update(
|
|
ctx,
|
|
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.ProboService(ctx, input.ControlID)
|
|
|
|
switch input.ResourceID.EntityType() {
|
|
case coredata.MeasureEntityType:
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlMeasureMappingCreate)
|
|
if _, _, err := svc.Controls.CreateMeasureMapping(ctx, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to measure: %w", err)
|
|
}
|
|
case coredata.DocumentEntityType:
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlDocumentMappingCreate)
|
|
if _, _, err := svc.Controls.CreateDocumentMapping(ctx, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to document: %w", err)
|
|
}
|
|
case coredata.AuditEntityType:
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlAuditMappingCreate)
|
|
if _, _, err := svc.Controls.CreateAuditMapping(ctx, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to audit: %w", err)
|
|
}
|
|
case coredata.SnapshotEntityType:
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlSnapshotMappingCreate)
|
|
if _, _, err := svc.Controls.CreateSnapshotMapping(ctx, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to snapshot: %w", err)
|
|
}
|
|
case coredata.ObligationEntityType:
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlObligationMappingCreate)
|
|
if _, _, err := svc.Controls.CreateObligationMapping(ctx, 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.ProboService(ctx, input.ControlID)
|
|
|
|
switch input.ResourceID.EntityType() {
|
|
case coredata.MeasureEntityType:
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlMeasureMappingDelete)
|
|
if _, _, err := svc.Controls.DeleteMeasureMapping(ctx, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from measure: %w", err)
|
|
}
|
|
case coredata.DocumentEntityType:
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlDocumentMappingDelete)
|
|
if _, _, err := svc.Controls.DeleteDocumentMapping(ctx, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from document: %w", err)
|
|
}
|
|
case coredata.AuditEntityType:
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlAuditMappingDelete)
|
|
if _, _, err := svc.Controls.DeleteAuditMapping(ctx, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from audit: %w", err)
|
|
}
|
|
case coredata.SnapshotEntityType:
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlSnapshotMappingDelete)
|
|
if _, _, err := svc.Controls.DeleteSnapshotMapping(ctx, input.ControlID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from snapshot: %w", err)
|
|
}
|
|
case coredata.ObligationEntityType:
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlObligationMappingDelete)
|
|
if _, _, err := svc.Controls.DeleteObligationMapping(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlGet)
|
|
|
|
prb := r.ProboService(ctx, input.ControlID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlGet)
|
|
|
|
prb := r.ProboService(ctx, input.ControlID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlGet)
|
|
|
|
prb := r.ProboService(ctx, input.ControlID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlGet)
|
|
|
|
prb := r.ProboService(ctx, input.ControlID)
|
|
|
|
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, 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) ListControlSnapshotsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListControlSnapshotsInput) (*mcp.CallToolResult, types.ListControlSnapshotsOutput, error) {
|
|
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlGet)
|
|
|
|
prb := r.ProboService(ctx, input.ControlID)
|
|
|
|
pageOrderBy := page.OrderBy[coredata.SnapshotOrderField]{
|
|
Field: coredata.SnapshotOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.SnapshotOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
snapshotPage, err := prb.Snapshots.ListForControlID(ctx, input.ControlID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListControlSnapshotsOutput{}, fmt.Errorf("failed to list control snapshots: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListControlSnapshotsOutput(snapshotPage), nil
|
|
}
|
|
|
|
func (r *Resolver) ListRiskObligationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskObligationsInput) (*mcp.CallToolResult, types.ListRiskObligationsOutput, error) {
|
|
r.MustAuthorize(ctx, input.RiskID, probo.ActionRiskGet)
|
|
|
|
prb := r.ProboService(ctx, input.RiskID)
|
|
|
|
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, 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.ProboService(ctx, input.RiskID)
|
|
|
|
switch input.ResourceID.EntityType() {
|
|
case coredata.DocumentEntityType:
|
|
r.MustAuthorize(ctx, input.RiskID, probo.ActionRiskDocumentMappingCreate)
|
|
if _, _, err := svc.Risks.CreateDocumentMapping(ctx, input.RiskID, input.ResourceID); err != nil {
|
|
return nil, types.LinkRiskOutput{}, fmt.Errorf("failed to link risk to document: %w", err)
|
|
}
|
|
case coredata.MeasureEntityType:
|
|
r.MustAuthorize(ctx, input.RiskID, probo.ActionRiskMeasureMappingCreate)
|
|
if _, _, err := svc.Risks.CreateMeasureMapping(ctx, input.RiskID, input.ResourceID); err != nil {
|
|
return nil, types.LinkRiskOutput{}, fmt.Errorf("failed to link risk to measure: %w", err)
|
|
}
|
|
case coredata.ObligationEntityType:
|
|
r.MustAuthorize(ctx, input.RiskID, probo.ActionRiskObligationMappingCreate)
|
|
if _, _, err := svc.Risks.CreateObligationMapping(ctx, 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.ProboService(ctx, input.RiskID)
|
|
|
|
switch input.ResourceID.EntityType() {
|
|
case coredata.DocumentEntityType:
|
|
r.MustAuthorize(ctx, input.RiskID, probo.ActionRiskDocumentMappingDelete)
|
|
if _, _, err := svc.Risks.DeleteDocumentMapping(ctx, input.RiskID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkRiskOutput{}, fmt.Errorf("failed to unlink risk from document: %w", err)
|
|
}
|
|
case coredata.MeasureEntityType:
|
|
r.MustAuthorize(ctx, input.RiskID, probo.ActionRiskMeasureMappingDelete)
|
|
if _, _, err := svc.Risks.DeleteMeasureMapping(ctx, input.RiskID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkRiskOutput{}, fmt.Errorf("failed to unlink risk from measure: %w", err)
|
|
}
|
|
case coredata.ObligationEntityType:
|
|
r.MustAuthorize(ctx, input.RiskID, probo.ActionRiskObligationMappingDelete)
|
|
if _, _, err := svc.Risks.DeleteObligationMapping(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionTaskList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionTaskGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
task, err := prb.Tasks.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionTaskCreate)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
priority := coredata.TaskPriorityMedium
|
|
if input.Priority != nil {
|
|
priority = *input.Priority
|
|
}
|
|
|
|
task, err := svc.Tasks.Create(
|
|
ctx,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionTaskUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
task, err := svc.Tasks.Update(
|
|
ctx,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionTaskAssign)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
task, err := svc.Tasks.Assign(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionTaskUnassign)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
task, err := svc.Tasks.Unassign(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionTaskDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.Tasks.Delete(ctx, 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) ListSnapshotsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListSnapshotsInput) (*mcp.CallToolResult, types.ListSnapshotsOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionSnapshotList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
pageOrderBy := page.OrderBy[coredata.SnapshotOrderField]{
|
|
Field: coredata.SnapshotOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.SnapshotOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
page, err := prb.Snapshots.ListForOrganizationID(ctx, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list organization snapshots: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListSnapshotsOutput(page), nil
|
|
}
|
|
|
|
func (r *Resolver) GetSnapshotTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetSnapshotInput) (*mcp.CallToolResult, types.GetSnapshotOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionSnapshotGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
snapshot, err := prb.Snapshots.Get(ctx, input.ID)
|
|
if err != nil {
|
|
return nil, types.GetSnapshotOutput{}, fmt.Errorf("failed to get snapshot: %w", err)
|
|
}
|
|
return nil, types.GetSnapshotOutput{
|
|
Snapshot: types.NewSnapshot(snapshot),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) TakeSnapshotTool(ctx context.Context, req *mcp.CallToolRequest, input *types.TakeSnapshotInput) (*mcp.CallToolResult, types.TakeSnapshotOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionSnapshotCreate)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
snapshot, err := prb.Snapshots.Create(
|
|
ctx,
|
|
&probo.CreateSnapshotRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
Description: input.Description,
|
|
Type: input.Type,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.TakeSnapshotOutput{}, fmt.Errorf("failed to take snapshot: %w", err)
|
|
}
|
|
return nil, types.TakeSnapshotOutput{
|
|
Snapshot: types.NewSnapshot(snapshot),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListDocumentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentsInput) (*mcp.CallToolResult, types.ListDocumentsOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDocumentList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
document, err := prb.Documents.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDocumentCreate)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
var trustCenterVisibility *coredata.TrustCenterVisibility
|
|
if input.TrustCenterVisibility != nil {
|
|
trustCenterVisibility = input.TrustCenterVisibility
|
|
}
|
|
|
|
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,
|
|
probo.CreateDocumentRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Title: input.Title,
|
|
Content: contentJSON,
|
|
Classification: input.Classification,
|
|
DocumentType: input.DocumentType,
|
|
TrustCenterVisibility: trustCenterVisibility,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
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,
|
|
probo.UpdateDocumentRequest{
|
|
DocumentID: input.ID,
|
|
Title: input.Title,
|
|
Content: content,
|
|
Classification: input.Classification,
|
|
DocumentType: input.DocumentType,
|
|
TrustCenterVisibility: input.TrustCenterVisibility,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.DocumentID, probo.ActionDocumentVersionList)
|
|
|
|
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.ProboService(ctx, input.DocumentID)
|
|
|
|
versionFilter := coredata.NewDocumentVersionFilter()
|
|
if input.Filter != nil && len(input.Filter.Statuses) > 0 {
|
|
versionFilter = versionFilter.WithStatuses(input.Filter.Statuses...)
|
|
}
|
|
|
|
versionPage, err := svc.Documents.ListVersions(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentVersionGet)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
version, err := svc.Documents.GetVersion(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionSignatureList)
|
|
|
|
prb := r.ProboService(ctx, input.DocumentVersionID)
|
|
|
|
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
|
|
var activeContract *bool
|
|
if input.Filter != nil {
|
|
if input.Filter.States != nil {
|
|
signatureStates = input.Filter.States
|
|
}
|
|
if input.Filter.ActiveContract != nil {
|
|
activeContract = input.Filter.ActiveContract
|
|
}
|
|
}
|
|
signatureFilter := coredata.NewDocumentVersionSignatureFilter(signatureStates, activeContract)
|
|
|
|
page, err := prb.Documents.ListSignatures(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentVersionSignatureGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
signature, err := prb.Documents.GetVersionSignature(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionSignatureRequest)
|
|
|
|
svc := r.ProboService(ctx, input.DocumentVersionID)
|
|
|
|
documentVersionSignature, err := svc.Documents.RequestSignature(
|
|
ctx,
|
|
probo.RequestSignatureRequest{
|
|
DocumentVersionID: input.DocumentVersionID,
|
|
Signatory: input.SignatoryID,
|
|
},
|
|
)
|
|
if err != nil {
|
|
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) {
|
|
r.MustAuthorize(ctx, input.DocumentID, probo.ActionDocumentDelete)
|
|
|
|
svc := r.ProboService(ctx, input.DocumentID)
|
|
|
|
err := svc.Documents.SoftDelete(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.DocumentVersionSignatureID, probo.ActionDocumentVersionCancelSignature)
|
|
|
|
svc := r.ProboService(ctx, input.DocumentVersionSignatureID)
|
|
|
|
err := svc.Documents.CancelSignatureRequest(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionRiskDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.Risks.Delete(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionMeasureDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.Measures.Delete(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.MeasureID, probo.ActionMeasureGet)
|
|
|
|
prb := r.ProboService(ctx, input.MeasureID)
|
|
|
|
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, input.MeasureID, cursor, coredata.NewRiskFilter(nil, 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) {
|
|
r.MustAuthorize(ctx, input.MeasureID, probo.ActionMeasureGet)
|
|
|
|
prb := r.ProboService(ctx, input.MeasureID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.MeasureID, probo.ActionMeasureGet)
|
|
|
|
prb := r.ProboService(ctx, input.MeasureID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.MeasureID, probo.ActionMeasureGet)
|
|
|
|
prb := r.ProboService(ctx, input.MeasureID)
|
|
|
|
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, 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.ProboService(ctx, input.MeasureID)
|
|
|
|
switch input.ResourceID.EntityType() {
|
|
case coredata.ControlEntityType:
|
|
r.MustAuthorize(ctx, input.MeasureID, probo.ActionControlMeasureMappingCreate)
|
|
if _, _, err := svc.Controls.CreateMeasureMapping(ctx, input.ResourceID, input.MeasureID); err != nil {
|
|
return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to control: %w", err)
|
|
}
|
|
case coredata.RiskEntityType:
|
|
r.MustAuthorize(ctx, input.MeasureID, probo.ActionRiskMeasureMappingCreate)
|
|
if _, _, err := svc.Risks.CreateMeasureMapping(ctx, input.ResourceID, input.MeasureID); err != nil {
|
|
return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to risk: %w", err)
|
|
}
|
|
case coredata.DocumentEntityType:
|
|
r.MustAuthorize(ctx, input.MeasureID, probo.ActionMeasureDocumentMappingCreate)
|
|
if _, _, err := svc.Measures.CreateDocumentMapping(ctx, input.MeasureID, input.ResourceID); err != nil {
|
|
return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to document: %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.ProboService(ctx, input.MeasureID)
|
|
|
|
switch input.ResourceID.EntityType() {
|
|
case coredata.ControlEntityType:
|
|
r.MustAuthorize(ctx, input.MeasureID, probo.ActionControlMeasureMappingDelete)
|
|
if _, _, err := svc.Controls.DeleteMeasureMapping(ctx, input.ResourceID, input.MeasureID); err != nil {
|
|
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from control: %w", err)
|
|
}
|
|
case coredata.RiskEntityType:
|
|
r.MustAuthorize(ctx, input.MeasureID, probo.ActionRiskMeasureMappingDelete)
|
|
if _, _, err := svc.Risks.DeleteMeasureMapping(ctx, input.ResourceID, input.MeasureID); err != nil {
|
|
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from risk: %w", err)
|
|
}
|
|
case coredata.DocumentEntityType:
|
|
r.MustAuthorize(ctx, input.MeasureID, probo.ActionMeasureDocumentMappingDelete)
|
|
if _, _, err := svc.Measures.DeleteDocumentMapping(ctx, input.MeasureID, input.ResourceID); err != nil {
|
|
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from document: %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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, iam.ActionMembershipProfileList)
|
|
|
|
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 input.Filter.State != nil {
|
|
filter.WithState(*input.Filter.State)
|
|
}
|
|
}
|
|
|
|
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 {
|
|
var errNotFound *iam.ErrProfileNotFound
|
|
if errors.As(err, &errNotFound) {
|
|
return nil, types.GetUserOutput{}, fmt.Errorf("user not found: %w", err)
|
|
}
|
|
return nil, types.GetUserOutput{}, fmt.Errorf("get user: %w", err)
|
|
}
|
|
r.MustAuthorize(ctx, profile.OrganizationID, iam.ActionMembershipProfileGet)
|
|
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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, iam.ActionMembershipProfileCreate)
|
|
|
|
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, &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 {
|
|
var errAlreadyExists *iam.ErrUserAlreadyExists
|
|
if errors.As(err, &errAlreadyExists) {
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ProfileID, iam.ActionInvitationCreate)
|
|
|
|
invitation, err := r.iamSvc.OrganizationService.InviteUser(ctx, &iam.CreateInvitationRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
ProfileID: input.ProfileID,
|
|
})
|
|
if err != nil {
|
|
var errOrgNotFound *iam.ErrOrganizationNotFound
|
|
var errUserExists *iam.ErrUserAlreadyExists
|
|
if errors.As(err, &errOrgNotFound) {
|
|
return nil, types.InviteUserOutput{}, fmt.Errorf("organization not found: %w", err)
|
|
}
|
|
if errors.As(err, &errUserExists) {
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, iam.ActionMembershipProfileUpdate)
|
|
|
|
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) {
|
|
r.MustAuthorize(ctx, input.MembershipID, iam.ActionMembershipUpdate)
|
|
if input.Role == coredata.MembershipRoleOwner {
|
|
r.MustAuthorize(ctx, input.MembershipID, iam.ActionMembershipRoleSetOwner)
|
|
}
|
|
|
|
membership, err := r.iamSvc.OrganizationService.UpdateMempership(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) {
|
|
r.MustAuthorize(ctx, input.ProfileID, iam.ActionMembershipProfileDelete)
|
|
|
|
err := r.iamSvc.OrganizationService.RemoveUser(ctx, input.OrganizationID, input.ProfileID)
|
|
if err != nil {
|
|
var errManagedBySCIM *iam.ErrUserManagedBySCIM
|
|
var errLastOwner *iam.ErrLastActiveOwner
|
|
if errors.As(err, &errManagedBySCIM) {
|
|
return nil, types.RemoveUserOutput{}, fmt.Errorf("user is managed by SCIM and cannot be removed: %w", err)
|
|
}
|
|
if errors.As(err, &errLastOwner) {
|
|
return nil, types.RemoveUserOutput{}, fmt.Errorf("cannot remove last active owner: %w", err)
|
|
}
|
|
return nil, types.RemoveUserOutput{}, fmt.Errorf("remove user: %w", err)
|
|
}
|
|
return nil, types.RemoveUserOutput{DeletedUserID: input.ProfileID}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteDataProtectionImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteDataProtectionImpactAssessmentInput) (*mcp.CallToolResult, types.DeleteDataProtectionImpactAssessmentOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDataProtectionImpactAssessmentDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.DataProtectionImpactAssessments.Delete(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionStatementOfApplicabilityList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionStatementOfApplicabilityGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
soa, err := prb.StatementsOfApplicability.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionStatementOfApplicabilityCreate)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
soa, err := svc.StatementsOfApplicability.Create(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionStatementOfApplicabilityUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
soa, err := svc.StatementsOfApplicability.Update(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionStatementOfApplicabilityDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.StatementsOfApplicability.Delete(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.StatementOfApplicabilityID, probo.ActionApplicabilityStatementList)
|
|
|
|
prb := r.ProboService(ctx, input.StatementOfApplicabilityID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionApplicabilityStatementGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
stmt, err := prb.StatementsOfApplicability.GetApplicabilityStatement(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.StatementOfApplicabilityID, probo.ActionApplicabilityStatementCreate)
|
|
|
|
svc := r.ProboService(ctx, input.StatementOfApplicabilityID)
|
|
|
|
stmt, err := svc.StatementsOfApplicability.CreateApplicabilityStatement(
|
|
ctx,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionApplicabilityStatementUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
stmt, err := svc.StatementsOfApplicability.UpdateApplicabilityStatement(
|
|
ctx,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionApplicabilityStatementDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.StatementsOfApplicability.DeleteApplicabilityStatement(ctx, 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
|
|
}
|
|
|
|
// ListVendorRiskAssessmentsTool handles the listVendorRiskAssessments tool
|
|
// List all risk assessments for a vendor
|
|
func (r *Resolver) ListVendorRiskAssessmentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListVendorRiskAssessmentsInput) (*mcp.CallToolResult, types.ListVendorRiskAssessmentsOutput, error) {
|
|
r.MustAuthorize(ctx, input.VendorID, probo.ActionVendorRiskAssessmentList)
|
|
|
|
prb := r.ProboService(ctx, input.VendorID)
|
|
|
|
pageOrderBy := page.OrderBy[coredata.VendorRiskAssessmentOrderField]{
|
|
Field: coredata.VendorRiskAssessmentOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.VendorRiskAssessmentOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := prb.Vendors.ListRiskAssessments(ctx, input.VendorID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListVendorRiskAssessmentsOutput{}, fmt.Errorf("cannot list vendor risk assessments: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListVendorRiskAssessmentsOutput(p), nil
|
|
}
|
|
|
|
// AddVendorRiskAssessmentTool handles the addVendorRiskAssessment tool
|
|
// Add a new risk assessment for a vendor
|
|
func (r *Resolver) AddVendorRiskAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddVendorRiskAssessmentInput) (*mcp.CallToolResult, types.AddVendorRiskAssessmentOutput, error) {
|
|
r.MustAuthorize(ctx, input.VendorID, probo.ActionVendorRiskAssessmentCreate)
|
|
|
|
prb := r.ProboService(ctx, input.VendorID)
|
|
|
|
assessment, err := prb.Vendors.CreateRiskAssessment(
|
|
ctx,
|
|
probo.CreateVendorRiskAssessmentRequest{
|
|
VendorID: input.VendorID,
|
|
ExpiresAt: input.ExpiresAt,
|
|
DataSensitivity: input.DataSensitivity,
|
|
BusinessImpact: input.BusinessImpact,
|
|
Notes: input.Notes,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddVendorRiskAssessmentOutput{}, fmt.Errorf("failed to create vendor risk assessment: %w", err)
|
|
}
|
|
|
|
return nil, types.NewAddVendorRiskAssessmentOutput(assessment), nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteVendorTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteVendorInput) (*mcp.CallToolResult, types.DeleteVendorOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionVendorDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.Vendors.Delete(ctx, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteVendorOutput{}, fmt.Errorf("failed to delete vendor: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteVendorOutput{
|
|
DeletedVendorID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteFindingTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteFindingInput) (*mcp.CallToolResult, types.DeleteFindingOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionFindingDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.Findings.Delete(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.FindingID, probo.ActionFindingAuditMappingCreate)
|
|
|
|
svc := r.ProboService(ctx, input.FindingID)
|
|
|
|
finding, audit, err := svc.Findings.CreateAuditMapping(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.FindingID, probo.ActionFindingAuditMappingDelete)
|
|
|
|
svc := r.ProboService(ctx, input.FindingID)
|
|
|
|
finding, audit, err := svc.Findings.DeleteAuditMapping(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.FindingID, probo.ActionFindingGet)
|
|
|
|
prb := r.ProboService(ctx, input.FindingID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAccessReviewCampaignList)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.OrganizationID)
|
|
|
|
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.Campaigns(scope).ListForOrganizationID(ctx, 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 with optional filters
|
|
func (r *Resolver) ListAccessEntriesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAccessEntriesInput) (*mcp.CallToolResult, types.ListAccessEntriesOutput, error) {
|
|
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessEntryList)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CampaignID)
|
|
|
|
pageOrderBy := page.OrderBy[coredata.AccessEntryOrderField]{
|
|
Field: coredata.AccessEntryOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.AccessEntryOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
var filter *coredata.AccessEntryFilter
|
|
if input.Filter != nil {
|
|
filter = &coredata.AccessEntryFilter{
|
|
Decision: input.Filter.Decision,
|
|
Flag: input.Filter.Flag,
|
|
IncrementalTag: input.Filter.IncrementalTag,
|
|
IsAdmin: input.Filter.IsAdmin,
|
|
AuthMethod: input.Filter.AuthMethod,
|
|
}
|
|
}
|
|
|
|
var p *page.Page[*coredata.AccessEntry, coredata.AccessEntryOrderField]
|
|
|
|
if input.AccessSourceID != nil {
|
|
var err error
|
|
p, err = r.accessReview.Entries(scope).ListForCampaignIDAndSourceID(
|
|
ctx,
|
|
input.CampaignID,
|
|
*input.AccessSourceID,
|
|
cursor,
|
|
filter,
|
|
)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list access entries: %w", err))
|
|
}
|
|
} else {
|
|
var err error
|
|
p, err = r.accessReview.Entries(scope).ListForCampaignID(ctx, input.CampaignID, cursor, filter)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list access entries: %w", err))
|
|
}
|
|
}
|
|
|
|
return nil, types.NewListAccessEntriesOutput(p), nil
|
|
}
|
|
|
|
// GetAccessReviewCampaignStatisticsTool handles the getAccessReviewCampaignStatistics tool
|
|
// Get statistics for an access review campaign
|
|
func (r *Resolver) GetAccessReviewCampaignStatisticsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAccessReviewCampaignStatisticsInput) (*mcp.CallToolResult, types.GetAccessReviewCampaignStatisticsOutput, error) {
|
|
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignGet)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CampaignID)
|
|
|
|
stats, err := r.accessReview.Entries(scope).Statistics(ctx, input.CampaignID)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot get campaign statistics: %w", err))
|
|
}
|
|
|
|
return nil, types.GetAccessReviewCampaignStatisticsOutput{
|
|
Statistics: types.NewAccessEntryStatistics(stats),
|
|
}, nil
|
|
}
|
|
|
|
// RecordAccessEntryDecisionTool handles the recordAccessEntryDecision tool
|
|
// Record a decision on an access entry
|
|
func (r *Resolver) RecordAccessEntryDecisionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RecordAccessEntryDecisionInput) (*mcp.CallToolResult, types.RecordAccessEntryDecisionOutput, error) {
|
|
r.MustAuthorize(ctx, input.AccessEntryID, probo.ActionAccessEntryDecide)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.AccessEntryID)
|
|
|
|
identity := authn.IdentityFromContext(ctx)
|
|
if identity == nil {
|
|
return nil, types.RecordAccessEntryDecisionOutput{}, fmt.Errorf("no identity in context")
|
|
}
|
|
|
|
decisionReq := accessreview.RecordAccessEntryDecisionRequest{
|
|
EntryID: input.AccessEntryID,
|
|
Decision: input.Decision,
|
|
DecisionNote: input.DecisionNote,
|
|
}
|
|
|
|
organizationID, err := r.accessReview.ResolveEntryOrganizationID(ctx, input.AccessEntryID)
|
|
if err == nil {
|
|
profile, err := r.iamSvc.OrganizationService.GetProfileForIdentityAndOrganization(ctx, identity.ID, organizationID)
|
|
if err == nil {
|
|
decisionReq.DecidedByID = &profile.ID
|
|
}
|
|
}
|
|
|
|
entry, err := r.accessReview.Entries(scope).RecordDecision(ctx, decisionReq)
|
|
if err != nil {
|
|
return nil, types.RecordAccessEntryDecisionOutput{}, fmt.Errorf("cannot record decision: %w", err)
|
|
}
|
|
|
|
return nil, types.RecordAccessEntryDecisionOutput{
|
|
AccessEntry: types.NewAccessEntry(entry),
|
|
}, nil
|
|
}
|
|
|
|
// RecordAccessEntryDecisionsTool handles the recordAccessEntryDecisions tool
|
|
// Record decisions on multiple access entries in a single batch
|
|
func (r *Resolver) RecordAccessEntryDecisionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RecordAccessEntryDecisionsInput) (*mcp.CallToolResult, types.RecordAccessEntryDecisionsOutput, error) {
|
|
if len(input.Decisions) == 0 {
|
|
return nil, types.RecordAccessEntryDecisionsOutput{
|
|
AccessEntries: []*types.AccessEntry{},
|
|
}, nil
|
|
}
|
|
|
|
const maxBatchSize = 100
|
|
if len(input.Decisions) > maxBatchSize {
|
|
return nil, types.RecordAccessEntryDecisionsOutput{}, 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 {
|
|
r.MustAuthorize(ctx, d.AccessEntryID, probo.ActionAccessEntryDecide)
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.Decisions[0].AccessEntryID)
|
|
|
|
identity := authn.IdentityFromContext(ctx)
|
|
if identity == nil {
|
|
return nil, types.RecordAccessEntryDecisionsOutput{}, fmt.Errorf("no identity in context")
|
|
}
|
|
|
|
// Cache profile lookups per organization so we resolve the correct
|
|
// decidedByID for each entry even when a batch spans multiple orgs.
|
|
profileCache := make(map[gid.GID]*gid.GID)
|
|
|
|
decisions := make([]accessreview.RecordAccessEntryDecisionRequest, len(input.Decisions))
|
|
for i, d := range input.Decisions {
|
|
var decidedByID *gid.GID
|
|
organizationID, err := r.accessReview.ResolveEntryOrganizationID(ctx, d.AccessEntryID)
|
|
if err == nil {
|
|
if cached, ok := profileCache[organizationID]; ok {
|
|
decidedByID = cached
|
|
} else {
|
|
profile, err := r.iamSvc.OrganizationService.GetProfileForIdentityAndOrganization(ctx, identity.ID, organizationID)
|
|
if err == nil {
|
|
decidedByID = &profile.ID
|
|
}
|
|
profileCache[organizationID] = decidedByID
|
|
}
|
|
}
|
|
|
|
decisions[i] = accessreview.RecordAccessEntryDecisionRequest{
|
|
EntryID: d.AccessEntryID,
|
|
Decision: d.Decision,
|
|
DecisionNote: d.DecisionNote,
|
|
DecidedByID: decidedByID,
|
|
}
|
|
}
|
|
|
|
entries, err := r.accessReview.Entries(scope).RecordDecisions(ctx, decisions)
|
|
if err != nil {
|
|
return nil, types.RecordAccessEntryDecisionsOutput{}, fmt.Errorf("cannot record decisions: %w", err)
|
|
}
|
|
|
|
accessEntries := make([]*types.AccessEntry, len(entries))
|
|
for i, e := range entries {
|
|
accessEntries[i] = types.NewAccessEntry(e)
|
|
}
|
|
|
|
return nil, types.RecordAccessEntryDecisionsOutput{
|
|
AccessEntries: 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) {
|
|
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignClose)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CampaignID)
|
|
|
|
campaign, err := r.accessReview.Campaigns(scope).Close(ctx, 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
|
|
}
|
|
|
|
// ListAccessSourcesTool handles the listAccessSources tool
|
|
// List access sources for an organization
|
|
func (r *Resolver) ListAccessSourcesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAccessSourcesInput) (*mcp.CallToolResult, types.ListAccessSourcesOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAccessSourceList)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.OrganizationID)
|
|
|
|
pageOrderBy := page.OrderBy[coredata.AccessSourceOrderField]{
|
|
Field: coredata.AccessSourceOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.AccessSourceOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := r.accessReview.Sources(scope).ListForOrganizationID(ctx, input.OrganizationID, cursor)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot list access sources: %w", err))
|
|
}
|
|
|
|
return nil, types.NewListAccessSourcesOutput(p), nil
|
|
}
|
|
|
|
// CreateAccessSourceTool handles the createAccessSource tool
|
|
// Create a new access source for an organization
|
|
func (r *Resolver) CreateAccessSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateAccessSourceInput) (*mcp.CallToolResult, types.CreateAccessSourceOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAccessSourceCreate)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.OrganizationID)
|
|
|
|
source, err := r.accessReview.Sources(scope).Create(ctx, accessreview.CreateAccessSourceRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
ConnectorID: input.ConnectorID,
|
|
Name: input.Name,
|
|
Category: coredata.AccessSourceCategorySaaS,
|
|
CsvData: input.CsvData,
|
|
})
|
|
if err != nil {
|
|
return nil, types.CreateAccessSourceOutput{}, fmt.Errorf("cannot create access source: %w", err)
|
|
}
|
|
|
|
return nil, types.CreateAccessSourceOutput{
|
|
AccessSource: types.NewAccessSource(source),
|
|
}, nil
|
|
}
|
|
|
|
// UpdateAccessSourceTool handles the updateAccessSource tool
|
|
// Update an existing access source
|
|
func (r *Resolver) UpdateAccessSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateAccessSourceInput) (*mcp.CallToolResult, types.UpdateAccessSourceOutput, error) {
|
|
r.MustAuthorize(ctx, input.AccessSourceID, probo.ActionAccessSourceUpdate)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.AccessSourceID)
|
|
|
|
updateReq := accessreview.UpdateAccessSourceRequest{
|
|
AccessSourceID: input.AccessSourceID,
|
|
Name: input.Name,
|
|
}
|
|
|
|
if rawConnectorID := UnwrapOmittable(input.ConnectorID); rawConnectorID != nil {
|
|
if *rawConnectorID != nil {
|
|
id, err := gid.ParseGID(**rawConnectorID)
|
|
if err != nil {
|
|
return nil, types.UpdateAccessSourceOutput{}, 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.Sources(scope).Update(ctx, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateAccessSourceOutput{}, fmt.Errorf("cannot update access source: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateAccessSourceOutput{
|
|
AccessSource: types.NewAccessSource(source),
|
|
}, nil
|
|
}
|
|
|
|
// DeleteAccessSourceTool handles the deleteAccessSource tool
|
|
// Delete an access source
|
|
func (r *Resolver) DeleteAccessSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteAccessSourceInput) (*mcp.CallToolResult, types.DeleteAccessSourceOutput, error) {
|
|
r.MustAuthorize(ctx, input.AccessSourceID, probo.ActionAccessSourceDelete)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.AccessSourceID)
|
|
|
|
if err := r.accessReview.Sources(scope).Delete(ctx, input.AccessSourceID); err != nil {
|
|
return nil, types.DeleteAccessSourceOutput{}, fmt.Errorf("cannot delete access source: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteAccessSourceOutput{
|
|
DeletedAccessSourceID: input.AccessSourceID,
|
|
}, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAccessReviewCampaignCreate)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.OrganizationID)
|
|
|
|
var description string
|
|
if input.Description != nil {
|
|
description = *input.Description
|
|
}
|
|
|
|
campaign, err := r.accessReview.Campaigns(scope).Create(ctx, accessreview.CreateAccessReviewCampaignRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
Description: description,
|
|
FrameworkControls: input.FrameworkControls,
|
|
AccessSourceIDs: input.AccessSourceIds,
|
|
})
|
|
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) {
|
|
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignUpdate)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CampaignID)
|
|
|
|
updateReq := accessreview.UpdateAccessReviewCampaignRequest{
|
|
CampaignID: input.CampaignID,
|
|
Name: input.Name,
|
|
Description: input.Description,
|
|
}
|
|
|
|
if rawControls := UnwrapOmittable(input.FrameworkControls); rawControls != nil {
|
|
if *rawControls != nil {
|
|
controls := make([]string, 0, len(**rawControls))
|
|
for _, v := range **rawControls {
|
|
if s, ok := v.(string); ok {
|
|
controls = append(controls, s)
|
|
}
|
|
}
|
|
updateReq.FrameworkControls = &controls
|
|
} else {
|
|
empty := []string{}
|
|
updateReq.FrameworkControls = &empty
|
|
}
|
|
}
|
|
|
|
campaign, err := r.accessReview.Campaigns(scope).Update(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignDelete)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CampaignID)
|
|
|
|
if err := r.accessReview.Campaigns(scope).Delete(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignStart)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CampaignID)
|
|
|
|
campaign, err := r.accessReview.Campaigns(scope).Start(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignCancel)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CampaignID)
|
|
|
|
campaign, err := r.accessReview.Campaigns(scope).Cancel(ctx, 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
|
|
}
|
|
|
|
// AddAccessReviewCampaignScopeSourceTool handles the addAccessReviewCampaignScopeSource tool
|
|
// Add an access source to an access review campaign's scope
|
|
func (r *Resolver) AddAccessReviewCampaignScopeSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddAccessReviewCampaignScopeSourceInput) (*mcp.CallToolResult, types.AddAccessReviewCampaignScopeSourceOutput, error) {
|
|
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignAddScopeSource)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CampaignID)
|
|
|
|
campaign, err := r.accessReview.Campaigns(scope).AddScopeSource(ctx, accessreview.AddCampaignScopeSourceRequest{
|
|
CampaignID: input.CampaignID,
|
|
AccessSourceID: input.AccessSourceID,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddAccessReviewCampaignScopeSourceOutput{}, fmt.Errorf("cannot add scope source to access review campaign: %w", err)
|
|
}
|
|
|
|
return nil, types.AddAccessReviewCampaignScopeSourceOutput{
|
|
Campaign: types.NewAccessReviewCampaign(campaign),
|
|
}, nil
|
|
}
|
|
|
|
// RemoveAccessReviewCampaignScopeSourceTool handles the removeAccessReviewCampaignScopeSource tool
|
|
// Remove an access source from an access review campaign's scope
|
|
func (r *Resolver) RemoveAccessReviewCampaignScopeSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RemoveAccessReviewCampaignScopeSourceInput) (*mcp.CallToolResult, types.RemoveAccessReviewCampaignScopeSourceOutput, error) {
|
|
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignRemoveScopeSource)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CampaignID)
|
|
|
|
campaign, err := r.accessReview.Campaigns(scope).RemoveScopeSource(ctx, accessreview.RemoveCampaignScopeSourceRequest{
|
|
CampaignID: input.CampaignID,
|
|
AccessSourceID: input.AccessSourceID,
|
|
})
|
|
if err != nil {
|
|
return nil, types.RemoveAccessReviewCampaignScopeSourceOutput{}, fmt.Errorf("cannot remove scope source from access review campaign: %w", err)
|
|
}
|
|
|
|
return nil, types.RemoveAccessReviewCampaignScopeSourceOutput{
|
|
Campaign: types.NewAccessReviewCampaign(campaign),
|
|
}, nil
|
|
}
|
|
|
|
// FlagAccessEntryTool handles the flagAccessEntry tool
|
|
// Flag an access entry during review
|
|
func (r *Resolver) FlagAccessEntryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.FlagAccessEntryInput) (*mcp.CallToolResult, types.FlagAccessEntryOutput, error) {
|
|
r.MustAuthorize(ctx, input.AccessEntryID, probo.ActionAccessEntryFlag)
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.AccessEntryID)
|
|
|
|
entry, err := r.accessReview.Entries(scope).FlagEntry(ctx, accessreview.FlagAccessEntryRequest{
|
|
EntryID: input.AccessEntryID,
|
|
Flags: input.Flags,
|
|
FlagReasons: input.FlagReasons,
|
|
})
|
|
if err != nil {
|
|
return nil, types.FlagAccessEntryOutput{}, fmt.Errorf("cannot flag access entry: %w", err)
|
|
}
|
|
|
|
return nil, types.FlagAccessEntryOutput{
|
|
AccessEntry: types.NewAccessEntry(entry),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) GetAuditReportUrlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAuditReportUrlInput) (*mcp.CallToolResult, types.GetAuditReportUrlOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionReportGetReportUrl)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
url, err := prb.Audits.GenerateReportURL(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentArchive)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
document, err := svc.Documents.Archive(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentUnarchive)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
document, err := svc.Documents.Unarchive(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionOrganizationContextGet)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
orgContext, err := prb.Organizations.GetContext(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionOrganizationContextUpdate)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
orgContext, err := prb.Organizations.UpdateContext(
|
|
ctx,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, iam.ActionAuditLogEntryGet)
|
|
|
|
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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, iam.ActionAuditLogEntryList)
|
|
|
|
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) RequestDocumentVersionApprovalTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RequestDocumentVersionApprovalInput) (*mcp.CallToolResult, types.RequestDocumentVersionApprovalOutput, error) {
|
|
r.MustAuthorize(ctx, input.DocumentID, probo.ActionDocumentVersionRequestApproval)
|
|
|
|
svc := r.ProboService(ctx, input.DocumentID)
|
|
|
|
quorum, err := svc.DocumentApprovals.RequestApproval(ctx, probo.RequestApprovalRequest{
|
|
DocumentID: input.DocumentID,
|
|
ApproverIDs: input.ApproverIds,
|
|
Changelog: input.Changelog,
|
|
})
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot request document version approval: %w", err))
|
|
}
|
|
|
|
documentVersion, err := svc.Documents.GetVersion(ctx, quorum.VersionID)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot get document version: %w", err))
|
|
}
|
|
|
|
return nil, types.RequestDocumentVersionApprovalOutput{
|
|
DocumentVersion: types.NewDocumentVersion(documentVersion),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) PublishMajorDocumentVersionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishMajorDocumentVersionInput) (*mcp.CallToolResult, types.PublishMajorDocumentVersionOutput, error) {
|
|
r.MustAuthorize(ctx, input.DocumentID, probo.ActionDocumentVersionPublish)
|
|
|
|
svc := r.ProboService(ctx, input.DocumentID)
|
|
user := authn.IdentityFromContext(ctx)
|
|
|
|
document, documentVersion, err := svc.Documents.PublishMajorVersion(
|
|
ctx,
|
|
input.DocumentID,
|
|
user.ID,
|
|
input.Changelog,
|
|
)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot publish major document version: %w", err))
|
|
}
|
|
|
|
return nil, types.PublishMajorDocumentVersionOutput{
|
|
Document: types.NewDocument(document),
|
|
DocumentVersion: types.NewDocumentVersion(documentVersion),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) PublishMinorDocumentVersionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishMinorDocumentVersionInput) (*mcp.CallToolResult, types.PublishMinorDocumentVersionOutput, error) {
|
|
r.MustAuthorize(ctx, input.DocumentID, probo.ActionDocumentVersionPublish)
|
|
|
|
svc := r.ProboService(ctx, input.DocumentID)
|
|
user := authn.IdentityFromContext(ctx)
|
|
|
|
document, documentVersion, err := svc.Documents.PublishMinorVersion(
|
|
ctx,
|
|
input.DocumentID,
|
|
user.ID,
|
|
input.Changelog,
|
|
)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot publish minor document version: %w", err))
|
|
}
|
|
|
|
return nil, types.PublishMinorDocumentVersionOutput{
|
|
Document: types.NewDocument(document),
|
|
DocumentVersion: types.NewDocumentVersion(documentVersion),
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) ListMeasureDocumentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasureDocumentsInput) (*mcp.CallToolResult, types.ListMeasureDocumentsOutput, error) {
|
|
r.MustAuthorize(ctx, input.MeasureID, probo.ActionMeasureGet)
|
|
|
|
prb := r.ProboService(ctx, input.MeasureID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionVoidApproval)
|
|
|
|
svc := r.ProboService(ctx, input.DocumentVersionID)
|
|
|
|
_, documentVersion, err := svc.DocumentApprovals.VoidApproval(ctx, 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) SendSigningNotificationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.SendSigningNotificationsInput) (*mcp.CallToolResult, types.SendSigningNotificationsOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDocumentSendSigningNotifications)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
err := svc.Documents.SendSigningNotifications(ctx, input.OrganizationID)
|
|
if err != nil {
|
|
panic(fmt.Errorf("cannot send signing notifications: %w", err))
|
|
}
|
|
|
|
return nil, types.SendSigningNotificationsOutput{
|
|
Success: true,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Resolver) DeleteDocumentDraftTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteDocumentDraftInput) (*mcp.CallToolResult, types.DeleteDocumentDraftOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentDeleteDraft)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
document, err := svc.Documents.DeleteDraft(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionStatementOfApplicabilityPublish)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishStatementOfApplicability(ctx, input.ID, input.ApproverIds)
|
|
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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionWebhookSubscriptionList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionWebhookSubscriptionGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
subscription, err := prb.WebhookSubscriptions.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionWebhookSubscriptionCreate)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
subscription, err := prb.WebhookSubscriptions.Create(
|
|
ctx,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionWebhookSubscriptionUpdate)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
subscription, err := prb.WebhookSubscriptions.Update(
|
|
ctx,
|
|
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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionWebhookSubscriptionDelete)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
err := prb.WebhookSubscriptions.Delete(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.WebhookSubscriptionID, probo.ActionWebhookSubscriptionGet)
|
|
|
|
prb := r.ProboService(ctx, input.WebhookSubscriptionID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionApprovalList)
|
|
|
|
svc := r.ProboService(ctx, input.DocumentVersionID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentVersionApprovalList)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
quorum, err := svc.DocumentApprovals.GetQuorum(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.QuorumID, probo.ActionDocumentVersionApprovalList)
|
|
|
|
svc := r.ProboService(ctx, input.QuorumID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentVersionApprovalList)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
decision, err := svc.DocumentApprovals.GetDecision(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDatumPublish)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishDataList(ctx, input.OrganizationID, input.ApproverIds)
|
|
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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAssetPublish)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishAssetList(ctx, input.OrganizationID, input.ApproverIds)
|
|
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
|
|
}
|
|
|
|
// ListVendorContactsTool handles the listVendorContacts tool
|
|
// List all contacts for a vendor
|
|
func (r *Resolver) ListVendorContactsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListVendorContactsInput) (*mcp.CallToolResult, types.ListVendorContactsOutput, error) {
|
|
r.MustAuthorize(ctx, input.VendorID, probo.ActionVendorContactList)
|
|
|
|
prb := r.ProboService(ctx, input.VendorID)
|
|
|
|
pageOrderBy := page.OrderBy[coredata.VendorContactOrderField]{
|
|
Field: coredata.VendorContactOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.VendorContactOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := prb.VendorContacts.List(ctx, input.VendorID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListVendorContactsOutput{}, fmt.Errorf("cannot list vendor contacts: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListVendorContactsOutput(p), nil
|
|
}
|
|
|
|
// AddVendorContactTool handles the addVendorContact tool
|
|
// Add a new contact to a vendor
|
|
func (r *Resolver) AddVendorContactTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddVendorContactInput) (*mcp.CallToolResult, types.AddVendorContactOutput, error) {
|
|
r.MustAuthorize(ctx, input.VendorID, probo.ActionVendorContactCreate)
|
|
|
|
prb := r.ProboService(ctx, input.VendorID)
|
|
|
|
emailAddr, err := mail.ParseAddr(input.Email)
|
|
if err != nil {
|
|
return nil, types.AddVendorContactOutput{}, fmt.Errorf("invalid email address: %w", err)
|
|
}
|
|
|
|
vendorContact, err := prb.VendorContacts.Create(ctx, probo.CreateVendorContactRequest{
|
|
VendorID: input.VendorID,
|
|
FullName: &input.FullName,
|
|
Email: &emailAddr,
|
|
Phone: &input.Phone,
|
|
Role: &input.Role,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddVendorContactOutput{}, fmt.Errorf("cannot create vendor contact: %w", err)
|
|
}
|
|
|
|
return nil, types.AddVendorContactOutput{
|
|
VendorContact: types.NewVendorContact(vendorContact),
|
|
}, nil
|
|
}
|
|
|
|
// UpdateVendorContactTool handles the updateVendorContact tool
|
|
// Update an existing vendor contact
|
|
func (r *Resolver) UpdateVendorContactTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateVendorContactInput) (*mcp.CallToolResult, types.UpdateVendorContactOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionVendorContactUpdate)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
updateReq := probo.UpdateVendorContactRequest{
|
|
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.UpdateVendorContactOutput{}, 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
|
|
}
|
|
|
|
vendorContact, err := prb.VendorContacts.Update(ctx, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateVendorContactOutput{}, fmt.Errorf("cannot update vendor contact: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateVendorContactOutput{
|
|
VendorContact: types.NewVendorContact(vendorContact),
|
|
}, nil
|
|
}
|
|
|
|
// DeleteVendorContactTool handles the deleteVendorContact tool
|
|
// Delete a vendor contact
|
|
func (r *Resolver) DeleteVendorContactTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteVendorContactInput) (*mcp.CallToolResult, types.DeleteVendorContactOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionVendorContactDelete)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
err := prb.VendorContacts.Delete(ctx, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteVendorContactOutput{}, fmt.Errorf("cannot delete vendor contact: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteVendorContactOutput{
|
|
DeletedVendorContactID: input.ID,
|
|
}, nil
|
|
}
|
|
|
|
// ListVendorServicesTool handles the listVendorServices tool
|
|
// List all services for a vendor
|
|
func (r *Resolver) ListVendorServicesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListVendorServicesInput) (*mcp.CallToolResult, types.ListVendorServicesOutput, error) {
|
|
r.MustAuthorize(ctx, input.VendorID, probo.ActionVendorServiceList)
|
|
|
|
prb := r.ProboService(ctx, input.VendorID)
|
|
|
|
pageOrderBy := page.OrderBy[coredata.VendorServiceOrderField]{
|
|
Field: coredata.VendorServiceOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.VendorServiceOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := prb.VendorServices.List(ctx, input.VendorID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListVendorServicesOutput{}, fmt.Errorf("cannot list vendor services: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListVendorServicesOutput(p), nil
|
|
}
|
|
|
|
// AddVendorServiceTool handles the addVendorService tool
|
|
// Add a new service to a vendor
|
|
func (r *Resolver) AddVendorServiceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddVendorServiceInput) (*mcp.CallToolResult, types.AddVendorServiceOutput, error) {
|
|
r.MustAuthorize(ctx, input.VendorID, probo.ActionVendorServiceCreate)
|
|
|
|
prb := r.ProboService(ctx, input.VendorID)
|
|
|
|
vendorService, err := prb.VendorServices.Create(ctx, probo.CreateVendorServiceRequest{
|
|
VendorID: input.VendorID,
|
|
Name: input.Name,
|
|
Description: input.Description,
|
|
})
|
|
if err != nil {
|
|
return nil, types.AddVendorServiceOutput{}, fmt.Errorf("cannot create vendor service: %w", err)
|
|
}
|
|
|
|
return nil, types.AddVendorServiceOutput{
|
|
VendorService: types.NewVendorService(vendorService),
|
|
}, nil
|
|
}
|
|
|
|
// UpdateVendorServiceTool handles the updateVendorService tool
|
|
// Update an existing vendor service
|
|
func (r *Resolver) UpdateVendorServiceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateVendorServiceInput) (*mcp.CallToolResult, types.UpdateVendorServiceOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionVendorServiceUpdate)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
updateReq := probo.UpdateVendorServiceRequest{
|
|
ID: input.ID,
|
|
}
|
|
|
|
if input.Name != nil {
|
|
updateReq.Name = input.Name
|
|
}
|
|
|
|
if input.Description != nil {
|
|
updateReq.Description = &input.Description
|
|
}
|
|
|
|
vendorService, err := prb.VendorServices.Update(ctx, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateVendorServiceOutput{}, fmt.Errorf("cannot update vendor service: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateVendorServiceOutput{
|
|
VendorService: types.NewVendorService(vendorService),
|
|
}, nil
|
|
}
|
|
|
|
// DeleteVendorServiceTool handles the deleteVendorService tool
|
|
// Delete a vendor service
|
|
func (r *Resolver) DeleteVendorServiceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteVendorServiceInput) (*mcp.CallToolResult, types.DeleteVendorServiceOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionVendorServiceDelete)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
err := prb.VendorServices.Delete(ctx, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteVendorServiceOutput{}, fmt.Errorf("cannot delete vendor service: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteVendorServiceOutput{
|
|
DeletedVendorServiceID: input.ID,
|
|
}, nil
|
|
}
|
|
func (r *Resolver) DeleteAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteAssetInput) (*mcp.CallToolResult, types.DeleteAssetOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionAssetDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.Assets.Delete(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionDatumDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.Data.Delete(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionObligationDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.Obligations.Delete(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionAuditDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.Audits.Delete(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionRightsRequestList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
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, 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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionRightsRequestGet)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
rightsRequest, err := prb.RightsRequests.Get(ctx, 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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionRightsRequestCreate)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
rightsRequest, err := svc.RightsRequests.Create(
|
|
ctx,
|
|
&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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionRightsRequestUpdate)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
var dataSubject **string
|
|
if input.DataSubject != nil {
|
|
dataSubject = &input.DataSubject
|
|
}
|
|
|
|
rightsRequest, err := svc.RightsRequests.Update(
|
|
ctx,
|
|
&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) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionRightsRequestDelete)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
err := svc.RightsRequests.Delete(ctx, 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
|
|
}
|
|
|
|
// GetTrustCenterTool handles the getTrustCenter tool
|
|
// Get the trust center for an organization
|
|
func (r *Resolver) GetTrustCenterTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTrustCenterInput) (*mcp.CallToolResult, types.GetTrustCenterOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionTrustCenterGet)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
trustCenter, err := prb.TrustCenters.GetByOrganizationID(ctx, input.OrganizationID)
|
|
if err != nil {
|
|
return nil, types.GetTrustCenterOutput{}, fmt.Errorf("cannot get trust center: %w", err)
|
|
}
|
|
|
|
tc := types.NewTrustCenter(trustCenter)
|
|
|
|
logoURL, err := prb.TrustCenters.GenerateLogoURL(ctx, trustCenter.ID, 1*time.Hour)
|
|
if err == nil {
|
|
tc.LogoFileURL = logoURL
|
|
}
|
|
|
|
darkLogoURL, err := prb.TrustCenters.GenerateDarkLogoURL(ctx, trustCenter.ID, 1*time.Hour)
|
|
if err == nil {
|
|
tc.DarkLogoFileURL = darkLogoURL
|
|
}
|
|
|
|
ndaFileURL, err := prb.TrustCenters.GenerateNDAFileURL(ctx, trustCenter.ID, 15*time.Minute)
|
|
if err == nil {
|
|
tc.NdaFileURL = ndaFileURL
|
|
}
|
|
|
|
return nil, types.GetTrustCenterOutput{TrustCenter: tc}, nil
|
|
}
|
|
|
|
// UpdateTrustCenterTool handles the updateTrustCenter tool
|
|
// Update the trust center settings
|
|
func (r *Resolver) UpdateTrustCenterTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrustCenterInput) (*mcp.CallToolResult, types.UpdateTrustCenterOutput, error) {
|
|
r.MustAuthorize(ctx, input.TrustCenterID, probo.ActionTrustCenterUpdate)
|
|
|
|
prb := r.ProboService(ctx, input.TrustCenterID)
|
|
|
|
updateReq := &probo.UpdateTrustCenterRequest{
|
|
ID: input.TrustCenterID,
|
|
}
|
|
if active := UnwrapOmittable(input.Active); active != nil {
|
|
updateReq.Active = *active
|
|
}
|
|
if sei := UnwrapOmittable(input.SearchEngineIndexing); sei != nil {
|
|
updateReq.SearchEngineIndexing = *sei
|
|
}
|
|
|
|
trustCenter, _, err := prb.TrustCenters.Update(ctx, updateReq)
|
|
if err != nil {
|
|
return nil, types.UpdateTrustCenterOutput{}, fmt.Errorf("cannot update trust center: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateTrustCenterOutput{TrustCenter: types.NewTrustCenter(trustCenter)}, nil
|
|
}
|
|
|
|
// ListTrustCenterReferencesTool handles the listTrustCenterReferences tool
|
|
// List all references for a trust center
|
|
func (r *Resolver) ListTrustCenterReferencesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrustCenterReferencesInput) (*mcp.CallToolResult, types.ListTrustCenterReferencesOutput, error) {
|
|
r.MustAuthorize(ctx, input.TrustCenterID, probo.ActionTrustCenterReferenceList)
|
|
|
|
prb := r.ProboService(ctx, input.TrustCenterID)
|
|
|
|
pageOrderBy := page.OrderBy[coredata.TrustCenterReferenceOrderField]{
|
|
Field: coredata.TrustCenterReferenceOrderFieldRank,
|
|
Direction: page.OrderDirectionAsc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.TrustCenterReferenceOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := prb.TrustCenterReferences.ListForTrustCenterID(ctx, input.TrustCenterID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListTrustCenterReferencesOutput{}, fmt.Errorf("cannot list trust center references: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListTrustCenterReferencesOutput(p), nil
|
|
}
|
|
|
|
// AddTrustCenterReferenceTool handles the addTrustCenterReference tool
|
|
// Add a new reference to the trust center
|
|
func (r *Resolver) AddTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTrustCenterReferenceInput) (*mcp.CallToolResult, types.AddTrustCenterReferenceOutput, error) {
|
|
r.MustAuthorize(ctx, input.TrustCenterID, probo.ActionTrustCenterReferenceCreate)
|
|
|
|
prb := r.ProboService(ctx, input.TrustCenterID)
|
|
|
|
var websiteURL string
|
|
if input.WebsiteURL != nil {
|
|
websiteURL = *input.WebsiteURL
|
|
}
|
|
|
|
reference, err := prb.TrustCenterReferences.Create(
|
|
ctx,
|
|
&probo.CreateTrustCenterReferenceRequest{
|
|
TrustCenterID: input.TrustCenterID,
|
|
Name: input.Name,
|
|
Description: input.Description,
|
|
WebsiteURL: websiteURL,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddTrustCenterReferenceOutput{}, fmt.Errorf("cannot add trust center reference: %w", err)
|
|
}
|
|
|
|
return nil, types.AddTrustCenterReferenceOutput{TrustCenterReference: types.NewTrustCenterReference(reference)}, nil
|
|
}
|
|
|
|
// UpdateTrustCenterReferenceTool handles the updateTrustCenterReference tool
|
|
// Update a trust center reference
|
|
func (r *Resolver) UpdateTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrustCenterReferenceInput) (*mcp.CallToolResult, types.UpdateTrustCenterReferenceOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionTrustCenterReferenceUpdate)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
updateRefReq := &probo.UpdateTrustCenterReferenceRequest{
|
|
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.TrustCenterReferences.Update(ctx, updateRefReq)
|
|
if err != nil {
|
|
return nil, types.UpdateTrustCenterReferenceOutput{}, fmt.Errorf("cannot update trust center reference: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateTrustCenterReferenceOutput{TrustCenterReference: types.NewTrustCenterReference(reference)}, nil
|
|
}
|
|
|
|
// DeleteTrustCenterReferenceTool handles the deleteTrustCenterReference tool
|
|
// Delete a trust center reference
|
|
func (r *Resolver) DeleteTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTrustCenterReferenceInput) (*mcp.CallToolResult, types.DeleteTrustCenterReferenceOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionTrustCenterReferenceDelete)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
err := prb.TrustCenterReferences.Delete(ctx, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteTrustCenterReferenceOutput{}, fmt.Errorf("cannot delete trust center reference: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteTrustCenterReferenceOutput{DeletedTrustCenterReferenceID: input.ID}, nil
|
|
}
|
|
|
|
// ListTrustCenterFilesTool handles the listTrustCenterFiles tool
|
|
// List all files for the trust center
|
|
func (r *Resolver) ListTrustCenterFilesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrustCenterFilesInput) (*mcp.CallToolResult, types.ListTrustCenterFilesOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionTrustCenterFileList)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
pageOrderBy := page.OrderBy[coredata.TrustCenterFileOrderField]{
|
|
Field: coredata.TrustCenterFileOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.TrustCenterFileOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
filter := coredata.NewTrustCenterFileFilter()
|
|
|
|
p, err := prb.TrustCenterFiles.ListForOrganizationID(ctx, input.OrganizationID, cursor, filter)
|
|
if err != nil {
|
|
return nil, types.ListTrustCenterFilesOutput{}, fmt.Errorf("cannot list trust center files: %w", err)
|
|
}
|
|
|
|
files := make([]*types.TrustCenterFile, 0, len(p.Data))
|
|
for _, f := range p.Data {
|
|
fileURL, err := prb.TrustCenterFiles.GenerateFileURL(ctx, f.ID, 1*time.Hour)
|
|
if err != nil {
|
|
return nil, types.ListTrustCenterFilesOutput{}, fmt.Errorf("cannot generate file URL: %w", err)
|
|
}
|
|
files = append(files, types.NewTrustCenterFile(f, fileURL))
|
|
}
|
|
|
|
return nil, types.NewListTrustCenterFilesOutput(files, p), nil
|
|
}
|
|
|
|
// DeleteTrustCenterFileTool handles the deleteTrustCenterFile tool
|
|
// Delete a trust center file
|
|
func (r *Resolver) DeleteTrustCenterFileTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTrustCenterFileInput) (*mcp.CallToolResult, types.DeleteTrustCenterFileOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionTrustCenterFileDelete)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
err := prb.TrustCenterFiles.Delete(ctx, input.ID)
|
|
if err != nil {
|
|
return nil, types.DeleteTrustCenterFileOutput{}, fmt.Errorf("cannot delete trust center file: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteTrustCenterFileOutput{DeletedTrustCenterFileID: input.ID}, nil
|
|
}
|
|
|
|
// ListComplianceExternalURLsTool handles the listComplianceExternalURLs tool
|
|
// List all external URLs for a trust center
|
|
func (r *Resolver) ListComplianceExternalURLsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListComplianceExternalURLsInput) (*mcp.CallToolResult, types.ListComplianceExternalURLsOutput, error) {
|
|
r.MustAuthorize(ctx, input.TrustCenterID, probo.ActionComplianceExternalURLList)
|
|
|
|
prb := r.ProboService(ctx, input.TrustCenterID)
|
|
|
|
pageOrderBy := page.OrderBy[coredata.ComplianceExternalURLOrderField]{
|
|
Field: coredata.ComplianceExternalURLOrderFieldRank,
|
|
Direction: page.OrderDirectionAsc,
|
|
}
|
|
if input.OrderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.ComplianceExternalURLOrderField]{
|
|
Field: input.OrderBy.Field,
|
|
Direction: input.OrderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
|
|
|
p, err := prb.ComplianceExternalURLs.List(ctx, input.TrustCenterID, cursor)
|
|
if err != nil {
|
|
return nil, types.ListComplianceExternalURLsOutput{}, fmt.Errorf("cannot list compliance external URLs: %w", err)
|
|
}
|
|
|
|
return nil, types.NewListComplianceExternalURLsOutput(p), nil
|
|
}
|
|
|
|
// AddComplianceExternalURLTool handles the addComplianceExternalURL tool
|
|
// Add a new external URL to the trust center
|
|
func (r *Resolver) AddComplianceExternalURLTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddComplianceExternalURLInput) (*mcp.CallToolResult, types.AddComplianceExternalURLOutput, error) {
|
|
r.MustAuthorize(ctx, input.TrustCenterID, probo.ActionComplianceExternalURLCreate)
|
|
|
|
prb := r.ProboService(ctx, input.TrustCenterID)
|
|
|
|
item, err := prb.ComplianceExternalURLs.Create(
|
|
ctx,
|
|
&probo.CreateComplianceExternalURLRequest{
|
|
TrustCenterID: input.TrustCenterID,
|
|
Name: input.Name,
|
|
URL: input.URL,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AddComplianceExternalURLOutput{}, fmt.Errorf("cannot add compliance external URL: %w", err)
|
|
}
|
|
|
|
return nil, types.AddComplianceExternalURLOutput{ComplianceExternalURL: types.NewComplianceExternalURL(item)}, nil
|
|
}
|
|
|
|
// UpdateComplianceExternalURLTool handles the updateComplianceExternalURL tool
|
|
// Update a compliance external URL
|
|
func (r *Resolver) UpdateComplianceExternalURLTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateComplianceExternalURLInput) (*mcp.CallToolResult, types.UpdateComplianceExternalURLOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionComplianceExternalURLUpdate)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
updateURLReq := &probo.UpdateComplianceExternalURLRequest{
|
|
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.ComplianceExternalURLs.Update(ctx, updateURLReq)
|
|
if err != nil {
|
|
return nil, types.UpdateComplianceExternalURLOutput{}, fmt.Errorf("cannot update compliance external URL: %w", err)
|
|
}
|
|
|
|
return nil, types.UpdateComplianceExternalURLOutput{ComplianceExternalURL: types.NewComplianceExternalURL(item)}, nil
|
|
}
|
|
|
|
// DeleteComplianceExternalURLTool handles the deleteComplianceExternalURL tool
|
|
// Delete a compliance external URL
|
|
func (r *Resolver) DeleteComplianceExternalURLTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteComplianceExternalURLInput) (*mcp.CallToolResult, types.DeleteComplianceExternalURLOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionComplianceExternalURLDelete)
|
|
|
|
prb := r.ProboService(ctx, input.ID)
|
|
|
|
err := prb.ComplianceExternalURLs.Delete(
|
|
ctx,
|
|
&probo.DeleteComplianceExternalURLRequest{
|
|
ID: input.ID,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.DeleteComplianceExternalURLOutput{}, fmt.Errorf("cannot delete compliance external URL: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteComplianceExternalURLOutput{DeletedComplianceExternalURLID: input.ID}, nil
|
|
}
|
|
|
|
// CreateCustomDomainTool handles the createCustomDomain tool
|
|
// Create a custom domain for the organization
|
|
func (r *Resolver) CreateCustomDomainTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateCustomDomainInput) (*mcp.CallToolResult, types.CreateCustomDomainOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionCustomDomainCreate)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
domain, err := prb.CustomDomains.CreateCustomDomain(
|
|
ctx,
|
|
probo.CreateCustomDomainRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Domain: input.Domain,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.CreateCustomDomainOutput{}, fmt.Errorf("cannot create custom domain: %w", err)
|
|
}
|
|
|
|
return nil, types.CreateCustomDomainOutput{CustomDomain: types.NewCustomDomain(domain)}, nil
|
|
}
|
|
|
|
// DeleteCustomDomainTool handles the deleteCustomDomain tool
|
|
// Delete the custom domain for the organization
|
|
func (r *Resolver) DeleteCustomDomainTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCustomDomainInput) (*mcp.CallToolResult, types.DeleteCustomDomainOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionCustomDomainDelete)
|
|
|
|
prb := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
domain, err := prb.CustomDomains.GetOrganizationCustomDomain(ctx, input.OrganizationID)
|
|
if err != nil {
|
|
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot get custom domain: %w", err)
|
|
}
|
|
|
|
if domain == nil {
|
|
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("organization has no custom domain")
|
|
}
|
|
|
|
deletedDomain := types.NewCustomDomain(domain)
|
|
|
|
if err := prb.CustomDomains.DeleteCustomDomain(ctx, input.OrganizationID); err != nil {
|
|
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot delete custom domain: %w", err)
|
|
}
|
|
|
|
return nil, types.DeleteCustomDomainOutput{DeletedCustomDomain: deletedDomain}, nil
|
|
}
|
|
|
|
func (r *Resolver) AssessVendorTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AssessVendorInput) (*mcp.CallToolResult, types.AssessVendorOutput, error) {
|
|
r.MustAuthorize(ctx, input.ID, probo.ActionVendorAssess)
|
|
|
|
svc := r.ProboService(ctx, input.ID)
|
|
|
|
result, err := svc.Vendors.Assess(
|
|
ctx,
|
|
probo.AssessVendorRequest{
|
|
ID: input.ID,
|
|
WebsiteURL: input.WebsiteURL,
|
|
Procedure: input.Procedure,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, types.AssessVendorOutput{}, fmt.Errorf("cannot assess vendor: %w", err)
|
|
}
|
|
|
|
return nil, types.NewAssessVendorOutput(result), nil
|
|
}
|
|
|
|
func (r *Resolver) PublishFindingListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishFindingListInput) (*mcp.CallToolResult, types.PublishFindingListOutput, error) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionFindingPublish)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishFindingList(ctx, input.OrganizationID, input.ApproverIds)
|
|
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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionObligationPublish)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishObligationList(ctx, input.OrganizationID, input.ApproverIds)
|
|
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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionProcessingActivityPublish)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishProcessingActivityList(ctx, input.OrganizationID, input.ApproverIds)
|
|
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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDataProtectionImpactAssessmentPublish)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishDataProtectionImpactAssessmentList(ctx, input.OrganizationID, input.ApproverIds)
|
|
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) {
|
|
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionTransferImpactAssessmentPublish)
|
|
|
|
svc := r.ProboService(ctx, input.OrganizationID)
|
|
|
|
document, documentVersion, err := svc.GeneratedDocuments.PublishTransferImpactAssessmentList(ctx, input.OrganizationID, input.ApproverIds)
|
|
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
|
|
}
|