예제 #1
0
func TestSubscription(t *testing.T) {
	var s Subscription
	var sJSON = []byte(`
    {
        "id": "5b2e1b6f-b3f7-4a94-8b05-aa441606d886",
        "event_type": "test_event_type",
        "context": "test_context",
        "account_id": "e4f05126-a0e8-437d-94f9-b553c959cdfb",
        "timestamp": "2015-07-10T10:50:34.437512Z"
    }`)

	if err := json.Unmarshal(sJSON, &s); err != nil {
		t.Error(err.Error())
	}

	sAccountID, _ := uuid.FromString("e4f05126-a0e8-437d-94f9-b553c959cdfb")
	sID, _ := uuid.FromString("5b2e1b6f-b3f7-4a94-8b05-aa441606d886")
	sTime, _ := time.Parse(time.RFC3339, "2015-07-10T10:50:34.437512Z")

	cases := []struct {
		label, actual, expected interface{}
	}{
		{"id", s.ID, sID},
		{"event type", s.EventType, "test_event_type"},
		{"context", s.Context, "test_context"},
		{"account id", s.AccountID, sAccountID},
		{"created at date", s.CreatedAt, sTime},
	}

	for _, c := range cases {
		if c.actual != c.expected {
			t.Errorf("Subscriber %v is %q, but expected %q", c.label, c.actual, c.expected)
		}
	}
}
예제 #2
0
파일: handler.go 프로젝트: TritonHo/meow
func updateRecordWithUserId(input interface{}, fieldNames map[string]bool, id, userId string, session *xorm.Session) (statusCode int, err error) {
	if _, err := uuid.FromString(id); err != nil {
		return http.StatusBadRequest, errUuidNotValid
	}
	if _, err := uuid.FromString(userId); err != nil {
		return http.StatusBadRequest, errUuidNotValid
	}

	//convert the fields set to array
	array := []string{}
	for k, _ := range fieldNames {
		array = append(array, k)
	}

	//update the database
	affected, err := session.Where("id = ? and user_id = ?", id, userId).Cols(array...).Update(input)
	if err != nil {
		return http.StatusInternalServerError, err
	}
	if affected == 0 {
		return http.StatusNotFound, errors.New("The record is not found.")
	}

	return http.StatusNoContent, nil
}
예제 #3
0
func PutOAuthUser(mdb *Store, u *pb.OAuthUser) (*pb.OAuthUser, error) {
	key, v, err := GetOAuthUser(mdb, u.Provider, u.UserId)
	if err != nil {
		return nil, err
	}
	if v != nil {
		if u.Uuid != "" && v.Uuid != "" {
			uuid1, _ := uuid.FromString(u.Uuid)
			uuid2, _ := uuid.FromString(v.Uuid)
			if !uuid.Equal(uuid1, uuid2) {
				return nil, fmt.Errorf("user mismatch")
			}
		}
		if u.Uuid == "" {
			u.Uuid = v.Uuid
		}
	}

	bytes, err := proto.Marshal(u)
	if err != nil {
		return nil, err
	}

	// refresh OAuth User info to store
	err = mdb.Put(key.Bytes(), bytes)
	if err != nil {
		return nil, err
	}
	return u, nil
}
예제 #4
0
func (t *testSyncerSuite) TestMysqlGTIDSync(c *C) {
	t.setupTest(c, mysql.MySQLFlavor)

	r, err := t.c.Execute("SELECT @@gtid_mode")
	c.Assert(err, IsNil)
	modeOn, _ := r.GetString(0, 0)
	if modeOn != "ON" {
		c.Skip("GTID mode is not ON")
	}

	r, err = t.c.Execute("SHOW GLOBAL VARIABLES LIKE 'SERVER_UUID'")
	c.Assert(err, IsNil)

	var masterUuid uuid.UUID
	if s, _ := r.GetString(0, 1); len(s) > 0 && s != "NONE" {
		masterUuid, err = uuid.FromString(s)
		c.Assert(err, IsNil)
	}

	set, _ := mysql.ParseMysqlGTIDSet(fmt.Sprintf("%s:%d-%d", masterUuid.String(), 1, 2))

	s, err := t.b.StartSyncGTID(set)
	c.Assert(err, IsNil)

	t.testSync(c, s)
}
예제 #5
0
func toID(param string) uuid.UUID {
	val, err := uuid.FromString(param)
	if err != nil {
		log.Fatal(err)
	}
	return val
}
예제 #6
0
func TestUUIDFlakeKey(t *testing.T) {
	Convey("Giving key, convert to bytes", t, func() {
		id, err := uuid.FromString("c6f8dca8-54f0-11dd-b489-003048343a40")
		So(err, ShouldBeNil)
		So(hex.EncodeToString(id.Bytes()), ShouldEqual, hex.EncodeToString(id[:16][:]))

		fid := flake.Id{}
		suffix := hex.EncodeToString(fid[:])
		key := NewUUIDFlakeKey(TableFeed, id, fid)
		So(key.Len(), ShouldEqual, 36)

		uid := "c6f8dca854f011ddb489003048343a40"
		So(key.String(), ShouldEqual, "00000001"+uid+suffix)
		So(hex.EncodeToString(key.Prefix().Bytes()), ShouldEqual, "00000001"+uid)
		So(string(key.Prefix().Bytes()), ShouldEqual, string(key.UUIDKey.Bytes()))

		key.UUIDKey.PrefixTable = TableFeedinfo
		So(key.String(), ShouldEqual, "00000002"+uid+suffix)
		So(hex.EncodeToString(key.Prefix().Bytes()), ShouldEqual, "00000002"+uid)

		key.Id[15] = 1
		suffix = hex.EncodeToString(key.Id[:])
		So(key.String(), ShouldEqual, "00000002"+uid+suffix)
		So(hex.EncodeToString(key.Prefix().Bytes()), ShouldEqual, "00000002"+uid)
	})
}
예제 #7
0
파일: auth.go 프로젝트: hi-trust/friendfeed
func (s *ApiServer) FetchProfile(ctx context.Context, req *pb.ProfileRequest) (*pb.Profile, error) {
	uuid1, err := uuid.FromString(req.Uuid)
	if err != nil {
		return nil, err
	}
	return store.GetProfileFromUuid(s.mdb, uuid1)
}
예제 #8
0
// Creates new instance of Worker. Returns error on fail.
func NewWorker() (worker *Worker, err error) {
	sock, err := newAsyncRWSocket("unix", flagEndpoint, time.Second*5)
	if err != nil {
		return
	}

	logger, err := NewLogger()
	if err != nil {
		return
	}

	workerID, _ := uuid.FromString(flagUUID)

	disown_timeout := 5 * time.Second

	w := Worker{
		unpacker:        newStreamUnpacker(),
		uuid:            workerID,
		logger:          logger,
		heartbeat_timer: time.NewTimer(HEARTBEAT_TIMEOUT),
		disown_timer:    time.NewTimer(disown_timeout),
		sessions:        make(map[int64](*Request)),
		from_handlers:   make(chan rawMessage),
		socketIO:        sock,
		fallback:        defaultFallbackHandler,
		disown_timeout:  disown_timeout,
	}
	w.disown_timer.Stop()
	w.handshake()
	w.heartbeat()
	worker = &w
	return
}
예제 #9
0
// Decode decodes a string according to the alphabet into a uuid.UUID. If s is
// too short, its most significant bits (MSB) will be padded with 0 (zero).
func (b base57) Decode(u string) (uuid.UUID, error) {
	str, err := b.stringToNum(u)
	if err != nil {
		return uuid.Nil, err
	}
	return uuid.FromString(str)
}
예제 #10
0
func (s *ApiServer) LikeEntry(ctx context.Context, req *pb.LikeRequest) (*pb.Entry, error) {
	entry, err := store.GetEntry(s.rdb, req.Entry)
	if err != nil {
		return nil, err
	}

	uuid1, err := uuid.FromString(req.User)
	if err != nil {
		return nil, err
	}
	profile, err := store.GetProfileFromUuid(s.mdb, uuid1)
	if err != nil || profile == nil {
		return nil, err
	}

	if req.Like {
		var key *store.UUIDKey
		key, entry, err = store.Like(s.rdb, profile, entry)
		if err == nil {
			s.spread(key)
		}
	} else {
		entry, err = store.DeleteLike(s.rdb, profile, entry)
	}
	return entry, err
}
예제 #11
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
}
예제 #12
0
// List runs the list action.
func (c *SpaceIterationsController) List(ctx *app.ListSpaceIterationsContext) error {
	spaceID, err := uuid.FromString(ctx.ID)
	if err != nil {
		return jsonapi.JSONErrorResponse(ctx, goa.ErrNotFound(err.Error()))
	}

	return application.Transactional(c.db, func(appl application.Application) error {

		_, err = appl.Spaces().Load(ctx, spaceID)
		if err != nil {
			return jsonapi.JSONErrorResponse(ctx, goa.ErrNotFound(err.Error()))
		}

		iterations, err := appl.Iterations().List(ctx, spaceID)
		if err != nil {
			return jsonapi.JSONErrorResponse(ctx, err)
		}

		// fetch extra information(counts of WI in each iteration of the space) to be added in response
		wiCounts, err := appl.WorkItems().GetCountsPerIteration(ctx, spaceID)
		if err != nil {
			return jsonapi.JSONErrorResponse(ctx, err)
		}
		res := &app.IterationList{}
		res.Data = ConvertIterations(ctx.RequestData, iterations, UpdateIterationsWithCounts(wiCounts))

		return ctx.OK(res)
	})
}
예제 #13
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
}
예제 #14
0
func (mgm tokenManager) Extract(tokenString string) (*account.Identity, error) {
	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		return mgm.publicKey, nil
	})
	if err != nil {
		return nil, errors.WithStack(err)
	}

	if !token.Valid {
		return nil, errors.New("Token not valid")
	}

	claimedUUID := token.Claims.(jwt.MapClaims)["sub"]
	if claimedUUID == nil {
		return nil, errors.New("Subject can not be nil")
	}
	// in case of nil UUID, below type casting will fail hence we need above check
	id, err := uuid.FromString(token.Claims.(jwt.MapClaims)["sub"].(string))
	if err != nil {
		return nil, errors.WithStack(err)
	}

	ident := account.Identity{
		ID:       id,
		Username: token.Claims.(jwt.MapClaims)["preferred_username"].(string),
	}

	return &ident, nil
}
예제 #15
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
}
예제 #16
0
func (s *ApiServer) ForwardFetchFeed(ctx context.Context, req *pb.FeedRequest) (*pb.Feed, error) {
	if req.PageSize <= 0 || req.PageSize >= 100 {
		req.PageSize = 50
	}

	profile, err := store.GetProfile(s.mdb, req.Id)
	if err != nil {
		return nil, err
	}

	uuid1, _ := uuid.FromString(profile.Uuid)
	preKey := store.NewUUIDKey(store.TableReverseEntryIndex, uuid1)
	log.Println("forward seeking:", preKey.String())

	start := req.Start
	var entries []*pb.Entry
	_, err = store.ForwardTableScan(s.rdb, preKey, func(i int, k, v []byte) error {
		if start > 0 {
			start--
			return nil // continue
		}

		entry := new(pb.Entry)
		rawdata, err := s.rdb.Get(v) // index value point to entry key
		if err != nil || len(rawdata) == 0 {
			return fmt.Errorf("entry data missing")
		}
		if err := proto.Unmarshal(rawdata, entry); err != nil {
			return err
		}
		if err = FormatFeedEntry(s.mdb, req, entry); err != nil {
			return err
		}

		entries = append(entries, entry)
		if i > int(req.PageSize+req.Start) {
			return &store.Error{"ok", store.StopIteration}
		}
		return nil
	})

	if err != nil {
		return nil, err
	}

	feed := &pb.Feed{
		Uuid:        profile.Uuid,
		Id:          profile.Id,
		Name:        profile.Name,
		Picture:     profile.Picture,
		Type:        profile.Type,
		Private:     profile.Private,
		SupId:       profile.SupId,
		Description: profile.Description,
		Entries:     entries[:],
	}
	return feed, nil
}
예제 #17
0
func TestNewWithAlphabet(t *testing.T) {
	abc := DefaultAlphabet[:len(DefaultAlphabet)-1] + "="
	enc := base57{newAlphabet(abc)}
	u1, _ := uuid.FromString("e9ae9ba7-4fb1-4a6d-bbca-5315ed438371")
	u2 := enc.Encode(u1)
	if u2 != "u=BFWRLr5dXbeWf==iasZi" {
		t.Errorf("expected uuid to be %q, got %q", "u=BFWRLr5dXbeWf==iasZi", u2)
	}
}
예제 #18
0
func convertToUuid(uuidStrings []string) []uuid.UUID {
	var uUIDs []uuid.UUID

	for i := 0; i < len(uuidStrings); i++ {
		uuidString, _ := uuid.FromString(uuidStrings[i])
		uUIDs = append(uUIDs, uuidString)
	}
	return uUIDs
}
예제 #19
0
파일: handler.go 프로젝트: TritonHo/meow
func deleteRecordWithUserId(input interface{}, id, userId string, session *xorm.Session) (statusCode int, err error) {
	if _, err := uuid.FromString(id); err != nil {
		return http.StatusBadRequest, errUuidNotValid
	}
	if _, err := uuid.FromString(userId); err != nil {
		return http.StatusBadRequest, errUuidNotValid
	}
	affectedCount, err := session.Where("id = ? and user_id = ?", id, userId).Delete(input)

	if err != nil {
		return http.StatusInternalServerError, err
	}
	if affectedCount == 0 {
		return http.StatusNotFound, errors.New("The record is not found.")
	}

	return http.StatusNoContent, err
}
예제 #20
0
// /a/comment
func (s *Server) CommentHandler(c *gin.Context) {
	c.Request.ParseForm()
	id := c.Request.Form.Get("id")
	entryId := c.Request.Form.Get("entry")
	rawBody := c.Request.Form.Get("body")
	if entryId == "" || rawBody == "" {
		c.JSON(http.StatusBadRequest, gin.H{"status": "bad request"})
		return
	}

	body := util.DefaultSanitize(rawBody)
	body = util.EntityToLink(body)

	profile, _ := s.CurrentUser(c)
	from := &pb.Feed{
		Id:   profile.Id,
		Name: profile.Name,
		Type: profile.Type,
	}
	comment := &pb.Comment{
		Body:    body,
		RawBody: rawBody,
		From:    from,
	}

	var err error
	var uuid1 uuid.UUID
	if id != "" {
		uuid1, err = uuid.FromString(id)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"status": "bad request"})
			return
		}
	} else {
		comment.Date = time.Now().UTC().Format(time.RFC3339)
		name := entryId + profile.Uuid + comment.Date
		uuid1 = uuid.NewV5(uuid.NamespaceURL, name)
	}
	comment.Id = uuid1.String()

	req := &pb.CommentRequest{
		Entry:   entryId,
		Comment: comment,
	}

	ctx, cancel := DefaultTimeoutContext()
	defer cancel()

	_, err = s.client.CommentEntry(ctx, req)
	if RequestError(c, err) {
		return
	}

	comment.Commands = []string{"edit", "delete"}
	c.JSON(200, comment)
}
예제 #21
0
// handshakeStruct
func unpackHandshake(session int64, data []interface{}) (msg messageInterface, err error) {
	u := uuid.UUID{}
	if uuid_t, ok := data[0].([]byte); ok {
		u, err = uuid.FromString(string(uuid_t))
		if err != nil {
			return
		}
	}
	msg = &handshakeStruct{messageInfo{HANDSHAKE, session}, u}
	return
}
예제 #22
0
func TestEncoding(t *testing.T) {
	for _, test := range testVector {
		u, err := uuid.FromString(test.uuid)
		if err != nil {
			t.Error(err)
		}

		suuid := New().Encode(u)

		if suuid != test.shortuuid {
			t.Errorf("expected %q, got %q", test.shortuuid, suuid)
		}
	}
}
예제 #23
0
파일: event_test.go 프로젝트: nivaha/notify
func TestEvent(t *testing.T) {
	var e Event
	var eJSON = []byte(`
    {
        "id": "5b2e1b6f-b3f7-4a94-8b05-aa441606d886",
        "event_type": "test_event_type",
        "context": "test_context",
        "original_account_id": "e4f05126-a0e8-437d-94f9-b553c959cdfb",
				"payload": "Инстинкт плюс возможность, равно прибыль.",
        "timestamp": "2015-07-10T10:50:34.437512Z"
    }`)

	if err := json.Unmarshal(eJSON, &e); err != nil {
		t.Error(err.Error())
	}

	eAccountID, _ := uuid.FromString("e4f05126-a0e8-437d-94f9-b553c959cdfb")
	eID, _ := uuid.FromString("5b2e1b6f-b3f7-4a94-8b05-aa441606d886")
	eTime, _ := time.Parse(time.RFC3339, "2015-07-10T10:50:34.437512Z")

	cases := []struct {
		label, actual, expected interface{}
	}{
		{"id", e.ID, eID},
		{"event type", e.EventType, "test_event_type"},
		{"context", e.Context, "test_context"},
		{"original account id", e.OriginalAccountID, eAccountID},
		{"created at date", e.CreatedAt, eTime},
		{"payload data", e.Data, "Инстинкт плюс возможность, равно прибыль."},
	}

	for _, c := range cases {
		if c.actual != c.expected {
			t.Errorf("Event %v is %q, but expected %q", c.label, c.actual, c.expected)
		}
	}
}
예제 #24
0
파일: uuids.go 프로젝트: nivaha/notify
func strToEventIDSlice(str string) (UUIDs, error) {
	result := make(UUIDs, 0, 10)
	trimmed := strings.Trim(str, "{}")

	for _, t := range strings.Split(trimmed, ",") {
		id, err := uuid.FromString(t)
		if err != nil {
			return nil, err
		}

		result = append(result, id)
	}

	return result, nil
}
예제 #25
0
파일: handler.go 프로젝트: TritonHo/meow
func getRecordWithUserIdDirect(out interface{}, id, userId string, db *xorm.Engine) (statusCode int, err error) {
	if _, err := uuid.FromString(id); err != nil {
		return http.StatusBadRequest, errUuidNotValid
	}

	found, err := db.Where("id = ? and user_id = ?", id, userId).Get(out)
	if err != nil {
		return http.StatusInternalServerError, err
	}
	if found == false {
		return http.StatusNotFound, errNotFound
	}

	return http.StatusOK, nil
}
예제 #26
0
func (mgm tokenManager) Locate(ctx context.Context) (uuid.UUID, error) {
	token := goajwt.ContextJWT(ctx)
	if token == nil {
		return uuid.UUID{}, errors.New("Missing token") // TODO, make specific tokenErrors
	}
	id := token.Claims.(jwt.MapClaims)["sub"]
	if id == nil {
		return uuid.UUID{}, errors.New("Missing sub")
	}
	idTyped, err := uuid.FromString(id.(string))
	if err != nil {
		return uuid.UUID{}, errors.New("uuid not of type string")
	}
	return idTyped, nil
}
예제 #27
0
// Update runs the update action.
func (c *IterationController) Update(ctx *app.UpdateIterationContext) error {
	_, err := login.ContextIdentity(ctx)
	if err != nil {
		return jsonapi.JSONErrorResponse(ctx, goa.ErrUnauthorized(err.Error()))
	}
	id, err := uuid.FromString(ctx.IterationID)
	if err != nil {
		return jsonapi.JSONErrorResponse(ctx, goa.ErrNotFound(err.Error()))
	}

	return application.Transactional(c.db, func(appl application.Application) error {
		itr, err := appl.Iterations().Load(ctx.Context, id)
		if err != nil {
			return jsonapi.JSONErrorResponse(ctx, err)
		}
		if ctx.Payload.Data.Attributes.Name != nil {
			itr.Name = *ctx.Payload.Data.Attributes.Name
		}
		if ctx.Payload.Data.Attributes.StartAt != nil {
			itr.StartAt = ctx.Payload.Data.Attributes.StartAt
		}
		if ctx.Payload.Data.Attributes.EndAt != nil {
			itr.EndAt = ctx.Payload.Data.Attributes.EndAt
		}
		if ctx.Payload.Data.Attributes.Description != nil {
			itr.Description = ctx.Payload.Data.Attributes.Description
		}
		if ctx.Payload.Data.Attributes.State != nil {
			if *ctx.Payload.Data.Attributes.State == iteration.IterationStateStart {
				res, err := appl.Iterations().CanStartIteration(ctx, itr)
				if res == false && err != nil {
					return jsonapi.JSONErrorResponse(ctx, err)
				}
			}
			itr.State = *ctx.Payload.Data.Attributes.State
		}
		itr, err = appl.Iterations().Save(ctx.Context, *itr)
		if err != nil {
			return jsonapi.JSONErrorResponse(ctx, err)
		}

		response := app.IterationSingle{
			Data: ConvertIteration(ctx.RequestData, itr),
		}

		return ctx.OK(&response)
	})
}
예제 #28
0
파일: handler.go 프로젝트: TritonHo/meow
//the id should be a uuid
func getRecord(out interface{}, id string, session *xorm.Session) (statusCode int, err error) {
	if _, err := uuid.FromString(id); err != nil {
		return http.StatusBadRequest, errUuidNotValid
	}

	found, err := session.Id(id).Get(out)

	if err != nil {
		return http.StatusInternalServerError, err
	}
	if found == false {
		return http.StatusNotFound, errNotFound
	}

	return http.StatusOK, nil
}
예제 #29
0
func checkClaims(claims *keycloakTokenClaims) error {
	if claims.Subject == "" {
		return errors.New("subject claim not found in token")
	}
	_, err := uuid.FromString(claims.Subject)
	if err != nil {
		return errors.New("subject claim from token is not UUID " + err.Error())
	}
	if claims.Username == "" {
		return errors.New("username claim not found in token")
	}
	if claims.Email == "" {
		return errors.New("email claim not found in token")
	}
	return nil
}
예제 #30
0
// Show runs the show action.
func (c *AreaController) Show(ctx *app.ShowAreaContext) error {
	id, err := uuid.FromString(ctx.ID)
	if err != nil {
		return jsonapi.JSONErrorResponse(ctx, goa.ErrNotFound(err.Error()))
	}

	return application.Transactional(c.db, func(appl application.Application) error {
		a, err := appl.Areas().Load(ctx, id)
		if err != nil {
			return jsonapi.JSONErrorResponse(ctx, err)
		}

		res := &app.AreaSingle{}
		res.Data = ConvertArea(appl, ctx.RequestData, a, addResolvedPath)
		return ctx.OK(res)
	})
}