Example #1
0
func (res *resource) handleUpdate(c APIContexter, w http.ResponseWriter, r *http.Request, params map[string]string, info information) error {
	id := params["id"]
	obj, err := res.source.FindOne(id, buildRequest(c, r))
	if err != nil {
		return err
	}

	ctx, err := unmarshalRequest(r)
	if err != nil {
		return err
	}

	// we have to make the Result to a pointer to unmarshal into it
	updatingObj := reflect.ValueOf(obj.Result())
	if updatingObj.Kind() == reflect.Struct {
		updatingObjPtr := reflect.New(reflect.TypeOf(obj.Result()))
		updatingObjPtr.Elem().Set(updatingObj)
		err = jsonapi.Unmarshal(ctx, updatingObjPtr.Interface())
		updatingObj = updatingObjPtr.Elem()
	} else {
		err = jsonapi.Unmarshal(ctx, updatingObj.Interface())
	}
	if err != nil {
		return NewHTTPError(nil, err.Error(), http.StatusNotAcceptable)
	}

	response, err := res.source.Update(updatingObj.Interface(), buildRequest(c, r))

	if err != nil {
		return err
	}

	switch response.StatusCode() {
	case http.StatusOK:
		updated := response.Result()
		if updated == nil {
			internalResponse, err := res.source.FindOne(id, buildRequest(c, r))
			if err != nil {
				return err
			}
			updated = internalResponse.Result()
			if updated == nil {
				return fmt.Errorf("Expected FindOne to return one object of resource %s", res.name)
			}

			response = internalResponse
		}

		return res.respondWith(response, info, http.StatusOK, w, r)
	case http.StatusAccepted:
		w.WriteHeader(http.StatusAccepted)
		return nil
	case http.StatusNoContent:
		w.WriteHeader(http.StatusNoContent)
		return nil
	default:
		return fmt.Errorf("invalid status code %d from resource %s for method Update", response.StatusCode(), res.name)
	}
}
Example #2
0
func (res *resource) handleCreate(c APIContexter, w http.ResponseWriter, r *http.Request, prefix string, info information) error {
	ctx, err := unmarshalRequest(r)
	if err != nil {
		return err
	}

	// Ok this is weird again, but reflect.New produces a pointer, so we need the pure type without pointer,
	// otherwise we would have a pointer pointer type that we don't want.
	resourceType := res.resourceType
	if resourceType.Kind() == reflect.Ptr {
		resourceType = resourceType.Elem()
	}
	newObj := reflect.New(resourceType).Interface()

	err = jsonapi.Unmarshal(ctx, newObj)
	if err != nil {
		return err
	}

	var response Responder

	if res.resourceType.Kind() == reflect.Struct {
		// we have to dereference the pointer if user wants to use non pointer values
		response, err = res.source.Create(reflect.ValueOf(newObj).Elem().Interface(), buildRequest(c, r))
	} else {
		response, err = res.source.Create(newObj, buildRequest(c, r))
	}
	if err != nil {
		return err
	}

	result, ok := response.Result().(jsonapi.MarshalIdentifier)

	if !ok {
		return fmt.Errorf("Expected one newly created object by resource %s", res.name)
	}

	if len(prefix) > 0 {
		w.Header().Set("Location", "/"+prefix+"/"+res.name+"/"+result.GetID())
	} else {
		w.Header().Set("Location", "/"+res.name+"/"+result.GetID())
	}

	// handle 200 status codes
	switch response.StatusCode() {
	case http.StatusCreated:
		return res.respondWith(response, info, http.StatusCreated, w, r)
	case http.StatusNoContent:
		w.WriteHeader(response.StatusCode())
		return nil
	case http.StatusAccepted:
		w.WriteHeader(response.StatusCode())
		return nil
	default:
		return fmt.Errorf("invalid status code %d from resource %s for method Create", response.StatusCode(), res.name)
	}
}
Example #3
0
func ParseJSONBody(c *echo.Context, dest interface{}) error {
	body, err := ioutil.ReadAll(c.Request().Body)
	if err != nil {
		return errors.InvalidRequest
	}

	err = jsonapi.Unmarshal(body, dest)
	if err != nil {
		return errors.InvalidRequest
	}
	return nil
}
Example #4
0
// DeviceTokenCreate will create a deviceToken for a specified user
// @parameters
//		@requires	deviceType
//		@requires token
// @returns the newly created deviceToken
func DeviceTokenCreate(c *gin.Context) {
	var dt models.DeviceToken
	buffer, err := ioutil.ReadAll(c.Request.Body)
	if err != nil {
		c.AbortWithError(http.StatusNotAcceptable, err)
	}

	err2 := jsonapi.Unmarshal(buffer, &dt)

	if err2 != nil {
		parseFail := appError.JSONParseFailure
		parseFail.Detail = err2.Error()
		c.AbortWithError(http.StatusMethodNotAllowed, err2).
			SetMeta(parseFail)
		return
	}

	dt.UserID = c.Keys["CurrentUserID"].(uint)

	// Validate our new deviceToken
	isValid, errApp := dt.Validate()

	if isValid == false {
		c.AbortWithError(errApp.Status, errApp).
			SetMeta(errApp)
		return
	}

	var existingDeviceToken models.DeviceToken

	// If deviceToken is not found, then create the token
	// else update the existing device token with the new one
	if database.DBCon.Where("user_id = ?", dt.UserID).First(&existingDeviceToken).RecordNotFound() {
		database.DBCon.Create(&dt)
	} else {
		database.DBCon.Model(&existingDeviceToken).Update("token", dt.Token)
		dt = existingDeviceToken
	}

	data, err := jsonapi.Marshal(&dt)

	if err != nil {
		c.AbortWithError(http.StatusInternalServerError, err).
			SetMeta(appError.JSONParseFailure)
		return
	}

	c.Data(http.StatusCreated, "application/vnd.api+json", data)
}
Example #5
0
// UnmarshalJSON sets *as to a copy of data.
func (as *AppSet) UnmarshalJSON(bytes []byte) error {
	var (
		appBytes       []byte
		containerBytes []byte
		err            error
		data           TmpJSON
	)
	if err = json.Unmarshal(bytes, &data); err != nil {
		return err
	}

	apps := SelectResources(data, "apps")
	containers := SelectResources(data, "containers")

	if appBytes, err = json.Marshal(apps); err != nil {
		return err
	}

	if containerBytes, err = json.Marshal(containers); err != nil {
		return err
	}

	var parsedApps []App
	if err = jsonapi.Unmarshal(appBytes, &parsedApps); err != nil {
		return err
	}

	var parsedContainers []Container
	if err = jsonapi.Unmarshal(containerBytes, &parsedContainers); err != nil {
		return err
	}

	as.App = parsedApps[0]
	as.Container = parsedContainers[0]
	return nil
}
Example #6
0
// TransactionCreate will create a transaction that occurs
// between two users in a group
// @parameters
//		@requires	type
//		@requires amount
//		@requires relatedObjectId
//		@requires relatedObjectType
//		@requires recipientId
//		@requires senderid
//		@optional memo
// @returns the newly created transaction
func TransactionCreate(c *gin.Context) {
	var t models.Transaction
	buffer, err := ioutil.ReadAll(c.Request.Body)
	if err != nil {
		c.AbortWithError(http.StatusNotAcceptable, err)
	}

	err2 := jsonapi.Unmarshal(buffer, &t)

	if err2 != nil {
		parseFail := appError.JSONParseFailure
		parseFail.Detail = err2.Error()
		c.AbortWithError(http.StatusMethodNotAllowed, err2).
			SetMeta(parseFail)
		return
	}

	t.CreatorID = c.Keys["CurrentUserID"].(uint)

	// Validate our new transaction
	isValid, errApp := t.Validate()

	if isValid == false {
		c.AbortWithError(errApp.Status, errApp).
			SetMeta(errApp)
		return
	}

	database.DBCon.Create(&t)

	database.DBCon.First(&t.Recipient, t.RecipientID)
	database.DBCon.First(&t.Sender, t.SenderID)
	database.DBCon.First(&t.Creator, t.CreatorID)

	data, err := jsonapi.Marshal(&t)

	if err != nil {
		c.AbortWithError(http.StatusInternalServerError, err).
			SetMeta(appError.JSONParseFailure)
		return
	}

	c.Data(http.StatusCreated, "application/vnd.api+json", data)
}
Example #7
0
// GroupUpdate is used to update a specific group, it'll also come with some form data'
// @returns a group struct
func GroupUpdate(c *gin.Context) {
	var group models.Group
	buffer, err := ioutil.ReadAll(c.Request.Body)

	if err != nil {
		c.AbortWithError(http.StatusNotAcceptable, err)
	}

	err2 := jsonapi.Unmarshal(buffer, &group)

	if err2 != nil {
		c.AbortWithError(http.StatusInternalServerError, err).
			SetMeta(appError.JSONParseFailure)
		return
	}

	// Little hack-ish
	// Remove all current relations
	database.DBCon.Exec("DELETE FROM group_users WHERE group_id = ?", group.ID)
	// Add all the given relations
	for _, c := range group.UserIDs {
		database.DBCon.
			Exec("INSERT INTO group_users (group_id, user_id) VALUES (?, ?)",
				group.ID, c)
	}

	database.DBCon.First(&group, group.ID)
	database.DBCon.Model(&group).Related(&group.Users, "Users")

	data, err := jsonapi.Marshal(group)

	if err != nil {
		c.AbortWithError(http.StatusInternalServerError, err).
			SetMeta(appError.JSONParseFailure)
		return
	}

	c.Data(http.StatusOK, "application/vnd.api+json", data)
}
Example #8
0
// GroupCreate is used to create one specific group, it'll come with some form data
// @returns a group struct
func GroupCreate(c *gin.Context) {

	var group models.Group
	buffer, err := ioutil.ReadAll(c.Request.Body)
	if err != nil {
		c.AbortWithError(http.StatusNotAcceptable, err)
	}

	err2 := jsonapi.Unmarshal(buffer, &group)

	if err2 != nil {
		parseFail := appError.JSONParseFailure
		parseFail.Detail = err2.Error()
		c.AbortWithError(http.StatusMethodNotAllowed, err2).
			SetMeta(parseFail)
		return
	}

	database.DBCon.Create(&group)

	// Add current user to the group
	database.DBCon.
		Exec("INSERT INTO group_users (group_id, user_id) VALUES (?, ?)",
			group.ID, c.Keys["CurrentUserID"].(uint))

	database.DBCon.Model(&group).Related(&group.Users, "Users")

	data, err3 := jsonapi.Marshal(&group)

	if err3 != nil {
		c.AbortWithError(http.StatusInternalServerError, err3).
			SetMeta(appError.JSONParseFailure)
		return
	}

	c.Data(http.StatusCreated, "application/vnd.api+json", data)

}
Example #9
0
// TransactionUpdate will update an existing transaction
// between two users in a group
// @parameters
//		@requires id
//		@optional	type
//		@optional recipientId
//		@optional senderId
//		@optional amount
//		@optional memo
// @returns the updated transaction
func TransactionUpdate(c *gin.Context) {
	var t models.Transaction
	var newT models.Transaction

	if database.DBCon.First(&t, c.Param("id")).RecordNotFound() {
		c.AbortWithError(http.StatusNotFound, appError.RecordNotFound).
			SetMeta(appError.RecordNotFound)
		return
	}

	// Ensure current user is creator of transaction
	if t.CreatorID != c.Keys["CurrentUserID"].(uint) {
		c.AbortWithError(appError.InsufficientPermission.Status, appError.InsufficientPermission).
			SetMeta(appError.InsufficientPermission)
		return
	}

	buffer, err := ioutil.ReadAll(c.Request.Body)

	if err != nil {
		c.AbortWithError(http.StatusNotAcceptable, err)
	}

	err2 := jsonapi.Unmarshal(buffer, &newT)

	if err2 != nil {
		c.AbortWithError(http.StatusInternalServerError, err).
			SetMeta(appError.JSONParseFailure)
		return
	}

	t.Type = newT.Type
	t.Amount = newT.Amount
	t.Memo = newT.Memo
	t.RecipientID = newT.RecipientID
	t.SenderID = newT.SenderID

	// Validate our new transaction
	isValid, errApp := t.Validate()

	if isValid == false {
		c.AbortWithError(errApp.Status, errApp).
			SetMeta(errApp)
		return
	}

	database.DBCon.Save(&t)

	database.DBCon.First(&t.Recipient, t.RecipientID)
	database.DBCon.First(&t.Sender, t.SenderID)
	database.DBCon.First(&t.Creator, t.CreatorID)

	data, err := jsonapi.Marshal(&t)

	if err != nil {
		c.AbortWithError(http.StatusInternalServerError, err).
			SetMeta(appError.JSONParseFailure)
		return
	}

	c.Data(http.StatusOK, "application/vnd.api+json", data)
}