user.go 31 KB

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