2
0

user.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. package controller
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net/http"
  7. "reflect"
  8. "github.com/gorilla/mux"
  9. "github.com/gorilla/websocket"
  10. "github.com/gravitl/netmaker/auth"
  11. "github.com/gravitl/netmaker/logger"
  12. "github.com/gravitl/netmaker/logic"
  13. "github.com/gravitl/netmaker/models"
  14. "github.com/gravitl/netmaker/mq"
  15. "github.com/gravitl/netmaker/servercfg"
  16. "golang.org/x/exp/slog"
  17. )
  18. var (
  19. upgrader = websocket.Upgrader{}
  20. )
  21. var ListRoles = listRoles
  22. func userHandlers(r *mux.Router) {
  23. r.HandleFunc("/api/users/adm/hassuperadmin", hasSuperAdmin).Methods(http.MethodGet)
  24. r.HandleFunc("/api/users/adm/createsuperadmin", createSuperAdmin).Methods(http.MethodPost)
  25. r.HandleFunc("/api/users/adm/transfersuperadmin/{username}", logic.SecurityCheck(true, http.HandlerFunc(transferSuperAdmin))).
  26. Methods(http.MethodPost)
  27. r.HandleFunc("/api/users/adm/authenticate", authenticateUser).Methods(http.MethodPost)
  28. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, http.HandlerFunc(updateUser))).Methods(http.MethodPut)
  29. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, checkFreeTierLimits(limitChoiceUsers, http.HandlerFunc(createUser)))).Methods(http.MethodPost)
  30. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, http.HandlerFunc(deleteUser))).Methods(http.MethodDelete)
  31. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(getUser)))).Methods(http.MethodGet)
  32. r.HandleFunc("/api/users/{username}/enable", logic.SecurityCheck(true, http.HandlerFunc(enableUserAccount))).Methods(http.MethodPost)
  33. r.HandleFunc("/api/users/{username}/disable", logic.SecurityCheck(true, http.HandlerFunc(disableUserAccount))).Methods(http.MethodPost)
  34. r.HandleFunc("/api/v1/users", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(getUserV1)))).Methods(http.MethodGet)
  35. r.HandleFunc("/api/users", logic.SecurityCheck(true, http.HandlerFunc(getUsers))).Methods(http.MethodGet)
  36. r.HandleFunc("/api/v1/users/roles", logic.SecurityCheck(true, http.HandlerFunc(ListRoles))).Methods(http.MethodGet)
  37. }
  38. // @Summary Authenticate a user to retrieve an authorization token
  39. // @Router /api/users/adm/authenticate [post]
  40. // @Tags Auth
  41. // @Accept json
  42. // @Param body body models.UserAuthParams true "Authentication parameters"
  43. // @Success 200 {object} models.SuccessResponse
  44. // @Failure 400 {object} models.ErrorResponse
  45. // @Failure 401 {object} models.ErrorResponse
  46. // @Failure 500 {object} models.ErrorResponse
  47. func authenticateUser(response http.ResponseWriter, request *http.Request) {
  48. // Auth request consists of Mac Address and Password (from node that is authorizing
  49. // in case of Master, auth is ignored and mac is set to "mastermac"
  50. var authRequest models.UserAuthParams
  51. var errorResponse = models.ErrorResponse{
  52. Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
  53. }
  54. decoder := json.NewDecoder(request.Body)
  55. decoderErr := decoder.Decode(&authRequest)
  56. defer request.Body.Close()
  57. if decoderErr != nil {
  58. logger.Log(0, "error decoding request body: ",
  59. decoderErr.Error())
  60. logic.ReturnErrorResponse(response, request, errorResponse)
  61. return
  62. }
  63. user, err := logic.GetUser(authRequest.UserName)
  64. if err != nil {
  65. logger.Log(0, authRequest.UserName, "user validation failed: ",
  66. err.Error())
  67. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "unauthorized"))
  68. return
  69. }
  70. if logic.IsOauthUser(user) == nil {
  71. logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("user is registered via SSO"), "badrequest"))
  72. return
  73. }
  74. if user.AccountDisabled {
  75. err = errors.New("user account disabled")
  76. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "unauthorized"))
  77. return
  78. }
  79. if !user.IsSuperAdmin && !logic.IsBasicAuthEnabled() {
  80. logic.ReturnErrorResponse(
  81. response,
  82. request,
  83. logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"),
  84. )
  85. return
  86. }
  87. if val := request.Header.Get("From-Ui"); val == "true" {
  88. // request came from UI, if normal user block Login
  89. user, err := logic.GetUser(authRequest.UserName)
  90. if err != nil {
  91. logger.Log(0, authRequest.UserName, "user validation failed: ",
  92. err.Error())
  93. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "unauthorized"))
  94. return
  95. }
  96. role, err := logic.GetRole(user.PlatformRoleID)
  97. if err != nil {
  98. logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("access denied to dashboard"), "unauthorized"))
  99. return
  100. }
  101. if role.DenyDashboardAccess {
  102. logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("access denied to dashboard"), "unauthorized"))
  103. return
  104. }
  105. }
  106. username := authRequest.UserName
  107. jwt, err := logic.VerifyAuthRequest(authRequest)
  108. if err != nil {
  109. logger.Log(0, username, "user validation failed: ",
  110. err.Error())
  111. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "badrequest"))
  112. return
  113. }
  114. if jwt == "" {
  115. // very unlikely that err is !nil and no jwt returned, but handle it anyways.
  116. logger.Log(0, username, "jwt token is empty")
  117. logic.ReturnErrorResponse(
  118. response,
  119. request,
  120. logic.FormatError(errors.New("no token returned"), "internal"),
  121. )
  122. return
  123. }
  124. var successResponse = models.SuccessResponse{
  125. Code: http.StatusOK,
  126. Message: "W1R3: Device " + username + " Authorized",
  127. Response: models.SuccessfulUserLoginResponse{
  128. AuthToken: jwt,
  129. UserName: username,
  130. },
  131. }
  132. // Send back the JWT
  133. successJSONResponse, jsonError := json.Marshal(successResponse)
  134. if jsonError != nil {
  135. logger.Log(0, username,
  136. "error marshalling resp: ", jsonError.Error())
  137. logic.ReturnErrorResponse(response, request, errorResponse)
  138. return
  139. }
  140. logger.Log(2, username, "was authenticated")
  141. response.Header().Set("Content-Type", "application/json")
  142. response.Write(successJSONResponse)
  143. go func() {
  144. if servercfg.IsPro && logic.GetRacAutoDisable() {
  145. // enable all associeated clients for the user
  146. clients, err := logic.GetAllExtClients()
  147. if err != nil {
  148. slog.Error("error getting clients: ", "error", err)
  149. return
  150. }
  151. for _, client := range clients {
  152. if client.OwnerID == username && !client.Enabled {
  153. slog.Info(
  154. fmt.Sprintf(
  155. "enabling ext client %s for user %s due to RAC autodisabling feature",
  156. client.ClientID,
  157. client.OwnerID,
  158. ),
  159. )
  160. if newClient, err := logic.ToggleExtClientConnectivity(&client, true); err != nil {
  161. slog.Error(
  162. "error enabling ext client in RAC autodisable hook",
  163. "error",
  164. err,
  165. )
  166. continue // dont return but try for other clients
  167. } else {
  168. // publish peer update to ingress gateway
  169. if ingressNode, err := logic.GetNodeByID(newClient.IngressGatewayID); err == nil {
  170. if err = mq.PublishPeerUpdate(false); err != nil {
  171. slog.Error("error updating ext clients on", "ingress", ingressNode.ID.String(), "err", err.Error())
  172. }
  173. }
  174. }
  175. }
  176. }
  177. }
  178. }()
  179. }
  180. // @Summary Check if the server has a super admin
  181. // @Router /api/users/adm/hassuperadmin [get]
  182. // @Tags Users
  183. // @Success 200 {object} bool
  184. // @Failure 500 {object} models.ErrorResponse
  185. func hasSuperAdmin(w http.ResponseWriter, r *http.Request) {
  186. w.Header().Set("Content-Type", "application/json")
  187. hasSuperAdmin, err := logic.HasSuperAdmin()
  188. if err != nil {
  189. logger.Log(0, "failed to check for admin: ", err.Error())
  190. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  191. return
  192. }
  193. json.NewEncoder(w).Encode(hasSuperAdmin)
  194. }
  195. // @Summary Get an individual user
  196. // @Router /api/users/{username} [get]
  197. // @Tags Users
  198. // @Param username path string true "Username of the user to fetch"
  199. // @Success 200 {object} models.User
  200. // @Failure 500 {object} models.ErrorResponse
  201. func getUser(w http.ResponseWriter, r *http.Request) {
  202. // set header.
  203. w.Header().Set("Content-Type", "application/json")
  204. var params = mux.Vars(r)
  205. usernameFetched := params["username"]
  206. user, err := logic.GetReturnUser(usernameFetched)
  207. if err != nil {
  208. logger.Log(0, usernameFetched, "failed to fetch user: ", err.Error())
  209. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  210. return
  211. }
  212. logger.Log(2, r.Header.Get("user"), "fetched user", usernameFetched)
  213. json.NewEncoder(w).Encode(user)
  214. }
  215. // @Summary Enable a user's account
  216. // @Router /api/users/{username}/enable [post]
  217. // @Tags Users
  218. // @Param username path string true "Username of the user to enable"
  219. // @Success 200 {object} models.SuccessResponse
  220. // @Failure 400 {object} models.ErrorResponse
  221. // @Failure 500 {object} models.ErrorResponse
  222. func enableUserAccount(w http.ResponseWriter, r *http.Request) {
  223. username := mux.Vars(r)["username"]
  224. user, err := logic.GetUser(username)
  225. if err != nil {
  226. logger.Log(0, "failed to fetch user: ", err.Error())
  227. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  228. return
  229. }
  230. user.AccountDisabled = false
  231. err = logic.UpsertUser(*user)
  232. if err != nil {
  233. logger.Log(0, "failed to enable user account: ", err.Error())
  234. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  235. }
  236. logic.ReturnSuccessResponse(w, r, "user account enabled")
  237. }
  238. // @Summary Disable a user's account
  239. // @Router /api/users/{username}/disable [post]
  240. // @Tags Users
  241. // @Param username path string true "Username of the user to disable"
  242. // @Success 200 {object} models.SuccessResponse
  243. // @Failure 400 {object} models.ErrorResponse
  244. // @Failure 500 {object} models.ErrorResponse
  245. func disableUserAccount(w http.ResponseWriter, r *http.Request) {
  246. username := mux.Vars(r)["username"]
  247. user, err := logic.GetUser(username)
  248. if err != nil {
  249. logger.Log(0, "failed to fetch user: ", err.Error())
  250. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  251. return
  252. }
  253. if user.PlatformRoleID == models.SuperAdminRole {
  254. err = errors.New("cannot disable super-admin user account")
  255. logger.Log(0, err.Error())
  256. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  257. return
  258. }
  259. user.AccountDisabled = true
  260. err = logic.UpsertUser(*user)
  261. if err != nil {
  262. logger.Log(0, "failed to disable user account: ", err.Error())
  263. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  264. }
  265. logic.ReturnSuccessResponse(w, r, "user account disabled")
  266. }
  267. // swagger:route GET /api/v1/users user getUserV1
  268. //
  269. // Get an individual user with role info.
  270. //
  271. // Schemes: https
  272. //
  273. // Security:
  274. // oauth
  275. //
  276. // Responses:
  277. // 200: ReturnUserWithRolesAndGroups
  278. func getUserV1(w http.ResponseWriter, r *http.Request) {
  279. // set header.
  280. w.Header().Set("Content-Type", "application/json")
  281. usernameFetched := r.URL.Query().Get("username")
  282. if usernameFetched == "" {
  283. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("username is required"), "badrequest"))
  284. return
  285. }
  286. user, err := logic.GetReturnUser(usernameFetched)
  287. if err != nil {
  288. logger.Log(0, usernameFetched, "failed to fetch user: ", err.Error())
  289. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  290. return
  291. }
  292. userRoleTemplate, err := logic.GetRole(user.PlatformRoleID)
  293. if err != nil {
  294. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  295. return
  296. }
  297. resp := models.ReturnUserWithRolesAndGroups{
  298. ReturnUser: user,
  299. PlatformRole: userRoleTemplate,
  300. UserGroups: map[models.UserGroupID]models.UserGroup{},
  301. }
  302. for gId := range user.UserGroups {
  303. grp, err := logic.GetUserGroup(gId)
  304. if err != nil {
  305. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  306. return
  307. }
  308. resp.UserGroups[gId] = grp
  309. }
  310. logger.Log(2, r.Header.Get("user"), "fetched user", usernameFetched)
  311. logic.ReturnSuccessResponseWithJson(w, r, resp, "fetched user with role info")
  312. }
  313. // swagger:route GET /api/users user getUsers
  314. //
  315. // Get all users.
  316. //
  317. // Schemes: https
  318. //
  319. // Security:
  320. // oauth
  321. //
  322. // Responses:
  323. // 200: userBodyResponse
  324. func getUsers(w http.ResponseWriter, r *http.Request) {
  325. // set header.
  326. w.Header().Set("Content-Type", "application/json")
  327. users, err := logic.GetUsers()
  328. if err != nil {
  329. logger.Log(0, "failed to fetch users: ", err.Error())
  330. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  331. return
  332. }
  333. logic.SortUsers(users[:])
  334. logger.Log(2, r.Header.Get("user"), "fetched users")
  335. json.NewEncoder(w).Encode(users)
  336. }
  337. // @Summary Create a super admin
  338. // @Router /api/users/adm/createsuperadmin [post]
  339. // @Tags Users
  340. // @Param body body models.User true "User details"
  341. // @Success 200 {object} models.User
  342. // @Failure 400 {object} models.ErrorResponse
  343. // @Failure 500 {object} models.ErrorResponse
  344. func createSuperAdmin(w http.ResponseWriter, r *http.Request) {
  345. w.Header().Set("Content-Type", "application/json")
  346. var u models.User
  347. err := json.NewDecoder(r.Body).Decode(&u)
  348. if err != nil {
  349. slog.Error("error decoding request body", "error", err.Error())
  350. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  351. return
  352. }
  353. if !logic.IsBasicAuthEnabled() {
  354. logic.ReturnErrorResponse(
  355. w,
  356. r,
  357. logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"),
  358. )
  359. return
  360. }
  361. err = logic.CreateSuperAdmin(&u)
  362. if err != nil {
  363. slog.Error("failed to create admin", "error", err.Error())
  364. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  365. return
  366. }
  367. logger.Log(1, u.UserName, "was made a super admin")
  368. json.NewEncoder(w).Encode(logic.ToReturnUser(u))
  369. }
  370. // @Summary Transfer super admin role to another admin user
  371. // @Router /api/users/adm/transfersuperadmin/{username} [post]
  372. // @Tags Users
  373. // @Param username path string true "Username of the user to transfer super admin role"
  374. // @Success 200 {object} models.User
  375. // @Failure 403 {object} models.ErrorResponse
  376. // @Failure 500 {object} models.ErrorResponse
  377. func transferSuperAdmin(w http.ResponseWriter, r *http.Request) {
  378. w.Header().Set("Content-Type", "application/json")
  379. caller, err := logic.GetUser(r.Header.Get("user"))
  380. if err != nil {
  381. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  382. }
  383. if caller.PlatformRoleID != models.SuperAdminRole {
  384. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("only superadmin can assign the superadmin role to another user"), "forbidden"))
  385. return
  386. }
  387. var params = mux.Vars(r)
  388. username := params["username"]
  389. u, err := logic.GetUser(username)
  390. if err != nil {
  391. slog.Error("error getting user", "user", u.UserName, "error", err.Error())
  392. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  393. return
  394. }
  395. if u.PlatformRoleID != models.AdminRole {
  396. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("only admins can be promoted to superadmin role"), "forbidden"))
  397. return
  398. }
  399. if !logic.IsBasicAuthEnabled() {
  400. logic.ReturnErrorResponse(
  401. w,
  402. r,
  403. logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"),
  404. )
  405. return
  406. }
  407. u.PlatformRoleID = models.SuperAdminRole
  408. err = logic.UpsertUser(*u)
  409. if err != nil {
  410. slog.Error("error updating user to superadmin: ", "user", u.UserName, "error", err.Error())
  411. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  412. return
  413. }
  414. caller.PlatformRoleID = models.AdminRole
  415. err = logic.UpsertUser(*caller)
  416. if err != nil {
  417. slog.Error("error demoting user to admin: ", "user", caller.UserName, "error", err.Error())
  418. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  419. return
  420. }
  421. slog.Info("user was made a super admin", "user", u.UserName)
  422. json.NewEncoder(w).Encode(logic.ToReturnUser(*u))
  423. }
  424. // @Summary Create a user
  425. // @Router /api/users/{username} [post]
  426. // @Tags Users
  427. // @Param username path string true "Username of the user to create"
  428. // @Param body body models.User true "User details"
  429. // @Success 200 {object} models.User
  430. // @Failure 400 {object} models.ErrorResponse
  431. // @Failure 403 {object} models.ErrorResponse
  432. // @Failure 500 {object} models.ErrorResponse
  433. func createUser(w http.ResponseWriter, r *http.Request) {
  434. w.Header().Set("Content-Type", "application/json")
  435. caller, err := logic.GetUser(r.Header.Get("user"))
  436. if err != nil {
  437. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  438. return
  439. }
  440. var user models.User
  441. err = json.NewDecoder(r.Body).Decode(&user)
  442. if err != nil {
  443. logger.Log(0, user.UserName, "error decoding request body: ",
  444. err.Error())
  445. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  446. return
  447. }
  448. if !servercfg.IsPro {
  449. user.PlatformRoleID = models.AdminRole
  450. }
  451. if user.PlatformRoleID == "" {
  452. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("platform role is missing"), "badrequest"))
  453. return
  454. }
  455. userRole, err := logic.GetRole(user.PlatformRoleID)
  456. if err != nil {
  457. err = errors.New("error fetching role " + user.PlatformRoleID.String() + " " + err.Error())
  458. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  459. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  460. return
  461. }
  462. if userRole.ID == models.SuperAdminRole {
  463. err = errors.New("additional superadmins cannot be created")
  464. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  465. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  466. return
  467. }
  468. if caller.PlatformRoleID != models.SuperAdminRole && user.PlatformRoleID == models.AdminRole {
  469. err = errors.New("only superadmin can create admin users")
  470. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  471. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  472. return
  473. }
  474. if !servercfg.IsPro && user.PlatformRoleID != models.AdminRole {
  475. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("non-admins users can only be created on Pro version"), "forbidden"))
  476. return
  477. }
  478. err = logic.CreateUser(&user)
  479. if err != nil {
  480. slog.Error("error creating new user: ", "user", user.UserName, "error", err.Error())
  481. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  482. return
  483. }
  484. logic.DeleteUserInvite(user.UserName)
  485. logic.DeletePendingUser(user.UserName)
  486. go mq.PublishPeerUpdate(false)
  487. slog.Info("user was created", "username", user.UserName)
  488. json.NewEncoder(w).Encode(logic.ToReturnUser(user))
  489. }
  490. // @Summary Update a user
  491. // @Router /api/users/{username} [put]
  492. // @Tags Users
  493. // @Param username path string true "Username of the user to update"
  494. // @Param body body models.User true "User details"
  495. // @Success 200 {object} models.User
  496. // @Failure 400 {object} models.ErrorResponse
  497. // @Failure 403 {object} models.ErrorResponse
  498. // @Failure 500 {object} models.ErrorResponse
  499. func updateUser(w http.ResponseWriter, r *http.Request) {
  500. w.Header().Set("Content-Type", "application/json")
  501. var params = mux.Vars(r)
  502. // start here
  503. var caller *models.User
  504. var err error
  505. var ismaster bool
  506. if r.Header.Get("user") == logic.MasterUser {
  507. ismaster = true
  508. } else {
  509. caller, err = logic.GetUser(r.Header.Get("user"))
  510. if err != nil {
  511. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  512. }
  513. }
  514. username := params["username"]
  515. user, err := logic.GetUser(username)
  516. if err != nil {
  517. logger.Log(0, username,
  518. "failed to update user info: ", err.Error())
  519. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  520. return
  521. }
  522. var userchange models.User
  523. // we decode our body request params
  524. err = json.NewDecoder(r.Body).Decode(&userchange)
  525. if err != nil {
  526. slog.Error("failed to decode body", "error ", err.Error())
  527. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  528. return
  529. }
  530. if user.UserName != userchange.UserName {
  531. logic.ReturnErrorResponse(
  532. w,
  533. r,
  534. logic.FormatError(
  535. errors.New("user in param and request body not matching"),
  536. "badrequest",
  537. ),
  538. )
  539. return
  540. }
  541. selfUpdate := false
  542. if !ismaster && caller.UserName == user.UserName {
  543. selfUpdate = true
  544. }
  545. if !ismaster && !selfUpdate {
  546. if caller.PlatformRoleID == models.AdminRole && user.PlatformRoleID == models.SuperAdminRole {
  547. slog.Error("non-superadmin user", "caller", caller.UserName, "attempted to update superadmin user", username)
  548. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("cannot update superadmin user"), "forbidden"))
  549. return
  550. }
  551. if caller.PlatformRoleID != models.AdminRole && caller.PlatformRoleID != models.SuperAdminRole {
  552. slog.Error("operation not allowed", "caller", caller.UserName, "attempted to update user", username)
  553. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("cannot update superadmin user"), "forbidden"))
  554. return
  555. }
  556. if caller.PlatformRoleID == models.AdminRole && user.PlatformRoleID == models.AdminRole {
  557. slog.Error("an admin user does not have permissions to update another admin user", "caller", caller.UserName, "attempted to update admin user", username)
  558. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("an admin user does not have permissions to update another admin user"), "forbidden"))
  559. return
  560. }
  561. if caller.PlatformRoleID == models.AdminRole && userchange.PlatformRoleID == models.AdminRole {
  562. err = errors.New("an admin user does not have permissions to assign the admin role to another user")
  563. slog.Error(
  564. "failed to update user",
  565. "caller",
  566. caller.UserName,
  567. "attempted to update user",
  568. username,
  569. "error",
  570. err,
  571. )
  572. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  573. return
  574. }
  575. }
  576. if !ismaster && selfUpdate {
  577. if user.PlatformRoleID != userchange.PlatformRoleID {
  578. slog.Error("user cannot change his own role", "caller", caller.UserName, "attempted to update user role", username)
  579. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("user not allowed to self assign role"), "forbidden"))
  580. return
  581. }
  582. if servercfg.IsPro {
  583. // user cannot update his own roles and groups
  584. if len(user.NetworkRoles) != len(userchange.NetworkRoles) || !reflect.DeepEqual(user.NetworkRoles, userchange.NetworkRoles) {
  585. err = errors.New("user cannot update self update their network roles")
  586. slog.Error("failed to update user", "caller", caller.UserName, "attempted to update user", username, "error", err)
  587. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  588. return
  589. }
  590. // user cannot update his own roles and groups
  591. if len(user.UserGroups) != len(userchange.UserGroups) || !reflect.DeepEqual(user.UserGroups, userchange.UserGroups) {
  592. err = errors.New("user cannot update self update their groups")
  593. slog.Error("failed to update user", "caller", caller.UserName, "attempted to update user", username, "error", err)
  594. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  595. return
  596. }
  597. }
  598. }
  599. if ismaster {
  600. if user.PlatformRoleID != models.SuperAdminRole && userchange.PlatformRoleID == models.SuperAdminRole {
  601. slog.Error("operation not allowed", "caller", logic.MasterUser, "attempted to update user role to superadmin", username)
  602. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("attempted to update user role to superadmin"), "forbidden"))
  603. return
  604. }
  605. }
  606. if logic.IsOauthUser(user) == nil && userchange.Password != "" {
  607. err := fmt.Errorf("cannot update user's password for an oauth user %s", username)
  608. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  609. return
  610. }
  611. user, err = logic.UpdateUser(&userchange, user)
  612. if err != nil {
  613. logger.Log(0, username,
  614. "failed to update user info: ", err.Error())
  615. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  616. return
  617. }
  618. go mq.PublishPeerUpdate(false)
  619. logger.Log(1, username, "was updated")
  620. json.NewEncoder(w).Encode(logic.ToReturnUser(*user))
  621. }
  622. // @Summary Delete a user
  623. // @Router /api/users/{username} [delete]
  624. // @Tags Users
  625. // @Param username path string true "Username of the user to delete"
  626. // @Success 200 {string} string
  627. // @Failure 500 {object} models.ErrorResponse
  628. func deleteUser(w http.ResponseWriter, r *http.Request) {
  629. // Set header
  630. w.Header().Set("Content-Type", "application/json")
  631. // get params
  632. var params = mux.Vars(r)
  633. caller, err := logic.GetUser(r.Header.Get("user"))
  634. if err != nil {
  635. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  636. }
  637. callerUserRole, err := logic.GetRole(caller.PlatformRoleID)
  638. if err != nil {
  639. slog.Error("failed to get role ", "role", callerUserRole.ID, "error", err)
  640. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  641. return
  642. }
  643. username := params["username"]
  644. user, err := logic.GetUser(username)
  645. if err != nil {
  646. logger.Log(0, username,
  647. "failed to update user info: ", err.Error())
  648. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  649. return
  650. }
  651. userRole, err := logic.GetRole(user.PlatformRoleID)
  652. if err != nil {
  653. slog.Error("failed to get role ", "role", userRole.ID, "error", err)
  654. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  655. return
  656. }
  657. if userRole.ID == models.SuperAdminRole {
  658. slog.Error(
  659. "failed to delete user: ", "user", username, "error", "superadmin cannot be deleted")
  660. logic.ReturnErrorResponse(
  661. w,
  662. r,
  663. logic.FormatError(fmt.Errorf("superadmin cannot be deleted"), "internal"),
  664. )
  665. return
  666. }
  667. if callerUserRole.ID != models.SuperAdminRole {
  668. if callerUserRole.ID == models.AdminRole && userRole.ID == models.AdminRole {
  669. slog.Error(
  670. "failed to delete user: ",
  671. "user",
  672. username,
  673. "error",
  674. "admin cannot delete another admin user, including oneself",
  675. )
  676. logic.ReturnErrorResponse(
  677. w,
  678. r,
  679. logic.FormatError(
  680. fmt.Errorf("admin cannot delete another admin user, including oneself"),
  681. "internal",
  682. ),
  683. )
  684. return
  685. }
  686. }
  687. err = logic.DeleteUser(username)
  688. if err != nil {
  689. logger.Log(0, username,
  690. "failed to delete user: ", err.Error())
  691. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  692. return
  693. }
  694. // check and delete extclient with this ownerID
  695. go func() {
  696. extclients, err := logic.GetAllExtClients()
  697. if err != nil {
  698. slog.Error("failed to get extclients", "error", err)
  699. return
  700. }
  701. for _, extclient := range extclients {
  702. if extclient.OwnerID == user.UserName {
  703. err = logic.DeleteExtClientAndCleanup(extclient)
  704. if err != nil {
  705. slog.Error("failed to delete extclient",
  706. "id", extclient.ClientID, "owner", username, "error", err)
  707. } else {
  708. if err := mq.PublishDeletedClientPeerUpdate(&extclient); err != nil {
  709. slog.Error("error setting ext peers: " + err.Error())
  710. }
  711. }
  712. }
  713. }
  714. mq.PublishPeerUpdate(false)
  715. if servercfg.IsDNSMode() {
  716. logic.SetDNS()
  717. }
  718. }()
  719. logger.Log(1, username, "was deleted")
  720. json.NewEncoder(w).Encode(params["username"] + " deleted.")
  721. }
  722. // Called when vpn client dials in to start the auth flow and first stage is to get register URL itself
  723. func socketHandler(w http.ResponseWriter, r *http.Request) {
  724. // Upgrade our raw HTTP connection to a websocket based one
  725. conn, err := upgrader.Upgrade(w, r, nil)
  726. if err != nil {
  727. logger.Log(0, "error during connection upgrade for node sign-in:", err.Error())
  728. return
  729. }
  730. if conn == nil {
  731. logger.Log(0, "failed to establish web-socket connection during node sign-in")
  732. return
  733. }
  734. // Start handling the session
  735. go auth.SessionHandler(conn)
  736. }
  737. // @Summary lists all user roles.
  738. // @Router /api/v1/user/roles [get]
  739. // @Tags Users
  740. // @Param role_id query string true "roleid required to get the role details"
  741. // @Success 200 {object} []models.UserRolePermissionTemplate
  742. // @Failure 500 {object} models.ErrorResponse
  743. func listRoles(w http.ResponseWriter, r *http.Request) {
  744. var roles []models.UserRolePermissionTemplate
  745. var err error
  746. roles, err = logic.ListPlatformRoles()
  747. if err != nil {
  748. logic.ReturnErrorResponse(w, r, models.ErrorResponse{
  749. Code: http.StatusInternalServerError,
  750. Message: err.Error(),
  751. })
  752. return
  753. }
  754. logic.ReturnSuccessResponseWithJson(w, r, roles, "successfully fetched user roles permission templates")
  755. }