diff --git a/api/questionnaire.go b/api/questionnaire.go index 890ffb2d2..cc7d3699e 100644 --- a/api/questionnaire.go +++ b/api/questionnaire.go @@ -123,6 +123,10 @@ func (h QuestionnaireHandler) Delete(ctx *gin.Context) { _ = ctx.Error(result.Error) return } + if m.Builtin() { + h.Status(ctx, http.StatusForbidden) + return + } result = h.DB(ctx).Delete(m) if result.Error != nil { _ = ctx.Error(result.Error) @@ -134,7 +138,9 @@ func (h QuestionnaireHandler) Delete(ctx *gin.Context) { // Update godoc // @summary Update a questionnaire. -// @description Update a questionnaire. +// @description Update a questionnaire. If the Questionnaire +// @description is builtin, only its "required" field can be changed +// @description and all other fields will be ignored. // @tags questionnaires // @accept json // @success 204 @@ -149,12 +155,30 @@ func (h QuestionnaireHandler) Update(ctx *gin.Context) { _ = ctx.Error(err) return } - m := r.Model() - m.ID = id - m.UpdateUser = h.CurrentUser(ctx) - db := h.DB(ctx).Model(m) + m := &model.Questionnaire{} + db := h.DB(ctx) + result := db.First(m, id) + if result.Error != nil { + _ = ctx.Error(result.Error) + return + } + + updated := r.Model() + updated.ID = id + updated.UpdateUser = h.CurrentUser(ctx) + var fields map[string]interface{} + if m.Builtin() { + fields = map[string]interface{}{ + "updateUser": updated.UpdateUser, + "required": updated.Required, + } + } else { + fields = h.fields(updated) + } + + db = h.DB(ctx).Model(m) db = db.Omit(clause.Associations) - result := db.Updates(h.fields(m)) + result = db.Updates(fields) if result.Error != nil { _ = ctx.Error(result.Error) return @@ -171,6 +195,7 @@ type Questionnaire struct { Sections []assessment.Section `json:"sections" yaml:"sections" binding:"required"` Thresholds assessment.Thresholds `json:"thresholds" yaml:"thresholds" binding:"required"` RiskMessages assessment.RiskMessages `json:"riskMessages" yaml:"riskMessages" binding:"required"` + Builtin bool `json:"builtin,omitempty" yaml:"builtin,omitempty"` } // With updates the resource with the model. @@ -179,6 +204,7 @@ func (r *Questionnaire) With(m *model.Questionnaire) { r.Name = m.Name r.Description = m.Description r.Required = m.Required + r.Builtin = m.Builtin() _ = json.Unmarshal(m.Sections, &r.Sections) _ = json.Unmarshal(m.Thresholds, &r.Thresholds) _ = json.Unmarshal(m.RiskMessages, &r.RiskMessages) diff --git a/migration/v10/model/assessment.go b/migration/v10/model/assessment.go index f3eeddfa0..a8cc0b6fe 100644 --- a/migration/v10/model/assessment.go +++ b/migration/v10/model/assessment.go @@ -12,6 +12,12 @@ type Questionnaire struct { Assessments []Assessment `gorm:"constraint:OnDelete:CASCADE"` } +// +// Builtin returns true if this is a Konveyor-provided questionnaire. +func (r *Questionnaire) Builtin() bool { + return r.UUID != nil +} + type Assessment struct { Model ApplicationID *uint `gorm:"uniqueIndex:AssessmentA"`