user.go 30 KB

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