user.go 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  1. package controller
  2. import (
  3. "context"
  4. "bytes"
  5. "encoding/base64"
  6. "encoding/json"
  7. "errors"
  8. "fmt"
  9. "github.com/gravitl/netmaker/db"
  10. "image/png"
  11. "net/http"
  12. "reflect"
  13. "time"
  14. "github.com/google/uuid"
  15. "github.com/gorilla/mux"
  16. "github.com/gorilla/websocket"
  17. "github.com/gravitl/netmaker/auth"
  18. "github.com/gravitl/netmaker/logger"
  19. "github.com/gravitl/netmaker/logic"
  20. "github.com/gravitl/netmaker/models"
  21. "github.com/gravitl/netmaker/mq"
  22. "github.com/gravitl/netmaker/schema"
  23. "github.com/gravitl/netmaker/servercfg"
  24. "github.com/pquerna/otp/totp"
  25. "golang.org/x/exp/slog"
  26. )
  27. var (
  28. upgrader = websocket.Upgrader{}
  29. )
  30. var ListRoles = listRoles
  31. func userHandlers(r *mux.Router) {
  32. r.HandleFunc("/api/users/adm/hassuperadmin", hasSuperAdmin).Methods(http.MethodGet)
  33. r.HandleFunc("/api/users/adm/createsuperadmin", createSuperAdmin).Methods(http.MethodPost)
  34. r.HandleFunc("/api/users/adm/transfersuperadmin/{username}", logic.SecurityCheck(true, http.HandlerFunc(transferSuperAdmin))).
  35. Methods(http.MethodPost)
  36. r.HandleFunc("/api/users/adm/authenticate", authenticateUser).Methods(http.MethodPost)
  37. r.HandleFunc("/api/users/auth/init-totp", logic.SecurityCheck(false, http.HandlerFunc(initiateTOTPSetup))).Methods(http.MethodPost)
  38. r.HandleFunc("/api/users/auth/complete-totp", logic.SecurityCheck(false, http.HandlerFunc(completeTOTPSetup))).Methods(http.MethodPost)
  39. r.HandleFunc("/api/users/auth/verify-totp", logic.PreAuthCheck(http.HandlerFunc(verifyTOTP))).Methods(http.MethodPost)
  40. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, http.HandlerFunc(updateUser))).Methods(http.MethodPut)
  41. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, checkFreeTierLimits(limitChoiceUsers, http.HandlerFunc(createUser)))).Methods(http.MethodPost)
  42. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, http.HandlerFunc(deleteUser))).Methods(http.MethodDelete)
  43. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(getUser)))).Methods(http.MethodGet)
  44. r.HandleFunc("/api/users/{username}/enable", logic.SecurityCheck(true, http.HandlerFunc(enableUserAccount))).Methods(http.MethodPost)
  45. r.HandleFunc("/api/users/{username}/disable", logic.SecurityCheck(true, http.HandlerFunc(disableUserAccount))).Methods(http.MethodPost)
  46. r.HandleFunc("/api/v1/users", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(getUserV1)))).Methods(http.MethodGet)
  47. r.HandleFunc("/api/users", logic.SecurityCheck(true, http.HandlerFunc(getUsers))).Methods(http.MethodGet)
  48. r.HandleFunc("/api/v1/users/roles", logic.SecurityCheck(true, http.HandlerFunc(ListRoles))).Methods(http.MethodGet)
  49. r.HandleFunc("/api/v1/users/access_token", logic.SecurityCheck(true, http.HandlerFunc(createUserAccessToken))).Methods(http.MethodPost)
  50. r.HandleFunc("/api/v1/users/access_token", logic.SecurityCheck(true, http.HandlerFunc(getUserAccessTokens))).Methods(http.MethodGet)
  51. r.HandleFunc("/api/v1/users/access_token", logic.SecurityCheck(true, http.HandlerFunc(deleteUserAccessTokens))).Methods(http.MethodDelete)
  52. r.HandleFunc("/api/v1/users/logout", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(logout)))).Methods(http.MethodPost)
  53. }
  54. // @Summary Authenticate a user to retrieve an authorization token
  55. // @Router /api/v1/users/{username}/access_token [post]
  56. // @Tags Auth
  57. // @Accept json
  58. // @Param body body models.UserAuthParams true "Authentication parameters"
  59. // @Success 200 {object} models.SuccessResponse
  60. // @Failure 400 {object} models.ErrorResponse
  61. // @Failure 401 {object} models.ErrorResponse
  62. // @Failure 500 {object} models.ErrorResponse
  63. func createUserAccessToken(w http.ResponseWriter, r *http.Request) {
  64. // Auth request consists of Mac Address and Password (from node that is authorizing
  65. // in case of Master, auth is ignored and mac is set to "mastermac"
  66. var req schema.UserAccessToken
  67. err := json.NewDecoder(r.Body).Decode(&req)
  68. if err != nil {
  69. logger.Log(0, "error decoding request body: ",
  70. err.Error())
  71. logic.ReturnErrorResponse(w, r, logic.FormatError(err, logic.BadReq))
  72. return
  73. }
  74. if req.Name == "" {
  75. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("name is required"), logic.BadReq))
  76. return
  77. }
  78. if req.UserName == "" {
  79. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("username is required"), logic.BadReq))
  80. return
  81. }
  82. caller, err := logic.GetUser(r.Header.Get("user"))
  83. if err != nil {
  84. logic.ReturnErrorResponse(w, r, logic.FormatError(err, logic.UnAuthorized))
  85. return
  86. }
  87. user, err := logic.GetUser(req.UserName)
  88. if err != nil {
  89. logic.ReturnErrorResponse(w, r, logic.FormatError(err, logic.UnAuthorized))
  90. return
  91. }
  92. if caller.UserName != user.UserName && caller.PlatformRoleID != models.SuperAdminRole {
  93. if caller.PlatformRoleID == models.AdminRole {
  94. if user.PlatformRoleID == models.SuperAdminRole || user.PlatformRoleID == models.AdminRole {
  95. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("not enough permissions to create token for user "+user.UserName), logic.Forbidden_Msg))
  96. return
  97. }
  98. } else {
  99. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("not enough permissions to create token for user "+user.UserName), logic.Forbidden_Msg))
  100. return
  101. }
  102. }
  103. req.ID = uuid.New().String()
  104. req.CreatedBy = r.Header.Get("user")
  105. req.CreatedAt = time.Now()
  106. jwt, err := logic.CreateUserAccessJwtToken(user.UserName, user.PlatformRoleID, req.ExpiresAt, req.ID)
  107. if jwt == "" {
  108. // very unlikely that err is !nil and no jwt returned, but handle it anyways.
  109. logic.ReturnErrorResponse(
  110. w,
  111. r,
  112. logic.FormatError(errors.New("error creating access token "+err.Error()), logic.Internal),
  113. )
  114. return
  115. }
  116. err = req.Create(r.Context())
  117. if err != nil {
  118. logic.ReturnErrorResponse(
  119. w,
  120. r,
  121. logic.FormatError(errors.New("error creating access token "+err.Error()), logic.Internal),
  122. )
  123. return
  124. }
  125. logic.LogEvent(&models.Event{
  126. Action: models.Create,
  127. Source: models.Subject{
  128. ID: caller.UserName,
  129. Name: caller.UserName,
  130. Type: models.UserSub,
  131. },
  132. TriggeredBy: caller.UserName,
  133. Target: models.Subject{
  134. ID: req.ID,
  135. Name: req.Name,
  136. Type: models.UserAccessTokenSub,
  137. Info: req,
  138. },
  139. Origin: models.Dashboard,
  140. })
  141. logic.ReturnSuccessResponseWithJson(w, r, models.SuccessfulUserLoginResponse{
  142. AuthToken: jwt,
  143. UserName: req.UserName,
  144. }, "api access token has generated for user "+req.UserName)
  145. }
  146. // @Summary Authenticate a user to retrieve an authorization token
  147. // @Router /api/v1/users/{username}/access_token [post]
  148. // @Tags Auth
  149. // @Accept json
  150. // @Param body body models.UserAuthParams true "Authentication parameters"
  151. // @Success 200 {object} models.SuccessResponse
  152. // @Failure 400 {object} models.ErrorResponse
  153. // @Failure 401 {object} models.ErrorResponse
  154. // @Failure 500 {object} models.ErrorResponse
  155. func getUserAccessTokens(w http.ResponseWriter, r *http.Request) {
  156. username := r.URL.Query().Get("username")
  157. if username == "" {
  158. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("username is required"), "badrequest"))
  159. return
  160. }
  161. logic.ReturnSuccessResponseWithJson(w, r, (&schema.UserAccessToken{UserName: username}).ListByUser(r.Context()), "fetched api access tokens for user "+username)
  162. }
  163. // @Summary Authenticate a user to retrieve an authorization token
  164. // @Router /api/v1/users/{username}/access_token [post]
  165. // @Tags Auth
  166. // @Accept json
  167. // @Param body body models.UserAuthParams true "Authentication parameters"
  168. // @Success 200 {object} models.SuccessResponse
  169. // @Failure 400 {object} models.ErrorResponse
  170. // @Failure 401 {object} models.ErrorResponse
  171. // @Failure 500 {object} models.ErrorResponse
  172. func deleteUserAccessTokens(w http.ResponseWriter, r *http.Request) {
  173. id := r.URL.Query().Get("id")
  174. if id == "" {
  175. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("id is required"), "badrequest"))
  176. return
  177. }
  178. a := schema.UserAccessToken{
  179. ID: id,
  180. }
  181. err := a.Get(r.Context())
  182. if err != nil {
  183. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("token does not exist"), "badrequest"))
  184. return
  185. }
  186. caller, err := logic.GetUser(r.Header.Get("user"))
  187. if err != nil {
  188. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "unauthorized"))
  189. return
  190. }
  191. user, err := logic.GetUser(a.UserName)
  192. if err != nil {
  193. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "unauthorized"))
  194. return
  195. }
  196. if caller.UserName != user.UserName && caller.PlatformRoleID != models.SuperAdminRole {
  197. if caller.PlatformRoleID == models.AdminRole {
  198. if user.PlatformRoleID == models.SuperAdminRole || user.PlatformRoleID == models.AdminRole {
  199. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("not enough permissions to delete token of user "+user.UserName), logic.Forbidden_Msg))
  200. return
  201. }
  202. } else {
  203. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("not enough permissions to delete token of user "+user.UserName), logic.Forbidden_Msg))
  204. return
  205. }
  206. }
  207. err = (&schema.UserAccessToken{ID: id}).Delete(r.Context())
  208. if err != nil {
  209. logic.ReturnErrorResponse(
  210. w,
  211. r,
  212. logic.FormatError(errors.New("error deleting access token "+err.Error()), "internal"),
  213. )
  214. return
  215. }
  216. logic.LogEvent(&models.Event{
  217. Action: models.Delete,
  218. Source: models.Subject{
  219. ID: caller.UserName,
  220. Name: caller.UserName,
  221. Type: models.UserSub,
  222. },
  223. TriggeredBy: caller.UserName,
  224. Target: models.Subject{
  225. ID: a.ID,
  226. Name: a.Name,
  227. Type: models.UserAccessTokenSub,
  228. Info: a,
  229. },
  230. Origin: models.Dashboard,
  231. })
  232. logic.ReturnSuccessResponseWithJson(w, r, nil, "revoked access token")
  233. }
  234. // @Summary Authenticate a user to retrieve an authorization token
  235. // @Router /api/users/adm/authenticate [post]
  236. // @Tags Auth
  237. // @Accept json
  238. // @Param body body models.UserAuthParams true "Authentication parameters"
  239. // @Success 200 {object} models.SuccessResponse
  240. // @Failure 400 {object} models.ErrorResponse
  241. // @Failure 401 {object} models.ErrorResponse
  242. // @Failure 500 {object} models.ErrorResponse
  243. func authenticateUser(response http.ResponseWriter, request *http.Request) {
  244. // Auth request consists of Mac Address and Password (from node that is authorizing
  245. // in case of Master, auth is ignored and mac is set to "mastermac"
  246. var authRequest models.UserAuthParams
  247. var errorResponse = models.ErrorResponse{
  248. Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
  249. }
  250. decoder := json.NewDecoder(request.Body)
  251. decoderErr := decoder.Decode(&authRequest)
  252. defer request.Body.Close()
  253. if decoderErr != nil {
  254. logger.Log(0, "error decoding request body: ",
  255. decoderErr.Error())
  256. logic.ReturnErrorResponse(response, request, errorResponse)
  257. return
  258. }
  259. user, err := logic.GetUser(authRequest.UserName)
  260. if err != nil {
  261. logger.Log(0, authRequest.UserName, "user validation failed: ",
  262. err.Error())
  263. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "unauthorized"))
  264. return
  265. }
  266. if logic.IsOauthUser(user) == nil {
  267. logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("user is registered via SSO"), "badrequest"))
  268. return
  269. }
  270. if user.AccountDisabled {
  271. err = errors.New("user account disabled")
  272. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "unauthorized"))
  273. return
  274. }
  275. if !user.IsSuperAdmin && !logic.IsBasicAuthEnabled() {
  276. logic.ReturnErrorResponse(
  277. response,
  278. request,
  279. logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"),
  280. )
  281. return
  282. }
  283. if val := request.Header.Get("From-Ui"); val == "true" {
  284. // request came from UI, if normal user block Login
  285. role, err := logic.GetRole(user.PlatformRoleID)
  286. if err != nil {
  287. logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("access denied to dashboard"), "unauthorized"))
  288. return
  289. }
  290. if role.DenyDashboardAccess {
  291. logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("access denied to dashboard"), "unauthorized"))
  292. return
  293. }
  294. // log user activity
  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.DashboardSub.String(),
  305. Name: models.DashboardSub.String(),
  306. Type: models.DashboardSub,
  307. },
  308. Origin: models.Dashboard,
  309. })
  310. } else {
  311. logic.LogEvent(&models.Event{
  312. Action: models.Login,
  313. Source: models.Subject{
  314. ID: user.UserName,
  315. Name: user.UserName,
  316. Type: models.UserSub,
  317. },
  318. TriggeredBy: user.UserName,
  319. Target: models.Subject{
  320. ID: models.ClientAppSub.String(),
  321. Name: models.ClientAppSub.String(),
  322. Type: models.ClientAppSub,
  323. },
  324. Origin: models.ClientApp,
  325. })
  326. }
  327. username := authRequest.UserName
  328. jwt, err := logic.VerifyAuthRequest(authRequest)
  329. if err != nil {
  330. logger.Log(0, username, "user validation failed: ",
  331. err.Error())
  332. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "badrequest"))
  333. return
  334. }
  335. if jwt == "" {
  336. // very unlikely that err is !nil and no jwt returned, but handle it anyways.
  337. logger.Log(0, username, "jwt token is empty")
  338. logic.ReturnErrorResponse(
  339. response,
  340. request,
  341. logic.FormatError(errors.New("no token returned"), "internal"),
  342. )
  343. return
  344. }
  345. var successResponse models.SuccessResponse
  346. if user.IsMFAEnabled {
  347. successResponse = models.SuccessResponse{
  348. Code: http.StatusOK,
  349. Message: "W1R3: TOTP required",
  350. Response: models.PartialUserLoginResponse{
  351. UserName: username,
  352. PreAuthToken: jwt,
  353. },
  354. }
  355. } else {
  356. successResponse = models.SuccessResponse{
  357. Code: http.StatusOK,
  358. Message: "W1R3: Device " + username + " Authorized",
  359. Response: models.SuccessfulUserLoginResponse{
  360. UserName: username,
  361. AuthToken: jwt,
  362. },
  363. }
  364. }
  365. // Send back the JWT
  366. successJSONResponse, jsonError := json.Marshal(successResponse)
  367. if jsonError != nil {
  368. logger.Log(0, username,
  369. "error marshalling resp: ", jsonError.Error())
  370. logic.ReturnErrorResponse(response, request, errorResponse)
  371. return
  372. }
  373. logger.Log(2, username, "was authenticated")
  374. response.Header().Set("Content-Type", "application/json")
  375. response.Write(successJSONResponse)
  376. go func() {
  377. if servercfg.IsPro && logic.GetRacAutoDisable() {
  378. // enable all associeated clients for the user
  379. clients, err := logic.GetAllExtClients()
  380. if err != nil {
  381. slog.Error("error getting clients: ", "error", err)
  382. return
  383. }
  384. for _, client := range clients {
  385. if client.OwnerID == username && !client.Enabled {
  386. slog.Info(
  387. fmt.Sprintf(
  388. "enabling ext client %s for user %s due to RAC autodisabling feature",
  389. client.ClientID,
  390. client.OwnerID,
  391. ),
  392. )
  393. if newClient, err := logic.ToggleExtClientConnectivity(&client, true); err != nil {
  394. slog.Error(
  395. "error enabling ext client in RAC autodisable hook",
  396. "error",
  397. err,
  398. )
  399. continue // dont return but try for other clients
  400. } else {
  401. // publish peer update to ingress gateway
  402. if ingressNode, err := logic.GetNodeByID(newClient.IngressGatewayID); err == nil {
  403. if err = mq.PublishPeerUpdate(false); err != nil {
  404. slog.Error("error updating ext clients on", "ingress", ingressNode.ID.String(), "err", err.Error())
  405. }
  406. }
  407. }
  408. }
  409. }
  410. }
  411. }()
  412. }
  413. // @Summary Initiate setting up TOTP 2FA for a user.
  414. // @Router /api/users/auth/init-totp [post]
  415. // @Tags Auth
  416. // @Success 200 {object} models.SuccessResponse
  417. // @Failure 400 {object} models.ErrorResponse
  418. // @Failure 500 {object} models.ErrorResponse
  419. func initiateTOTPSetup(w http.ResponseWriter, r *http.Request) {
  420. username := r.Header.Get("user")
  421. user, err := logic.GetUser(username)
  422. if err != nil {
  423. logger.Log(0, "failed to get user: ", err.Error())
  424. err = fmt.Errorf("user not found: %v", err)
  425. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  426. return
  427. }
  428. if user.AuthType == models.OAuth {
  429. err = fmt.Errorf("auth type is %s, cannot process totp setup", user.AuthType)
  430. logger.Log(0, err.Error())
  431. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  432. return
  433. }
  434. key, err := totp.Generate(totp.GenerateOpts{
  435. Issuer: "Netmaker",
  436. AccountName: username,
  437. })
  438. if err != nil {
  439. err = fmt.Errorf("failed to generate totp key: %v", err)
  440. logger.Log(0, err.Error())
  441. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  442. return
  443. }
  444. user.TOTPSecret = key.Secret()
  445. err = logic.UpsertUser(*user)
  446. if err != nil {
  447. err = fmt.Errorf("error upserting user: %v", err)
  448. logger.Log(0, err.Error())
  449. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  450. return
  451. }
  452. qrCodeImg, err := key.Image(200, 200)
  453. if err != nil {
  454. err = fmt.Errorf("failed to generate totp key: %v", err)
  455. logger.Log(0, err.Error())
  456. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  457. return
  458. }
  459. var qrCodePng bytes.Buffer
  460. err = png.Encode(&qrCodePng, qrCodeImg)
  461. if err != nil {
  462. err = fmt.Errorf("failed to generate totp key: %v", err)
  463. logger.Log(0, err.Error())
  464. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  465. return
  466. }
  467. qrCode := "data:image/png;base64," + base64.StdEncoding.EncodeToString(qrCodePng.Bytes())
  468. logic.ReturnSuccessResponseWithJson(w, r, models.TOTPInitiateResponse{
  469. OTPAuthURL: key.URL(),
  470. QRCode: qrCode,
  471. }, "totp setup initiated")
  472. }
  473. // @Summary Verify and complete setting up TOTP 2FA for a user.
  474. // @Router /api/users/auth/complete-totp [post]
  475. // @Tags Auth
  476. // @Param body body models.UserTOTPVerificationParams true "TOTP verification parameters"
  477. // @Success 200 {object} models.SuccessResponse
  478. // @Failure 400 {object} models.ErrorResponse
  479. // @Failure 500 {object} models.ErrorResponse
  480. func completeTOTPSetup(w http.ResponseWriter, r *http.Request) {
  481. username := r.Header.Get("user")
  482. var req models.UserTOTPVerificationParams
  483. err := json.NewDecoder(r.Body).Decode(&req)
  484. if err != nil {
  485. logger.Log(0, "failed to decode request body: ", err.Error())
  486. err = fmt.Errorf("invalid request body: %v", err)
  487. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  488. return
  489. }
  490. user, err := logic.GetUser(username)
  491. if err != nil {
  492. logger.Log(0, "failed to get user: ", err.Error())
  493. err = fmt.Errorf("user not found: %v", err)
  494. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  495. return
  496. }
  497. if user.AuthType == models.OAuth {
  498. err = fmt.Errorf("auth type is %s, cannot process totp setup", user.AuthType)
  499. logger.Log(0, err.Error())
  500. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  501. return
  502. }
  503. if totp.Validate(req.TOTP, user.TOTPSecret) {
  504. user.IsMFAEnabled = true
  505. err = logic.UpsertUser(*user)
  506. if err != nil {
  507. err = fmt.Errorf("error upserting user: %v", err)
  508. logger.Log(0, err.Error())
  509. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  510. return
  511. }
  512. logic.ReturnSuccessResponse(w, r, fmt.Sprintf("totp setup complete for user %s", username))
  513. } else {
  514. err = fmt.Errorf("cannot setup totp for user %s: invalid totp", username)
  515. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  516. }
  517. }
  518. // @Summary Verify a user's TOTP token.
  519. // @Router /api/users/auth/verify-totp [post]
  520. // @Tags Auth
  521. // @Accept json
  522. // @Param body body models.UserTOTPVerificationParams true "TOTP verification parameters"
  523. // @Success 200 {object} models.SuccessResponse
  524. // @Failure 400 {object} models.ErrorResponse
  525. // @Failure 401 {object} models.ErrorResponse
  526. // @Failure 500 {object} models.ErrorResponse
  527. func verifyTOTP(w http.ResponseWriter, r *http.Request) {
  528. username := r.Header.Get("user")
  529. var req models.UserTOTPVerificationParams
  530. err := json.NewDecoder(r.Body).Decode(&req)
  531. if err != nil {
  532. logger.Log(0, "failed to decode request body: ", err.Error())
  533. err = fmt.Errorf("invalid request body: %v", err)
  534. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  535. return
  536. }
  537. user, err := logic.GetUser(username)
  538. if err != nil {
  539. logger.Log(0, "failed to get user: ", err.Error())
  540. err = fmt.Errorf("user not found: %v", err)
  541. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  542. return
  543. }
  544. if !user.IsMFAEnabled {
  545. err = fmt.Errorf("mfa is disabled for user(%s), cannot process totp verification", username)
  546. logger.Log(0, err.Error())
  547. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  548. return
  549. }
  550. if totp.Validate(req.TOTP, user.TOTPSecret) {
  551. jwt, err := logic.CreateUserJWT(user.UserName, user.PlatformRoleID)
  552. if err != nil {
  553. err = fmt.Errorf("error creating token: %v", err)
  554. logger.Log(0, err.Error())
  555. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  556. return
  557. }
  558. // update last login time
  559. user.LastLoginTime = time.Now().UTC()
  560. err = logic.UpsertUser(*user)
  561. if err != nil {
  562. err = fmt.Errorf("error upserting user: %v", err)
  563. logger.Log(0, err.Error())
  564. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  565. return
  566. }
  567. logic.ReturnSuccessResponseWithJson(w, r, models.SuccessfulUserLoginResponse{
  568. UserName: username,
  569. AuthToken: jwt,
  570. }, "W1R3: User "+username+" Authorized")
  571. } else {
  572. err = fmt.Errorf("invalid totp")
  573. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "unauthorized"))
  574. }
  575. }
  576. // @Summary Check if the server has a super admin
  577. // @Router /api/users/adm/hassuperadmin [get]
  578. // @Tags Users
  579. // @Success 200 {object} bool
  580. // @Failure 500 {object} models.ErrorResponse
  581. func hasSuperAdmin(w http.ResponseWriter, r *http.Request) {
  582. w.Header().Set("Content-Type", "application/json")
  583. hasSuperAdmin, err := logic.HasSuperAdmin()
  584. if err != nil {
  585. logger.Log(0, "failed to check for admin: ", err.Error())
  586. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  587. return
  588. }
  589. json.NewEncoder(w).Encode(hasSuperAdmin)
  590. }
  591. // @Summary Get an individual user
  592. // @Router /api/users/{username} [get]
  593. // @Tags Users
  594. // @Param username path string true "Username of the user to fetch"
  595. // @Success 200 {object} models.User
  596. // @Failure 500 {object} models.ErrorResponse
  597. func getUser(w http.ResponseWriter, r *http.Request) {
  598. // set header.
  599. w.Header().Set("Content-Type", "application/json")
  600. var params = mux.Vars(r)
  601. usernameFetched := params["username"]
  602. user, err := logic.GetReturnUser(usernameFetched)
  603. if err != nil {
  604. logger.Log(0, usernameFetched, "failed to fetch user: ", err.Error())
  605. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  606. return
  607. }
  608. logger.Log(2, r.Header.Get("user"), "fetched user", usernameFetched)
  609. json.NewEncoder(w).Encode(user)
  610. }
  611. // @Summary Enable a user's account
  612. // @Router /api/users/{username}/enable [post]
  613. // @Tags Users
  614. // @Param username path string true "Username of the user to enable"
  615. // @Success 200 {object} models.SuccessResponse
  616. // @Failure 400 {object} models.ErrorResponse
  617. // @Failure 500 {object} models.ErrorResponse
  618. func enableUserAccount(w http.ResponseWriter, r *http.Request) {
  619. username := mux.Vars(r)["username"]
  620. user, err := logic.GetUser(username)
  621. if err != nil {
  622. logger.Log(0, "failed to fetch user: ", err.Error())
  623. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  624. return
  625. }
  626. user.AccountDisabled = false
  627. err = logic.UpsertUser(*user)
  628. if err != nil {
  629. logger.Log(0, "failed to enable user account: ", err.Error())
  630. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  631. }
  632. logic.ReturnSuccessResponse(w, r, "user account enabled")
  633. }
  634. // @Summary Disable a user's account
  635. // @Router /api/users/{username}/disable [post]
  636. // @Tags Users
  637. // @Param username path string true "Username of the user to disable"
  638. // @Success 200 {object} models.SuccessResponse
  639. // @Failure 400 {object} models.ErrorResponse
  640. // @Failure 500 {object} models.ErrorResponse
  641. func disableUserAccount(w http.ResponseWriter, r *http.Request) {
  642. username := mux.Vars(r)["username"]
  643. user, err := logic.GetUser(username)
  644. if err != nil {
  645. logger.Log(0, "failed to fetch user: ", err.Error())
  646. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  647. return
  648. }
  649. if user.PlatformRoleID == models.SuperAdminRole {
  650. err = errors.New("cannot disable super-admin user account")
  651. logger.Log(0, err.Error())
  652. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  653. return
  654. }
  655. user.AccountDisabled = true
  656. err = logic.UpsertUser(*user)
  657. if err != nil {
  658. logger.Log(0, "failed to disable user account: ", err.Error())
  659. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  660. }
  661. logic.ReturnSuccessResponse(w, r, "user account disabled")
  662. }
  663. // swagger:route GET /api/v1/users user getUserV1
  664. //
  665. // Get an individual user with role info.
  666. //
  667. // Schemes: https
  668. //
  669. // Security:
  670. // oauth
  671. //
  672. // Responses:
  673. // 200: ReturnUserWithRolesAndGroups
  674. func getUserV1(w http.ResponseWriter, r *http.Request) {
  675. // set header.
  676. w.Header().Set("Content-Type", "application/json")
  677. usernameFetched := r.URL.Query().Get("username")
  678. if usernameFetched == "" {
  679. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("username is required"), "badrequest"))
  680. return
  681. }
  682. user, err := logic.GetReturnUser(usernameFetched)
  683. if err != nil {
  684. logger.Log(0, usernameFetched, "failed to fetch user: ", err.Error())
  685. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  686. return
  687. }
  688. userRoleTemplate, err := logic.GetRole(user.PlatformRoleID)
  689. if err != nil {
  690. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  691. return
  692. }
  693. resp := models.ReturnUserWithRolesAndGroups{
  694. ReturnUser: user,
  695. PlatformRole: userRoleTemplate,
  696. UserGroups: map[models.UserGroupID]models.UserGroup{},
  697. }
  698. for gId := range user.UserGroups {
  699. grp, err := logic.GetUserGroup(gId)
  700. if err != nil {
  701. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  702. return
  703. }
  704. resp.UserGroups[gId] = grp
  705. }
  706. logger.Log(2, r.Header.Get("user"), "fetched user", usernameFetched)
  707. logic.ReturnSuccessResponseWithJson(w, r, resp, "fetched user with role info")
  708. }
  709. // swagger:route GET /api/users user getUsers
  710. //
  711. // Get all users.
  712. //
  713. // Schemes: https
  714. //
  715. // Security:
  716. // oauth
  717. //
  718. // Responses:
  719. // 200: userBodyResponse
  720. func getUsers(w http.ResponseWriter, r *http.Request) {
  721. // set header.
  722. w.Header().Set("Content-Type", "application/json")
  723. users, err := logic.GetUsers()
  724. if err != nil {
  725. logger.Log(0, "failed to fetch users: ", err.Error())
  726. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  727. return
  728. }
  729. logic.SortUsers(users[:])
  730. logger.Log(2, r.Header.Get("user"), "fetched users")
  731. json.NewEncoder(w).Encode(users)
  732. }
  733. // @Summary Create a super admin
  734. // @Router /api/users/adm/createsuperadmin [post]
  735. // @Tags Users
  736. // @Param body body models.User true "User details"
  737. // @Success 200 {object} models.User
  738. // @Failure 400 {object} models.ErrorResponse
  739. // @Failure 500 {object} models.ErrorResponse
  740. func createSuperAdmin(w http.ResponseWriter, r *http.Request) {
  741. w.Header().Set("Content-Type", "application/json")
  742. var u models.User
  743. err := json.NewDecoder(r.Body).Decode(&u)
  744. if err != nil {
  745. slog.Error("error decoding request body", "error", err.Error())
  746. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  747. return
  748. }
  749. if !logic.IsBasicAuthEnabled() {
  750. logic.ReturnErrorResponse(
  751. w,
  752. r,
  753. logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"),
  754. )
  755. return
  756. }
  757. err = logic.CreateSuperAdmin(&u)
  758. if err != nil {
  759. slog.Error("failed to create admin", "error", err.Error())
  760. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  761. return
  762. }
  763. logger.Log(1, u.UserName, "was made a super admin")
  764. json.NewEncoder(w).Encode(logic.ToReturnUser(u))
  765. }
  766. // @Summary Transfer super admin role to another admin user
  767. // @Router /api/users/adm/transfersuperadmin/{username} [post]
  768. // @Tags Users
  769. // @Param username path string true "Username of the user to transfer super admin role"
  770. // @Success 200 {object} models.User
  771. // @Failure 403 {object} models.ErrorResponse
  772. // @Failure 500 {object} models.ErrorResponse
  773. func transferSuperAdmin(w http.ResponseWriter, r *http.Request) {
  774. w.Header().Set("Content-Type", "application/json")
  775. caller, err := logic.GetUser(r.Header.Get("user"))
  776. if err != nil {
  777. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  778. }
  779. if caller.PlatformRoleID != models.SuperAdminRole {
  780. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("only superadmin can assign the superadmin role to another user"), "forbidden"))
  781. return
  782. }
  783. var params = mux.Vars(r)
  784. username := params["username"]
  785. u, err := logic.GetUser(username)
  786. if err != nil {
  787. slog.Error("error getting user", "user", u.UserName, "error", err.Error())
  788. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  789. return
  790. }
  791. if u.PlatformRoleID != models.AdminRole {
  792. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("only admins can be promoted to superadmin role"), "forbidden"))
  793. return
  794. }
  795. if !logic.IsBasicAuthEnabled() {
  796. logic.ReturnErrorResponse(
  797. w,
  798. r,
  799. logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"),
  800. )
  801. return
  802. }
  803. u.PlatformRoleID = models.SuperAdminRole
  804. err = logic.UpsertUser(*u)
  805. if err != nil {
  806. slog.Error("error updating user to superadmin: ", "user", u.UserName, "error", err.Error())
  807. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  808. return
  809. }
  810. caller.PlatformRoleID = models.AdminRole
  811. err = logic.UpsertUser(*caller)
  812. if err != nil {
  813. slog.Error("error demoting user to admin: ", "user", caller.UserName, "error", err.Error())
  814. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  815. return
  816. }
  817. slog.Info("user was made a super admin", "user", u.UserName)
  818. json.NewEncoder(w).Encode(logic.ToReturnUser(*u))
  819. }
  820. // @Summary Create a user
  821. // @Router /api/users/{username} [post]
  822. // @Tags Users
  823. // @Param username path string true "Username of the user to create"
  824. // @Param body body models.User true "User details"
  825. // @Success 200 {object} models.User
  826. // @Failure 400 {object} models.ErrorResponse
  827. // @Failure 403 {object} models.ErrorResponse
  828. // @Failure 500 {object} models.ErrorResponse
  829. func createUser(w http.ResponseWriter, r *http.Request) {
  830. w.Header().Set("Content-Type", "application/json")
  831. caller, err := logic.GetUser(r.Header.Get("user"))
  832. if err != nil {
  833. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  834. return
  835. }
  836. var user models.User
  837. err = json.NewDecoder(r.Body).Decode(&user)
  838. if err != nil {
  839. logger.Log(0, user.UserName, "error decoding request body: ",
  840. err.Error())
  841. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  842. return
  843. }
  844. if !servercfg.IsPro {
  845. user.PlatformRoleID = models.AdminRole
  846. }
  847. if user.UserName == logic.MasterUser {
  848. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("username not allowed"), "badrequest"))
  849. return
  850. }
  851. if user.PlatformRoleID == "" {
  852. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("platform role is missing"), "badrequest"))
  853. return
  854. }
  855. userRole, err := logic.GetRole(user.PlatformRoleID)
  856. if err != nil {
  857. err = errors.New("error fetching role " + user.PlatformRoleID.String() + " " + err.Error())
  858. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  859. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  860. return
  861. }
  862. if userRole.ID == models.SuperAdminRole {
  863. err = errors.New("additional superadmins cannot be created")
  864. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  865. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  866. return
  867. }
  868. if caller.PlatformRoleID != models.SuperAdminRole && user.PlatformRoleID == models.AdminRole {
  869. err = errors.New("only superadmin can create admin users")
  870. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  871. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  872. return
  873. }
  874. if !servercfg.IsPro && user.PlatformRoleID != models.AdminRole {
  875. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("non-admins users can only be created on Pro version"), "forbidden"))
  876. return
  877. }
  878. err = logic.CreateUser(&user)
  879. if err != nil {
  880. slog.Error("error creating new user: ", "user", user.UserName, "error", err.Error())
  881. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  882. return
  883. }
  884. logic.LogEvent(&models.Event{
  885. Action: models.Create,
  886. Source: models.Subject{
  887. ID: caller.UserName,
  888. Name: caller.UserName,
  889. Type: models.UserSub,
  890. },
  891. TriggeredBy: caller.UserName,
  892. Target: models.Subject{
  893. ID: user.UserName,
  894. Name: user.UserName,
  895. Type: models.UserSub,
  896. Info: user,
  897. },
  898. Origin: models.Dashboard,
  899. })
  900. logic.DeleteUserInvite(user.UserName)
  901. logic.DeletePendingUser(user.UserName)
  902. go mq.PublishPeerUpdate(false)
  903. slog.Info("user was created", "username", user.UserName)
  904. json.NewEncoder(w).Encode(logic.ToReturnUser(user))
  905. }
  906. // @Summary Update a user
  907. // @Router /api/users/{username} [put]
  908. // @Tags Users
  909. // @Param username path string true "Username of the user to update"
  910. // @Param body body models.User true "User details"
  911. // @Success 200 {object} models.User
  912. // @Failure 400 {object} models.ErrorResponse
  913. // @Failure 403 {object} models.ErrorResponse
  914. // @Failure 500 {object} models.ErrorResponse
  915. func updateUser(w http.ResponseWriter, r *http.Request) {
  916. w.Header().Set("Content-Type", "application/json")
  917. var params = mux.Vars(r)
  918. // start here
  919. var caller *models.User
  920. var err error
  921. var ismaster bool
  922. if r.Header.Get("user") == logic.MasterUser {
  923. ismaster = true
  924. } else {
  925. caller, err = logic.GetUser(r.Header.Get("user"))
  926. if err != nil {
  927. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  928. }
  929. }
  930. username := params["username"]
  931. user, err := logic.GetUser(username)
  932. if err != nil {
  933. logger.Log(0, username,
  934. "failed to update user info: ", err.Error())
  935. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  936. return
  937. }
  938. var userchange models.User
  939. // we decode our body request params
  940. err = json.NewDecoder(r.Body).Decode(&userchange)
  941. if err != nil {
  942. slog.Error("failed to decode body", "error ", err.Error())
  943. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  944. return
  945. }
  946. if user.UserName != userchange.UserName {
  947. logic.ReturnErrorResponse(
  948. w,
  949. r,
  950. logic.FormatError(
  951. errors.New("user in param and request body not matching"),
  952. "badrequest",
  953. ),
  954. )
  955. return
  956. }
  957. selfUpdate := false
  958. if !ismaster && caller.UserName == user.UserName {
  959. selfUpdate = true
  960. }
  961. if !ismaster && !selfUpdate {
  962. if caller.PlatformRoleID == models.AdminRole && user.PlatformRoleID == models.SuperAdminRole {
  963. slog.Error("non-superadmin user", "caller", caller.UserName, "attempted to update superadmin user", username)
  964. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("cannot update superadmin user"), "forbidden"))
  965. return
  966. }
  967. if caller.PlatformRoleID != models.AdminRole && caller.PlatformRoleID != models.SuperAdminRole {
  968. slog.Error("operation not allowed", "caller", caller.UserName, "attempted to update user", username)
  969. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("cannot update superadmin user"), "forbidden"))
  970. return
  971. }
  972. if caller.PlatformRoleID == models.AdminRole && user.PlatformRoleID == models.AdminRole {
  973. slog.Error("an admin user does not have permissions to update another admin user", "caller", caller.UserName, "attempted to update admin user", username)
  974. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("an admin user does not have permissions to update another admin user"), "forbidden"))
  975. return
  976. }
  977. if caller.PlatformRoleID == models.AdminRole && userchange.PlatformRoleID == models.AdminRole {
  978. err = errors.New("an admin user does not have permissions to assign the admin role to another user")
  979. slog.Error(
  980. "failed to update user",
  981. "caller",
  982. caller.UserName,
  983. "attempted to update user",
  984. username,
  985. "error",
  986. err,
  987. )
  988. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  989. return
  990. }
  991. }
  992. if !ismaster && selfUpdate {
  993. if user.PlatformRoleID != userchange.PlatformRoleID {
  994. slog.Error("user cannot change his own role", "caller", caller.UserName, "attempted to update user role", username)
  995. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("user not allowed to self assign role"), "forbidden"))
  996. return
  997. }
  998. if servercfg.IsPro {
  999. // user cannot update his own roles and groups
  1000. if len(user.NetworkRoles) != len(userchange.NetworkRoles) || !reflect.DeepEqual(user.NetworkRoles, userchange.NetworkRoles) {
  1001. err = errors.New("user cannot update self update their network roles")
  1002. slog.Error("failed to update user", "caller", caller.UserName, "attempted to update user", username, "error", err)
  1003. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  1004. return
  1005. }
  1006. // user cannot update his own roles and groups
  1007. if len(user.UserGroups) != len(userchange.UserGroups) || !reflect.DeepEqual(user.UserGroups, userchange.UserGroups) {
  1008. err = errors.New("user cannot update self update their groups")
  1009. slog.Error("failed to update user", "caller", caller.UserName, "attempted to update user", username, "error", err)
  1010. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  1011. return
  1012. }
  1013. }
  1014. }
  1015. if ismaster {
  1016. if user.PlatformRoleID != models.SuperAdminRole && userchange.PlatformRoleID == models.SuperAdminRole {
  1017. slog.Error("operation not allowed", "caller", logic.MasterUser, "attempted to update user role to superadmin", username)
  1018. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("attempted to update user role to superadmin"), "forbidden"))
  1019. return
  1020. }
  1021. }
  1022. if logic.IsOauthUser(user) == nil && userchange.Password != "" {
  1023. err := fmt.Errorf("cannot update user's password for an oauth user %s", username)
  1024. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  1025. return
  1026. }
  1027. logic.AddGlobalNetRolesToAdmins(&userchange)
  1028. if userchange.PlatformRoleID != user.PlatformRoleID || !logic.CompareMaps(user.UserGroups, userchange.UserGroups) {
  1029. (&schema.UserAccessToken{UserName: user.UserName}).DeleteAllUserTokens(r.Context())
  1030. }
  1031. oldUser := *user
  1032. e := models.Event{
  1033. Action: models.Update,
  1034. Source: models.Subject{
  1035. ID: caller.UserName,
  1036. Name: caller.UserName,
  1037. Type: models.UserSub,
  1038. },
  1039. TriggeredBy: caller.UserName,
  1040. Target: models.Subject{
  1041. ID: user.UserName,
  1042. Name: user.UserName,
  1043. Type: models.UserSub,
  1044. },
  1045. Diff: models.Diff{
  1046. Old: oldUser,
  1047. New: userchange,
  1048. },
  1049. Origin: models.Dashboard,
  1050. }
  1051. user, err = logic.UpdateUser(&userchange, user)
  1052. if err != nil {
  1053. logger.Log(0, username,
  1054. "failed to update user info: ", err.Error())
  1055. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  1056. return
  1057. }
  1058. logic.LogEvent(&e)
  1059. go mq.PublishPeerUpdate(false)
  1060. logger.Log(1, username, "was updated")
  1061. json.NewEncoder(w).Encode(logic.ToReturnUser(*user))
  1062. }
  1063. // @Summary Delete a user
  1064. // @Router /api/users/{username} [delete]
  1065. // @Tags Users
  1066. // @Param username path string true "Username of the user to delete"
  1067. // @Success 200 {string} string
  1068. // @Failure 500 {object} models.ErrorResponse
  1069. func deleteUser(w http.ResponseWriter, r *http.Request) {
  1070. // Set header
  1071. w.Header().Set("Content-Type", "application/json")
  1072. // get params
  1073. var params = mux.Vars(r)
  1074. caller, err := logic.GetUser(r.Header.Get("user"))
  1075. if err != nil {
  1076. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1077. }
  1078. callerUserRole, err := logic.GetRole(caller.PlatformRoleID)
  1079. if err != nil {
  1080. slog.Error("failed to get role ", "role", callerUserRole.ID, "error", err)
  1081. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1082. return
  1083. }
  1084. username := params["username"]
  1085. user, err := logic.GetUser(username)
  1086. if err != nil {
  1087. logger.Log(0, username,
  1088. "failed to update user info: ", err.Error())
  1089. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1090. return
  1091. }
  1092. userRole, err := logic.GetRole(user.PlatformRoleID)
  1093. if err != nil {
  1094. slog.Error("failed to get role ", "role", userRole.ID, "error", err)
  1095. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1096. return
  1097. }
  1098. if userRole.ID == models.SuperAdminRole {
  1099. slog.Error(
  1100. "failed to delete user: ", "user", username, "error", "superadmin cannot be deleted")
  1101. logic.ReturnErrorResponse(
  1102. w,
  1103. r,
  1104. logic.FormatError(fmt.Errorf("superadmin cannot be deleted"), "internal"),
  1105. )
  1106. return
  1107. }
  1108. if callerUserRole.ID != models.SuperAdminRole {
  1109. if callerUserRole.ID == models.AdminRole && userRole.ID == models.AdminRole {
  1110. slog.Error(
  1111. "failed to delete user: ",
  1112. "user",
  1113. username,
  1114. "error",
  1115. "admin cannot delete another admin user, including oneself",
  1116. )
  1117. logic.ReturnErrorResponse(
  1118. w,
  1119. r,
  1120. logic.FormatError(
  1121. fmt.Errorf("admin cannot delete another admin user, including oneself"),
  1122. "internal",
  1123. ),
  1124. )
  1125. return
  1126. }
  1127. }
  1128. err = logic.DeleteUser(username)
  1129. if err != nil {
  1130. logger.Log(0, username,
  1131. "failed to delete user: ", err.Error())
  1132. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1133. return
  1134. }
  1135. logic.LogEvent(&models.Event{
  1136. Action: models.Delete,
  1137. Source: models.Subject{
  1138. ID: caller.UserName,
  1139. Name: caller.UserName,
  1140. Type: models.UserSub,
  1141. },
  1142. TriggeredBy: caller.UserName,
  1143. Target: models.Subject{
  1144. ID: user.UserName,
  1145. Name: user.UserName,
  1146. Type: models.UserSub,
  1147. },
  1148. Origin: models.Dashboard,
  1149. })
  1150. // check and delete extclient with this ownerID
  1151. go func() {
  1152. extclients, err := logic.GetAllExtClients()
  1153. if err != nil {
  1154. slog.Error("failed to get extclients", "error", err)
  1155. return
  1156. }
  1157. for _, extclient := range extclients {
  1158. if extclient.OwnerID == user.UserName {
  1159. err = logic.DeleteExtClientAndCleanup(extclient)
  1160. if err != nil {
  1161. slog.Error("failed to delete extclient",
  1162. "id", extclient.ClientID, "owner", username, "error", err)
  1163. } else {
  1164. if err := mq.PublishDeletedClientPeerUpdate(&extclient); err != nil {
  1165. slog.Error("error setting ext peers: " + err.Error())
  1166. }
  1167. }
  1168. }
  1169. }
  1170. mq.PublishPeerUpdate(false)
  1171. if servercfg.IsDNSMode() {
  1172. logic.SetDNS()
  1173. }
  1174. }()
  1175. logger.Log(1, username, "was deleted")
  1176. json.NewEncoder(w).Encode(params["username"] + " deleted.")
  1177. }
  1178. // Called when vpn client dials in to start the auth flow and first stage is to get register URL itself
  1179. func socketHandler(w http.ResponseWriter, r *http.Request) {
  1180. // Upgrade our raw HTTP connection to a websocket based one
  1181. conn, err := upgrader.Upgrade(w, r, nil)
  1182. if err != nil {
  1183. logger.Log(0, "error during connection upgrade for node sign-in:", err.Error())
  1184. return
  1185. }
  1186. if conn == nil {
  1187. logger.Log(0, "failed to establish web-socket connection during node sign-in")
  1188. return
  1189. }
  1190. // Start handling the session
  1191. go auth.SessionHandler(conn)
  1192. }
  1193. // @Summary lists all user roles.
  1194. // @Router /api/v1/user/roles [get]
  1195. // @Tags Users
  1196. // @Param role_id query string true "roleid required to get the role details"
  1197. // @Success 200 {object} []models.UserRolePermissionTemplate
  1198. // @Failure 500 {object} models.ErrorResponse
  1199. func listRoles(w http.ResponseWriter, r *http.Request) {
  1200. var roles []models.UserRolePermissionTemplate
  1201. var err error
  1202. roles, err = logic.ListPlatformRoles()
  1203. if err != nil {
  1204. logic.ReturnErrorResponse(w, r, models.ErrorResponse{
  1205. Code: http.StatusInternalServerError,
  1206. Message: err.Error(),
  1207. })
  1208. return
  1209. }
  1210. logic.ReturnSuccessResponseWithJson(w, r, roles, "successfully fetched user roles permission templates")
  1211. }
  1212. // swagger:route POST /api/v1/user/logout user logout
  1213. //
  1214. // LogOut user.
  1215. //
  1216. // Schemes: https
  1217. //
  1218. // Security:
  1219. // oauth
  1220. //
  1221. // Responses:
  1222. // 200: userBodyResponse
  1223. func logout(w http.ResponseWriter, r *http.Request) {
  1224. // set header.
  1225. w.Header().Set("Content-Type", "application/json")
  1226. userName := r.URL.Query().Get("username")
  1227. user, err := logic.GetUser(userName)
  1228. if err != nil {
  1229. logic.ReturnErrorResponse(w, r, logic.FormatError(err, logic.BadReq))
  1230. return
  1231. }
  1232. var target models.SubjectType
  1233. if val := r.Header.Get("From-Ui"); val == "true" {
  1234. target = models.DashboardSub
  1235. } else {
  1236. target = models.ClientAppSub
  1237. }
  1238. if target != "" {
  1239. logic.LogEvent(&models.Event{
  1240. Action: models.LogOut,
  1241. Source: models.Subject{
  1242. ID: user.UserName,
  1243. Name: user.UserName,
  1244. Type: models.UserSub,
  1245. },
  1246. TriggeredBy: user.UserName,
  1247. Target: models.Subject{
  1248. ID: target.String(),
  1249. Name: target.String(),
  1250. Type: target,
  1251. },
  1252. Origin: models.Origin(target),
  1253. })
  1254. }
  1255. logic.ReturnSuccessResponse(w, r, "user logged out")
  1256. }