user.go 57 KB

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