From 978a6d09b2f1a4f69601c88258d9119f07bc1bcb Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 13 Oct 2015 10:48:53 -0700 Subject: [PATCH] User guards Fixes #14 --- api/users.go | 25 +++++++++++++++++++++++++ errors/users.go | 2 ++ 2 files changed, 27 insertions(+) diff --git a/api/users.go b/api/users.go index 199cc38..309565d 100644 --- a/api/users.go +++ b/api/users.go @@ -6,6 +6,7 @@ import ( "log" "net/http" "net/url" + "strconv" "github.com/thermokarst/bactdb/Godeps/_workspace/src/github.com/gorilla/mux" "github.com/thermokarst/bactdb/Godeps/_workspace/src/github.com/lib/pq" @@ -44,6 +45,11 @@ func (u UserService) List(val *url.Values, claims *types.Claims) (types.Entity, return nil, newJSONError(err, http.StatusInternalServerError) } + // Only Admins can view all users + if claims.Role != "A" { + return nil, newJSONError(errors.ErrUserForbidden, http.StatusForbidden) + } + users, err := models.ListUsers(opt, claims) if err != nil { return nil, newJSONError(err, http.StatusInternalServerError) @@ -60,6 +66,11 @@ func (u UserService) List(val *url.Values, claims *types.Claims) (types.Entity, // Get retrieves a single user. func (u UserService) Get(id int64, dummy string, claims *types.Claims) (types.Entity, *types.AppError) { + // Only Admins can view any users, otherwise users are limited to themselves + if claims.Role != "A" && claims.Sub != id { + return nil, newJSONError(errors.ErrUserForbidden, http.StatusForbidden) + } + user, err := models.GetUser(id, dummy, claims) user.Password = "" if err != nil { @@ -77,6 +88,11 @@ func (u UserService) Get(id int64, dummy string, claims *types.Claims) (types.En // Update modifies an existing user. func (u UserService) Update(id int64, e *types.Entity, dummy string, claims *types.Claims) *types.AppError { + // Only Admins can view any users, otherwise users are limited to themselves + if claims.Role != "A" && claims.Sub != id { + return newJSONError(errors.ErrUserForbidden, http.StatusForbidden) + } + user := (*e).(*payloads.User).User originalUser, err := models.GetUser(id, dummy, claims) @@ -260,6 +276,15 @@ func HandleUserLockout(w http.ResponseWriter, r *http.Request) *types.AppError { func HandleUserPasswordChange(w http.ResponseWriter, r *http.Request) *types.AppError { claims := helpers.GetClaims(r) + id, err := strconv.ParseInt(r.FormValue("id"), 10, 64) + if err != nil { + return newJSONError(err, http.StatusInternalServerError) + } + + // Only a user can change their own password + if claims.Sub != id { + return newJSONError(errors.ErrUserForbidden, http.StatusForbidden) + } if err := models.UpdateUserPassword(&claims, r.FormValue("password")); err != nil { return newJSONError(err, http.StatusInternalServerError) diff --git a/errors/users.go b/errors/users.go index eaa7cdc..13e6953 100644 --- a/errors/users.go +++ b/errors/users.go @@ -13,4 +13,6 @@ var ( ErrInvalidEmailOrPassword = errors.New("Invalid email or password") // ErrEmailAddressTaken when email already registered. ErrEmailAddressTaken = errors.New("Email address is already registered") + // ErrUserForbidden when user not allowed to view a resource + ErrUserForbidden = errors.New("User ccount not authorized") )