// Load returns the work item link type for the given ID.
// Returns NotFoundError, ConversionError or InternalError
func (r *GormWorkItemLinkTypeRepository) Load(ctx context.Context, ID string) (*app.WorkItemLinkTypeSingle, error) {
	id, err := satoriuuid.FromString(ID)
	if err != nil {
		// treat as not found: clients don't know it must be a UUID
		return nil, errors.NewNotFoundError("work item link type", ID)
	}
	log.Info(ctx, map[string]interface{}{
		"pkg":    "link",
		"wiltID": ID,
	}, "Loading work item link type")
	res := WorkItemLinkType{}
	db := r.db.Model(&res).Where("id=?", ID).First(&res)
	if db.RecordNotFound() {
		log.Error(ctx, map[string]interface{}{
			"wiltID": ID,
		}, "work item link type not found")
		return nil, errors.NewNotFoundError("work item link type", id.String())
	}
	if db.Error != nil {
		return nil, errors.NewInternalError(db.Error.Error())
	}
	// Convert the created link type entry into a JSONAPI response
	result := ConvertLinkTypeFromModel(res)

	return &result, nil
}
Exemple #2
0
// Delete deletes the space with the given id
// returns NotFoundError or InternalError
func (r *GormRepository) Delete(ctx context.Context, ID satoriuuid.UUID) error {
	if ID == satoriuuid.Nil {
		log.Error(ctx, map[string]interface{}{
			"spaceID": ID.String(),
		}, "unable to find the space by ID")
		return errors.NewNotFoundError("space", ID.String())
	}
	space := Space{ID: ID}
	tx := r.db.Delete(space)

	if err := tx.Error; err != nil {
		log.Error(ctx, map[string]interface{}{
			"spaceID": ID.String(),
		}, "unable to delete the space")
		return errors.NewInternalError(err.Error())
	}
	if tx.RowsAffected == 0 {
		log.Error(ctx, map[string]interface{}{
			"spaceID": ID.String(),
		}, "none row was affected by the deletion operation")
		return errors.NewNotFoundError("space", ID.String())
	}

	return nil
}
// Delete deletes the work item link with the given id
// returns NotFoundError or InternalError
func (r *GormWorkItemLinkRepository) Delete(ctx context.Context, ID string) error {
	id, err := satoriuuid.FromString(ID)
	if err != nil {
		// treat as not found: clients don't know it must be a UUID
		return errors.NewNotFoundError("work item link", ID)
	}
	var link = WorkItemLink{
		ID: id,
	}
	log.Info(ctx, map[string]interface{}{
		"pkg":   "link",
		"wilID": ID,
	}, "Deleting the work item link repository")

	db := r.db.Delete(&link)
	if db.Error != nil {
		log.Error(ctx, map[string]interface{}{
			"wilID": ID,
			"err":   db.Error,
		}, "unable to delete work item link repository")
		return errors.NewInternalError(db.Error.Error())
	}
	if db.RowsAffected == 0 {
		return errors.NewNotFoundError("work item link", id.String())
	}
	return nil
}
// Delete deletes the work item link category with the given id
// returns NotFoundError or InternalError
func (r *GormWorkItemLinkCategoryRepository) Delete(ctx context.Context, ID string) error {
	id, err := satoriuuid.FromString(ID)
	if err != nil {
		// treat as not found: clients don't know it must be a UUID
		return errors.NewNotFoundError("work item link category", ID)
	}

	var cat = WorkItemLinkCategory{
		ID: id,
	}

	log.Info(ctx, map[string]interface{}{
		"pkg":    "link",
		"wilcID": ID,
	}, "Work item link category to delete")

	db := r.db.Delete(&cat)
	if db.Error != nil {
		return errors.NewInternalError(db.Error.Error())
	}

	if db.RowsAffected == 0 {
		return errors.NewNotFoundError("work item link category", id.String())
	}
	return nil
}
Exemple #5
0
// Delete a single comment
func (m *GormCommentRepository) Delete(ctx context.Context, id uuid.UUID) error {
	if id == uuid.Nil {
		return errors.NewNotFoundError("comment", id.String())
	}
	tx := m.db.Delete(&Comment{ID: id})
	if tx.RowsAffected == 0 {
		return errors.NewNotFoundError("comment", id.String())
	}
	if err := tx.Error; err != nil {
		return errors.NewInternalError(err.Error())
	}
	return nil
}
// LoadTypeFromDB return work item type for the given id
func (r *GormWorkItemTypeRepository) LoadTypeFromDB(ctx context.Context, name string) (*WorkItemType, error) {
	log.Logger().Infoln("Loading work item type", name)
	res, ok := cache.Get(name)
	if !ok {
		log.Info(ctx, map[string]interface{}{
			"pkg":  "workitem",
			"type": name,
		}, "Work item type doesn't exist in the cache. Loading from DB...")
		res = WorkItemType{}

		db := r.db.Model(&res).Where("name=?", name).First(&res)
		if db.RecordNotFound() {
			log.Error(ctx, map[string]interface{}{
				"witName": name,
			}, "work item type repository not found")
			return nil, errors.NewNotFoundError("work item type", name)
		}
		if err := db.Error; err != nil {
			return nil, errors.NewInternalError(err.Error())
		}
		cache.Put(res)
	}

	return &res, nil
}
Exemple #7
0
// Save updates the given iteration in the db. Version must be the same as the one in the stored version
// returns NotFoundError, VersionConflictError or InternalError
func (m *GormIterationRepository) Save(ctx context.Context, i Iteration) (*Iteration, error) {
	itr := Iteration{}
	tx := m.db.Where("id=?", i.ID).First(&itr)
	if tx.RecordNotFound() {
		log.Error(ctx, map[string]interface{}{
			"iterationID": i.ID,
		}, "iteration cannot be found")
		// treating this as a not found error: the fact that we're using number internal is implementation detail
		return nil, errors.NewNotFoundError("iteration", i.ID.String())
	}
	if err := tx.Error; err != nil {
		log.Error(ctx, map[string]interface{}{
			"iterationID": i.ID,
			"err":         err,
		}, "unknown error happened when searching the iteration")
		return nil, errors.NewInternalError(err.Error())
	}
	tx = tx.Save(&i)
	if err := tx.Error; err != nil {
		log.Error(ctx, map[string]interface{}{
			"iterationID": i.ID,
			"err":         err,
		}, "unable to save the iterations")
		return nil, errors.NewInternalError(err.Error())
	}
	return &i, nil
}
Exemple #8
0
// Save updates the given space in the db. Version must be the same as the one in the stored version
// returns NotFoundError, BadParameterError, VersionConflictError or InternalError
func (r *GormRepository) Save(ctx context.Context, p *Space) (*Space, error) {
	pr := Space{}
	tx := r.db.Where("id=?", p.ID).First(&pr)
	oldVersion := p.Version
	p.Version++
	if tx.RecordNotFound() {
		// treating this as a not found error: the fact that we're using number internal is implementation detail
		return nil, errors.NewNotFoundError("space", p.ID.String())
	}
	if err := tx.Error; err != nil {
		return nil, errors.NewInternalError(err.Error())
	}
	tx = tx.Where("Version = ?", oldVersion).Save(p)
	if err := tx.Error; err != nil {
		if gormsupport.IsCheckViolation(tx.Error, "spaces_name_check") {
			return nil, errors.NewBadParameterError("Name", p.Name).Expected("not empty")
		}
		if gormsupport.IsUniqueViolation(tx.Error, "spaces_name_idx") {
			return nil, errors.NewBadParameterError("Name", p.Name).Expected("unique")
		}
		return nil, errors.NewInternalError(err.Error())
	}
	if tx.RowsAffected == 0 {
		return nil, errors.NewVersionConflictError("version conflict")
	}

	log.Info(ctx, map[string]interface{}{
		"pkg":     "space",
		"spaceID": p.ID,
	}, "space updated successfully")
	return p, nil
}
Exemple #9
0
// ParseWorkItemIDToUint64 does what it says
func ParseWorkItemIDToUint64(wiIDStr string) (uint64, error) {
	wiID, err := strconv.ParseUint(wiIDStr, 10, 64)
	if err != nil {
		return 0, errors.NewNotFoundError("work item ID", wiIDStr)
	}
	return wiID, nil
}
// Delete implements application.WorkItemRepository
func (r *UndoableWorkItemRepository) Delete(ctx context.Context, ID string) error {
	id, err := strconv.ParseUint(ID, 10, 64)
	if err != nil {
		// treating this as a not found error: the fact that we're using number internal is implementation detail
		return errors.NewNotFoundError("work item", ID)
	}

	log.Info(ctx, map[string]interface{}{
		"pkg": "workitem",
		"id":  id,
	}, "Loading work iteme")

	old := WorkItem{}
	db := r.wrapped.db.First(&old, id)
	if db.Error != nil {
		return errors.NewInternalError(fmt.Sprintf("could not load %s, %s", ID, db.Error.Error()))
	}

	err = r.wrapped.Delete(ctx, ID)
	if err == nil {
		r.undo.Append(func(db *gorm.DB) error {
			old.DeletedAt = nil
			db = db.Save(&old)
			return db.Error
		})
	}
	return errs.WithStack(err)
}
func TestNewNotFoundError(t *testing.T) {
	t.Parallel()
	resource.Require(t, resource.UnitTest)
	param := "assigness"
	value := "10"
	err := errors.NewNotFoundError(param, value)
	assert.Equal(t, fmt.Sprintf("%s with id '%s' not found", param, value), err.Error())
}
// Delete deletes the work item with the given id
// returns NotFoundError or InternalError
func (r *GormWorkItemRepository) Delete(ctx context.Context, ID string) error {
	var workItem = WorkItem{}
	id, err := strconv.ParseUint(ID, 10, 64)
	if err != nil || id == 0 {
		// treat as not found: clients don't know it must be a number
		return errors.NewNotFoundError("work item", ID)
	}
	workItem.ID = id
	tx := r.db.Delete(workItem)

	if err = tx.Error; err != nil {
		return errors.NewInternalError(err.Error())
	}
	if tx.RowsAffected == 0 {
		return errors.NewNotFoundError("work item", ID)
	}

	return nil
}
// DeleteRelatedLinks deletes all links in which the source or target equals the
// given work item ID.
func (r *GormWorkItemLinkRepository) DeleteRelatedLinks(ctx context.Context, wiIDStr string) error {
	wiId, err := strconv.ParseUint(wiIDStr, 10, 64)
	if err != nil {
		// treat as not found: clients don't know it must be a uint64
		return errors.NewNotFoundError("work item link", wiIDStr)
	}
	db := r.db.Where("? in (source_id, target_id)", wiId).Delete(&WorkItemLink{})
	if db.Error != nil {
		return errors.NewInternalError(db.Error.Error())
	}
	return nil
}
Exemple #14
0
// Load a single Area regardless of parent
func (m *GormAreaRepository) Load(ctx context.Context, id uuid.UUID) (*Area, error) {
	defer goa.MeasureSince([]string{"goa", "db", "Area", "get"}, time.Now())
	var obj Area

	tx := m.db.Where("id = ?", id).First(&obj)
	if tx.RecordNotFound() {
		return nil, errors.NewNotFoundError("Area", id.String())
	}
	if tx.Error != nil {
		return nil, errors.NewInternalError(tx.Error.Error())
	}
	return &obj, nil
}
Exemple #15
0
// Load returns the space for the given id
// returns NotFoundError or InternalError
func (r *GormRepository) Load(ctx context.Context, ID satoriuuid.UUID) (*Space, error) {
	res := Space{}
	tx := r.db.Where("id=?", ID).First(&res)
	if tx.RecordNotFound() {
		log.Error(ctx, map[string]interface{}{
			"spaceID": ID.String(),
		}, "state or known referer was empty")
		return nil, errors.NewNotFoundError("space", ID.String())
	}
	if tx.Error != nil {
		return nil, errors.NewInternalError(tx.Error.Error())
	}
	return &res, nil
}
// LoadFromDB returns the work item with the given ID in model representation.
func (r *GormWorkItemRepository) LoadFromDB(ctx context.Context, ID string) (*WorkItem, error) {
	id, err := strconv.ParseUint(ID, 10, 64)
	if err != nil || id == 0 {
		// treating this as a not found error: the fact that we're using number internal is implementation detail
		return nil, errors.NewNotFoundError("work item", ID)
	}
	log.Info(nil, map[string]interface{}{
		"pkg":  "workitem",
		"wiID": ID,
	}, "Loading work item")

	res := WorkItem{}
	tx := r.db.First(&res, id)
	if tx.RecordNotFound() {
		log.Error(nil, map[string]interface{}{
			"wiID": ID,
		}, "work item not found")
		return nil, errors.NewNotFoundError("work item", ID)
	}
	if tx.Error != nil {
		return nil, errors.NewInternalError(tx.Error.Error())
	}
	return &res, nil
}
Exemple #17
0
// ListChildren fetches all Areas belonging to a parent - list all child areas.
func (m *GormAreaRepository) ListChildren(ctx context.Context, parentArea *Area) ([]*Area, error) {
	defer goa.MeasureSince([]string{"goa", "db", "Area", "querychild"}, time.Now())
	var objs []*Area

	predicateString := (parentArea.ID).String()
	if parentArea.Path != "" {
		predicateString = parentArea.Path + "." + predicateString
	}
	tx := m.db.Where("path ~ ?", ConvertToLtreeFormat(predicateString)).Find(&objs)
	if tx.RecordNotFound() {
		return nil, errors.NewNotFoundError("Area", parentArea.ID.String())
	}
	if tx.Error != nil {
		return nil, errors.NewInternalError(tx.Error.Error())
	}
	return objs, nil
}
// Save updates the given work item link in storage. Version must be the same as the one int the stored version.
// returns NotFoundError, VersionConflictError, ConversionError or InternalError
func (r *GormWorkItemLinkRepository) Save(ctx context.Context, lt app.WorkItemLinkSingle) (*app.WorkItemLinkSingle, error) {
	res := WorkItemLink{}
	if lt.Data.ID == nil {
		return nil, errors.NewBadParameterError("work item link", nil)
	}
	db := r.db.Model(&res).Where("id=?", *lt.Data.ID).First(&res)
	if db.RecordNotFound() {
		log.Error(ctx, map[string]interface{}{
			"wilID": *lt.Data.ID,
		}, "work item link not found")
		return nil, errors.NewNotFoundError("work item link", *lt.Data.ID)
	}
	if db.Error != nil {
		log.Error(ctx, map[string]interface{}{
			"wilID": *lt.Data.ID,
			"err":   db.Error,
		}, "unable to find work item link")
		return nil, errors.NewInternalError(db.Error.Error())
	}
	if lt.Data.Attributes.Version == nil || res.Version != *lt.Data.Attributes.Version {
		return nil, errors.NewVersionConflictError("version conflict")
	}
	if err := ConvertLinkToModel(lt, &res); err != nil {
		return nil, errs.WithStack(err)
	}
	res.Version = res.Version + 1
	if err := r.ValidateCorrectSourceAndTargetType(ctx, res.SourceID, res.TargetID, res.LinkTypeID); err != nil {
		return nil, errs.WithStack(err)
	}
	db = r.db.Save(&res)
	if db.Error != nil {
		log.Error(ctx, map[string]interface{}{
			"wilID": res.ID,
			"err":   db.Error,
		}, "unable to save work item link")
		return nil, errors.NewInternalError(db.Error.Error())
	}

	log.Info(ctx, map[string]interface{}{
		"pkg":   "link",
		"wilID": res.ID,
	}, "Work item link updated")
	result := ConvertLinkFromModel(res)
	return &result, nil
}
// LoadCategoryFromDB return work item link category for the name
func (r *GormWorkItemLinkCategoryRepository) LoadCategoryFromDB(ctx context.Context, name string) (*WorkItemLinkCategory, error) {
	log.Info(ctx, map[string]interface{}{
		"pkg":          "link",
		"categoryName": name,
	}, "Loading work item link category: %s", name)

	res := WorkItemLinkCategory{}
	db := r.db.Model(&res).Where("name=?", name).First(&res)
	if db.RecordNotFound() {
		log.Error(ctx, map[string]interface{}{
			"wilcName": name,
		}, "work item link category not found")
		return nil, errors.NewNotFoundError("work item link category", name)
	}
	if db.Error != nil {
		return nil, errors.NewInternalError(db.Error.Error())
	}
	return &res, nil
}
// LoadTypeFromDB return work item link type for the given ID
func (r *GormWorkItemLinkTypeRepository) LoadTypeFromDBByID(ctx context.Context, ID satoriuuid.UUID) (*WorkItemLinkType, error) {
	log.Info(ctx, map[string]interface{}{
		"pkg":    "link",
		"wiltID": ID.String(),
	}, "Loading work item link type with ID ", ID)

	res := WorkItemLinkType{}
	db := r.db.Model(&res).Where("ID=?", ID.String()).First(&res)
	if db.RecordNotFound() {
		log.Error(ctx, map[string]interface{}{
			"wiltID": ID.String(),
		}, "work item link type not found")
		return nil, errors.NewNotFoundError("work item link type", ID.String())
	}
	if db.Error != nil {
		return nil, errors.NewInternalError(db.Error.Error())
	}
	return &res, nil
}
// Create implements application.WorkItemRepository
func (r *UndoableWorkItemRepository) Create(ctx context.Context, typeID string, fields map[string]interface{}, creator string) (*app.WorkItem, error) {
	result, err := r.wrapped.Create(ctx, typeID, fields, creator)
	if err != nil {
		return result, errs.WithStack(err)
	}
	id, err := strconv.ParseUint(result.ID, 10, 64)
	if err != nil {
		// treating this as a not found error: the fact that we're using number internal is implementation detail
		return nil, errors.NewNotFoundError("work item", result.ID)
	}

	toDelete := WorkItem{ID: id}

	r.undo.Append(func(db *gorm.DB) error {
		db = db.Unscoped().Delete(&toDelete)
		return db.Error
	})

	return result, errs.WithStack(err)
}
Exemple #22
0
// Load a single Iteration regardless of parent
func (m *GormIterationRepository) Load(ctx context.Context, id uuid.UUID) (*Iteration, error) {
	defer goa.MeasureSince([]string{"goa", "db", "iteration", "get"}, time.Now())
	var obj Iteration

	tx := m.db.Where("id = ?", id).First(&obj)
	if tx.RecordNotFound() {
		log.Error(ctx, map[string]interface{}{
			"iterationID": id.String(),
		}, "iteration cannot be found")
		return nil, errors.NewNotFoundError("Iteration", id.String())
	}
	if tx.Error != nil {
		log.Error(ctx, map[string]interface{}{
			"iterationID": id.String(),
			"err":         tx.Error,
		}, "unable to load the iteration")
		return nil, errors.NewInternalError(tx.Error.Error())
	}
	return &obj, nil
}
// LoadTypeFromDB return work item link type for the given name in the correct link category
// NOTE: Two link types can coexist with different categoryIDs.
func (r *GormWorkItemLinkTypeRepository) LoadTypeFromDBByNameAndCategory(ctx context.Context, name string, categoryId satoriuuid.UUID) (*WorkItemLinkType, error) {
	log.Info(ctx, map[string]interface{}{
		"pkg":        "link",
		"wiltName":   name,
		"categoryId": categoryId,
	}, "Loading work item link type %s with category ID %s", name, categoryId.String())

	res := WorkItemLinkType{}
	db := r.db.Model(&res).Where("name=? AND link_category_id=?", name, categoryId.String()).First(&res)
	if db.RecordNotFound() {
		log.Error(ctx, map[string]interface{}{
			"wiltName":   name,
			"categoryId": categoryId.String(),
		}, "work item link type not found")
		return nil, errors.NewNotFoundError("work item link type", name)
	}
	if db.Error != nil {
		return nil, errors.NewInternalError(db.Error.Error())
	}
	return &res, nil
}
Exemple #24
0
// Save a single comment
func (m *GormCommentRepository) Save(ctx context.Context, comment *Comment) (*Comment, error) {
	c := Comment{}
	tx := m.db.Where("id=?", comment.ID).First(&c)
	if tx.RecordNotFound() {
		log.Error(ctx, map[string]interface{}{
			"commentID": comment.ID,
		}, "comment not found!")
		// treating this as a not found error: the fact that we're using number internal is implementation detail
		return nil, errors.NewNotFoundError("comment", comment.ID.String())
	}
	if err := tx.Error; err != nil {
		log.Error(ctx, map[string]interface{}{
			"commentID": comment.ID,
			"err":       err,
		}, "comment search operation failed!")

		return nil, errors.NewInternalError(err.Error())
	}
	// make sure no comment is created with an empty 'markup' value
	if comment.Markup == "" {
		comment.Markup = rendering.SystemMarkupDefault
	}
	tx = tx.Save(comment)
	if err := tx.Error; err != nil {
		log.Error(ctx, map[string]interface{}{
			"commentID": comment.ID,
			"err":       err,
		}, "unable to save the comment!")

		return nil, errors.NewInternalError(err.Error())
	}

	log.Debug(ctx, map[string]interface{}{
		"pkg":       "comment",
		"commentID": comment.ID,
	}, "Comment updated!")

	return comment, nil
}
Exemple #25
0
// Load a single comment regardless of parent
func (m *GormCommentRepository) Load(ctx context.Context, id uuid.UUID) (*Comment, error) {
	defer goa.MeasureSince([]string{"goa", "db", "comment", "get"}, time.Now())
	var obj Comment

	tx := m.db.Where("id=?", id).First(&obj)
	if tx.RecordNotFound() {
		log.Error(ctx, map[string]interface{}{
			"commentID": id.String(),
		}, "comment search operation failed!")

		return nil, errors.NewNotFoundError("comment", id.String())
	}
	if tx.Error != nil {
		log.Error(ctx, map[string]interface{}{
			"commentID": id.String(),
			"err":       tx.Error,
		}, "unable to load the comment")

		return nil, errors.NewInternalError(tx.Error.Error())
	}
	return &obj, nil
}
// Save updates the given work item in storage. Version must be the same as the one int the stored version
// returns NotFoundError, VersionConflictError, ConversionError or InternalError
func (r *GormWorkItemRepository) Save(ctx context.Context, wi app.WorkItem) (*app.WorkItem, error) {
	res := WorkItem{}
	id, err := strconv.ParseUint(wi.ID, 10, 64)
	if err != nil || id == 0 {
		return nil, errors.NewNotFoundError("work item", wi.ID)
	}

	log.Info(ctx, map[string]interface{}{
		"pkg":  "workitem",
		"wiID": wi.ID,
	}, "Looking for id for the work item repository")
	tx := r.db.First(&res, id)
	if tx.RecordNotFound() {
		log.Error(ctx, map[string]interface{}{
			"wiID": wi.ID,
		}, "work item repository not found")
		return nil, errors.NewNotFoundError("work item", wi.ID)
	}
	if tx.Error != nil {
		return nil, errors.NewInternalError(err.Error())
	}
	if res.Version != wi.Version {
		return nil, errors.NewVersionConflictError("version conflict")
	}

	wiType, err := r.wir.LoadTypeFromDB(ctx, wi.Type)
	if err != nil {
		return nil, errors.NewBadParameterError("Type", wi.Type)
	}

	res.Version = res.Version + 1
	res.Type = wi.Type
	res.Fields = Fields{}

	for fieldName, fieldDef := range wiType.Fields {
		if fieldName == SystemCreatedAt {
			continue
		}
		fieldValue := wi.Fields[fieldName]
		var err error
		res.Fields[fieldName], err = fieldDef.ConvertToModel(fieldName, fieldValue)
		if err != nil {
			return nil, errors.NewBadParameterError(fieldName, fieldValue)
		}
	}

	tx = tx.Where("Version = ?", wi.Version).Save(&res)
	if err := tx.Error; err != nil {
		log.Error(ctx, map[string]interface{}{
			"wiID": wi.ID,
			"err":  err,
		}, "unable to save the work item repository")
		return nil, errors.NewInternalError(err.Error())
	}
	if tx.RowsAffected == 0 {
		return nil, errors.NewVersionConflictError("version conflict")
	}
	log.Info(ctx, map[string]interface{}{
		"pkg":  "workitem",
		"wiID": wi.ID,
	}, "Updated work item repository")
	return convertWorkItemModelToApp(wiType, &res)
}
Exemple #27
0
// ConvertLinkTypeToModel converts the incoming app representation of a work item link type to the model layout.
// Values are only overwrriten if they are set in "in", otherwise the values in "out" remain.
func ConvertLinkTypeToModel(in app.WorkItemLinkTypeSingle, out *WorkItemLinkType) error {
	attrs := in.Data.Attributes
	rel := in.Data.Relationships
	var err error

	if in.Data.ID != nil {
		id, err := satoriuuid.FromString(*in.Data.ID)
		if err != nil {
			//log.Printf("Error when converting %s to UUID: %s", *in.Data.ID, err.Error())
			// treat as not found: clients don't know it must be a UUID
			return errors.NewNotFoundError("work item link type", id.String())
		}
		out.ID = id
	}

	if in.Data.Type != EndpointWorkItemLinkTypes {
		return errors.NewBadParameterError("data.type", in.Data.Type).Expected(EndpointWorkItemLinkTypes)
	}

	if attrs != nil {
		// If the name is not nil, it MUST NOT be empty
		if attrs.Name != nil {
			if *attrs.Name == "" {
				return errors.NewBadParameterError("data.attributes.name", *attrs.Name)
			}
			out.Name = *attrs.Name
		}

		if attrs.Description != nil {
			out.Description = attrs.Description
		}

		if attrs.Version != nil {
			out.Version = *attrs.Version
		}

		// If the forwardName is not nil, it MUST NOT be empty
		if attrs.ForwardName != nil {
			if *attrs.ForwardName == "" {
				return errors.NewBadParameterError("data.attributes.forward_name", *attrs.ForwardName)
			}
			out.ForwardName = *attrs.ForwardName
		}

		// If the ReverseName is not nil, it MUST NOT be empty
		if attrs.ReverseName != nil {
			if *attrs.ReverseName == "" {
				return errors.NewBadParameterError("data.attributes.reverse_name", *attrs.ReverseName)
			}
			out.ReverseName = *attrs.ReverseName
		}

		if attrs.Topology != nil {
			if err := CheckValidTopology(*attrs.Topology); err != nil {
				return errs.WithStack(err)
			}
			out.Topology = *attrs.Topology
		}
	}

	if rel != nil && rel.LinkCategory != nil && rel.LinkCategory.Data != nil {
		d := rel.LinkCategory.Data
		// If the the link category is not nil, it MUST be "workitemlinkcategories"
		if d.Type != EndpointWorkItemLinkCategories {
			return errors.NewBadParameterError("data.relationships.link_category.data.type", d.Type).Expected(EndpointWorkItemLinkCategories)
		}
		// The the link category MUST NOT be empty
		if d.ID == "" {
			return errors.NewBadParameterError("data.relationships.link_category.data.id", d.ID)
		}
		out.LinkCategoryID, err = satoriuuid.FromString(d.ID)
		if err != nil {
			//log.Printf("Error when converting %s to UUID: %s", in.Data.ID, err.Error())
			// treat as not found: clients don't know it must be a UUID
			return errors.NewNotFoundError("work item link category", d.ID)
		}
	}

	if rel != nil && rel.SourceType != nil && rel.SourceType.Data != nil {
		d := rel.SourceType.Data
		// If the the link type is not nil, it MUST be "workitemlinktypes"
		if d.Type != EndpointWorkItemTypes {
			return errors.NewBadParameterError("data.relationships.source_type.data.type", d.Type).Expected(EndpointWorkItemTypes)
		}
		// The the link type MUST NOT be empty
		if d.ID == "" {
			return errors.NewBadParameterError("data.relationships.source_type.data.id", d.ID)
		}
		out.SourceTypeName = d.ID
	}

	if rel != nil && rel.TargetType != nil && rel.TargetType.Data != nil {
		d := rel.TargetType.Data
		// If the the link type is not nil, it MUST be "workitemlinktypes"
		if d.Type != EndpointWorkItemTypes {
			return errors.NewBadParameterError("data.relationships.target_type.data.type", d.Type).Expected(EndpointWorkItemTypes)
		}
		// The the link type MUST NOT be empty
		if d.ID == "" {
			return errors.NewBadParameterError("data.relationships.target_type.data.id", d.ID)
		}
		out.TargetTypeName = d.ID
	}

	return nil
}
// Save updates the given work item link category in storage. Version must be the same as the one int the stored version.
// returns NotFoundError, VersionConflictError, ConversionError or InternalError
func (r *GormWorkItemLinkCategoryRepository) Save(ctx context.Context, linkCat app.WorkItemLinkCategorySingle) (*app.WorkItemLinkCategorySingle, error) {
	res := WorkItemLinkCategory{}
	if linkCat.Data.ID == nil {
		return nil, errors.NewBadParameterError("data.id", linkCat.Data.ID)
	}
	id, err := satoriuuid.FromString(*linkCat.Data.ID)
	if err != nil {
		log.Error(ctx, map[string]interface{}{
			"wilcID": *linkCat.Data.ID,
			"err":    err,
		}, "error when converting %s to UUID: %s", *linkCat.Data.ID, err.Error())
		// treat as not found: clients don't know it must be a UUID
		return nil, errors.NewNotFoundError("work item link category", id.String())
	}

	if linkCat.Data.Type != EndpointWorkItemLinkCategories {
		return nil, errors.NewBadParameterError("data.type", linkCat.Data.Type).Expected(EndpointWorkItemLinkCategories)
	}

	// If the name is not nil, it MUST NOT be empty
	if linkCat.Data.Attributes.Name != nil && *linkCat.Data.Attributes.Name == "" {
		return nil, errors.NewBadParameterError("data.attributes.name", *linkCat.Data.Attributes.Name)
	}

	db := r.db.Model(&res).Where("id=?", *linkCat.Data.ID).First(&res)
	if db.RecordNotFound() {
		log.Error(ctx, map[string]interface{}{
			"wilcID": *linkCat.Data.ID,
		}, "work item link category not found")
		return nil, errors.NewNotFoundError("work item link category", id.String())
	}
	if db.Error != nil {
		log.Error(ctx, map[string]interface{}{
			"wilcID": *linkCat.Data.ID,
			"err":    db.Error,
		}, "unable to find work item link category")
		return nil, errors.NewInternalError(db.Error.Error())
	}
	if linkCat.Data.Attributes.Version == nil || res.Version != *linkCat.Data.Attributes.Version {
		return nil, errors.NewVersionConflictError("version conflict")
	}

	newLinkCat := WorkItemLinkCategory{
		ID:      id,
		Version: *linkCat.Data.Attributes.Version + 1,
	}

	if linkCat.Data.Attributes.Name != nil {
		newLinkCat.Name = *linkCat.Data.Attributes.Name
	}
	if linkCat.Data.Attributes.Description != nil {
		newLinkCat.Description = linkCat.Data.Attributes.Description
	}

	db = db.Save(&newLinkCat)
	if db.Error != nil {
		log.Error(ctx, map[string]interface{}{
			"wilcID": newLinkCat.ID,
			"err":    db.Error,
		}, "unable to save work item link category repository")
		return nil, errors.NewInternalError(db.Error.Error())
	}
	log.Info(ctx, map[string]interface{}{
		"pkg":             "link",
		"wilcID":          newLinkCat.ID,
		"newLinkCategory": newLinkCat,
	}, "Work item link category updated")
	result := ConvertLinkCategoryFromModel(newLinkCat)
	return &result, nil
}
Exemple #29
0
// ConvertLinkToModel converts the incoming app representation of a work item link to the model layout.
// Values are only overwrriten if they are set in "in", otherwise the values in "out" remain.
// NOTE: Only the LinkTypeID, SourceID, and TargetID fields will be set.
//       You need to preload the elements after calling this function.
func ConvertLinkToModel(in app.WorkItemLinkSingle, out *WorkItemLink) error {
	attrs := in.Data.Attributes
	rel := in.Data.Relationships
	var err error

	if in.Data.ID != nil {
		id, err := satoriuuid.FromString(*in.Data.ID)
		if err != nil {
			//log.Printf("Error when converting %s to UUID: %s", *in.Data.ID, err.Error())
			// treat as not found: clients don't know it must be a UUID
			return errors.NewNotFoundError("work item link", id.String())
		}
		out.ID = id
	}

	if in.Data.Type != EndpointWorkItemLinks {
		return errors.NewBadParameterError("data.type", in.Data.Type).Expected(EndpointWorkItemLinks)
	}

	if attrs != nil {
		if attrs.Version != nil {
			out.Version = *attrs.Version
		}
	}

	if rel != nil && rel.LinkType != nil && rel.LinkType.Data != nil {
		d := rel.LinkType.Data
		// If the the link category is not nil, it MUST be "workitemlinktypes"
		if d.Type != EndpointWorkItemLinkTypes {
			return errors.NewBadParameterError("data.relationships.link_type.data.type", d.Type).Expected(EndpointWorkItemLinkTypes)
		}
		// The the link type id MUST NOT be empty
		if d.ID == "" {
			return errors.NewBadParameterError("data.relationships.link_type.data.id", d.ID)
		}
		if out.LinkTypeID, err = satoriuuid.FromString(d.ID); err != nil {
			//log.Printf("Error when converting %s to UUID: %s", in.Data.ID, err.Error())
			// treat as not found: clients don't know it must be a UUID
			return errors.NewNotFoundError("work item link type", d.ID)
		}
	}

	if rel != nil && rel.Source != nil && rel.Source.Data != nil {
		d := rel.Source.Data
		// If the the source type is not nil, it MUST be "workitems"
		if d.Type != EndpointWorkItems {
			return errors.NewBadParameterError("data.relationships.source.data.type", d.Type).Expected(EndpointWorkItems)
		}
		// The the work item id MUST NOT be empty
		if d.ID == "" {
			return errors.NewBadParameterError("data.relationships.source.data.id", d.ID)
		}
		if out.SourceID, err = strconv.ParseUint(d.ID, 10, 64); err != nil {
			return errors.NewBadParameterError("data.relationships.source.data.id", d.ID)
		}
	}

	if rel != nil && rel.Target != nil && rel.Target.Data != nil {
		d := rel.Target.Data
		// If the the target type is not nil, it MUST be "workitems"
		if d.Type != EndpointWorkItems {
			return errors.NewBadParameterError("data.relationships.target.data.type", d.Type).Expected(EndpointWorkItems)
		}
		// The the work item id MUST NOT be empty
		if d.ID == "" {
			return errors.NewBadParameterError("data.relationships.target.data.id", d.ID)
		}
		if out.TargetID, err = strconv.ParseUint(d.ID, 10, 64); err != nil {
			return errors.NewBadParameterError("data.relationships.target.data.id", d.ID)
		}
	}

	return nil
}