Modify User (as a regular user) fails #891 (#959)

This commit is contained in:
John Murphy 2017-01-18 00:43:59 +08:00 committed by GitHub
parent f169b68bdf
commit 56b8772f13
16 changed files with 354 additions and 102 deletions

View file

@ -137,6 +137,7 @@ deps:
npm install
go get github.com/jteeuwen/go-bindata/...
go get github.com/Masterminds/glide
go get github.com/groob/mockimpl
glide install
distclean:

View file

@ -64,6 +64,12 @@ type UserService interface {
// ModifyUser updates a user's parameters given a UserPayload.
ModifyUser(ctx context.Context, userID uint, p UserPayload) (user *User, err error)
// ChangeUserAdmin is used to modify the admin state of the user identified by id.
ChangeUserAdmin(ctx context.Context, id uint, isAdmin bool) (*User, error)
// ChangeUserEnabled is used to enable/disable the user identified by id.
ChangeUserEnabled(ctx context.Context, id uint, isEnabled bool) (*User, error)
}
// User is the model struct which represents a kolide user

View file

@ -32,6 +32,9 @@ func makeGetAppConfigEndpoint(svc kolide.Service) endpoint.Endpoint {
// only admin can see smtp settings
if vc.IsAdmin() {
smtpSettings = smtpSettingsFromAppConfig(config)
if smtpSettings.SMTPPassword != "" {
smtpSettings.SMTPPassword = "********"
}
}
response := appConfigResponse{
OrgInfo: &kolide.OrgInfo{
@ -43,9 +46,6 @@ func makeGetAppConfigEndpoint(svc kolide.Service) endpoint.Endpoint {
},
SMTPSettings: smtpSettings,
}
if response.SMTPSettings.SMTPPassword != "" {
response.SMTPSettings.SMTPPassword = "********"
}
return response, nil
}
}

View file

@ -25,7 +25,7 @@ func testGetAppConfig(t *testing.T, r *testResource) {
req, err := http.NewRequest("GET", r.server.URL+"/api/v1/kolide/config", nil)
require.Nil(t, err)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.userToken))
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.adminToken))
client := &http.Client{}
resp, err := client.Do(req)
require.Nil(t, err)
@ -63,7 +63,7 @@ func testModifyAppConfig(t *testing.T, r *testResource) {
require.Nil(t, err)
req, err := http.NewRequest("PATCH", r.server.URL+"/api/v1/kolide/config", &buffer)
require.Nil(t, err)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.userToken))
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.adminToken))
client := &http.Client{}
resp, err := client.Do(req)
require.Nil(t, err)
@ -92,7 +92,7 @@ func testModifyAppConfigWithValidationFail(t *testing.T, r *testResource) {
require.Nil(t, err)
req, err := http.NewRequest("PATCH", r.server.URL+"/api/v1/kolide/config", &buffer)
require.Nil(t, err)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.userToken))
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.adminToken))
client := &http.Client{}
resp, err := client.Do(req)
require.Nil(t, err)

View file

@ -26,7 +26,7 @@ func testImportConfigWithGlob(t *testing.T, r *testResource) {
buff := bytes.NewBufferString(testJSON)
req, err := http.NewRequest("POST", r.server.URL+"/api/v1/kolide/osquery/config/import", buff)
require.Nil(t, err)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.userToken))
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.adminToken))
client := &http.Client{}
resp, err := client.Do(req)
require.Nil(t, err)
@ -48,7 +48,7 @@ func testImportConfigWithMissingGlob(t *testing.T, r *testResource) {
buff := bytes.NewBufferString(testJSON)
req, err := http.NewRequest("POST", r.server.URL+"/api/v1/kolide/osquery/config/import", buff)
require.Nil(t, err)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.userToken))
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.adminToken))
client := &http.Client{}
resp, err := client.Do(req)
require.Nil(t, err)
@ -73,7 +73,7 @@ func testImportConfig(t *testing.T, r *testResource) {
buff := bytes.NewBufferString(testJSON)
req, err := http.NewRequest("POST", r.server.URL+"/api/v1/kolide/osquery/config/import", buff)
require.Nil(t, err)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.userToken))
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.adminToken))
client := &http.Client{}
resp, err := client.Do(req)
require.Nil(t, err)
@ -93,7 +93,7 @@ func testImportConfigMissingExternal(t *testing.T, r *testResource) {
buff := bytes.NewBufferString(testJSON)
req, err := http.NewRequest("POST", r.server.URL+"/api/v1/kolide/osquery/config/import", buff)
require.Nil(t, err)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.userToken))
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.adminToken))
client := &http.Client{}
resp, err := client.Do(req)
require.Nil(t, err)

View file

@ -180,72 +180,6 @@ const (
admin
)
func validateModifyUserRequest(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
r := request.(modifyUserRequest)
vc, ok := viewer.FromContext(ctx)
if !ok {
return nil, errNoContext
}
uid := requestUserIDFromContext(ctx)
p := r.payload
must := requireRoleForUserModification(p)
var badArgs []invalidArgument
if !vc.IsAdmin() {
for _, field := range must[admin] {
badArgs = append(badArgs, invalidArgument{name: field, reason: "must be an admin"})
}
}
if !vc.CanPerformWriteActionOnUser(uid) {
for _, field := range must[self] {
badArgs = append(badArgs, invalidArgument{name: field, reason: "no write permissions on user"})
}
}
if len(badArgs) != 0 {
return nil, permissionError{badArgs: badArgs}
}
return next(ctx, request)
}
}
// checks if fields were set in a user payload
// returns a map of updated fields for each role required
func requireRoleForUserModification(p kolide.UserPayload) map[permission][]string {
must := make(map[permission][]string)
adminFields := []string{}
if p.Enabled != nil {
adminFields = append(adminFields, "enabled")
}
if p.Admin != nil {
adminFields = append(adminFields, "admin")
}
if len(adminFields) != 0 {
must[admin] = adminFields
}
selfFields := []string{}
if p.Username != nil {
selfFields = append(selfFields, "username")
}
if p.GravatarURL != nil {
selfFields = append(selfFields, "gravatar_url")
}
if p.Position != nil {
selfFields = append(selfFields, "position")
}
if p.Email != nil {
selfFields = append(selfFields, "email")
}
if p.Password != nil {
selfFields = append(selfFields, "password")
}
// self is always a must, otherwise
// anyone can edit the field, and we don't have that requirement
must[self] = selfFields
return must
}
func requestUserIDFromContext(ctx context.Context) uint {
userID, ok := ctx.Value("request-id").(uint)
if !ok {

View file

@ -107,17 +107,6 @@ func TestEndpointPermissions(t *testing.T) {
requestID: admin1.ID,
wantErr: permissionError{message: "no read permissions on user"},
},
{
endpoint: validateModifyUserRequest(e),
request: modifyUserRequest{},
wantErr: errNoContext,
},
{
endpoint: validateModifyUserRequest(e),
request: modifyUserRequest{payload: kolide.UserPayload{Enabled: boolPtr(true)}},
vc: &viewer.Viewer{User: user1},
wantErr: permissionError{message: "unauthorized: must be an admin"},
},
}
for _, tt := range endpointTests {

View file

@ -15,7 +15,7 @@ func testGetOptions(t *testing.T, r *testResource) {
req, err := http.NewRequest("GET", r.server.URL+"/api/v1/kolide/options", nil)
require.Nil(t, err)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.userToken))
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.adminToken))
client := &http.Client{}
resp, err := client.Do(req)
require.Nil(t, err)
@ -34,7 +34,7 @@ func testModifyOptions(t *testing.T, r *testResource) {
buff := bytes.NewBufferString(inJson)
req, err := http.NewRequest("PATCH", r.server.URL+"/api/v1/kolide/options", buff)
require.Nil(t, err)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.userToken))
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.adminToken))
client := &http.Client{}
resp, err := client.Do(req)
require.Nil(t, err)
@ -55,7 +55,7 @@ func testModifyOptionsValidationFail(t *testing.T, r *testResource) {
buff := bytes.NewBufferString(inJson)
req, err := http.NewRequest("PATCH", r.server.URL+"/api/v1/kolide/options", buff)
require.Nil(t, err)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.userToken))
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.adminToken))
client := &http.Client{}
resp, err := client.Do(req)
require.Nil(t, err)

View file

@ -22,9 +22,10 @@ import (
)
type testResource struct {
server *httptest.Server
userToken string
ds kolide.Datastore
server *httptest.Server
adminToken string
userToken string
ds kolide.Datastore
}
func setupEndpointTest(t *testing.T) *testResource {
@ -80,7 +81,19 @@ func setupEndpointTest(t *testing.T) *testResource {
Err string `json:"error,omitempty"`
}{}
json.NewDecoder(resp.Body).Decode(&jsn)
test.adminToken = jsn.Token
// log in non admin user
userParam.Username = "user1"
userParam.Password = testUsers["user1"].PlaintextPassword
marshalledUser, _ = json.Marshal(userParam)
requestBody = &nopCloser{bytes.NewBuffer(marshalledUser)}
resp, err = http.Post(test.server.URL+"/api/v1/kolide/login", "application/json", requestBody)
require.Nil(t, err)
err = json.NewDecoder(resp.Body).Decode(&jsn)
require.Nil(t, err)
test.userToken = jsn.Token
return test
}
@ -101,6 +114,10 @@ var testFunctions = [...]func(*testing.T, *testResource){
testImportConfigMissingExternal,
testImportConfigWithMissingGlob,
testImportConfigWithGlob,
testAdminUserSetAdmin,
testNonAdminUserSetAdmin,
testAdminUserSetEnabled,
testNonAdminUserSetEnabled,
}
func TestEndpoints(t *testing.T) {

View file

@ -60,6 +60,52 @@ func makeGetUserEndpoint(svc kolide.Service) endpoint.Endpoint {
}
}
type adminUserRequest struct {
ID uint `json:"id"`
Admin bool `json:"admin"`
}
type adminUserResponse struct {
User *kolide.User `json:"user,omitempty"`
Err error `json:"error,omitempty"`
}
func (r adminUserResponse) error() error { return r.Err }
func makeAdminUserEndpoint(svc kolide.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(adminUserRequest)
user, err := svc.ChangeUserAdmin(ctx, req.ID, req.Admin)
if err != nil {
return adminUserResponse{Err: err}, nil
}
return adminUserResponse{User: user}, nil
}
}
type enableUserRequest struct {
ID uint `json:"id"`
Enabled bool `json:"enabled"`
}
type enableUserResponse struct {
User *kolide.User `json:"user,omitempty"`
Err error `json:"error,omitempty"`
}
func (r enableUserResponse) error() error { return r.Err }
func makeEnableUserEndpoint(svc kolide.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(enableUserRequest)
user, err := svc.ChangeUserEnabled(ctx, req.ID, req.Enabled)
if err != nil {
return enableUserResponse{Err: err}, nil
}
return enableUserResponse{User: user}, nil
}
}
func makeGetSessionUserEndpoint(svc kolide.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
user, err := svc.AuthenticatedUser(ctx)

View file

@ -0,0 +1,105 @@
package service
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func testAdminUserSetAdmin(t *testing.T, r *testResource) {
user, err := r.ds.User("user1")
require.Nil(t, err)
assert.False(t, user.Admin)
inJson := `{"admin":true}`
buff := bytes.NewBufferString(inJson)
path := fmt.Sprintf("/api/v1/kolide/users/%d/admin", user.ID)
req, err := http.NewRequest("POST", r.server.URL+path, buff)
require.Nil(t, err)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.adminToken))
client := &http.Client{}
resp, err := client.Do(req)
require.Nil(t, err)
var actual adminUserResponse
err = json.NewDecoder(resp.Body).Decode(&actual)
require.Nil(t, err)
assert.Nil(t, actual.Err)
require.NotNil(t, actual.User)
assert.True(t, actual.User.Admin)
user, err = r.ds.User("user1")
require.Nil(t, err)
assert.True(t, user.Admin)
}
func testNonAdminUserSetAdmin(t *testing.T, r *testResource) {
user, err := r.ds.User("user1")
require.Nil(t, err)
assert.False(t, user.Admin)
inJson := `{"admin":true}`
buff := bytes.NewBufferString(inJson)
path := fmt.Sprintf("/api/v1/kolide/users/%d/admin", user.ID)
req, err := http.NewRequest("POST", r.server.URL+path, buff)
require.Nil(t, err)
// user NOT admin
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.userToken))
client := &http.Client{}
resp, err := client.Do(req)
require.Nil(t, err)
assert.Equal(t, http.StatusServiceUnavailable, resp.StatusCode)
rb := make([]byte, 500)
resp.Body.Read(rb)
user, err = r.ds.User("user1")
require.Nil(t, err)
assert.False(t, user.Admin)
}
func testAdminUserSetEnabled(t *testing.T, r *testResource) {
user, err := r.ds.User("user1")
require.Nil(t, err)
assert.True(t, user.Enabled)
inJson := `{"enabled":false}`
buff := bytes.NewBufferString(inJson)
path := fmt.Sprintf("/api/v1/kolide/users/%d/enable", user.ID)
req, err := http.NewRequest("POST", r.server.URL+path, buff)
require.Nil(t, err)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.adminToken))
client := &http.Client{}
resp, err := client.Do(req)
require.Nil(t, err)
var actual adminUserResponse
err = json.NewDecoder(resp.Body).Decode(&actual)
require.Nil(t, err)
assert.Nil(t, actual.Err)
require.NotNil(t, actual.User)
assert.False(t, actual.User.Enabled)
user, err = r.ds.User("user1")
require.Nil(t, err)
assert.False(t, user.Enabled)
}
func testNonAdminUserSetEnabled(t *testing.T, r *testResource) {
user, err := r.ds.User("user1")
require.Nil(t, err)
assert.True(t, user.Enabled)
inJson := `{"enabled":false}`
buff := bytes.NewBufferString(inJson)
path := fmt.Sprintf("/api/v1/kolide/users/%d/enable", user.ID)
req, err := http.NewRequest("POST", r.server.URL+path, buff)
require.Nil(t, err)
// user NOT admin
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.userToken))
client := &http.Client{}
resp, err := client.Do(req)
require.Nil(t, err)
assert.Equal(t, http.StatusServiceUnavailable, resp.StatusCode)
rb := make([]byte, 500)
resp.Body.Read(rb)
user, err = r.ds.User("user1")
require.Nil(t, err)
// shouldn't change
assert.True(t, user.Enabled)
}

View file

@ -25,6 +25,8 @@ type KolideEndpoints struct {
GetUser endpoint.Endpoint
ListUsers endpoint.Endpoint
ModifyUser endpoint.Endpoint
AdminUser endpoint.Endpoint
EnableUser endpoint.Endpoint
RequirePasswordReset endpoint.Endpoint
PerformRequiredPasswordReset endpoint.Endpoint
GetSessionsForUserInfo endpoint.Endpoint
@ -94,7 +96,9 @@ func MakeKolideServerEndpoints(svc kolide.Service, jwtKey string) KolideEndpoint
ChangePassword: authenticatedUser(jwtKey, svc, canPerformActions(makeChangePasswordEndpoint(svc))),
GetUser: authenticatedUser(jwtKey, svc, canReadUser(makeGetUserEndpoint(svc))),
ListUsers: authenticatedUser(jwtKey, svc, canPerformActions(makeListUsersEndpoint(svc))),
ModifyUser: authenticatedUser(jwtKey, svc, validateModifyUserRequest(makeModifyUserEndpoint(svc))),
ModifyUser: authenticatedUser(jwtKey, svc, canPerformActions(makeModifyUserEndpoint(svc))),
AdminUser: authenticatedUser(jwtKey, svc, mustBeAdmin(makeAdminUserEndpoint(svc))),
EnableUser: authenticatedUser(jwtKey, svc, mustBeAdmin(makeEnableUserEndpoint(svc))),
RequirePasswordReset: authenticatedUser(jwtKey, svc, mustBeAdmin(makeRequirePasswordResetEndpoint(svc))),
// PerformRequiredPasswordReset needs only to authenticate the
// logged in user
@ -158,6 +162,8 @@ type kolideHandlers struct {
GetUser http.Handler
ListUsers http.Handler
ModifyUser http.Handler
AdminUser http.Handler
EnableUser http.Handler
RequirePasswordReset http.Handler
PerformRequiredPasswordReset http.Handler
GetSessionsForUserInfo http.Handler
@ -223,6 +229,8 @@ func makeKolideKitHandlers(ctx context.Context, e KolideEndpoints, opts []kithtt
ModifyUser: newServer(e.ModifyUser, decodeModifyUserRequest),
RequirePasswordReset: newServer(e.RequirePasswordReset, decodeRequirePasswordResetRequest),
PerformRequiredPasswordReset: newServer(e.PerformRequiredPasswordReset, decodePerformRequiredPasswordResetRequest),
EnableUser: newServer(e.EnableUser, decodeEnableUserRequest),
AdminUser: newServer(e.AdminUser, decodeAdminUserRequest),
GetSessionsForUserInfo: newServer(e.GetSessionsForUserInfo, decodeGetInfoAboutSessionsForUserRequest),
DeleteSessionsForUser: newServer(e.DeleteSessionsForUser, decodeDeleteSessionsForUserRequest),
GetSessionInfo: newServer(e.GetSessionInfo, decodeGetInfoAboutSessionRequest),
@ -320,6 +328,8 @@ func attachKolideAPIRoutes(r *mux.Router, h *kolideHandlers) {
r.Handle("/api/v1/kolide/users", h.CreateUser).Methods("POST").Name("create_user")
r.Handle("/api/v1/kolide/users/{id}", h.GetUser).Methods("GET").Name("get_user")
r.Handle("/api/v1/kolide/users/{id}", h.ModifyUser).Methods("PATCH").Name("modify_user")
r.Handle("/api/v1/kolide/users/{id}/enable", h.EnableUser).Methods("POST").Name("enable_user")
r.Handle("/api/v1/kolide/users/{id}/admin", h.AdminUser).Methods("POST").Name("admin_user")
r.Handle("/api/v1/kolide/users/{id}/require_password_reset", h.RequirePasswordReset).Methods("POST").Name("require_password_reset")
r.Handle("/api/v1/kolide/users/{id}/sessions", h.GetSessionsForUserInfo).Methods("GET").Name("get_session_for_user")
r.Handle("/api/v1/kolide/users/{id}/sessions", h.DeleteSessionsForUser).Methods("DELETE").Name("delete_session_for_user")

View file

@ -8,6 +8,68 @@ import (
"golang.org/x/net/context"
)
func (mw loggingMiddleware) ChangeUserAdmin(ctx context.Context, id uint, isAdmin bool) (*kolide.User, error) {
var (
loggedInUser = "unauthenticated"
userName = "none"
err error
user *kolide.User
)
vc, ok := viewer.FromContext(ctx)
if ok {
loggedInUser = vc.Username()
}
defer func(begin time.Time) {
_ = mw.logger.Log(
"method", "ChangeUserAdmin",
"user", userName,
"changed_by", loggedInUser,
"admin", isAdmin,
"err", err,
"took", time.Since(begin),
)
}(time.Now())
user, err = mw.Service.ChangeUserAdmin(ctx, id, isAdmin)
if user != nil {
userName = user.Username
}
return user, err
}
func (mw loggingMiddleware) ChangeUserEnabled(ctx context.Context, id uint, isEnabled bool) (*kolide.User, error) {
var (
loggedInUser = "unauthenticated"
userName = "none"
err error
user *kolide.User
)
vc, ok := viewer.FromContext(ctx)
if ok {
loggedInUser = vc.Username()
}
defer func(begin time.Time) {
_ = mw.logger.Log(
"method", "ChangeUserEnabled",
"user", userName,
"changed_by", loggedInUser,
"enabled", isEnabled,
"err", err,
"took", time.Since(begin),
)
}(time.Now())
user, err = mw.Service.ChangeUserEnabled(ctx, id, isEnabled)
if user != nil {
userName = user.Username
}
return user, err
}
func (mw loggingMiddleware) NewAdminCreatedUser(ctx context.Context, p kolide.UserPayload) (*kolide.User, error) {
var (
user *kolide.User

View file

@ -8,6 +8,38 @@ import (
"golang.org/x/net/context"
)
func (mw metricsMiddleware) ChangeUserAdmin(ctx context.Context, id uint, isAdmin bool) (*kolide.User, error) {
var (
user *kolide.User
err error
)
defer func(begin time.Time) {
lvs := []string{"method", "ChangeUserAdmin", "error", fmt.Sprint(err != nil)}
mw.requestCount.With(lvs...).Add(1)
mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
}(time.Now())
user, err = mw.Service.ChangeUserAdmin(ctx, id, isAdmin)
return user, err
}
func (mw metricsMiddleware) ChangeUserEnabled(ctx context.Context, id uint, isEnabled bool) (*kolide.User, error) {
var (
user *kolide.User
err error
)
defer func(begin time.Time) {
lvs := []string{"method", "ChangeUserEnabled", "error", fmt.Sprint(err != nil)}
mw.requestCount.With(lvs...).Add(1)
mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
}(time.Now())
user, err = mw.Service.ChangeUserEnabled(ctx, id, isEnabled)
return user, err
}
func (mw metricsMiddleware) NewUser(ctx context.Context, p kolide.UserPayload) (*kolide.User, error) {
var (
user *kolide.User

View file

@ -49,6 +49,30 @@ func (svc service) newUser(p kolide.UserPayload) (*kolide.User, error) {
return user, nil
}
func (svc service) ChangeUserAdmin(ctx context.Context, id uint, isAdmin bool) (*kolide.User, error) {
user, err := svc.ds.UserByID(id)
if err != nil {
return nil, err
}
user.Admin = isAdmin
if err = svc.saveUser(user); err != nil {
return nil, err
}
return user, nil
}
func (svc service) ChangeUserEnabled(ctx context.Context, id uint, isEnabled bool) (*kolide.User, error) {
user, err := svc.ds.UserByID(id)
if err != nil {
return nil, err
}
user.Enabled = isEnabled
if err = svc.saveUser(user); err != nil {
return nil, err
}
return user, nil
}
func (svc service) ModifyUser(ctx context.Context, userID uint, p kolide.UserPayload) (*kolide.User, error) {
user, err := svc.User(ctx, userID)
if err != nil {
@ -57,6 +81,14 @@ func (svc service) ModifyUser(ctx context.Context, userID uint, p kolide.UserPay
// the method assumes that the correct authorization
// has been validated higher up the stack
if p.Admin != nil {
user.Admin = *p.Admin
}
if p.Enabled != nil {
user.Enabled = *p.Enabled
}
if p.Username != nil {
user.Username = *p.Username
}
@ -65,18 +97,10 @@ func (svc service) ModifyUser(ctx context.Context, userID uint, p kolide.UserPay
user.Name = *p.Name
}
if p.Admin != nil {
user.Admin = *p.Admin
}
if p.Email != nil {
user.Email = *p.Email
}
if p.Enabled != nil {
user.Enabled = *p.Enabled
}
if p.Position != nil {
user.Position = *p.Position
}

View file

@ -8,6 +8,32 @@ import (
"golang.org/x/net/context"
)
func decodeEnableUserRequest(ctx context.Context, r *http.Request) (interface{}, error) {
id, err := idFromRequest(r, "id")
if err != nil {
return nil, err
}
var req enableUserRequest
if err = json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, err
}
req.ID = id
return req, nil
}
func decodeAdminUserRequest(ctx context.Context, r *http.Request) (interface{}, error) {
id, err := idFromRequest(r, "id")
if err != nil {
return nil, err
}
var req adminUserRequest
if err = json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, err
}
req.ID = id
return req, nil
}
func decodeCreateUserRequest(ctx context.Context, r *http.Request) (interface{}, error) {
var req createUserRequest
if err := json.NewDecoder(r.Body).Decode(&req.payload); err != nil {