user.go 38 KB

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