1package api 2 3import ( 4 "database/sql" 5 "net/http" 6 "time" 7 8 log "github.com/Sirupsen/logrus" 9 "github.com/ansible-semaphore/semaphore/db" 10 11 "github.com/ansible-semaphore/semaphore/util" 12 "github.com/gorilla/context" 13 "golang.org/x/crypto/bcrypt" 14) 15 16func getUsers(w http.ResponseWriter, r *http.Request) { 17 var users []db.User 18 if _, err := db.Mysql.Select(&users, "select * from user"); err != nil { 19 panic(err) 20 } 21 22 util.WriteJSON(w, http.StatusOK, users) 23} 24 25func addUser(w http.ResponseWriter, r *http.Request) { 26 type User struct { 27 Pwd string `db:"-" json:"password"` 28 db.User 29 } 30 31 var user User 32 if err := util.Bind(w, r, &user); err != nil { 33 w.WriteHeader(http.StatusBadRequest) 34 return 35 } 36 37 editor := context.Get(r, "user").(*db.User) 38 if !editor.Admin { 39 log.Warn(editor.Username + " is not permitted to create users") 40 w.WriteHeader(http.StatusUnauthorized) 41 return 42 } 43 44 password, err := bcrypt.GenerateFromPassword([]byte(user.Pwd), 11) 45 if err != nil { 46 w.WriteHeader(http.StatusBadRequest) 47 return 48 } 49 50 user.Password = string(password) 51 user.Created = db.GetParsedTime(time.Now()) 52 53 err = db.Mysql.Insert(&user.User) 54 55 if err != nil { 56 log.Warn(editor.Username + " is not created: " + err.Error()) 57 w.WriteHeader(http.StatusBadRequest) 58 } 59 60 util.WriteJSON(w, http.StatusCreated, user) 61} 62 63func getUserMiddleware(next http.Handler) http.Handler { 64 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 65 userID, err := util.GetIntParam("user_id", w, r) 66 if err != nil { 67 return 68 } 69 70 var user db.User 71 if err := db.Mysql.SelectOne(&user, "select * from user where id=?", userID); err != nil { 72 if err == sql.ErrNoRows { 73 w.WriteHeader(http.StatusNotFound) 74 return 75 } 76 77 panic(err) 78 } 79 80 editor := context.Get(r, "user").(*db.User) 81 if !editor.Admin && editor.ID != user.ID { 82 log.Warn(editor.Username + " is not permitted to edit users") 83 w.WriteHeader(http.StatusUnauthorized) 84 return 85 } 86 87 context.Set(r, "_user", user) 88 next.ServeHTTP(w, r) 89 }) 90} 91 92func updateUser(w http.ResponseWriter, r *http.Request) { 93 oldUser := context.Get(r, "_user").(db.User) 94 editor := context.Get(r, "user").(*db.User) 95 96 type User struct { 97 Pwd string `db:"password" json:"password"` 98 db.User 99 } 100 101 var user User 102 if err := util.Bind(w, r, &user); err != nil { 103 return 104 } 105 106 if !editor.Admin && editor.ID != oldUser.ID { 107 log.Warn(editor.Username + " is not permitted to edit users") 108 w.WriteHeader(http.StatusUnauthorized) 109 return 110 } 111 112 if editor.ID == oldUser.ID && oldUser.Admin != user.Admin { 113 log.Warn("User can't edit his own role") 114 w.WriteHeader(http.StatusUnauthorized) 115 return 116 } 117 118 if oldUser.External && oldUser.Username != user.Username { 119 log.Warn("Username is not editable for external LDAP users") 120 w.WriteHeader(http.StatusBadRequest) 121 return 122 } 123 124 var err error 125 126 if user.Pwd != "" { 127 var password []byte 128 password, err = bcrypt.GenerateFromPassword([]byte(user.Pwd), 11) 129 if err != nil { 130 w.WriteHeader(http.StatusBadRequest) 131 return 132 } 133 _, err = db.Mysql.Exec( 134 "update user set name=?, username=?, email=?, alert=?, admin=?, password=? where id=?", 135 user.Name, 136 user.Username, 137 user.Email, 138 user.Alert, 139 user.Admin, 140 string(password), 141 oldUser.ID) 142 143 } else { 144 _, err = db.Mysql.Exec( 145 "update user set name=?, username=?, email=?, alert=?, admin=? where id=?", 146 user.Name, 147 user.Username, 148 user.Email, 149 user.Alert, 150 user.Admin, 151 oldUser.ID) 152 } 153 154 if err != nil { 155 log.Error(err.Error()) 156 w.WriteHeader(http.StatusBadRequest) 157 return 158 } 159 160 w.WriteHeader(http.StatusNoContent) 161} 162 163func updateUserPassword(w http.ResponseWriter, r *http.Request) { 164 user := context.Get(r, "_user").(db.User) 165 editor := context.Get(r, "user").(*db.User) 166 167 var pwd struct { 168 Pwd string `json:"password"` 169 } 170 171 if !editor.Admin && editor.ID != user.ID { 172 log.Warn(editor.Username + " is not permitted to edit users") 173 w.WriteHeader(http.StatusUnauthorized) 174 return 175 } 176 177 if user.External { 178 log.Warn("Password is not editable for external LDAP users") 179 w.WriteHeader(http.StatusBadRequest) 180 return 181 } 182 183 if err := util.Bind(w, r, &pwd); err != nil { 184 return 185 } 186 187 password, err := bcrypt.GenerateFromPassword([]byte(pwd.Pwd), 11) 188 util.LogWarning(err) 189 if _, err := db.Mysql.Exec("update user set password=? where id=?", string(password), user.ID); err != nil { 190 panic(err) 191 } 192 193 w.WriteHeader(http.StatusNoContent) 194} 195 196func deleteUser(w http.ResponseWriter, r *http.Request) { 197 user := context.Get(r, "_user").(db.User) 198 editor := context.Get(r, "user").(*db.User) 199 200 if !editor.Admin && editor.ID != user.ID { 201 log.Warn(editor.Username + " is not permitted to delete users") 202 w.WriteHeader(http.StatusUnauthorized) 203 return 204 } 205 206 if _, err := db.Mysql.Exec("delete from project__user where user_id=?", user.ID); err != nil { 207 panic(err) 208 } 209 if _, err := db.Mysql.Exec("delete from user where id=?", user.ID); err != nil { 210 panic(err) 211 } 212 213 w.WriteHeader(http.StatusNoContent) 214} 215