userHttpController.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. package controller
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net/http"
  7. "strings"
  8. "github.com/gorilla/mux"
  9. "github.com/gravitl/netmaker/auth"
  10. "github.com/gravitl/netmaker/database"
  11. "github.com/gravitl/netmaker/logger"
  12. "github.com/gravitl/netmaker/logic"
  13. "github.com/gravitl/netmaker/models"
  14. )
  15. func userHandlers(r *mux.Router) {
  16. r.HandleFunc("/api/users/adm/hasadmin", hasAdmin).Methods("GET")
  17. r.HandleFunc("/api/users/adm/createadmin", createAdmin).Methods("POST")
  18. r.HandleFunc("/api/users/adm/authenticate", authenticateUser).Methods("POST")
  19. r.HandleFunc("/api/users/{username}", authorizeUser(http.HandlerFunc(updateUser))).Methods("PUT")
  20. r.HandleFunc("/api/users/networks/{username}", authorizeUserAdm(http.HandlerFunc(updateUserNetworks))).Methods("PUT")
  21. r.HandleFunc("/api/users/{username}/adm", authorizeUserAdm(http.HandlerFunc(updateUserAdm))).Methods("PUT")
  22. r.HandleFunc("/api/users/{username}", authorizeUserAdm(http.HandlerFunc(createUser))).Methods("POST")
  23. r.HandleFunc("/api/users/{username}", authorizeUser(http.HandlerFunc(deleteUser))).Methods("DELETE")
  24. r.HandleFunc("/api/users/{username}", authorizeUser(http.HandlerFunc(getUser))).Methods("GET")
  25. r.HandleFunc("/api/users", authorizeUserAdm(http.HandlerFunc(getUsers))).Methods("GET")
  26. r.HandleFunc("/api/oauth/login", auth.HandleAuthLogin).Methods("GET")
  27. r.HandleFunc("/api/oauth/callback", auth.HandleAuthCallback).Methods("GET")
  28. }
  29. // Node authenticates using its password and retrieves a JWT for authorization.
  30. func authenticateUser(response http.ResponseWriter, request *http.Request) {
  31. // Auth request consists of Mac Address and Password (from node that is authorizing
  32. // in case of Master, auth is ignored and mac is set to "mastermac"
  33. var authRequest models.UserAuthParams
  34. var errorResponse = models.ErrorResponse{
  35. Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
  36. }
  37. decoder := json.NewDecoder(request.Body)
  38. decoderErr := decoder.Decode(&authRequest)
  39. defer request.Body.Close()
  40. if decoderErr != nil {
  41. returnErrorResponse(response, request, errorResponse)
  42. return
  43. }
  44. jwt, err := logic.VerifyAuthRequest(authRequest)
  45. if err != nil {
  46. returnErrorResponse(response, request, formatError(err, "badrequest"))
  47. return
  48. }
  49. if jwt == "" {
  50. // very unlikely that err is !nil and no jwt returned, but handle it anyways.
  51. returnErrorResponse(response, request, formatError(errors.New("No token returned"), "internal"))
  52. return
  53. }
  54. username := authRequest.UserName
  55. var successResponse = models.SuccessResponse{
  56. Code: http.StatusOK,
  57. Message: "W1R3: Device " + username + " Authorized",
  58. Response: models.SuccessfulUserLoginResponse{
  59. AuthToken: jwt,
  60. UserName: username,
  61. },
  62. }
  63. // Send back the JWT
  64. successJSONResponse, jsonError := json.Marshal(successResponse)
  65. if jsonError != nil {
  66. returnErrorResponse(response, request, errorResponse)
  67. return
  68. }
  69. logger.Log(2, username, "was authenticated")
  70. response.Header().Set("Content-Type", "application/json")
  71. response.Write(successJSONResponse)
  72. }
  73. // The middleware for most requests to the API
  74. // They all pass through here first
  75. // This will validate the JWT (or check for master token)
  76. // This will also check against the authNetwork and make sure the node should be accessing that endpoint,
  77. // even if it's technically ok
  78. // This is kind of a poor man's RBAC. There's probably a better/smarter way.
  79. // TODO: Consider better RBAC implementations
  80. func authorizeUser(next http.Handler) http.HandlerFunc {
  81. return func(w http.ResponseWriter, r *http.Request) {
  82. w.Header().Set("Content-Type", "application/json")
  83. var params = mux.Vars(r)
  84. // get the auth token
  85. bearerToken := r.Header.Get("Authorization")
  86. username := params["username"]
  87. err := ValidateUserToken(bearerToken, username, false)
  88. if err != nil {
  89. returnErrorResponse(w, r, formatError(err, "unauthorized"))
  90. return
  91. }
  92. r.Header.Set("user", username)
  93. next.ServeHTTP(w, r)
  94. }
  95. }
  96. func authorizeUserAdm(next http.Handler) http.HandlerFunc {
  97. return func(w http.ResponseWriter, r *http.Request) {
  98. w.Header().Set("Content-Type", "application/json")
  99. var params = mux.Vars(r)
  100. //get the auth token
  101. bearerToken := r.Header.Get("Authorization")
  102. username := params["username"]
  103. err := ValidateUserToken(bearerToken, username, true)
  104. if err != nil {
  105. returnErrorResponse(w, r, formatError(err, "unauthorized"))
  106. return
  107. }
  108. r.Header.Set("user", username)
  109. next.ServeHTTP(w, r)
  110. }
  111. }
  112. // ValidateUserToken - self explained
  113. func ValidateUserToken(token string, user string, adminonly bool) error {
  114. var tokenSplit = strings.Split(token, " ")
  115. //I put this in in case the user doesn't put in a token at all (in which case it's empty)
  116. //There's probably a smarter way of handling this.
  117. var authToken = "928rt238tghgwe@TY@$Y@#WQAEGB2FC#@HG#@$Hddd"
  118. if len(tokenSplit) > 1 {
  119. authToken = tokenSplit[1]
  120. } else {
  121. return errors.New("Missing Auth Token.")
  122. }
  123. username, _, isadmin, err := logic.VerifyUserToken(authToken)
  124. if err != nil {
  125. return errors.New("Error Verifying Auth Token")
  126. }
  127. isAuthorized := false
  128. if adminonly {
  129. isAuthorized = isadmin
  130. } else {
  131. isAuthorized = username == user || isadmin
  132. }
  133. if !isAuthorized {
  134. return errors.New("You are unauthorized to access this endpoint.")
  135. }
  136. return nil
  137. }
  138. func hasAdmin(w http.ResponseWriter, r *http.Request) {
  139. w.Header().Set("Content-Type", "application/json")
  140. hasadmin, err := logic.HasAdmin()
  141. if err != nil {
  142. returnErrorResponse(w, r, formatError(err, "internal"))
  143. return
  144. }
  145. json.NewEncoder(w).Encode(hasadmin)
  146. }
  147. // GetUserInternal - gets an internal user
  148. func GetUserInternal(username string) (models.User, error) {
  149. var user models.User
  150. record, err := database.FetchRecord(database.USERS_TABLE_NAME, username)
  151. if err != nil {
  152. return user, err
  153. }
  154. if err = json.Unmarshal([]byte(record), &user); err != nil {
  155. return models.User{}, err
  156. }
  157. return user, err
  158. }
  159. // Get an individual node. Nothin fancy here folks.
  160. func getUser(w http.ResponseWriter, r *http.Request) {
  161. // set header.
  162. w.Header().Set("Content-Type", "application/json")
  163. var params = mux.Vars(r)
  164. usernameFetched := params["username"]
  165. user, err := logic.GetUser(usernameFetched)
  166. if err != nil {
  167. returnErrorResponse(w, r, formatError(err, "internal"))
  168. return
  169. }
  170. logger.Log(2, r.Header.Get("user"), "fetched user", usernameFetched)
  171. json.NewEncoder(w).Encode(user)
  172. }
  173. // Get an individual node. Nothin fancy here folks.
  174. func getUsers(w http.ResponseWriter, r *http.Request) {
  175. // set header.
  176. w.Header().Set("Content-Type", "application/json")
  177. users, err := logic.GetUsers()
  178. if err != nil {
  179. returnErrorResponse(w, r, formatError(err, "internal"))
  180. return
  181. }
  182. logger.Log(2, r.Header.Get("user"), "fetched users")
  183. json.NewEncoder(w).Encode(users)
  184. }
  185. func createAdmin(w http.ResponseWriter, r *http.Request) {
  186. w.Header().Set("Content-Type", "application/json")
  187. var admin models.User
  188. // get node from body of request
  189. _ = json.NewDecoder(r.Body).Decode(&admin)
  190. admin, err := logic.CreateAdmin(admin)
  191. if err != nil {
  192. returnErrorResponse(w, r, formatError(err, "badrequest"))
  193. return
  194. }
  195. logger.Log(1, admin.UserName, "was made a new admin")
  196. json.NewEncoder(w).Encode(admin)
  197. }
  198. func createUser(w http.ResponseWriter, r *http.Request) {
  199. w.Header().Set("Content-Type", "application/json")
  200. var user models.User
  201. // get node from body of request
  202. _ = json.NewDecoder(r.Body).Decode(&user)
  203. user, err := logic.CreateUser(user)
  204. if err != nil {
  205. returnErrorResponse(w, r, formatError(err, "badrequest"))
  206. return
  207. }
  208. logger.Log(1, user.UserName, "was created")
  209. json.NewEncoder(w).Encode(user)
  210. }
  211. func updateUserNetworks(w http.ResponseWriter, r *http.Request) {
  212. w.Header().Set("Content-Type", "application/json")
  213. var params = mux.Vars(r)
  214. var user models.User
  215. // start here
  216. username := params["username"]
  217. user, err := GetUserInternal(username)
  218. if err != nil {
  219. returnErrorResponse(w, r, formatError(err, "internal"))
  220. return
  221. }
  222. var userchange models.User
  223. // we decode our body request params
  224. err = json.NewDecoder(r.Body).Decode(&userchange)
  225. if err != nil {
  226. returnErrorResponse(w, r, formatError(err, "internal"))
  227. return
  228. }
  229. err = logic.UpdateUserNetworks(userchange.Networks, userchange.IsAdmin, &user)
  230. if err != nil {
  231. returnErrorResponse(w, r, formatError(err, "badrequest"))
  232. return
  233. }
  234. logger.Log(1, username, "status was updated")
  235. json.NewEncoder(w).Encode(user)
  236. }
  237. func updateUser(w http.ResponseWriter, r *http.Request) {
  238. w.Header().Set("Content-Type", "application/json")
  239. var params = mux.Vars(r)
  240. var user models.User
  241. // start here
  242. username := params["username"]
  243. user, err := GetUserInternal(username)
  244. if err != nil {
  245. returnErrorResponse(w, r, formatError(err, "internal"))
  246. return
  247. }
  248. if auth.IsOauthUser(&user) == nil {
  249. returnErrorResponse(w, r, formatError(fmt.Errorf("can not update user info for oauth user %s", username), "forbidden"))
  250. return
  251. }
  252. var userchange models.User
  253. // we decode our body request params
  254. err = json.NewDecoder(r.Body).Decode(&userchange)
  255. if err != nil {
  256. returnErrorResponse(w, r, formatError(err, "internal"))
  257. return
  258. }
  259. userchange.Networks = nil
  260. user, err = logic.UpdateUser(userchange, user)
  261. if err != nil {
  262. returnErrorResponse(w, r, formatError(err, "badrequest"))
  263. return
  264. }
  265. logger.Log(1, username, "was updated")
  266. json.NewEncoder(w).Encode(user)
  267. }
  268. func updateUserAdm(w http.ResponseWriter, r *http.Request) {
  269. w.Header().Set("Content-Type", "application/json")
  270. var params = mux.Vars(r)
  271. var user models.User
  272. // start here
  273. username := params["username"]
  274. user, err := GetUserInternal(username)
  275. if err != nil {
  276. returnErrorResponse(w, r, formatError(err, "internal"))
  277. return
  278. }
  279. if auth.IsOauthUser(&user) != nil {
  280. returnErrorResponse(w, r, formatError(fmt.Errorf("can not update user info for oauth user"), "forbidden"))
  281. return
  282. }
  283. var userchange models.User
  284. // we decode our body request params
  285. err = json.NewDecoder(r.Body).Decode(&userchange)
  286. if err != nil {
  287. returnErrorResponse(w, r, formatError(err, "internal"))
  288. return
  289. }
  290. user, err = logic.UpdateUser(userchange, user)
  291. if err != nil {
  292. returnErrorResponse(w, r, formatError(err, "badrequest"))
  293. return
  294. }
  295. logger.Log(1, username, "was updated (admin)")
  296. json.NewEncoder(w).Encode(user)
  297. }
  298. func deleteUser(w http.ResponseWriter, r *http.Request) {
  299. // Set header
  300. w.Header().Set("Content-Type", "application/json")
  301. // get params
  302. var params = mux.Vars(r)
  303. username := params["username"]
  304. success, err := logic.DeleteUser(username)
  305. if err != nil {
  306. returnErrorResponse(w, r, formatError(err, "internal"))
  307. return
  308. } else if !success {
  309. returnErrorResponse(w, r, formatError(errors.New("delete unsuccessful."), "badrequest"))
  310. return
  311. }
  312. logger.Log(1, username, "was deleted")
  313. json.NewEncoder(w).Encode(params["username"] + " deleted.")
  314. }