user.go 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698
  1. package controller
  2. import (
  3. "bytes"
  4. "encoding/base64"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "image/png"
  9. "net/http"
  10. "reflect"
  11. "time"
  12. "github.com/pquerna/otp"
  13. "golang.org/x/crypto/bcrypt"
  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/{username}/validate-identity", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(validateUserIdentity)))).Methods(http.MethodPost)
  38. r.HandleFunc("/api/users/{username}/auth/init-totp", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(initiateTOTPSetup)))).Methods(http.MethodPost)
  39. r.HandleFunc("/api/users/{username}/auth/complete-totp", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(completeTOTPSetup)))).Methods(http.MethodPost)
  40. r.HandleFunc("/api/users/{username}/auth/verify-totp", logic.PreAuthCheck(logic.ContinueIfUserMatch(http.HandlerFunc(verifyTOTP)))).Methods(http.MethodPost)
  41. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, http.HandlerFunc(updateUser))).Methods(http.MethodPut)
  42. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, checkFreeTierLimits(limitChoiceUsers, http.HandlerFunc(createUser)))).Methods(http.MethodPost)
  43. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, http.HandlerFunc(deleteUser))).Methods(http.MethodDelete)
  44. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(getUser)))).Methods(http.MethodGet)
  45. r.HandleFunc("/api/users/{username}/enable", logic.SecurityCheck(true, http.HandlerFunc(enableUserAccount))).Methods(http.MethodPost)
  46. r.HandleFunc("/api/users/{username}/disable", logic.SecurityCheck(true, http.HandlerFunc(disableUserAccount))).Methods(http.MethodPost)
  47. r.HandleFunc("/api/users/{username}/settings", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(getUserSettings)))).Methods(http.MethodGet)
  48. r.HandleFunc("/api/users/{username}/settings", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(updateUserSettings)))).Methods(http.MethodPut)
  49. r.HandleFunc("/api/v1/users", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(getUserV1)))).Methods(http.MethodGet)
  50. r.HandleFunc("/api/users", logic.SecurityCheck(true, http.HandlerFunc(getUsers))).Methods(http.MethodGet)
  51. r.HandleFunc("/api/v1/users/roles", logic.SecurityCheck(true, http.HandlerFunc(ListRoles))).Methods(http.MethodGet)
  52. r.HandleFunc("/api/v1/users/access_token", logic.SecurityCheck(true, http.HandlerFunc(createUserAccessToken))).Methods(http.MethodPost)
  53. r.HandleFunc("/api/v1/users/access_token", logic.SecurityCheck(true, http.HandlerFunc(getUserAccessTokens))).Methods(http.MethodGet)
  54. r.HandleFunc("/api/v1/users/access_token", logic.SecurityCheck(true, http.HandlerFunc(deleteUserAccessTokens))).Methods(http.MethodDelete)
  55. r.HandleFunc("/api/v1/users/logout", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(logout)))).Methods(http.MethodPost)
  56. }
  57. // @Summary Authenticate a user to retrieve an authorization token
  58. // @Router /api/v1/users/{username}/access_token [post]
  59. // @Tags Auth
  60. // @Accept json
  61. // @Param body body models.UserAuthParams true "Authentication parameters"
  62. // @Success 200 {object} models.SuccessResponse
  63. // @Failure 400 {object} models.ErrorResponse
  64. // @Failure 401 {object} models.ErrorResponse
  65. // @Failure 500 {object} models.ErrorResponse
  66. func createUserAccessToken(w http.ResponseWriter, r *http.Request) {
  67. // Auth request consists of Mac Address and Password (from node that is authorizing
  68. // in case of Master, auth is ignored and mac is set to "mastermac"
  69. var req schema.UserAccessToken
  70. err := json.NewDecoder(r.Body).Decode(&req)
  71. if err != nil {
  72. logger.Log(0, "error decoding request body: ",
  73. err.Error())
  74. logic.ReturnErrorResponse(w, r, logic.FormatError(err, logic.BadReq))
  75. return
  76. }
  77. if req.Name == "" {
  78. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("name is required"), logic.BadReq))
  79. return
  80. }
  81. if req.UserName == "" {
  82. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("username is required"), logic.BadReq))
  83. return
  84. }
  85. caller, err := logic.GetUser(r.Header.Get("user"))
  86. if err != nil {
  87. logic.ReturnErrorResponse(w, r, logic.FormatError(err, logic.UnAuthorized))
  88. return
  89. }
  90. user, err := logic.GetUser(req.UserName)
  91. if err != nil {
  92. logic.ReturnErrorResponse(w, r, logic.FormatError(err, logic.UnAuthorized))
  93. return
  94. }
  95. if caller.UserName != user.UserName && caller.PlatformRoleID != models.SuperAdminRole {
  96. if caller.PlatformRoleID == models.AdminRole {
  97. if user.PlatformRoleID == models.SuperAdminRole || user.PlatformRoleID == models.AdminRole {
  98. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("not enough permissions to create token for user "+user.UserName), logic.Forbidden_Msg))
  99. return
  100. }
  101. } else {
  102. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("not enough permissions to create token for user "+user.UserName), logic.Forbidden_Msg))
  103. return
  104. }
  105. }
  106. req.ID = uuid.New().String()
  107. req.CreatedBy = r.Header.Get("user")
  108. req.CreatedAt = time.Now()
  109. jwt, err := logic.CreateUserAccessJwtToken(user.UserName, user.PlatformRoleID, req.ExpiresAt, req.ID)
  110. if jwt == "" {
  111. // very unlikely that err is !nil and no jwt returned, but handle it anyways.
  112. logic.ReturnErrorResponse(
  113. w,
  114. r,
  115. logic.FormatError(errors.New("error creating access token "+err.Error()), logic.Internal),
  116. )
  117. return
  118. }
  119. err = req.Create(r.Context())
  120. if err != nil {
  121. logic.ReturnErrorResponse(
  122. w,
  123. r,
  124. logic.FormatError(errors.New("error creating access token "+err.Error()), logic.Internal),
  125. )
  126. return
  127. }
  128. logic.LogEvent(&models.Event{
  129. Action: models.Create,
  130. Source: models.Subject{
  131. ID: caller.UserName,
  132. Name: caller.UserName,
  133. Type: models.UserSub,
  134. },
  135. TriggeredBy: caller.UserName,
  136. Target: models.Subject{
  137. ID: req.ID,
  138. Name: req.Name,
  139. Type: models.UserAccessTokenSub,
  140. Info: req,
  141. },
  142. Origin: models.Dashboard,
  143. })
  144. logic.ReturnSuccessResponseWithJson(w, r, models.SuccessfulUserLoginResponse{
  145. AuthToken: jwt,
  146. UserName: req.UserName,
  147. }, "api access token has generated for user "+req.UserName)
  148. }
  149. // @Summary Authenticate a user to retrieve an authorization token
  150. // @Router /api/v1/users/{username}/access_token [post]
  151. // @Tags Auth
  152. // @Accept json
  153. // @Param body body models.UserAuthParams true "Authentication parameters"
  154. // @Success 200 {object} models.SuccessResponse
  155. // @Failure 400 {object} models.ErrorResponse
  156. // @Failure 401 {object} models.ErrorResponse
  157. // @Failure 500 {object} models.ErrorResponse
  158. func getUserAccessTokens(w http.ResponseWriter, r *http.Request) {
  159. username := r.URL.Query().Get("username")
  160. if username == "" {
  161. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("username is required"), "badrequest"))
  162. return
  163. }
  164. logic.ReturnSuccessResponseWithJson(w, r, (&schema.UserAccessToken{UserName: username}).ListByUser(r.Context()), "fetched api access tokens for user "+username)
  165. }
  166. // @Summary Authenticate a user to retrieve an authorization token
  167. // @Router /api/v1/users/{username}/access_token [post]
  168. // @Tags Auth
  169. // @Accept json
  170. // @Param body body models.UserAuthParams true "Authentication parameters"
  171. // @Success 200 {object} models.SuccessResponse
  172. // @Failure 400 {object} models.ErrorResponse
  173. // @Failure 401 {object} models.ErrorResponse
  174. // @Failure 500 {object} models.ErrorResponse
  175. func deleteUserAccessTokens(w http.ResponseWriter, r *http.Request) {
  176. id := r.URL.Query().Get("id")
  177. if id == "" {
  178. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("id is required"), "badrequest"))
  179. return
  180. }
  181. a := schema.UserAccessToken{
  182. ID: id,
  183. }
  184. err := a.Get(r.Context())
  185. if err != nil {
  186. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("token does not exist"), "badrequest"))
  187. return
  188. }
  189. caller, err := logic.GetUser(r.Header.Get("user"))
  190. if err != nil {
  191. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "unauthorized"))
  192. return
  193. }
  194. user, err := logic.GetUser(a.UserName)
  195. if err != nil {
  196. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "unauthorized"))
  197. return
  198. }
  199. if caller.UserName != user.UserName && caller.PlatformRoleID != models.SuperAdminRole {
  200. if caller.PlatformRoleID == models.AdminRole {
  201. if user.PlatformRoleID == models.SuperAdminRole || user.PlatformRoleID == models.AdminRole {
  202. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("not enough permissions to delete token of user "+user.UserName), logic.Forbidden_Msg))
  203. return
  204. }
  205. } else {
  206. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("not enough permissions to delete token of user "+user.UserName), logic.Forbidden_Msg))
  207. return
  208. }
  209. }
  210. err = (&schema.UserAccessToken{ID: id}).Delete(r.Context())
  211. if err != nil {
  212. logic.ReturnErrorResponse(
  213. w,
  214. r,
  215. logic.FormatError(errors.New("error deleting access token "+err.Error()), "internal"),
  216. )
  217. return
  218. }
  219. logic.LogEvent(&models.Event{
  220. Action: models.Delete,
  221. Source: models.Subject{
  222. ID: caller.UserName,
  223. Name: caller.UserName,
  224. Type: models.UserSub,
  225. },
  226. TriggeredBy: caller.UserName,
  227. Target: models.Subject{
  228. ID: a.ID,
  229. Name: a.Name,
  230. Type: models.UserAccessTokenSub,
  231. Info: a,
  232. },
  233. Origin: models.Dashboard,
  234. })
  235. logic.ReturnSuccessResponseWithJson(w, r, nil, "revoked access token")
  236. }
  237. // @Summary Authenticate a user to retrieve an authorization token
  238. // @Router /api/users/adm/authenticate [post]
  239. // @Tags Auth
  240. // @Accept json
  241. // @Param body body models.UserAuthParams true "Authentication parameters"
  242. // @Success 200 {object} models.SuccessResponse
  243. // @Failure 400 {object} models.ErrorResponse
  244. // @Failure 401 {object} models.ErrorResponse
  245. // @Failure 500 {object} models.ErrorResponse
  246. func authenticateUser(response http.ResponseWriter, request *http.Request) {
  247. appName := request.Header.Get("X-Application-Name")
  248. if appName == "" {
  249. appName = logic.NetmakerDesktopApp
  250. }
  251. // Auth request consists of Mac Address and Password (from node that is authorizing
  252. // in case of Master, auth is ignored and mac is set to "mastermac"
  253. var authRequest models.UserAuthParams
  254. var errorResponse = models.ErrorResponse{
  255. Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
  256. }
  257. decoder := json.NewDecoder(request.Body)
  258. decoderErr := decoder.Decode(&authRequest)
  259. defer request.Body.Close()
  260. if decoderErr != nil {
  261. logger.Log(0, "error decoding request body: ",
  262. decoderErr.Error())
  263. logic.ReturnErrorResponse(response, request, errorResponse)
  264. return
  265. }
  266. user, err := logic.GetUser(authRequest.UserName)
  267. if err != nil {
  268. logger.Log(0, authRequest.UserName, "user validation failed: ",
  269. err.Error())
  270. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "unauthorized"))
  271. return
  272. }
  273. if logic.IsOauthUser(user) == nil {
  274. logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("user is registered via SSO"), "badrequest"))
  275. return
  276. }
  277. if user.AccountDisabled {
  278. err = errors.New("user account disabled")
  279. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "unauthorized"))
  280. return
  281. }
  282. if user.PlatformRoleID != models.SuperAdminRole && !logic.IsBasicAuthEnabled() {
  283. logic.ReturnErrorResponse(
  284. response,
  285. request,
  286. logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"),
  287. )
  288. return
  289. }
  290. if val := request.Header.Get("From-Ui"); val == "true" {
  291. // request came from UI, if normal user block Login
  292. role, err := logic.GetRole(user.PlatformRoleID)
  293. if err != nil {
  294. logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("access denied to dashboard"), "unauthorized"))
  295. return
  296. }
  297. if role.DenyDashboardAccess {
  298. logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("access denied to dashboard"), "unauthorized"))
  299. return
  300. }
  301. }
  302. username := authRequest.UserName
  303. jwt, err := logic.VerifyAuthRequest(authRequest, appName)
  304. if err != nil {
  305. logger.Log(0, username, "user validation failed: ",
  306. err.Error())
  307. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "badrequest"))
  308. return
  309. }
  310. if jwt == "" {
  311. // very unlikely that err is !nil and no jwt returned, but handle it anyways.
  312. logger.Log(0, username, "jwt token is empty")
  313. logic.ReturnErrorResponse(
  314. response,
  315. request,
  316. logic.FormatError(errors.New("no token returned"), "internal"),
  317. )
  318. return
  319. }
  320. var successResponse models.SuccessResponse
  321. if user.IsMFAEnabled {
  322. successResponse = models.SuccessResponse{
  323. Code: http.StatusOK,
  324. Message: "W1R3: TOTP required",
  325. Response: models.PartialUserLoginResponse{
  326. UserName: username,
  327. PreAuthToken: jwt,
  328. },
  329. }
  330. } else {
  331. successResponse = models.SuccessResponse{
  332. Code: http.StatusOK,
  333. Message: "W1R3: Device " + username + " Authorized",
  334. Response: models.SuccessfulUserLoginResponse{
  335. UserName: username,
  336. AuthToken: jwt,
  337. },
  338. }
  339. }
  340. // Send back the JWT
  341. successJSONResponse, jsonError := json.Marshal(successResponse)
  342. if jsonError != nil {
  343. logger.Log(0, username,
  344. "error marshalling resp: ", jsonError.Error())
  345. logic.ReturnErrorResponse(response, request, errorResponse)
  346. return
  347. }
  348. logger.Log(2, username, "was authenticated")
  349. // log user activity
  350. if !user.IsMFAEnabled {
  351. if val := request.Header.Get("From-Ui"); val == "true" {
  352. logic.LogEvent(&models.Event{
  353. Action: models.Login,
  354. Source: models.Subject{
  355. ID: user.UserName,
  356. Name: user.UserName,
  357. Type: models.UserSub,
  358. },
  359. TriggeredBy: user.UserName,
  360. Target: models.Subject{
  361. ID: models.DashboardSub.String(),
  362. Name: models.DashboardSub.String(),
  363. Type: models.DashboardSub,
  364. },
  365. Origin: models.Dashboard,
  366. })
  367. } else {
  368. logic.LogEvent(&models.Event{
  369. Action: models.Login,
  370. Source: models.Subject{
  371. ID: user.UserName,
  372. Name: user.UserName,
  373. Type: models.UserSub,
  374. },
  375. TriggeredBy: user.UserName,
  376. Target: models.Subject{
  377. ID: models.ClientAppSub.String(),
  378. Name: models.ClientAppSub.String(),
  379. Type: models.ClientAppSub,
  380. },
  381. Origin: models.ClientApp,
  382. })
  383. }
  384. }
  385. response.Header().Set("Content-Type", "application/json")
  386. response.Write(successJSONResponse)
  387. go func() {
  388. if servercfg.IsPro {
  389. // enable all associeated clients for the user
  390. clients, err := logic.GetAllExtClients()
  391. if err != nil {
  392. slog.Error("error getting clients: ", "error", err)
  393. return
  394. }
  395. for _, client := range clients {
  396. if client.OwnerID == username && !client.Enabled {
  397. slog.Info(
  398. fmt.Sprintf(
  399. "enabling ext client %s for user %s due to RAC autodisabling feature",
  400. client.ClientID,
  401. client.OwnerID,
  402. ),
  403. )
  404. if newClient, err := logic.ToggleExtClientConnectivity(&client, true); err != nil {
  405. slog.Error(
  406. "error enabling ext client in RAC autodisable hook",
  407. "error",
  408. err,
  409. )
  410. continue // dont return but try for other clients
  411. } else {
  412. // publish peer update to ingress gateway
  413. if ingressNode, err := logic.GetNodeByID(newClient.IngressGatewayID); err == nil {
  414. if err = mq.PublishPeerUpdate(false); err != nil {
  415. slog.Error("error updating ext clients on", "ingress", ingressNode.ID.String(), "err", err.Error())
  416. }
  417. }
  418. }
  419. }
  420. }
  421. }
  422. }()
  423. }
  424. // @Summary Validates a user's identity against it's token. This is used by UI before a user performing a critical operation to validate the user's identity.
  425. // @Router /api/users/{username}/validate-identity [post]
  426. // @Tags Auth
  427. // @Accept json
  428. // @Param body body models.UserIdentityValidationRequest true "User Identity Validation Request"
  429. // @Success 200 {object} models.SuccessResponse
  430. // @Failure 400 {object} models.ErrorResponse
  431. func validateUserIdentity(w http.ResponseWriter, r *http.Request) {
  432. username := r.Header.Get("user")
  433. var req models.UserIdentityValidationRequest
  434. err := json.NewDecoder(r.Body).Decode(&req)
  435. if err != nil {
  436. logger.Log(0, "failed to decode request body: ", err.Error())
  437. err = fmt.Errorf("invalid request body: %v", err)
  438. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  439. return
  440. }
  441. user, err := logic.GetUser(username)
  442. if err != nil {
  443. logger.Log(0, "failed to get user: ", err.Error())
  444. err = fmt.Errorf("user not found: %v", err)
  445. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  446. return
  447. }
  448. var resp models.UserIdentityValidationResponse
  449. err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password))
  450. if err != nil {
  451. logic.ReturnSuccessResponseWithJson(w, r, resp, "user identity validation failed")
  452. } else {
  453. resp.IdentityValidated = true
  454. logic.ReturnSuccessResponseWithJson(w, r, resp, "user identity validated")
  455. }
  456. }
  457. // @Summary Initiate setting up TOTP 2FA for a user.
  458. // @Router /api/users/auth/init-totp [post]
  459. // @Tags Auth
  460. // @Success 200 {object} models.SuccessResponse
  461. // @Failure 400 {object} models.ErrorResponse
  462. // @Failure 500 {object} models.ErrorResponse
  463. func initiateTOTPSetup(w http.ResponseWriter, r *http.Request) {
  464. username := r.Header.Get("user")
  465. user, err := logic.GetUser(username)
  466. if err != nil {
  467. logger.Log(0, "failed to get user: ", err.Error())
  468. err = fmt.Errorf("user not found: %v", err)
  469. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  470. return
  471. }
  472. if user.AuthType == models.OAuth {
  473. err = fmt.Errorf("auth type is %s, cannot process totp setup", user.AuthType)
  474. logger.Log(0, err.Error())
  475. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  476. return
  477. }
  478. key, err := totp.Generate(totp.GenerateOpts{
  479. Issuer: "Netmaker",
  480. AccountName: username,
  481. })
  482. if err != nil {
  483. err = fmt.Errorf("failed to generate totp key: %v", err)
  484. logger.Log(0, err.Error())
  485. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  486. return
  487. }
  488. qrCodeImg, err := key.Image(200, 200)
  489. if err != nil {
  490. err = fmt.Errorf("failed to generate totp key: %v", err)
  491. logger.Log(0, err.Error())
  492. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  493. return
  494. }
  495. var qrCodePng bytes.Buffer
  496. err = png.Encode(&qrCodePng, qrCodeImg)
  497. if err != nil {
  498. err = fmt.Errorf("failed to generate totp key: %v", err)
  499. logger.Log(0, err.Error())
  500. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  501. return
  502. }
  503. qrCode := "data:image/png;base64," + base64.StdEncoding.EncodeToString(qrCodePng.Bytes())
  504. logic.ReturnSuccessResponseWithJson(w, r, models.TOTPInitiateResponse{
  505. OTPAuthURL: key.URL(),
  506. OTPAuthURLSignature: logic.GenerateOTPAuthURLSignature(key.URL()),
  507. QRCode: qrCode,
  508. }, "totp setup initiated")
  509. }
  510. // @Summary Verify and complete setting up TOTP 2FA for a user.
  511. // @Router /api/users/auth/complete-totp [post]
  512. // @Tags Auth
  513. // @Param body body models.UserTOTPVerificationParams true "TOTP verification parameters"
  514. // @Success 200 {object} models.SuccessResponse
  515. // @Failure 400 {object} models.ErrorResponse
  516. // @Failure 500 {object} models.ErrorResponse
  517. func completeTOTPSetup(w http.ResponseWriter, r *http.Request) {
  518. username := r.Header.Get("user")
  519. var req models.UserTOTPVerificationParams
  520. err := json.NewDecoder(r.Body).Decode(&req)
  521. if err != nil {
  522. logger.Log(0, "failed to decode request body: ", err.Error())
  523. err = fmt.Errorf("invalid request body: %v", err)
  524. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  525. return
  526. }
  527. if !logic.VerifyOTPAuthURL(req.OTPAuthURL, req.OTPAuthURLSignature) {
  528. err = fmt.Errorf("otp auth url signature mismatch")
  529. logger.Log(0, err.Error())
  530. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  531. return
  532. }
  533. user, err := logic.GetUser(username)
  534. if err != nil {
  535. logger.Log(0, "failed to get user: ", err.Error())
  536. err = fmt.Errorf("user not found: %v", err)
  537. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  538. return
  539. }
  540. if user.AuthType == models.OAuth {
  541. err = fmt.Errorf("auth type is %s, cannot process totp setup", user.AuthType)
  542. logger.Log(0, err.Error())
  543. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  544. return
  545. }
  546. otpAuthURL, err := otp.NewKeyFromURL(req.OTPAuthURL)
  547. if err != nil {
  548. err = fmt.Errorf("error parsing otp auth url: %v", err)
  549. logger.Log(0, err.Error())
  550. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  551. return
  552. }
  553. totpSecret := otpAuthURL.Secret()
  554. if totp.Validate(req.TOTP, totpSecret) {
  555. user.IsMFAEnabled = true
  556. user.TOTPSecret = totpSecret
  557. err = logic.UpsertUser(*user)
  558. if err != nil {
  559. err = fmt.Errorf("error upserting user: %v", err)
  560. logger.Log(0, err.Error())
  561. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  562. return
  563. }
  564. logic.LogEvent(&models.Event{
  565. Action: models.EnableMFA,
  566. Source: models.Subject{
  567. ID: user.UserName,
  568. Name: user.UserName,
  569. Type: models.UserSub,
  570. },
  571. TriggeredBy: user.UserName,
  572. Target: models.Subject{
  573. ID: user.UserName,
  574. Name: user.UserName,
  575. Type: models.UserSub,
  576. },
  577. Origin: models.Dashboard,
  578. })
  579. logic.ReturnSuccessResponse(w, r, fmt.Sprintf("totp setup complete for user %s", username))
  580. } else {
  581. err = fmt.Errorf("cannot setup totp for user %s: invalid otp", username)
  582. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  583. }
  584. }
  585. // @Summary Verify a user's TOTP token.
  586. // @Router /api/users/auth/verify-totp [post]
  587. // @Tags Auth
  588. // @Accept json
  589. // @Param body body models.UserTOTPVerificationParams true "TOTP verification parameters"
  590. // @Success 200 {object} models.SuccessResponse
  591. // @Failure 400 {object} models.ErrorResponse
  592. // @Failure 401 {object} models.ErrorResponse
  593. // @Failure 500 {object} models.ErrorResponse
  594. func verifyTOTP(w http.ResponseWriter, r *http.Request) {
  595. username := r.Header.Get("user")
  596. appName := r.Header.Get("X-Application-Name")
  597. if appName == "" {
  598. appName = logic.NetmakerDesktopApp
  599. }
  600. var req models.UserTOTPVerificationParams
  601. err := json.NewDecoder(r.Body).Decode(&req)
  602. if err != nil {
  603. logger.Log(0, "failed to decode request body: ", err.Error())
  604. err = fmt.Errorf("invalid request body: %v", err)
  605. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  606. return
  607. }
  608. user, err := logic.GetUser(username)
  609. if err != nil {
  610. logger.Log(0, "failed to get user: ", err.Error())
  611. err = fmt.Errorf("user not found: %v", err)
  612. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  613. return
  614. }
  615. if !user.IsMFAEnabled {
  616. err = fmt.Errorf("mfa is disabled for user(%s), cannot process totp verification", username)
  617. logger.Log(0, err.Error())
  618. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  619. return
  620. }
  621. if totp.Validate(req.TOTP, user.TOTPSecret) {
  622. jwt, err := logic.CreateUserJWT(user.UserName, user.PlatformRoleID, appName)
  623. if err != nil {
  624. err = fmt.Errorf("error creating token: %v", err)
  625. logger.Log(0, err.Error())
  626. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  627. return
  628. }
  629. // update last login time
  630. user.LastLoginTime = time.Now().UTC()
  631. err = logic.UpsertUser(*user)
  632. if err != nil {
  633. err = fmt.Errorf("error upserting user: %v", err)
  634. logger.Log(0, err.Error())
  635. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  636. return
  637. }
  638. logic.LogEvent(&models.Event{
  639. Action: models.Login,
  640. Source: models.Subject{
  641. ID: user.UserName,
  642. Name: user.UserName,
  643. Type: models.UserSub,
  644. },
  645. TriggeredBy: user.UserName,
  646. Target: models.Subject{
  647. ID: models.DashboardSub.String(),
  648. Name: models.DashboardSub.String(),
  649. Type: models.DashboardSub,
  650. },
  651. Origin: models.Dashboard,
  652. })
  653. logic.ReturnSuccessResponseWithJson(w, r, models.SuccessfulUserLoginResponse{
  654. UserName: username,
  655. AuthToken: jwt,
  656. }, "W1R3: User "+username+" Authorized")
  657. } else {
  658. err = fmt.Errorf("invalid otp")
  659. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "unauthorized"))
  660. }
  661. }
  662. // @Summary Check if the server has a super admin
  663. // @Router /api/users/adm/hassuperadmin [get]
  664. // @Tags Users
  665. // @Success 200 {object} bool
  666. // @Failure 500 {object} models.ErrorResponse
  667. func hasSuperAdmin(w http.ResponseWriter, r *http.Request) {
  668. w.Header().Set("Content-Type", "application/json")
  669. hasSuperAdmin, err := logic.HasSuperAdmin()
  670. if err != nil {
  671. logger.Log(0, "failed to check for admin: ", err.Error())
  672. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  673. return
  674. }
  675. json.NewEncoder(w).Encode(hasSuperAdmin)
  676. }
  677. // @Summary Get an individual user
  678. // @Router /api/users/{username} [get]
  679. // @Tags Users
  680. // @Param username path string true "Username of the user to fetch"
  681. // @Success 200 {object} models.User
  682. // @Failure 500 {object} models.ErrorResponse
  683. func getUser(w http.ResponseWriter, r *http.Request) {
  684. // set header.
  685. w.Header().Set("Content-Type", "application/json")
  686. var params = mux.Vars(r)
  687. usernameFetched := params["username"]
  688. user, err := logic.GetReturnUser(usernameFetched)
  689. if err != nil {
  690. logger.Log(0, usernameFetched, "failed to fetch user: ", err.Error())
  691. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  692. return
  693. }
  694. logger.Log(2, r.Header.Get("user"), "fetched user", usernameFetched)
  695. json.NewEncoder(w).Encode(user)
  696. }
  697. // @Summary Enable a user's account
  698. // @Router /api/users/{username}/enable [post]
  699. // @Tags Users
  700. // @Param username path string true "Username of the user to enable"
  701. // @Success 200 {object} models.SuccessResponse
  702. // @Failure 400 {object} models.ErrorResponse
  703. // @Failure 500 {object} models.ErrorResponse
  704. func enableUserAccount(w http.ResponseWriter, r *http.Request) {
  705. username := mux.Vars(r)["username"]
  706. user, err := logic.GetUser(username)
  707. if err != nil {
  708. logger.Log(0, "failed to fetch user: ", err.Error())
  709. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  710. return
  711. }
  712. var caller *models.User
  713. var isMaster bool
  714. if r.Header.Get("user") == logic.MasterUser {
  715. isMaster = true
  716. } else {
  717. caller, err = logic.GetUser(r.Header.Get("user"))
  718. if err != nil {
  719. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  720. return
  721. }
  722. }
  723. if !isMaster && caller.UserName == user.UserName {
  724. // This implies that a user is trying to enable themselves.
  725. // This can never happen, since a disabled user cannot be
  726. // authenticated.
  727. err := fmt.Errorf("cannot enable self")
  728. logger.Log(0, err.Error())
  729. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  730. return
  731. }
  732. switch user.PlatformRoleID {
  733. case models.SuperAdminRole:
  734. // This can never happen, since a superadmin user cannot
  735. // be disabled.
  736. case models.AdminRole:
  737. if !isMaster && caller.PlatformRoleID != models.SuperAdminRole {
  738. err = fmt.Errorf("%s cannot enable an admin", caller.PlatformRoleID)
  739. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  740. return
  741. }
  742. case models.PlatformUser:
  743. if !isMaster && caller.PlatformRoleID != models.SuperAdminRole && caller.PlatformRoleID != models.AdminRole {
  744. err = fmt.Errorf("%s cannot enable a platform-user", caller.PlatformRoleID)
  745. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  746. return
  747. }
  748. case models.ServiceUser:
  749. if !isMaster && caller.PlatformRoleID != models.SuperAdminRole && caller.PlatformRoleID != models.AdminRole {
  750. err = fmt.Errorf("%s cannot enable a service-user", caller.PlatformRoleID)
  751. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  752. return
  753. }
  754. }
  755. user.AccountDisabled = false
  756. err = logic.UpsertUser(*user)
  757. if err != nil {
  758. logger.Log(0, "failed to enable user account: ", err.Error())
  759. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  760. }
  761. logic.ReturnSuccessResponse(w, r, "user account enabled")
  762. }
  763. // @Summary Disable a user's account
  764. // @Router /api/users/{username}/disable [post]
  765. // @Tags Users
  766. // @Param username path string true "Username of the user to disable"
  767. // @Success 200 {object} models.SuccessResponse
  768. // @Failure 400 {object} models.ErrorResponse
  769. // @Failure 500 {object} models.ErrorResponse
  770. func disableUserAccount(w http.ResponseWriter, r *http.Request) {
  771. username := mux.Vars(r)["username"]
  772. user, err := logic.GetUser(username)
  773. if err != nil {
  774. logger.Log(0, "failed to fetch user: ", err.Error())
  775. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  776. return
  777. }
  778. var caller *models.User
  779. var isMaster bool
  780. if r.Header.Get("user") == logic.MasterUser {
  781. isMaster = true
  782. } else {
  783. caller, err = logic.GetUser(r.Header.Get("user"))
  784. if err != nil {
  785. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  786. return
  787. }
  788. }
  789. if !isMaster && caller.UserName == user.UserName {
  790. // This implies that a user is trying to disable themselves.
  791. // This should not be allowed.
  792. err = fmt.Errorf("cannot disable self")
  793. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  794. return
  795. }
  796. switch user.PlatformRoleID {
  797. case models.SuperAdminRole:
  798. err = errors.New("cannot disable a super-admin")
  799. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  800. return
  801. case models.AdminRole:
  802. if !isMaster && caller.PlatformRoleID != models.SuperAdminRole {
  803. err = fmt.Errorf("%s cannot disable an admin", caller.PlatformRoleID)
  804. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  805. return
  806. }
  807. case models.PlatformUser:
  808. if !isMaster && caller.PlatformRoleID != models.SuperAdminRole && caller.PlatformRoleID != models.AdminRole {
  809. err = fmt.Errorf("%s cannot disable a platform-user", caller.PlatformRoleID)
  810. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  811. return
  812. }
  813. case models.ServiceUser:
  814. if !isMaster && caller.PlatformRoleID != models.SuperAdminRole && caller.PlatformRoleID != models.AdminRole {
  815. err = fmt.Errorf("%s cannot disable a service-user", caller.PlatformRoleID)
  816. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  817. return
  818. }
  819. }
  820. user.AccountDisabled = true
  821. err = logic.UpsertUser(*user)
  822. if err != nil {
  823. logger.Log(0, "failed to disable user account: ", err.Error())
  824. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  825. }
  826. go func() {
  827. extclients, err := logic.GetAllExtClients()
  828. if err != nil {
  829. logger.Log(0, "failed to get user extclients:", err.Error())
  830. return
  831. }
  832. for _, extclient := range extclients {
  833. if extclient.OwnerID == user.UserName {
  834. err = logic.DeleteExtClientAndCleanup(extclient)
  835. if err != nil {
  836. logger.Log(0, "failed to delete user extclient:", err.Error())
  837. } else {
  838. err := mq.PublishDeletedClientPeerUpdate(&extclient)
  839. if err != nil {
  840. logger.Log(0, "failed to publish deleted client peer update:", err.Error())
  841. }
  842. }
  843. }
  844. }
  845. }()
  846. logic.ReturnSuccessResponse(w, r, "user account disabled")
  847. }
  848. // @Summary Get a user's preferences and settings
  849. // @Router /api/users/{username}/settings [get]
  850. // @Tags Users
  851. // @Param username path string true "Username of the user"
  852. // @Success 200 {object} models.SuccessResponse
  853. func getUserSettings(w http.ResponseWriter, r *http.Request) {
  854. userID := r.Header.Get("user")
  855. userSettings := logic.GetUserSettings(userID)
  856. logic.ReturnSuccessResponseWithJson(w, r, userSettings, "fetched user settings")
  857. }
  858. // @Summary Update a user's preferences and settings
  859. // @Router /api/users/{username}/settings [put]
  860. // @Tags Users
  861. // @Param username path string true "Username of the user"
  862. // @Success 200 {object} models.SuccessResponse
  863. // @Failure 400 {object} models.ErrorResponse
  864. // @Failure 500 {object} models.ErrorResponse
  865. func updateUserSettings(w http.ResponseWriter, r *http.Request) {
  866. userID := r.Header.Get("user")
  867. var req models.UserSettings
  868. err := json.NewDecoder(r.Body).Decode(&req)
  869. if err != nil {
  870. logger.Log(0, "failed to decode request body: ", err.Error())
  871. err = fmt.Errorf("invalid request body: %v", err)
  872. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  873. return
  874. }
  875. err = logic.UpsertUserSettings(userID, req)
  876. if err != nil {
  877. err = fmt.Errorf("failed to update user settings: %v", err.Error())
  878. logger.Log(0, err.Error())
  879. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  880. return
  881. }
  882. logic.ReturnSuccessResponseWithJson(w, r, req, "updated user settings")
  883. }
  884. // swagger:route GET /api/v1/users user getUserV1
  885. //
  886. // Get an individual user with role info.
  887. //
  888. // Schemes: https
  889. //
  890. // Security:
  891. // oauth
  892. //
  893. // Responses:
  894. // 200: ReturnUserWithRolesAndGroups
  895. func getUserV1(w http.ResponseWriter, r *http.Request) {
  896. // set header.
  897. w.Header().Set("Content-Type", "application/json")
  898. usernameFetched := r.URL.Query().Get("username")
  899. if usernameFetched == "" {
  900. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("username is required"), "badrequest"))
  901. return
  902. }
  903. user, err := logic.GetReturnUser(usernameFetched)
  904. if err != nil {
  905. logger.Log(0, usernameFetched, "failed to fetch user: ", err.Error())
  906. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  907. return
  908. }
  909. user.NumAccessTokens, _ = (&schema.UserAccessToken{
  910. UserName: user.UserName,
  911. }).CountByUser(r.Context())
  912. userRoleTemplate, err := logic.GetRole(user.PlatformRoleID)
  913. if err != nil {
  914. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  915. return
  916. }
  917. resp := models.ReturnUserWithRolesAndGroups{
  918. ReturnUser: user,
  919. PlatformRole: userRoleTemplate,
  920. UserGroups: map[models.UserGroupID]models.UserGroup{},
  921. }
  922. for gId := range user.UserGroups {
  923. grp, err := logic.GetUserGroup(gId)
  924. if err != nil {
  925. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  926. return
  927. }
  928. resp.UserGroups[gId] = grp
  929. }
  930. logger.Log(2, r.Header.Get("user"), "fetched user", usernameFetched)
  931. logic.ReturnSuccessResponseWithJson(w, r, resp, "fetched user with role info")
  932. }
  933. // swagger:route GET /api/users user getUsers
  934. //
  935. // Get all users.
  936. //
  937. // Schemes: https
  938. //
  939. // Security:
  940. // oauth
  941. //
  942. // Responses:
  943. // 200: userBodyResponse
  944. func getUsers(w http.ResponseWriter, r *http.Request) {
  945. // set header.
  946. w.Header().Set("Content-Type", "application/json")
  947. users, err := logic.GetUsers()
  948. if err != nil {
  949. logger.Log(0, "failed to fetch users: ", err.Error())
  950. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  951. return
  952. }
  953. for i := range users {
  954. users[i].NumAccessTokens, _ = (&schema.UserAccessToken{
  955. UserName: users[i].UserName,
  956. }).CountByUser(r.Context())
  957. }
  958. logic.SortUsers(users[:])
  959. logger.Log(2, r.Header.Get("user"), "fetched users")
  960. json.NewEncoder(w).Encode(users)
  961. }
  962. // @Summary Create a super admin
  963. // @Router /api/users/adm/createsuperadmin [post]
  964. // @Tags Users
  965. // @Param body body models.User true "User details"
  966. // @Success 200 {object} models.User
  967. // @Failure 400 {object} models.ErrorResponse
  968. // @Failure 500 {object} models.ErrorResponse
  969. func createSuperAdmin(w http.ResponseWriter, r *http.Request) {
  970. w.Header().Set("Content-Type", "application/json")
  971. var u models.User
  972. err := json.NewDecoder(r.Body).Decode(&u)
  973. if err != nil {
  974. slog.Error("error decoding request body", "error", err.Error())
  975. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  976. return
  977. }
  978. if !logic.IsBasicAuthEnabled() {
  979. logic.ReturnErrorResponse(
  980. w,
  981. r,
  982. logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"),
  983. )
  984. return
  985. }
  986. err = logic.CreateSuperAdmin(&u)
  987. if err != nil {
  988. slog.Error("failed to create admin", "error", err.Error())
  989. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  990. return
  991. }
  992. logger.Log(1, u.UserName, "was made a super admin")
  993. json.NewEncoder(w).Encode(logic.ToReturnUser(u))
  994. }
  995. // @Summary Transfer super admin role to another admin user
  996. // @Router /api/users/adm/transfersuperadmin/{username} [post]
  997. // @Tags Users
  998. // @Param username path string true "Username of the user to transfer super admin role"
  999. // @Success 200 {object} models.User
  1000. // @Failure 403 {object} models.ErrorResponse
  1001. // @Failure 500 {object} models.ErrorResponse
  1002. func transferSuperAdmin(w http.ResponseWriter, r *http.Request) {
  1003. w.Header().Set("Content-Type", "application/json")
  1004. caller, err := logic.GetUser(r.Header.Get("user"))
  1005. if err != nil {
  1006. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1007. }
  1008. if caller.PlatformRoleID != models.SuperAdminRole {
  1009. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("only superadmin can assign the superadmin role to another user"), "forbidden"))
  1010. return
  1011. }
  1012. var params = mux.Vars(r)
  1013. username := params["username"]
  1014. u, err := logic.GetUser(username)
  1015. if err != nil {
  1016. slog.Error("error getting user", "user", u.UserName, "error", err.Error())
  1017. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  1018. return
  1019. }
  1020. if u.PlatformRoleID != models.AdminRole {
  1021. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("only admins can be promoted to superadmin role"), "forbidden"))
  1022. return
  1023. }
  1024. if !logic.IsBasicAuthEnabled() {
  1025. logic.ReturnErrorResponse(
  1026. w,
  1027. r,
  1028. logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"),
  1029. )
  1030. return
  1031. }
  1032. u.IsSuperAdmin = true
  1033. u.PlatformRoleID = models.SuperAdminRole
  1034. err = logic.UpsertUser(*u)
  1035. if err != nil {
  1036. slog.Error("error updating user to superadmin: ", "user", u.UserName, "error", err.Error())
  1037. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1038. return
  1039. }
  1040. caller.IsSuperAdmin = false
  1041. caller.PlatformRoleID = models.AdminRole
  1042. err = logic.UpsertUser(*caller)
  1043. if err != nil {
  1044. slog.Error("error demoting user to admin: ", "user", caller.UserName, "error", err.Error())
  1045. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1046. return
  1047. }
  1048. slog.Info("user was made a super admin", "user", u.UserName)
  1049. json.NewEncoder(w).Encode(logic.ToReturnUser(*u))
  1050. }
  1051. // @Summary Create a user
  1052. // @Router /api/users/{username} [post]
  1053. // @Tags Users
  1054. // @Param username path string true "Username of the user to create"
  1055. // @Param body body models.User true "User details"
  1056. // @Success 200 {object} models.User
  1057. // @Failure 400 {object} models.ErrorResponse
  1058. // @Failure 403 {object} models.ErrorResponse
  1059. // @Failure 500 {object} models.ErrorResponse
  1060. func createUser(w http.ResponseWriter, r *http.Request) {
  1061. w.Header().Set("Content-Type", "application/json")
  1062. caller, err := logic.GetUser(r.Header.Get("user"))
  1063. if err != nil {
  1064. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  1065. return
  1066. }
  1067. var user models.User
  1068. err = json.NewDecoder(r.Body).Decode(&user)
  1069. if err != nil {
  1070. logger.Log(0, user.UserName, "error decoding request body: ",
  1071. err.Error())
  1072. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  1073. return
  1074. }
  1075. if !servercfg.IsPro {
  1076. user.PlatformRoleID = models.AdminRole
  1077. }
  1078. if user.UserName == logic.MasterUser {
  1079. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("username not allowed"), "badrequest"))
  1080. return
  1081. }
  1082. if user.PlatformRoleID == "" {
  1083. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("platform role is missing"), "badrequest"))
  1084. return
  1085. }
  1086. userRole, err := logic.GetRole(user.PlatformRoleID)
  1087. if err != nil {
  1088. err = errors.New("error fetching role " + user.PlatformRoleID.String() + " " + err.Error())
  1089. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  1090. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  1091. return
  1092. }
  1093. if userRole.ID == models.SuperAdminRole {
  1094. err = errors.New("additional superadmins cannot be created")
  1095. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  1096. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  1097. return
  1098. }
  1099. if caller.PlatformRoleID != models.SuperAdminRole && user.PlatformRoleID == models.AdminRole {
  1100. err = errors.New("only superadmin can create admin users")
  1101. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  1102. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  1103. return
  1104. }
  1105. if !servercfg.IsPro && user.PlatformRoleID != models.AdminRole {
  1106. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("non-admins users can only be created on Pro version"), "forbidden"))
  1107. return
  1108. }
  1109. err = logic.CreateUser(&user)
  1110. if err != nil {
  1111. slog.Error("error creating new user: ", "user", user.UserName, "error", err.Error())
  1112. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  1113. return
  1114. }
  1115. logic.LogEvent(&models.Event{
  1116. Action: models.Create,
  1117. Source: models.Subject{
  1118. ID: caller.UserName,
  1119. Name: caller.UserName,
  1120. Type: models.UserSub,
  1121. },
  1122. TriggeredBy: caller.UserName,
  1123. Target: models.Subject{
  1124. ID: user.UserName,
  1125. Name: user.UserName,
  1126. Type: models.UserSub,
  1127. Info: user,
  1128. },
  1129. Origin: models.Dashboard,
  1130. })
  1131. logic.DeleteUserInvite(user.UserName)
  1132. logic.DeletePendingUser(user.UserName)
  1133. go mq.PublishPeerUpdate(false)
  1134. slog.Info("user was created", "username", user.UserName)
  1135. json.NewEncoder(w).Encode(logic.ToReturnUser(user))
  1136. }
  1137. // @Summary Update a user
  1138. // @Router /api/users/{username} [put]
  1139. // @Tags Users
  1140. // @Param username path string true "Username of the user to update"
  1141. // @Param body body models.User true "User details"
  1142. // @Success 200 {object} models.User
  1143. // @Failure 400 {object} models.ErrorResponse
  1144. // @Failure 403 {object} models.ErrorResponse
  1145. // @Failure 500 {object} models.ErrorResponse
  1146. func updateUser(w http.ResponseWriter, r *http.Request) {
  1147. w.Header().Set("Content-Type", "application/json")
  1148. var params = mux.Vars(r)
  1149. // start here
  1150. var caller *models.User
  1151. var err error
  1152. var ismaster bool
  1153. if r.Header.Get("user") == logic.MasterUser {
  1154. ismaster = true
  1155. } else {
  1156. caller, err = logic.GetUser(r.Header.Get("user"))
  1157. if err != nil {
  1158. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1159. }
  1160. }
  1161. username := params["username"]
  1162. user, err := logic.GetUser(username)
  1163. if err != nil {
  1164. logger.Log(0, username,
  1165. "failed to update user info: ", err.Error())
  1166. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1167. return
  1168. }
  1169. var userchange models.User
  1170. // we decode our body request params
  1171. err = json.NewDecoder(r.Body).Decode(&userchange)
  1172. if err != nil {
  1173. slog.Error("failed to decode body", "error ", err.Error())
  1174. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  1175. return
  1176. }
  1177. if user.UserName != userchange.UserName {
  1178. logic.ReturnErrorResponse(
  1179. w,
  1180. r,
  1181. logic.FormatError(
  1182. errors.New("user in param and request body not matching"),
  1183. "badrequest",
  1184. ),
  1185. )
  1186. return
  1187. }
  1188. selfUpdate := false
  1189. if !ismaster && caller.UserName == user.UserName {
  1190. selfUpdate = true
  1191. }
  1192. if !ismaster && !selfUpdate {
  1193. if caller.PlatformRoleID == models.AdminRole && user.PlatformRoleID == models.SuperAdminRole {
  1194. slog.Error("non-superadmin user", "caller", caller.UserName, "attempted to update superadmin user", username)
  1195. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("cannot update superadmin user"), "forbidden"))
  1196. return
  1197. }
  1198. if caller.PlatformRoleID != models.AdminRole && caller.PlatformRoleID != models.SuperAdminRole {
  1199. slog.Error("operation not allowed", "caller", caller.UserName, "attempted to update user", username)
  1200. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("cannot update superadmin user"), "forbidden"))
  1201. return
  1202. }
  1203. if caller.PlatformRoleID == models.AdminRole && user.PlatformRoleID == models.AdminRole {
  1204. slog.Error("an admin user does not have permissions to update another admin user", "caller", caller.UserName, "attempted to update admin user", username)
  1205. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("an admin user does not have permissions to update another admin user"), "forbidden"))
  1206. return
  1207. }
  1208. if caller.PlatformRoleID == models.AdminRole && userchange.PlatformRoleID == models.AdminRole {
  1209. err = errors.New("an admin user does not have permissions to assign the admin role to another user")
  1210. slog.Error(
  1211. "failed to update user",
  1212. "caller",
  1213. caller.UserName,
  1214. "attempted to update user",
  1215. username,
  1216. "error",
  1217. err,
  1218. )
  1219. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  1220. return
  1221. }
  1222. }
  1223. if !ismaster && selfUpdate {
  1224. if user.PlatformRoleID != userchange.PlatformRoleID {
  1225. slog.Error("user cannot change his own role", "caller", caller.UserName, "attempted to update user role", username)
  1226. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("user not allowed to self assign role"), "forbidden"))
  1227. return
  1228. }
  1229. if logic.IsMFAEnforced() && user.IsMFAEnabled && !userchange.IsMFAEnabled {
  1230. err = errors.New("mfa is enforced, user cannot unset their own mfa")
  1231. slog.Error("failed to update user", "caller", caller.UserName, "attempted to update user", username, "error", err)
  1232. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  1233. return
  1234. }
  1235. if servercfg.IsPro {
  1236. // user cannot update his own roles and groups
  1237. if len(user.NetworkRoles) != len(userchange.NetworkRoles) || !reflect.DeepEqual(user.NetworkRoles, userchange.NetworkRoles) {
  1238. err = errors.New("user cannot update self update their network roles")
  1239. slog.Error("failed to update user", "caller", caller.UserName, "attempted to update user", username, "error", err)
  1240. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  1241. return
  1242. }
  1243. // user cannot update his own roles and groups
  1244. if len(user.UserGroups) != len(userchange.UserGroups) || !reflect.DeepEqual(user.UserGroups, userchange.UserGroups) {
  1245. err = errors.New("user cannot update self update their groups")
  1246. slog.Error("failed to update user", "caller", caller.UserName, "attempted to update user", username, "error", err)
  1247. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  1248. return
  1249. }
  1250. }
  1251. }
  1252. if ismaster {
  1253. if user.PlatformRoleID != models.SuperAdminRole && userchange.PlatformRoleID == models.SuperAdminRole {
  1254. slog.Error("operation not allowed", "caller", logic.MasterUser, "attempted to update user role to superadmin", username)
  1255. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("attempted to update user role to superadmin"), "forbidden"))
  1256. return
  1257. }
  1258. }
  1259. if logic.IsOauthUser(user) == nil && userchange.Password != "" {
  1260. err := fmt.Errorf("cannot update user's password for an oauth user %s", username)
  1261. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  1262. return
  1263. }
  1264. logic.AddGlobalNetRolesToAdmins(&userchange)
  1265. if userchange.PlatformRoleID != user.PlatformRoleID || !logic.CompareMaps(user.UserGroups, userchange.UserGroups) {
  1266. (&schema.UserAccessToken{UserName: user.UserName}).DeleteAllUserTokens(r.Context())
  1267. }
  1268. oldUser := *user
  1269. if ismaster {
  1270. caller = &models.User{
  1271. UserName: logic.MasterUser,
  1272. }
  1273. }
  1274. action := models.Update
  1275. // TODO: here we are relying on the dashboard to only
  1276. // make singular updates, but it's possible that the
  1277. // API can be called to make multiple changes to the
  1278. // user. We should update it to log multiple events
  1279. // or create singular update APIs.
  1280. if userchange.IsMFAEnabled != user.IsMFAEnabled {
  1281. if userchange.IsMFAEnabled {
  1282. // the update API won't be used to enable MFA.
  1283. action = models.EnableMFA
  1284. } else {
  1285. action = models.DisableMFA
  1286. }
  1287. }
  1288. e := models.Event{
  1289. Action: action,
  1290. Source: models.Subject{
  1291. ID: caller.UserName,
  1292. Name: caller.UserName,
  1293. Type: models.UserSub,
  1294. },
  1295. TriggeredBy: caller.UserName,
  1296. Target: models.Subject{
  1297. ID: user.UserName,
  1298. Name: user.UserName,
  1299. Type: models.UserSub,
  1300. },
  1301. Diff: models.Diff{
  1302. Old: oldUser,
  1303. New: userchange,
  1304. },
  1305. Origin: models.Dashboard,
  1306. }
  1307. user, err = logic.UpdateUser(&userchange, user)
  1308. if err != nil {
  1309. logger.Log(0, username,
  1310. "failed to update user info: ", err.Error())
  1311. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  1312. return
  1313. }
  1314. logic.LogEvent(&e)
  1315. go mq.PublishPeerUpdate(false)
  1316. go func() {
  1317. // Populating all the networks the user has access to by
  1318. // being a member of groups.
  1319. userMembershipNetworkAccess := make(map[models.NetworkID]struct{})
  1320. for groupID := range user.UserGroups {
  1321. userGroup, _ := logic.GetUserGroup(groupID)
  1322. for netID := range userGroup.NetworkRoles {
  1323. userMembershipNetworkAccess[netID] = struct{}{}
  1324. }
  1325. }
  1326. extclients, err := logic.GetAllExtClients()
  1327. if err != nil {
  1328. slog.Error("failed to fetch extclients", "error", err)
  1329. return
  1330. }
  1331. for _, extclient := range extclients {
  1332. if extclient.OwnerID != user.UserName {
  1333. continue
  1334. }
  1335. var shouldDelete bool
  1336. if user.PlatformRoleID == models.SuperAdminRole || user.PlatformRoleID == models.AdminRole {
  1337. // Super-admin and Admin's access is not determined by group membership
  1338. // or network roles. Even if a user is removed from the group, they
  1339. // continue to have access to the network.
  1340. // So, no need to delete the extclient.
  1341. shouldDelete = false
  1342. } else {
  1343. _, hasAccess := user.NetworkRoles[models.NetworkID(extclient.Network)]
  1344. if hasAccess {
  1345. // The user has access to the network by themselves and not by
  1346. // virtue of being a member of the group.
  1347. // So, no need to delete the extclient.
  1348. shouldDelete = false
  1349. } else {
  1350. _, hasAccessThroughGroups := userMembershipNetworkAccess[models.NetworkID(extclient.Network)]
  1351. if !hasAccessThroughGroups {
  1352. // The user does not have access to the network by either
  1353. // being a Super-admin or Admin, by network roles or by virtue
  1354. // of being a member a group that has access to the network.
  1355. // So, delete the extclient.
  1356. shouldDelete = true
  1357. }
  1358. }
  1359. }
  1360. if shouldDelete {
  1361. err = logic.DeleteExtClientAndCleanup(extclient)
  1362. if err != nil {
  1363. slog.Error("failed to delete extclient",
  1364. "id", extclient.ClientID, "owner", user.UserName, "error", err)
  1365. } else {
  1366. if err := mq.PublishDeletedClientPeerUpdate(&extclient); err != nil {
  1367. slog.Error("error setting ext peers: " + err.Error())
  1368. }
  1369. }
  1370. }
  1371. }
  1372. }()
  1373. logger.Log(1, username, "was updated")
  1374. json.NewEncoder(w).Encode(logic.ToReturnUser(*user))
  1375. }
  1376. // @Summary Delete a user
  1377. // @Router /api/users/{username} [delete]
  1378. // @Tags Users
  1379. // @Param username path string true "Username of the user to delete"
  1380. // @Success 200 {string} string
  1381. // @Failure 500 {object} models.ErrorResponse
  1382. func deleteUser(w http.ResponseWriter, r *http.Request) {
  1383. // Set header
  1384. w.Header().Set("Content-Type", "application/json")
  1385. // get params
  1386. var params = mux.Vars(r)
  1387. caller, err := logic.GetUser(r.Header.Get("user"))
  1388. if err != nil {
  1389. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1390. }
  1391. callerUserRole, err := logic.GetRole(caller.PlatformRoleID)
  1392. if err != nil {
  1393. slog.Error("failed to get role ", "role", callerUserRole.ID, "error", err)
  1394. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1395. return
  1396. }
  1397. username := params["username"]
  1398. user, err := logic.GetUser(username)
  1399. if err != nil {
  1400. logger.Log(0, username,
  1401. "failed to update user info: ", err.Error())
  1402. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1403. return
  1404. }
  1405. userRole, err := logic.GetRole(user.PlatformRoleID)
  1406. if err != nil {
  1407. slog.Error("failed to get role ", "role", userRole.ID, "error", err)
  1408. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1409. return
  1410. }
  1411. if userRole.ID == models.SuperAdminRole {
  1412. slog.Error(
  1413. "failed to delete user: ", "user", username, "error", "superadmin cannot be deleted")
  1414. logic.ReturnErrorResponse(
  1415. w,
  1416. r,
  1417. logic.FormatError(fmt.Errorf("superadmin cannot be deleted"), "internal"),
  1418. )
  1419. return
  1420. }
  1421. if callerUserRole.ID != models.SuperAdminRole {
  1422. if callerUserRole.ID == models.AdminRole && userRole.ID == models.AdminRole {
  1423. slog.Error(
  1424. "failed to delete user: ",
  1425. "user",
  1426. username,
  1427. "error",
  1428. "admin cannot delete another admin user, including oneself",
  1429. )
  1430. logic.ReturnErrorResponse(
  1431. w,
  1432. r,
  1433. logic.FormatError(
  1434. fmt.Errorf("admin cannot delete another admin user, including oneself"),
  1435. "internal",
  1436. ),
  1437. )
  1438. return
  1439. }
  1440. }
  1441. if user.AuthType == models.OAuth || user.ExternalIdentityProviderID != "" {
  1442. err = fmt.Errorf("cannot delete idp user %s", username)
  1443. logger.Log(0, username, "failed to delete user: ", err.Error())
  1444. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  1445. return
  1446. }
  1447. err = logic.DeleteUser(username)
  1448. if err != nil {
  1449. logger.Log(0, username,
  1450. "failed to delete user: ", err.Error())
  1451. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  1452. return
  1453. }
  1454. logic.LogEvent(&models.Event{
  1455. Action: models.Delete,
  1456. Source: models.Subject{
  1457. ID: caller.UserName,
  1458. Name: caller.UserName,
  1459. Type: models.UserSub,
  1460. },
  1461. TriggeredBy: caller.UserName,
  1462. Target: models.Subject{
  1463. ID: user.UserName,
  1464. Name: user.UserName,
  1465. Type: models.UserSub,
  1466. },
  1467. Origin: models.Dashboard,
  1468. })
  1469. // check and delete extclient with this ownerID
  1470. go func() {
  1471. extclients, err := logic.GetAllExtClients()
  1472. if err != nil {
  1473. slog.Error("failed to get extclients", "error", err)
  1474. return
  1475. }
  1476. for _, extclient := range extclients {
  1477. if extclient.OwnerID == user.UserName {
  1478. err = logic.DeleteExtClientAndCleanup(extclient)
  1479. if err != nil {
  1480. slog.Error("failed to delete extclient",
  1481. "id", extclient.ClientID, "owner", username, "error", err)
  1482. } else {
  1483. if err := mq.PublishDeletedClientPeerUpdate(&extclient); err != nil {
  1484. slog.Error("error setting ext peers: " + err.Error())
  1485. }
  1486. }
  1487. }
  1488. }
  1489. _ = logic.DeleteUserInvite(user.UserName)
  1490. mq.PublishPeerUpdate(false)
  1491. if servercfg.IsDNSMode() {
  1492. logic.SetDNS()
  1493. }
  1494. }()
  1495. logger.Log(1, username, "was deleted")
  1496. json.NewEncoder(w).Encode(params["username"] + " deleted.")
  1497. }
  1498. // Called when vpn client dials in to start the auth flow and first stage is to get register URL itself
  1499. func socketHandler(w http.ResponseWriter, r *http.Request) {
  1500. // Upgrade our raw HTTP connection to a websocket based one
  1501. conn, err := upgrader.Upgrade(w, r, nil)
  1502. if err != nil {
  1503. logger.Log(0, "error during connection upgrade for node sign-in:", err.Error())
  1504. return
  1505. }
  1506. if conn == nil {
  1507. logger.Log(0, "failed to establish web-socket connection during node sign-in")
  1508. return
  1509. }
  1510. // Start handling the session
  1511. go auth.SessionHandler(conn)
  1512. }
  1513. // @Summary lists all user roles.
  1514. // @Router /api/v1/user/roles [get]
  1515. // @Tags Users
  1516. // @Param role_id query string true "roleid required to get the role details"
  1517. // @Success 200 {object} []models.UserRolePermissionTemplate
  1518. // @Failure 500 {object} models.ErrorResponse
  1519. func listRoles(w http.ResponseWriter, r *http.Request) {
  1520. var roles []models.UserRolePermissionTemplate
  1521. var err error
  1522. roles, err = logic.ListPlatformRoles()
  1523. if err != nil {
  1524. logic.ReturnErrorResponse(w, r, models.ErrorResponse{
  1525. Code: http.StatusInternalServerError,
  1526. Message: err.Error(),
  1527. })
  1528. return
  1529. }
  1530. logic.ReturnSuccessResponseWithJson(w, r, roles, "successfully fetched user roles permission templates")
  1531. }
  1532. // swagger:route POST /api/v1/user/logout user logout
  1533. //
  1534. // LogOut user.
  1535. //
  1536. // Schemes: https
  1537. //
  1538. // Security:
  1539. // oauth
  1540. //
  1541. // Responses:
  1542. // 200: userBodyResponse
  1543. func logout(w http.ResponseWriter, r *http.Request) {
  1544. // set header.
  1545. w.Header().Set("Content-Type", "application/json")
  1546. userName := r.URL.Query().Get("username")
  1547. user, err := logic.GetUser(userName)
  1548. if err != nil {
  1549. logic.ReturnErrorResponse(w, r, logic.FormatError(err, logic.BadReq))
  1550. return
  1551. }
  1552. var target models.SubjectType
  1553. if val := r.Header.Get("From-Ui"); val == "true" {
  1554. target = models.DashboardSub
  1555. } else {
  1556. target = models.ClientAppSub
  1557. }
  1558. if target != "" {
  1559. logic.LogEvent(&models.Event{
  1560. Action: models.LogOut,
  1561. Source: models.Subject{
  1562. ID: user.UserName,
  1563. Name: user.UserName,
  1564. Type: models.UserSub,
  1565. },
  1566. TriggeredBy: user.UserName,
  1567. Target: models.Subject{
  1568. ID: target.String(),
  1569. Name: target.String(),
  1570. Type: target,
  1571. },
  1572. Origin: models.Origin(target),
  1573. })
  1574. }
  1575. logic.ReturnSuccessResponse(w, r, "user logged out")
  1576. }