user.go 31 KB

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