github.com/merlinepedra/gophish1@v0.9.0/controllers/api/user_test.go (about) 1 package api 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "net/http" 8 "net/http/httptest" 9 10 "golang.org/x/crypto/bcrypt" 11 12 ctx "github.com/gophish/gophish/context" 13 "github.com/gophish/gophish/models" 14 ) 15 16 func (s *APISuite) createUnpriviledgedUser(slug string) *models.User { 17 role, err := models.GetRoleBySlug(slug) 18 s.Nil(err) 19 unauthorizedUser := &models.User{ 20 Username: "foo", 21 Hash: "bar", 22 ApiKey: "12345", 23 Role: role, 24 RoleID: role.ID, 25 } 26 err = models.PutUser(unauthorizedUser) 27 s.Nil(err) 28 return unauthorizedUser 29 } 30 31 func (s *APISuite) TestGetUsers() { 32 r := httptest.NewRequest(http.MethodGet, "/api/users", nil) 33 r = ctx.Set(r, "user", s.admin) 34 w := httptest.NewRecorder() 35 36 s.apiServer.Users(w, r) 37 s.Equal(w.Code, http.StatusOK) 38 39 got := []models.User{} 40 err := json.NewDecoder(w.Body).Decode(&got) 41 s.Nil(err) 42 43 // We only expect one user 44 s.Equal(1, len(got)) 45 // And it should be the admin user 46 s.Equal(s.admin.Id, got[0].Id) 47 } 48 49 func (s *APISuite) TestCreateUser() { 50 payload := &userRequest{ 51 Username: "foo", 52 Password: "bar", 53 Role: models.RoleUser, 54 } 55 body, err := json.Marshal(payload) 56 s.Nil(err) 57 58 r := httptest.NewRequest(http.MethodPost, "/api/users", bytes.NewBuffer(body)) 59 r.Header.Set("Content-Type", "application/json") 60 r = ctx.Set(r, "user", s.admin) 61 w := httptest.NewRecorder() 62 63 s.apiServer.Users(w, r) 64 s.Equal(w.Code, http.StatusOK) 65 66 got := &models.User{} 67 err = json.NewDecoder(w.Body).Decode(got) 68 s.Nil(err) 69 s.Equal(got.Username, payload.Username) 70 s.Equal(got.Role.Slug, payload.Role) 71 } 72 73 // TestModifyUser tests that a user with the appropriate access is able to 74 // modify their username and password. 75 func (s *APISuite) TestModifyUser() { 76 unpriviledgedUser := s.createUnpriviledgedUser(models.RoleUser) 77 newPassword := "new-password" 78 newUsername := "new-username" 79 payload := userRequest{ 80 Username: newUsername, 81 Password: newPassword, 82 Role: unpriviledgedUser.Role.Slug, 83 } 84 body, err := json.Marshal(payload) 85 s.Nil(err) 86 url := fmt.Sprintf("/api/users/%d", unpriviledgedUser.Id) 87 r := httptest.NewRequest(http.MethodPut, url, bytes.NewBuffer(body)) 88 r.Header.Set("Content-Type", "application/json") 89 r.Header.Set("Authorization", fmt.Sprintf("Bearer %s", unpriviledgedUser.ApiKey)) 90 w := httptest.NewRecorder() 91 92 s.apiServer.ServeHTTP(w, r) 93 response := &models.User{} 94 err = json.NewDecoder(w.Body).Decode(response) 95 s.Nil(err) 96 s.Equal(w.Code, http.StatusOK) 97 s.Equal(response.Username, newUsername) 98 got, err := models.GetUser(unpriviledgedUser.Id) 99 s.Nil(err) 100 s.Equal(response.Username, got.Username) 101 s.Equal(newUsername, got.Username) 102 err = bcrypt.CompareHashAndPassword([]byte(got.Hash), []byte(newPassword)) 103 s.Nil(err) 104 } 105 106 // TestUnauthorizedListUsers ensures that users without the ModifySystem 107 // permission are unable to list the users registered in Gophish. 108 func (s *APISuite) TestUnauthorizedListUsers() { 109 // First, let's create a standard user which doesn't 110 // have ModifySystem permissions. 111 unauthorizedUser := s.createUnpriviledgedUser(models.RoleUser) 112 // We'll try to make a request to the various users API endpoints to 113 // ensure that they fail. Previously, we could hit the handlers directly 114 // but we need to go through the router for this test to ensure the 115 // middleware gets applied. 116 r := httptest.NewRequest(http.MethodGet, "/api/users/", nil) 117 r.Header.Set("Authorization", fmt.Sprintf("Bearer %s", unauthorizedUser.ApiKey)) 118 w := httptest.NewRecorder() 119 120 s.apiServer.ServeHTTP(w, r) 121 s.Equal(w.Code, http.StatusForbidden) 122 } 123 124 // TestUnauthorizedModifyUsers verifies that users without ModifySystem 125 // permission (a "standard" user) can only get or modify their own information. 126 func (s *APISuite) TestUnauthorizedGetUser() { 127 // First, we'll make sure that a user with the "user" role is unable to 128 // get the information of another user (in this case, the main admin). 129 unauthorizedUser := s.createUnpriviledgedUser(models.RoleUser) 130 url := fmt.Sprintf("/api/users/%d", s.admin.Id) 131 r := httptest.NewRequest(http.MethodGet, url, nil) 132 r.Header.Set("Authorization", fmt.Sprintf("Bearer %s", unauthorizedUser.ApiKey)) 133 w := httptest.NewRecorder() 134 135 s.apiServer.ServeHTTP(w, r) 136 s.Equal(w.Code, http.StatusForbidden) 137 } 138 139 // TestUnauthorizedModifyRole ensures that users without the ModifySystem 140 // privilege are unable to modify their own role, preventing a potential 141 // privilege escalation issue. 142 func (s *APISuite) TestUnauthorizedSetRole() { 143 unauthorizedUser := s.createUnpriviledgedUser(models.RoleUser) 144 url := fmt.Sprintf("/api/users/%d", unauthorizedUser.Id) 145 payload := &userRequest{ 146 Username: unauthorizedUser.Username, 147 Role: models.RoleAdmin, 148 } 149 body, err := json.Marshal(payload) 150 s.Nil(err) 151 r := httptest.NewRequest(http.MethodPut, url, bytes.NewBuffer(body)) 152 r.Header.Set("Authorization", fmt.Sprintf("Bearer %s", unauthorizedUser.ApiKey)) 153 w := httptest.NewRecorder() 154 155 s.apiServer.ServeHTTP(w, r) 156 s.Equal(w.Code, http.StatusBadRequest) 157 response := &models.Response{} 158 err = json.NewDecoder(w.Body).Decode(response) 159 s.Nil(err) 160 s.Equal(response.Message, ErrInsufficientPermission.Error()) 161 } 162 163 // TestModifyWithExistingUsername verifies that it's not possible to modify 164 // an user's username to one which already exists. 165 func (s *APISuite) TestModifyWithExistingUsername() { 166 unauthorizedUser := s.createUnpriviledgedUser(models.RoleUser) 167 payload := &userRequest{ 168 Username: s.admin.Username, 169 Role: unauthorizedUser.Role.Slug, 170 } 171 body, err := json.Marshal(payload) 172 s.Nil(err) 173 url := fmt.Sprintf("/api/users/%d", unauthorizedUser.Id) 174 r := httptest.NewRequest(http.MethodPut, url, bytes.NewReader(body)) 175 r.Header.Set("Authorization", fmt.Sprintf("Bearer %s", unauthorizedUser.ApiKey)) 176 w := httptest.NewRecorder() 177 178 s.apiServer.ServeHTTP(w, r) 179 s.Equal(w.Code, http.StatusBadRequest) 180 expected := &models.Response{ 181 Message: ErrUsernameTaken.Error(), 182 Success: false, 183 } 184 got := &models.Response{} 185 err = json.NewDecoder(w.Body).Decode(got) 186 s.Nil(err) 187 s.Equal(got.Message, expected.Message) 188 }