예제 #1
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
}
예제 #2
0
// Create creates a new work item link type in the repository.
// Returns BadParameterError, ConversionError or InternalError
func (r *GormWorkItemLinkTypeRepository) Create(ctx context.Context, name string, description *string, sourceTypeName, targetTypeName, forwardName, reverseName, topology string, linkCategoryID satoriuuid.UUID) (*app.WorkItemLinkTypeSingle, error) {
	linkType := &WorkItemLinkType{
		Name:           name,
		Description:    description,
		SourceTypeName: sourceTypeName,
		TargetTypeName: targetTypeName,
		ForwardName:    forwardName,
		ReverseName:    reverseName,
		Topology:       topology,
		LinkCategoryID: linkCategoryID,
	}
	if err := linkType.CheckValidForCreation(); err != nil {
		return nil, errs.WithStack(err)
	}

	// Check link category exists
	linkCategory := WorkItemLinkCategory{}
	db := r.db.Where("id=?", linkType.LinkCategoryID).Find(&linkCategory)
	if db.RecordNotFound() {
		return nil, errors.NewBadParameterError("work item link category", linkType.LinkCategoryID)
	}
	if db.Error != nil {
		return nil, errors.NewInternalError(fmt.Sprintf("Failed to find work item link category: %s", db.Error.Error()))
	}
	db = r.db.Create(linkType)
	if db.Error != nil {
		return nil, errors.NewInternalError(db.Error.Error())
	}
	// Convert the created link type entry into a JSONAPI response
	result := ConvertLinkTypeFromModel(*linkType)
	return &result, nil
}
예제 #3
0
// Refresh obtain a new access token using the refresh token.
func (c *LoginController) Refresh(ctx *app.RefreshLoginContext) error {
	refreshToken := ctx.Payload.RefreshToken
	if refreshToken == nil {
		return jsonapi.JSONErrorResponse(ctx, errors.NewBadParameterError("refresh_token", nil).Expected("not nil"))
	}

	client := &http.Client{Timeout: 10 * time.Second}
	res, err := client.PostForm(configuration.GetKeycloakEndpointToken(), url.Values{
		"client_id":     {configuration.GetKeycloakClientID()},
		"client_secret": {configuration.GetKeycloakSecret()},
		"refresh_token": {*refreshToken},
		"grant_type":    {"refresh_token"},
	})
	if err != nil {
		return jsonapi.JSONErrorResponse(ctx, errors.NewInternalError("Error when obtaining token "+err.Error()))
	}
	switch res.StatusCode {
	case 200:
		// OK
	case 401:
		return jsonapi.JSONErrorResponse(ctx, errors.NewUnauthorizedError(res.Status+" "+readBody(res.Body)))
	case 400:
		return jsonapi.JSONErrorResponse(ctx, errors.NewBadParameterError(readBody(res.Body), nil))
	default:
		return jsonapi.JSONErrorResponse(ctx, errors.NewInternalError(res.Status+" "+readBody(res.Body)))
	}

	token, err := readToken(res, ctx)
	if err != nil {
		return err
	}

	return ctx.OK(&app.AuthToken{Token: token})
}
예제 #4
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
}
// Create creates a new work item in the repository
// returns BadParameterError, ConversionError or InternalError
func (r *GormWorkItemTypeRepository) Create(ctx context.Context, extendedTypeName *string, name string, fields map[string]app.FieldDefinition) (*app.WorkItemType, error) {
	existing, _ := r.LoadTypeFromDB(ctx, name)
	if existing != nil {
		log.Error(ctx, map[string]interface{}{"witName": name}, "unable to create new work item type")
		return nil, errors.NewBadParameterError("name", name)
	}
	allFields := map[string]FieldDefinition{}
	path := name
	if extendedTypeName != nil {
		extendedType := WorkItemType{}
		db := r.db.First(&extendedType, "name = ?", extendedTypeName)
		if db.RecordNotFound() {
			return nil, errors.NewBadParameterError("extendedTypeName", *extendedTypeName)
		}
		if err := db.Error; err != nil {
			return nil, errors.NewInternalError(err.Error())
		}
		// copy fields from extended type
		for key, value := range extendedType.Fields {
			allFields[key] = value
		}
		path = extendedType.Path + pathSep + name
	}

	// now process new fields, checking whether they are ok to add.
	for field, definition := range fields {
		existing, exists := allFields[field]
		ct, err := convertFieldTypeToModels(*definition.Type)
		if err != nil {
			return nil, errs.WithStack(err)
		}
		converted := FieldDefinition{
			Required: definition.Required,
			Type:     ct,
		}
		if exists && !compatibleFields(existing, converted) {
			return nil, fmt.Errorf("incompatible change for field %s", field)
		}
		allFields[field] = converted
	}

	created := WorkItemType{
		Version: 0,
		Name:    name,
		Path:    path,
		Fields:  allFields,
	}

	if err := r.db.Save(&created).Error; err != nil {
		return nil, errors.NewInternalError(err.Error())
	}

	result := convertTypeFromModels(&created)
	return &result, nil
}
예제 #6
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
}
예제 #7
0
// SearchFullText Search returns work items for the given query
func (r *GormSearchRepository) SearchFullText(ctx context.Context, rawSearchString string, start *int, limit *int) ([]*app.WorkItem, uint64, error) {
	// parse
	// generateSearchQuery
	// ....
	parsedSearchDict, err := parseSearchString(rawSearchString)
	if err != nil {
		return nil, 0, errs.WithStack(err)
	}

	sqlSearchQueryParameter := generateSQLSearchInfo(parsedSearchDict)
	var rows []workitem.WorkItem
	rows, count, err := r.search(ctx, sqlSearchQueryParameter, parsedSearchDict.workItemTypes, start, limit)
	if err != nil {
		return nil, 0, errs.WithStack(err)
	}
	result := make([]*app.WorkItem, len(rows))

	for index, value := range rows {
		var err error
		// FIXME: Against best practice http://go-database-sql.org/retrieving.html
		wiType, err := r.wir.LoadTypeFromDB(ctx, value.Type)
		if err != nil {
			return nil, 0, errors.NewInternalError(err.Error())
		}
		result[index], err = convertFromModel(*wiType, value)
		if err != nil {
			return nil, 0, errors.NewConversionError(err.Error())
		}
	}

	return result, count, nil
}
예제 #8
0
// 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)
}
예제 #9
0
// 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
}
예제 #10
0
// 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
}
예제 #11
0
// Create creates a new work item in the repository
// returns BadParameterError, ConversionError or InternalError
func (r *GormWorkItemRepository) Create(ctx context.Context, typeID string, fields map[string]interface{}, creator string) (*app.WorkItem, error) {
	wiType, err := r.wir.LoadTypeFromDB(ctx, typeID)
	if err != nil {
		return nil, errors.NewBadParameterError("type", typeID)
	}
	wi := WorkItem{
		Type:   typeID,
		Fields: Fields{},
	}
	fields[SystemCreator] = creator
	for fieldName, fieldDef := range wiType.Fields {
		if fieldName == SystemCreatedAt {
			continue
		}
		fieldValue := fields[fieldName]
		var err error
		wi.Fields[fieldName], err = fieldDef.ConvertToModel(fieldName, fieldValue)
		if err != nil {
			return nil, errors.NewBadParameterError(fieldName, fieldValue)
		}
		if fieldName == SystemDescription && wi.Fields[fieldName] != nil {
			description := rendering.NewMarkupContentFromMap(wi.Fields[fieldName].(map[string]interface{}))
			if !rendering.IsMarkupSupported(description.Markup) {
				return nil, errors.NewBadParameterError(fieldName, fieldValue)
			}
		}
	}
	tx := r.db
	if err = tx.Create(&wi).Error; err != nil {
		return nil, errors.NewInternalError(err.Error())
	}
	return convertWorkItemModelToApp(wiType, &wi)
}
// 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
}
예제 #13
0
// 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
}
예제 #14
0
func TestNewInternalError(t *testing.T) {
	t.Parallel()
	resource.Require(t, resource.UnitTest)
	err := errors.NewInternalError("System disk could not be read")

	// not sure what assertion to do here.
	t.Log(err)
}
예제 #15
0
// 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
}
예제 #16
0
// Load returns the work item for the given id
// returns NotFoundError, ConversionError or InternalError
func (r *GormWorkItemRepository) Load(ctx context.Context, ID string) (*app.WorkItem, error) {
	res, err := r.LoadFromDB(ctx, ID)
	if err != nil {
		return nil, errs.WithStack(err)
	}
	wiType, err := r.wir.LoadTypeFromDB(ctx, res.Type)
	if err != nil {
		return nil, errors.NewInternalError(err.Error())
	}
	return convertWorkItemModelToApp(wiType, res)
}
예제 #17
0
// 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
}
예제 #18
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
}
예제 #19
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
}
예제 #20
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
}
예제 #21
0
// Load multiple areas
func (m *GormAreaRepository) LoadMultiple(ctx context.Context, ids []uuid.UUID) ([]*Area, error) {
	defer goa.MeasureSince([]string{"goa", "db", "Area", "getmultiple"}, time.Now())
	var objs []*Area

	for i := 0; i < len(ids); i++ {
		m.db = m.db.Or("id = ?", ids[i])
	}
	tx := m.db.Find(&objs)
	if tx.Error != nil {
		return nil, errors.NewInternalError(tx.Error.Error())
	}
	return objs, nil
}
예제 #22
0
// ErrorHandler turns a Go error into an JSONAPI HTTP response. It should be placed in the middleware chain
// below the logger middleware so the logger properly logs the HTTP response. ErrorHandler
// understands instances of goa.ServiceError and returns the status and response body embodied in
// them, it turns other Go error types into a 500 internal error response.
// If verbose is false the details of internal errors is not included in HTTP responses.
// If you use github.com/pkg/errors then wrapping the error will allow a trace to be printed to the logs
func ErrorHandler(service *goa.Service, verbose bool) goa.Middleware {
	return func(h goa.Handler) goa.Handler {
		return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
			e := h(ctx, rw, req)
			if e == nil {
				return nil
			}
			cause := errs.Cause(e)
			status := http.StatusInternalServerError
			var respBody interface{}
			respBody, status = ErrorToJSONAPIErrors(e)
			rw.Header().Set("Content-Type", ErrorMediaIdentifier)
			if err, ok := cause.(goa.ServiceError); ok {
				status = err.ResponseStatus()
				//respBody = err
				goa.ContextResponse(ctx).ErrorCode = err.Token()
				//rw.Header().Set("Content-Type", ErrorMediaIdentifier)
			} else {
				//respBody = e.Error()
				//rw.Header().Set("Content-Type", "text/plain")
			}
			if status >= 500 && status < 600 {
				//reqID := ctx.Value(reqIDKey)
				reqID := ctx.Value(1) // TODO remove this hack
				if reqID == nil {
					reqID = shortID()
					//ctx = context.WithValue(ctx, reqIDKey, reqID)
					ctx = context.WithValue(ctx, 1, reqID) // TODO remove this hack
				}
				log.Error(ctx, map[string]interface{}{
					"msg": respBody,
					"err": fmt.Sprintf("%+v", e),
				}, "uncaught error detected in ErrorHandler")

				if !verbose {
					rw.Header().Set("Content-Type", goa.ErrorMediaIdentifier)
					msg := errors.NewInternalError(fmt.Sprintf("%s [%s]", http.StatusText(http.StatusInternalServerError), reqID))
					//respBody = goa.ErrInternal(msg)
					respBody, status = ErrorToJSONAPIErrors(msg)
					// Preserve the ID of the original error as that's what gets logged, the client
					// received error ID must match the original
					// TODO for JSONAPI this won't work I guess.
					if origErrID := goa.ContextResponse(ctx).ErrorCode; origErrID != "" {
						respBody.(*goa.ErrorResponse).ID = origErrID
					}
				}
			}
			return service.Send(ctx, status, respBody)
		}
	}
}
예제 #23
0
func readToken(res *http.Response, ctx jsonapi.InternalServerError) (*app.TokenData, error) {
	// Read the json out of the response body
	buf := new(bytes.Buffer)
	io.Copy(buf, res.Body)
	res.Body.Close()
	jsonString := strings.TrimSpace(buf.String())

	var token app.TokenData
	err := json.Unmarshal([]byte(jsonString), &token)
	if err != nil {
		return nil, jsonapi.JSONErrorResponse(ctx, errors.NewInternalError(fmt.Sprintf("error when unmarshal json with access token %s ", jsonString)+err.Error()))
	}
	return &token, nil
}
예제 #24
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
}
예제 #25
0
func (r *GormWorkItemRepository) GetCountsPerIteration(ctx context.Context, spaceID uuid.UUID) (map[string]WICountsPerIteration, error) {
	var res []WICountsPerIteration
	db := r.db.Table("work_items").Select(`iterations.id as IterationId, count(*) as Total,
				count( case fields->>'system.state' when 'closed' then '1' else null end ) as Closed`).Joins(`left join iterations
				on fields@> concat('{"system.iteration": "', iterations.id, '"}')::jsonb`).Where(`iterations.space_id = ?
				and work_items.deleted_at IS NULL`, spaceID).Group(`IterationId`).Scan(&res)
	if db.Error != nil {
		return nil, errors.NewInternalError(db.Error.Error())
	}
	countsMap := map[string]WICountsPerIteration{}
	for _, iterationWithCount := range res {
		countsMap[iterationWithCount.IterationId] = iterationWithCount
	}
	return countsMap, nil
}
예제 #26
0
// Create creates a new work item link category in the repository.
// Returns BadParameterError, ConversionError or InternalError
func (r *GormWorkItemLinkCategoryRepository) Create(ctx context.Context, name *string, description *string) (*app.WorkItemLinkCategorySingle, error) {
	if name == nil || *name == "" {
		return nil, errors.NewBadParameterError("name", name)
	}
	created := WorkItemLinkCategory{
		// Omit "lifecycle" and "ID" fields as they will be filled by the DB
		Name:        *name,
		Description: description,
	}
	db := r.db.Create(&created)
	if db.Error != nil {
		return nil, errors.NewInternalError(db.Error.Error())
	}
	// Convert the created link category entry into a JSONAPI response
	result := ConvertLinkCategoryFromModel(created)
	return &result, nil
}
예제 #27
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
}
예제 #28
0
// List returns work item selected by the given criteria.Expression, starting with start (zero-based) and returning at most limit items
func (r *GormWorkItemRepository) List(ctx context.Context, criteria criteria.Expression, start *int, limit *int) ([]*app.WorkItem, uint64, error) {
	result, count, err := r.listItemsFromDB(ctx, criteria, start, limit)
	if err != nil {
		return nil, 0, errs.WithStack(err)
	}

	res := make([]*app.WorkItem, len(result))

	for index, value := range result {
		wiType, err := r.wir.LoadTypeFromDB(ctx, value.Type)
		if err != nil {
			return nil, 0, errors.NewInternalError(err.Error())
		}
		res[index], err = convertWorkItemModelToApp(wiType, &value)
	}

	return res, count, nil
}
예제 #29
0
// 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
}
예제 #30
0
// 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
}