user.go 35 KB

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