Allow editing metadata of generated document versions
Title, document type, and classification on generated documents could not be changed: any version-tracked field on a GENERATED write-mode document was rejected with ErrDocumentVersionGenerated. The error now fires only when content is being changed, so manual metadata edits flow through the same draft-on-edit path as authored documents and produce a draft version that the user can review and publish. The CLI document update --document-type enum gains STATEMENT_OF_APPLICABILITY (which generated SoA documents already use), and the GraphQL resolver maps the content-edit rejection to a Conflict instead of falling through to a generic Internal error. Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -106,7 +106,7 @@ func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command {
|
||||
if err := cmdutil.ValidateEnum(
|
||||
"document-type",
|
||||
flagDocumentType,
|
||||
[]string{"OTHER", "GOVERNANCE", "POLICY", "PROCEDURE", "PLAN", "REGISTER", "RECORD", "REPORT", "TEMPLATE"},
|
||||
[]string{"OTHER", "GOVERNANCE", "POLICY", "PROCEDURE", "PLAN", "REGISTER", "RECORD", "REPORT", "TEMPLATE", "STATEMENT_OF_APPLICABILITY"},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -174,7 +174,7 @@ func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command {
|
||||
|
||||
cmd.Flags().StringVar(&flagTitle, "title", "", "Document title")
|
||||
cmd.Flags().StringVar(&flagContent, "content", "", "Document content")
|
||||
cmd.Flags().StringVar(&flagDocumentType, "document-type", "", "Document type: OTHER, GOVERNANCE, POLICY, PROCEDURE, PLAN, REGISTER, RECORD, REPORT, TEMPLATE")
|
||||
cmd.Flags().StringVar(&flagDocumentType, "document-type", "", "Document type: OTHER, GOVERNANCE, POLICY, PROCEDURE, PLAN, REGISTER, RECORD, REPORT, TEMPLATE, STATEMENT_OF_APPLICABILITY")
|
||||
cmd.Flags().StringVar(&flagClassification, "classification", "", "Classification: PUBLIC, INTERNAL, CONFIDENTIAL, SECRET")
|
||||
cmd.Flags().StringVar(&flagTrustCenterVisibility, "trust-center-visibility", "", "Trust center visibility: NONE, PRIVATE, PUBLIC")
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ func (e ErrDocumentGenerated) Error() string {
|
||||
}
|
||||
|
||||
func (e ErrDocumentVersionGenerated) Error() string {
|
||||
return "cannot edit a generated document version"
|
||||
return "cannot edit content of a generated document version"
|
||||
}
|
||||
|
||||
func (e ErrDocumentVersionSignatureAlreadySigned) Error() string {
|
||||
@@ -1800,7 +1800,7 @@ func (s *DocumentService) Update(
|
||||
|
||||
hasVersionChanges := req.Title != nil || req.Content != nil || req.Classification != nil || req.DocumentType != nil
|
||||
|
||||
if hasVersionChanges && document.WriteMode == coredata.DocumentWriteModeGenerated {
|
||||
if req.Content != nil && document.WriteMode == coredata.DocumentWriteModeGenerated {
|
||||
return &ErrDocumentVersionGenerated{}
|
||||
}
|
||||
|
||||
|
||||
@@ -2909,6 +2909,19 @@ func (s *GeneratedDocumentService) publishOrRequestApproval(
|
||||
minor bool,
|
||||
now time.Time,
|
||||
) error {
|
||||
previousVersion := &coredata.DocumentVersion{}
|
||||
err := previousVersion.LoadLatestVersion(ctx, tx, s.svc.scope, document.ID)
|
||||
switch {
|
||||
case err == nil:
|
||||
version.Title = previousVersion.Title
|
||||
version.Classification = previousVersion.Classification
|
||||
version.DocumentType = previousVersion.DocumentType
|
||||
case errors.Is(err, coredata.ErrResourceNotFound):
|
||||
// First publish: keep the caller-provided defaults.
|
||||
default:
|
||||
return fmt.Errorf("cannot load previous document version: %w", err)
|
||||
}
|
||||
|
||||
if minor {
|
||||
if document.CurrentPublishedMajor == nil || document.CurrentPublishedMinor == nil {
|
||||
return &ErrCannotPublishMinorWithoutMajor{}
|
||||
@@ -2936,7 +2949,14 @@ func (s *GeneratedDocumentService) publishOrRequestApproval(
|
||||
|
||||
if err := version.Insert(ctx, tx, s.svc.scope); err != nil {
|
||||
if errors.Is(err, coredata.ErrResourceAlreadyExists) {
|
||||
return fmt.Errorf("a version is pending approval, approve or reject it before publishing a new one: %w", err)
|
||||
switch previousVersion.Status {
|
||||
case coredata.DocumentVersionStatusDraft:
|
||||
return fmt.Errorf("a draft version exists, publish or delete it before publishing a new one: %w", err)
|
||||
case coredata.DocumentVersionStatusPendingApproval:
|
||||
return fmt.Errorf("a version is pending approval, approve or reject it before publishing a new one: %w", err)
|
||||
default:
|
||||
return fmt.Errorf("a version already exists at this number: %w", err)
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("cannot insert document version: %w", err)
|
||||
}
|
||||
|
||||
@@ -864,6 +864,9 @@ func (r *mutationResolver) UpdateDocument(ctx context.Context, input types.Updat
|
||||
if errArchived, ok := errors.AsType[*probo.ErrDocumentArchived](err); ok {
|
||||
return nil, gqlutils.Conflict(ctx, errArchived)
|
||||
}
|
||||
if errGenerated, ok := errors.AsType[*probo.ErrDocumentVersionGenerated](err); ok {
|
||||
return nil, gqlutils.Conflict(ctx, errGenerated)
|
||||
}
|
||||
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
|
||||
return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user