Beispiel #1
0
//Adds a new account to the db. Passwords are generated using bcrypt
func newAccountHandler(req *http.Request, db *gorm.DB, rendr render.Render) {
	username := req.FormValue("username")
	password := req.FormValue("password")

	if username == "" {
		log.Println(http.StatusBadRequest, "Username blank")
		rendr.Text(http.StatusBadRequest, "Supply valid username")
		return
	}
	if password == "" {
		log.Println(http.StatusBadRequest, "Password blank")
		rendr.Text(http.StatusBadRequest, "Supply valid password")
		return
	}

	hash, err := bcrypt.GenerateFromPassword([]byte(password), 0)
	if err != nil {
		log.Println(err.Error())
		rendr.Text(http.StatusBadRequest, err.Error())
		return
	}

	acc := &account{Username: username, Password: hash, Funds: 0}
	err = db.Create(acc).Error
	if err != nil {
		log.Println(err.Error())
		rendr.Text(http.StatusBadRequest, err.Error())
		return
	}
	rendr.Text(http.StatusOK, "Account created")
}
Beispiel #2
0
//Deletes a certain account from the db
func deleteAccountHandler(db *gorm.DB, acc account, rendr render.Render) {
	if err := db.Delete(&acc).Error; err != nil {
		rendr.Text(http.StatusInternalServerError, err.Error())
	} else {
		rendr.Text(http.StatusOK, "Account deleted")
	}
}
Beispiel #3
0
// Returns a json list of all the users
func getAllUsersHandler(db *gorm.DB, ren render.Render) {
	users := make([]User, 0, 0)
	if err := db.Find(&users).Error; err != nil {
		ren.Text(http.StatusInternalServerError, err.Error())
		return
	}
	ren.JSON(http.StatusOK, users)
}
Beispiel #4
0
//Gets a single user as specified in the `id` path param
func getUserHandler(db *gorm.DB, params martini.Params, ren render.Render) {
	u, err := findUserFromIDParam(db, params["id"])
	if err != nil {
		ren.Text(err.toMartiniRender())
		return
	}
	ren.JSON(http.StatusOK, u)
}
Beispiel #5
0
//Simple auth handler based on a global key. This may have to be rewritten...
func authHandler(r *http.Request, ctx martini.Context, ren render.Render) {
	log.Println(r.Header)
	if r.Header.Get("Authorization") != APIKey {
		ren.Text(http.StatusUnauthorized, "Invalid authorization")
		return
	}
	//Call the next handler
	ctx.Next()
}
Beispiel #6
0
//Get /users
func (u *UserHandler) GetUsers(request *http.Request, rd render.Render, params martini.Params) {

	users, err := u.userService.GetUsers()
	if err != nil {
		rd.Text(500, err.Error())
		return
	}

	rd.JSON(200, users)
}
Beispiel #7
0
//Transfer funds between two accounts. `from account` is retrieved from the context of the
//authorization handler. `to account` is retrieved from the request query parameters
func transferHandler(rendr render.Render, fromAcc account, req *http.Request, db *gorm.DB) {
	toAccountName := req.FormValue("to_account")
	amount, err := strconv.ParseFloat(req.FormValue("amount"), 64)
	if err != nil {
		log.Println(http.StatusBadRequest, err.Error())
		rendr.Text(http.StatusBadRequest, err.Error())
		return
	}

	toAcc, err := findAccount(db, &account{Username: toAccountName})
	if err != nil {
		log.Println(http.StatusNotFound, "Other account not found")
		rendr.Text(http.StatusNotFound, "Other account not found")
		return
	}

	err = transferFunds(db, fromAcc.ID, toAcc.ID, amount)
	if err != nil {
		log.Println(err.Error())
		rendr.Text(http.StatusBadRequest, err.Error())
		return
	}

	rendr.Text(http.StatusOK, "Transaction successful")
}
Beispiel #8
0
//Get /users/:user_id/relationships
func (u *UserHandler) GetAllRelations(request *http.Request, rd render.Render, params martini.Params) {
	// 获取 url 参数
	userid, err := strconv.ParseInt(params["user_id"], 10, 64)
	if err != nil {
		rd.Text(400, "The request cannot be fulfilled due to bad syntax.")
		return
	}

	//验证 user 是否存在
	_, err = u.userService.GetUser(userid)
	if err != nil {
		if err == pg.ErrNoRows {
			rd.Text(400, fmt.Sprintln("user", userid, "not exist"))
		} else {
			rd.Text(500, err.Error())
		}
		return
	}

	rs, err := u.userService.GetUserRelations(userid)
	if err != nil {
		rd.Text(500, err.Error())
		return
	}

	relations := make([]interface{}, 0, 0)
	for _, r := range rs {
		relations = append(relations, fmtRelationShip(r))
	}

	rd.JSON(200, relations)
}
func deleteTodoHandler(params martini.Params, rendr render.Render, db *gorm.DB) {
	id, err := strconv.Atoi(params["id"])
	if err != nil {
		panic(err)
	}

	t, err := findTodo(db, &todo{ID: id})
	if err != nil {
		rendr.Text(http.StatusBadRequest, err.Error())
		return
	}

	db.Delete(&t)
	rendr.JSON(http.StatusOK, t)
}
Beispiel #10
0
//Adds a user using POST data. Expects `Content-Type` to be `application/x-www-form-urlencoded`
func addUserHandler(db *gorm.DB, r *http.Request, ren render.Render) {
	name := r.FormValue("name")
	dob := r.FormValue("dob")
	address := r.FormValue("address")
	description := r.FormValue("description")

	toCheck := []string{name, dob, address, description}
	for _, key := range toCheck {
		if key == "" {
			ren.Text(http.StatusBadRequest, "Provide 'name', 'dob', 'address' and 'description' when creating a new user")
			return
		}
	}

	u := User{Name: name, Dob: dob, Address: address, Description: description, CreatedAt: time.Now()}
	db.Create(&u)
}
func newTodoHandler(r *http.Request, rendr render.Render, db *gorm.DB) {
	todoText := r.FormValue("text")
	if todoText == "" {
		rendr.Text(http.StatusBadRequest, "Provide a `text` parameter")
		return
	}
	completedBool, err := strconv.ParseBool(r.FormValue("completed"))
	if err != nil {
		rendr.Text(http.StatusBadRequest, "Provide a `completed` paramter as a boolean")
		return
	}

	t := todo{Text: todoText, Completed: completedBool}
	db.Create(&t)

	rendr.JSON(http.StatusOK, t)
}
func oneTodoHandler(params martini.Params, rendr render.Render, db *gorm.DB, r *http.Request) {
	id, err := strconv.Atoi(params["id"])
	if err != nil {
		panic(err)
	}

	t, err := findTodo(db, &todo{ID: id})
	if err == gorm.RecordNotFound {
		rendr.Text(http.StatusNotFound, "Resource not found")
		return
	}
	if err != nil {
		rendr.Text(http.StatusInternalServerError, err.Error())
		return
	}

	rendr.JSON(http.StatusOK, t)
}
Beispiel #13
0
//Post /users
func (u *UserHandler) CreateUser(request *http.Request, rd render.Render, params martini.Params) {

	// 获取 json body 参数
	decoder := json.NewDecoder(request.Body)
	p := struct {
		Name string `json:"name"`
	}{}
	err := decoder.Decode(&p)
	if err != nil || len(p.Name) == 0 {
		rd.Text(400, "The request cannot be fulfilled due to bad syntax.")
		return
	}

	user, err := u.userService.CreateUser(p.Name)
	if err != nil {
		rd.Text(500, err.Error())
		return
	}

	rd.JSON(200, user)
}
func updateTodoHandler(r *http.Request, params martini.Params, rendr render.Render, db *gorm.DB) {
	id, err := strconv.Atoi(params["id"])
	if err != nil {
		rendr.Text(http.StatusBadRequest, "Provide a `completed` paramter as a boolean")
		return
	}

	t, err := findTodo(db, &todo{ID: id})
	if err != nil {
		rendr.Text(http.StatusBadRequest, err.Error())
		return
	}

	text := r.FormValue("text")
	if text != "" {
		t.Text = text
	}

	completed := r.FormValue("completed")
	if completed != "" {
		completedBool, err := strconv.ParseBool(completed)
		if err != nil {
			rendr.Text(http.StatusBadRequest, err.Error())
			return
		}
		t.Completed = completedBool
	}

	db.Save(t)
	rendr.JSON(http.StatusOK, t)
}
Beispiel #15
0
//Logs a user in. If successful returns the authorization token
//Note that since we don't have a logout handler, a token for a deleted account can be valid. This
//is partially migitated by the 5 minute exp mark.
func loginHandler(req *http.Request, db *gorm.DB, rendr render.Render) {
	username := req.FormValue("username")
	password := req.FormValue("password")

	acc, err := findAccount(db, &account{Username: username})
	if err != nil {
		rendr.Text(http.StatusNotFound, "Username not found")
		return
	}

	err = bcrypt.CompareHashAndPassword(acc.Password, []byte(password))
	if err != nil {
		rendr.Text(http.StatusUnauthorized, "Invalid password")
		return
	}

	token := jwt.New(signingMethod)
	token.Claims["exp"] = time.Now().Add(tokenExpires).Unix()
	token.Claims["id"] = acc.ID

	tokenStr, err := token.SignedString([]byte(secretKey))
	if err != nil {
		rendr.Text(http.StatusInternalServerError, err.Error())
		return
	}

	tokenJSON := make(map[string]string)
	tokenJSON["token"] = tokenStr

	rendr.JSON(http.StatusOK, tokenJSON)
}
Beispiel #16
0
//Deletes a user based on a given path `id` param
func deleteUserHandler(db *gorm.DB, params martini.Params, ren render.Render) {
	u, err := findUserFromIDParam(db, params["id"])
	if err != nil {
		ren.Text(err.toMartiniRender())
		return
	}
	if db.Delete(&u).Error != nil {
		ren.Text(http.StatusInternalServerError, err.Error())
		return
	}
	ren.Text(http.StatusOK, fmt.Sprintf("User with id: %d was deleted", u.ID))
}
Beispiel #17
0
//If we don't write a response here, the next handler will execute
func auth(req *http.Request, rendr render.Render, ctx martini.Context, db *gorm.DB) {
	tokenStr := req.Header.Get("Authorization")
	token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
		if token.Method != signingMethod {
			log.Println("token.Method != signingMethod")
			return nil, fmt.Errorf("Invalid signingMethod")
		}
		return secretKey, nil
	})

	if err != nil {
		log.Println(err.Error())
		log.Println("token was:", tokenStr)
		rendr.Text(http.StatusUnauthorized, err.Error())
		return
	}

	if !token.Valid {
		rendr.Text(http.StatusUnauthorized, "Invalid token")
		return
	}

	userID, ok := token.Claims["id"].(float64)
	if !ok {
		rendr.Text(http.StatusInternalServerError, "Bad token")
		return
	}

	acc, err := findAccount(db, &account{ID: int(userID)})
	if err != nil {
		rendr.Text(http.StatusNotFound, "User not found")
		return
	}

	//Attach the current user to the context for other handlers
	//Pass by value because we don't want to manipulate the object for each request, causes race
	//conditions. Instead, let's do everything in transactions wher we `select` the account first
	ctx.Map(acc)
	ctx.Next()
}
Beispiel #18
0
func withdrawHandler(rendr render.Render, acc account, req *http.Request, db *gorm.DB) {
	amount, err := strconv.ParseFloat(req.FormValue("amount"), 64)
	if err != nil {
		rendr.Text(http.StatusBadRequest, err.Error())
		return
	}

	if err = withdrawFunds(db, acc.ID, amount); err != nil {
		rendr.Text(http.StatusBadRequest, err.Error())
		return
	}

	rendr.Text(http.StatusOK, "Withdrawal successful")
}
Beispiel #19
0
//Deposit funds to an account. The account is retrieved from the context of the previous
//authorization handler
func depositHandler(rendr render.Render, acc account, req *http.Request, db *gorm.DB) {
	amount, err := strconv.ParseFloat(req.FormValue("amount"), 64)
	if err != nil {
		log.Println(err.Error())
		rendr.Text(http.StatusBadRequest, err.Error())
		return
	}

	err = depositFunds(db, acc.ID, amount)
	if err != nil {
		log.Println(err.Error())
		rendr.Text(http.StatusBadRequest, err.Error())
		return
	}
	rendr.Text(http.StatusOK, "Deposit successful")
}
Beispiel #20
0
//Updates a user based on a given path parameter `id`. Beware: if there are no supplied parameters to
//updated it returns a 400 notifying that no update was made. We might need to change the status
//code, but I'd rather prefer the failure to be visible.
//Expects `Content-Type` to be `application/x-www-form-urlencoded`
func updateUserHandler(db *gorm.DB, params martini.Params, r *http.Request, ren render.Render) {
	u, err := findUserFromIDParam(db, params["id"])
	if err != nil {
		ren.Text(err.toMartiniRender())
		return
	}

	anyUpdates := false
	name := r.FormValue("name")
	if name != "" {
		anyUpdates = true
		u.Name = name
	}
	dob := r.FormValue("dob")
	if dob != "" {
		anyUpdates = true
		u.Dob = dob
	}
	address := r.FormValue("address")
	if address != "" {
		anyUpdates = true
		u.Address = address
	}
	description := r.FormValue("description")
	if description != "" {
		anyUpdates = true
		u.Description = description
	}

	if !anyUpdates {
		ren.Text(http.StatusBadRequest, "At least provide one valid parameter to update")
		return
	}

	if err := db.Save(u).Error; err != nil {
		ren.Text(http.StatusInternalServerError, err.Error())
		return
	}

	ren.JSON(http.StatusOK, u)
}
Beispiel #21
0
//Put /users/:user_id/relationships/:other_user_id
func (u *UserHandler) ChangeUserRelation(request *http.Request, rd render.Render, params martini.Params) {

	// 获取 url 参数
	userid, err1 := strconv.ParseInt(params["user_id"], 10, 64)
	otherid, err2 := strconv.ParseInt(params["other_user_id"], 10, 64)
	if err1 != nil || err2 != nil {
		rd.Text(400, "The request cannot be fulfilled due to bad syntax.")
		return
	}

	// 获取 json body 参数
	decoder := json.NewDecoder(request.Body)
	p := struct {
		State string `json:"state"`
	}{}
	err := decoder.Decode(&p)

	//验证 user 是否存在
	_, err = u.userService.GetUser(userid)
	if err != nil {
		if err == pg.ErrNoRows {
			rd.Text(400, fmt.Sprintln("user", userid, "not exist"))
		} else {
			rd.Text(500, err.Error())
		}
		return
	}
	_, err = u.userService.GetUser(otherid)
	if err != nil {
		if err == pg.ErrNoRows {
			rd.Text(400, fmt.Sprintln("user", otherid, "not exist"))
		} else {
			rd.Text(500, err.Error())
		}
		return
	}

	if _, ok := Model.AllowedRelation[p.State]; err != nil || !ok {
		rd.Text(400, "The request cannot be fulfilled due to bad syntax.")
		return
	}

	r, err := u.userService.ChangeUserRelation(userid, otherid, Model.AllowedRelation[p.State])
	if err != nil {
		rd.Text(500, err.Error())
		return
	}

	rd.JSON(200, fmtRelationShip(r))
}
Beispiel #22
0
func (this *Request) showError(err error, r render.Render) {
	r.Text(500, fmt.Sprintf("%v", err))
}