user.go 29 KB

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