Example #1
0
// FriendshipIndex takes in query params through
// gin.Context and is restricted to the currentUser
// @returns an array of friendship JSON objects
func FriendshipIndex(c *gin.Context) {
	friendships := []models.Friendship{}
	var curUser models.User
	database.DBCon.First(&curUser, c.Keys["CurrentUserID"])

	database.DBCon.Model(&curUser).Related(&friendships, "Friendships")

	// Get user and friend and friendshipData
	// TODO: n + 1 query problem here, so we'll figure this out later
	for i := range friendships {
		var fd models.FriendshipData
		database.DBCon.First(&friendships[i].Friend, friendships[i].FriendID)
		database.DBCon.First(&fd, friendships[i].FriendshipDataID)

		if curUser.ID == fd.PositiveUserID {
			friendships[i].Balance = fd.Balance
		} else {
			friendships[i].Balance = -fd.Balance
		}

		friendships[i].User = curUser
	}

	data, err := jsonapi.Marshal(friendships)

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

	c.Data(http.StatusOK, "application/vnd.api+json", data)
}
Example #2
0
// FriendshipShow takes a given ID from gin.Context
// @returns a specific friendship JSON object
func FriendshipShow(c *gin.Context) {
	friendship := models.Friendship{}

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

	var fd models.FriendshipData

	database.DBCon.First(&friendship.User, friendship.UserID)
	database.DBCon.First(&friendship.Friend, friendship.FriendID)
	database.DBCon.First(&fd, friendship.FriendshipDataID)

	if friendship.UserID == fd.PositiveUserID {
		friendship.Balance = fd.Balance
	} else {
		friendship.Balance = -fd.Balance
	}

	data, err := jsonapi.Marshal(friendship)

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

	c.Data(http.StatusOK, "application/vnd.api+json", data)
}
Example #3
0
// UserShow is used to show one specific user
// @returns a user struct
func UserShow(c *gin.Context) {
	var user models.User
	database.DBCon.First(&user, c.Param("id"))

	data, err := jsonapi.Marshal(jsonapi.MarshalIncludedRelations(user))

	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "couldn't marshal to json"})
	}

	c.Data(http.StatusOK, "application/vnd.api+json", data)
}
Example #4
0
// UserIndex is used when the user's index is routed to
// this handler will run. Generally, it will
// come with some query parameters like limit and offset
// @returns an array of users
func UserIndex(c *gin.Context) {
	var users []models.User
	number, err := strconv.Atoi(c.Param("limit"))
	database.DBCon.Limit(number).Find(&users)

	data, err := jsonapi.Marshal(users)

	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "couldn't marshal to json"})
	}

	c.Data(http.StatusOK, "application/vnd.api+json", data)
}
Example #5
0
// MarshalJSON returns as as the JSON encoding of as.
func (as AppSet) MarshalJSON() ([]byte, error) {
	var (
		app           []byte
		appJSON       map[string]map[string]interface{}
		container     []byte
		containerJSON map[string]map[string]interface{}
		marshaled     []byte
		err           error
	)

	if app, err = jsonapi.Marshal(as.App); err != nil {
		return nil, err
	}

	if err = json.Unmarshal(app, &appJSON); err != nil {
		return nil, err
	}

	if container, err = jsonapi.Marshal(as.Container); err != nil {
		return nil, err
	}

	if err = json.Unmarshal(container, &containerJSON); err != nil {
		return nil, err
	}

	data := map[string][]map[string]interface{}{
		"data": []map[string]interface{}{
			appJSON["data"],
			containerJSON["data"],
		},
	}

	if marshaled, err = json.Marshal(data); err != nil {
		return nil, err
	}

	return marshaled, nil
}
Example #6
0
func JSON(c *echo.Context, code int, i interface{}) error {
	b, err := jsonapi.Marshal(i)

	if err != nil {
		return err
	}

	r := c.Response()

	r.Header().Set("Content-Type", "application/vnd.api+json")
	r.WriteHeader(code)
	r.Write(b)
	return nil
}
Example #7
0
// TransactionIndex outputs a certain number of transactions
// will always be scoped to the current user
func TransactionIndex(c *gin.Context) {
	relatedObjectID := c.Query("relatedObjectId")
	relatedObjectType := c.Query("relatedObjectType")
	isSettledQuery := c.Query("isSettled")
	statusQuery := c.Query("status")
	curUserID := c.Keys["CurrentUserID"]

	var transactions []models.Transaction

	query := database.DBCon

	isSettled, err := strconv.ParseBool(isSettledQuery)
	if isSettledQuery != "" && err == nil {
		query = query.Where("is_settled = ?", isSettled)
	}

	// TODO: Check that statusQuery is a valid status
	if statusQuery != "" {
		query = query.Where("status = ?", statusQuery)
	}

	if relatedObjectID != "" && relatedObjectType != "" {
		query.
			Where("related_object_id = ? AND related_object_type = ?", relatedObjectID, relatedObjectType).
			Order("created_at desc").
			Find(&transactions)
	} else {
		query.
			Where("creator_id = ?", curUserID).
			Find(&transactions)
	}

	// Get creator and relatedUser
	// TODO: n + 1 query problem here, so we'll figure this out later
	for i := range transactions {
		database.DBCon.First(&transactions[i].Recipient, transactions[i].RecipientID)
		database.DBCon.First(&transactions[i].Sender, transactions[i].SenderID)
		database.DBCon.First(&transactions[i].Creator, transactions[i].CreatorID)
	}

	data, err := jsonapi.Marshal(transactions)

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

	c.Data(http.StatusOK, "application/vnd.api+json", data)
}
Example #8
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 #9
0
// GroupIndex When the group's index is routed to
// this handler will run. Generally, it will
// come with some query parameters like limit and offset
// @returns an array of group structs
func GroupIndex(c *gin.Context) {
	groups := []models.Group{}
	var curUser models.User
	database.DBCon.First(&curUser, c.Keys["CurrentUserID"])

	database.DBCon.Model(&curUser).Preload("Users").Related(&groups, "Groups")

	data, err := jsonapi.Marshal(groups)

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

	c.Data(http.StatusOK, "application/vnd.api+json", data)
}
Example #10
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 #11
0
// GroupShow is used to show one specific group, returns a group struct
// @returns a group struct
func GroupShow(c *gin.Context) {
	var group models.Group
	var users []models.User

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

	database.DBCon.Model(&group).Related(&users, "Users")
	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 #12
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 #13
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 #14
0
func Get(c *echo.Context) error {
	filepath := c.Query("path")
	showHidden := c.Query("show_hidden") == "true"
	create := c.Query("create") == "true"

	if len(filepath) < 1 {
		return c.JSON(
			http.StatusBadRequest,
			hash{
				"error": "Path not specified",
			},
		)
	}

	s, err := os.Stat(filepath)
	if err != nil {
		log.Error(err.(*os.PathError).Err.Error())
		m := err.(*os.PathError).Err.Error()
		if m == "no such file or directory" || m == "The system cannot find the file specified." {
			if create {
				err := os.MkdirAll(filepath, 0777)
				if err != nil {
					return err
				}
				s, err = os.Stat(filepath)
				if err != nil {
					return err
				}
			} else {
				return c.JSON(
					http.StatusNotFound,
					hash{
						"error": "no such file or directory",
					},
				)
			}
		} else {
			return err
		}
	}

	if s.Mode().IsDir() {
		f, err := os.Open(filepath)
		if err != nil {
			return err
		}
		defer f.Close()

		files, err := f.Readdir(-1)
		if err != nil {
			return err
		}

		rt := make([]*file, 0)

		for _, fi := range files {
			name := fi.Name()
			if !showHidden && isFileHidden(fi) {
				continue
			}

			fullpath := path.Join(filepath, name)
			id, err := loadFileId(fullpath)
			if err != nil {
				log.Errorf("Cannot retrieve file id for file: %s: %s", fullpath, err.Error())
				continue
			}

			f := &file{
				Id:      id,
				ModTime: fi.ModTime().Unix(),
				Name:    name,
				Size:    fi.Size(),
			}
			if fi.IsDir() {
				f.Type = "directory"
			} else {
				f.Type = "regular file"
			}
			rt = append(rt, f)
		}
		/*
		 * The Content-Length is not set is the buffer length is more than 2048
		 */
		b, err := jsonapi.Marshal(rt)
		if err != nil {
			log.Error(err)
			return err
		}

		r := c.Response()
		r.Header().Set("Content-Length", strconv.Itoa(len(b)))
		r.Header().Set("Content-Type", "application/json; charset=utf-8")
		r.Write(b)
		return nil
	}

	return c.File(
		filepath,
		s.Name(),
		true,
	)
}
Example #15
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)
}