user.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. package controller
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net/http"
  7. "github.com/gorilla/mux"
  8. "github.com/gorilla/websocket"
  9. "github.com/gravitl/netmaker/auth"
  10. "github.com/gravitl/netmaker/logger"
  11. "github.com/gravitl/netmaker/logic"
  12. "github.com/gravitl/netmaker/models"
  13. "github.com/gravitl/netmaker/mq"
  14. "github.com/gravitl/netmaker/servercfg"
  15. "golang.org/x/exp/slog"
  16. )
  17. var (
  18. upgrader = websocket.Upgrader{}
  19. )
  20. func userHandlers(r *mux.Router) {
  21. r.HandleFunc("/api/users/adm/hassuperadmin", hasSuperAdmin).Methods(http.MethodGet)
  22. r.HandleFunc("/api/users/adm/createsuperadmin", createSuperAdmin).Methods(http.MethodPost)
  23. r.HandleFunc("/api/users/adm/transfersuperadmin/{username}", logic.SecurityCheck(true, http.HandlerFunc(transferSuperAdmin))).Methods(http.MethodPost)
  24. r.HandleFunc("/api/users/adm/authenticate", authenticateUser).Methods(http.MethodPost)
  25. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, http.HandlerFunc(updateUser))).Methods(http.MethodPut)
  26. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, checkFreeTierLimits(limitChoiceUsers, http.HandlerFunc(createUser)))).Methods(http.MethodPost)
  27. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(true, http.HandlerFunc(deleteUser))).Methods(http.MethodDelete)
  28. r.HandleFunc("/api/users/{username}", logic.SecurityCheck(false, logic.ContinueIfUserMatch(http.HandlerFunc(getUser)))).Methods(http.MethodGet)
  29. r.HandleFunc("/api/users", logic.SecurityCheck(true, http.HandlerFunc(getUsers))).Methods(http.MethodGet)
  30. r.HandleFunc("/api/oauth/login", auth.HandleAuthLogin).Methods(http.MethodGet)
  31. r.HandleFunc("/api/oauth/callback", auth.HandleAuthCallback).Methods(http.MethodGet)
  32. r.HandleFunc("/api/oauth/headless", auth.HandleHeadlessSSO)
  33. r.HandleFunc("/api/oauth/register/{regKey}", auth.RegisterHostSSO).Methods(http.MethodGet)
  34. }
  35. // swagger:route POST /api/users/adm/authenticate authenticate authenticateUser
  36. //
  37. // User authenticates using its password and retrieves a JWT for authorization.
  38. //
  39. // Schemes: https
  40. //
  41. // Security:
  42. // oauth
  43. //
  44. // Responses:
  45. // 200: successResponse
  46. func authenticateUser(response http.ResponseWriter, request *http.Request) {
  47. // Auth request consists of Mac Address and Password (from node that is authorizing
  48. // in case of Master, auth is ignored and mac is set to "mastermac"
  49. var authRequest models.UserAuthParams
  50. var errorResponse = models.ErrorResponse{
  51. Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
  52. }
  53. if !servercfg.IsBasicAuthEnabled() {
  54. logic.ReturnErrorResponse(response, request, logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"))
  55. return
  56. }
  57. decoder := json.NewDecoder(request.Body)
  58. decoderErr := decoder.Decode(&authRequest)
  59. defer request.Body.Close()
  60. if decoderErr != nil {
  61. logger.Log(0, "error decoding request body: ",
  62. decoderErr.Error())
  63. logic.ReturnErrorResponse(response, request, errorResponse)
  64. return
  65. }
  66. if val := request.Header.Get("From-Ui"); val == "true" {
  67. // request came from UI, if normal user block Login
  68. user, err := logic.GetUser(authRequest.UserName)
  69. if err != nil {
  70. logger.Log(0, authRequest.UserName, "user validation failed: ",
  71. err.Error())
  72. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "unauthorized"))
  73. return
  74. }
  75. if !(user.IsAdmin || user.IsSuperAdmin) {
  76. logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("only admins can access dashboard"), "unauthorized"))
  77. return
  78. }
  79. }
  80. username := authRequest.UserName
  81. jwt, err := logic.VerifyAuthRequest(authRequest)
  82. if err != nil {
  83. logger.Log(0, username, "user validation failed: ",
  84. err.Error())
  85. logic.ReturnErrorResponse(response, request, logic.FormatError(err, "badrequest"))
  86. return
  87. }
  88. if jwt == "" {
  89. // very unlikely that err is !nil and no jwt returned, but handle it anyways.
  90. logger.Log(0, username, "jwt token is empty")
  91. logic.ReturnErrorResponse(response, request, logic.FormatError(errors.New("no token returned"), "internal"))
  92. return
  93. }
  94. var successResponse = models.SuccessResponse{
  95. Code: http.StatusOK,
  96. Message: "W1R3: Device " + username + " Authorized",
  97. Response: models.SuccessfulUserLoginResponse{
  98. AuthToken: jwt,
  99. UserName: username,
  100. },
  101. }
  102. // Send back the JWT
  103. successJSONResponse, jsonError := json.Marshal(successResponse)
  104. if jsonError != nil {
  105. logger.Log(0, username,
  106. "error marshalling resp: ", err.Error())
  107. logic.ReturnErrorResponse(response, request, errorResponse)
  108. return
  109. }
  110. logger.Log(2, username, "was authenticated")
  111. response.Header().Set("Content-Type", "application/json")
  112. response.Write(successJSONResponse)
  113. go func() {
  114. if servercfg.IsPro && servercfg.GetRacAutoDisable() {
  115. // enable all associeated clients for the user
  116. clients, err := logic.GetAllExtClients()
  117. if err != nil {
  118. slog.Error("error getting clients: ", "error", err)
  119. return
  120. }
  121. for _, client := range clients {
  122. if client.OwnerID == username && !client.Enabled {
  123. slog.Info(fmt.Sprintf("enabling ext client %s for user %s due to RAC autodisabling feature", client.ClientID, client.OwnerID))
  124. if newClient, err := logic.ToggleExtClientConnectivity(&client, true); err != nil {
  125. slog.Error("error enabling ext client in RAC autodisable hook", "error", err)
  126. continue // dont return but try for other clients
  127. } else {
  128. // publish peer update to ingress gateway
  129. if ingressNode, err := logic.GetNodeByID(newClient.IngressGatewayID); err == nil {
  130. if err = mq.PublishPeerUpdate(false); err != nil {
  131. slog.Error("error updating ext clients on", "ingress", ingressNode.ID.String(), "err", err.Error())
  132. }
  133. }
  134. }
  135. }
  136. }
  137. }
  138. }()
  139. }
  140. // swagger:route GET /api/users/adm/hassuperadmin user hasSuperAdmin
  141. //
  142. // Checks whether the server has an admin.
  143. //
  144. // Schemes: https
  145. //
  146. // Security:
  147. // oauth
  148. //
  149. // Responses:
  150. // 200: hasAdmin
  151. func hasSuperAdmin(w http.ResponseWriter, r *http.Request) {
  152. w.Header().Set("Content-Type", "application/json")
  153. hasSuperAdmin, err := logic.HasSuperAdmin()
  154. if err != nil {
  155. logger.Log(0, "failed to check for admin: ", err.Error())
  156. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  157. return
  158. }
  159. json.NewEncoder(w).Encode(hasSuperAdmin)
  160. }
  161. // swagger:route GET /api/users/{username} user getUser
  162. //
  163. // Get an individual user.
  164. //
  165. // Schemes: https
  166. //
  167. // Security:
  168. // oauth
  169. //
  170. // Responses:
  171. // 200: userBodyResponse
  172. func getUser(w http.ResponseWriter, r *http.Request) {
  173. // set header.
  174. w.Header().Set("Content-Type", "application/json")
  175. var params = mux.Vars(r)
  176. usernameFetched := params["username"]
  177. user, err := logic.GetReturnUser(usernameFetched)
  178. if err != nil {
  179. logger.Log(0, usernameFetched, "failed to fetch user: ", err.Error())
  180. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  181. return
  182. }
  183. logger.Log(2, r.Header.Get("user"), "fetched user", usernameFetched)
  184. json.NewEncoder(w).Encode(user)
  185. }
  186. // swagger:route GET /api/users user getUsers
  187. //
  188. // Get all users.
  189. //
  190. // Schemes: https
  191. //
  192. // Security:
  193. // oauth
  194. //
  195. // Responses:
  196. // 200: userBodyResponse
  197. func getUsers(w http.ResponseWriter, r *http.Request) {
  198. // set header.
  199. w.Header().Set("Content-Type", "application/json")
  200. users, err := logic.GetUsers()
  201. if err != nil {
  202. logger.Log(0, "failed to fetch users: ", err.Error())
  203. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  204. return
  205. }
  206. logic.SortUsers(users[:])
  207. logger.Log(2, r.Header.Get("user"), "fetched users")
  208. json.NewEncoder(w).Encode(users)
  209. }
  210. // swagger:route POST /api/users/adm/createsuperadmin user createAdmin
  211. //
  212. // Make a user an admin.
  213. //
  214. // Schemes: https
  215. //
  216. // Security:
  217. // oauth
  218. //
  219. // Responses:
  220. // 200: userBodyResponse
  221. func createSuperAdmin(w http.ResponseWriter, r *http.Request) {
  222. w.Header().Set("Content-Type", "application/json")
  223. var u models.User
  224. err := json.NewDecoder(r.Body).Decode(&u)
  225. if err != nil {
  226. slog.Error("error decoding request body", "error", err.Error())
  227. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  228. return
  229. }
  230. if !servercfg.IsBasicAuthEnabled() {
  231. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"))
  232. return
  233. }
  234. err = logic.CreateSuperAdmin(&u)
  235. if err != nil {
  236. slog.Error("failed to create admin", "error", err.Error())
  237. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  238. return
  239. }
  240. logger.Log(1, u.UserName, "was made a super admin")
  241. json.NewEncoder(w).Encode(logic.ToReturnUser(u))
  242. }
  243. // swagger:route POST /api/users/adm/transfersuperadmin user transferSuperAdmin
  244. //
  245. // Transfers superadmin role to an admin user.
  246. //
  247. // Schemes: https
  248. //
  249. // Security:
  250. // oauth
  251. //
  252. // Responses:
  253. // 200: userBodyResponse
  254. func transferSuperAdmin(w http.ResponseWriter, r *http.Request) {
  255. w.Header().Set("Content-Type", "application/json")
  256. caller, err := logic.GetUser(r.Header.Get("user"))
  257. if err != nil {
  258. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  259. }
  260. if !caller.IsSuperAdmin {
  261. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("only superadmin can assign the superadmin role to another user"), "forbidden"))
  262. return
  263. }
  264. var params = mux.Vars(r)
  265. username := params["username"]
  266. u, err := logic.GetUser(username)
  267. if err != nil {
  268. slog.Error("error getting user", "user", u.UserName, "error", err.Error())
  269. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  270. return
  271. }
  272. if !u.IsAdmin {
  273. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("only admins can be promoted to superadmin role"), "forbidden"))
  274. return
  275. }
  276. if !servercfg.IsBasicAuthEnabled() {
  277. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("basic auth is disabled"), "badrequest"))
  278. return
  279. }
  280. u.IsSuperAdmin = true
  281. u.IsAdmin = false
  282. err = logic.UpsertUser(*u)
  283. if err != nil {
  284. slog.Error("error updating user to superadmin: ", "user", u.UserName, "error", err.Error())
  285. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  286. return
  287. }
  288. caller.IsSuperAdmin = false
  289. caller.IsAdmin = true
  290. err = logic.UpsertUser(*caller)
  291. if err != nil {
  292. slog.Error("error demoting user to admin: ", "user", caller.UserName, "error", err.Error())
  293. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  294. return
  295. }
  296. slog.Info("user was made a super admin", "user", u.UserName)
  297. json.NewEncoder(w).Encode(logic.ToReturnUser(*u))
  298. }
  299. // swagger:route POST /api/users/{username} user createUser
  300. //
  301. // Create a user.
  302. //
  303. // Schemes: https
  304. //
  305. // Security:
  306. // oauth
  307. //
  308. // Responses:
  309. // 200: userBodyResponse
  310. func createUser(w http.ResponseWriter, r *http.Request) {
  311. w.Header().Set("Content-Type", "application/json")
  312. caller, err := logic.GetUser(r.Header.Get("user"))
  313. if err != nil {
  314. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  315. return
  316. }
  317. var user models.User
  318. err = json.NewDecoder(r.Body).Decode(&user)
  319. if err != nil {
  320. logger.Log(0, user.UserName, "error decoding request body: ",
  321. err.Error())
  322. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  323. return
  324. }
  325. if !caller.IsSuperAdmin && user.IsAdmin {
  326. err = errors.New("only superadmin can create admin users")
  327. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  328. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  329. return
  330. }
  331. if user.IsSuperAdmin {
  332. err = errors.New("additional superadmins cannot be created")
  333. slog.Error("error creating new user: ", "user", user.UserName, "error", err)
  334. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  335. return
  336. }
  337. if !servercfg.IsPro && !user.IsAdmin {
  338. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("non-admins users can only be created on Pro version"), "forbidden"))
  339. return
  340. }
  341. err = logic.CreateUser(&user)
  342. if err != nil {
  343. slog.Error("error creating new user: ", "user", user.UserName, "error", err.Error())
  344. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  345. return
  346. }
  347. slog.Info("user was created", "username", user.UserName)
  348. json.NewEncoder(w).Encode(logic.ToReturnUser(user))
  349. }
  350. // swagger:route PUT /api/users/{username} user updateUser
  351. //
  352. // Update a user.
  353. //
  354. // Schemes: https
  355. //
  356. // Security:
  357. // oauth
  358. //
  359. // Responses:
  360. // 200: userBodyResponse
  361. func updateUser(w http.ResponseWriter, r *http.Request) {
  362. w.Header().Set("Content-Type", "application/json")
  363. var params = mux.Vars(r)
  364. // start here
  365. var caller *models.User
  366. var err error
  367. var ismaster bool
  368. if r.Header.Get("user") == logic.MasterUser {
  369. ismaster = true
  370. } else {
  371. caller, err = logic.GetUser(r.Header.Get("user"))
  372. if err != nil {
  373. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  374. }
  375. }
  376. username := params["username"]
  377. user, err := logic.GetUser(username)
  378. if err != nil {
  379. logger.Log(0, username,
  380. "failed to update user info: ", err.Error())
  381. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  382. return
  383. }
  384. var userchange models.User
  385. // we decode our body request params
  386. err = json.NewDecoder(r.Body).Decode(&userchange)
  387. if err != nil {
  388. slog.Error("failed to decode body", "error ", err.Error())
  389. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  390. return
  391. }
  392. if user.UserName != userchange.UserName {
  393. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("user in param and request body not matching"), "badrequest"))
  394. return
  395. }
  396. selfUpdate := false
  397. if !ismaster && caller.UserName == user.UserName {
  398. selfUpdate = true
  399. }
  400. if !ismaster && !selfUpdate {
  401. if caller.IsAdmin && user.IsSuperAdmin {
  402. slog.Error("non-superadmin user", "caller", caller.UserName, "attempted to update superadmin user", username)
  403. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("cannot update superadmin user"), "forbidden"))
  404. return
  405. }
  406. if !caller.IsAdmin && !caller.IsSuperAdmin {
  407. slog.Error("operation not allowed", "caller", caller.UserName, "attempted to update user", username)
  408. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("cannot update superadmin user"), "forbidden"))
  409. return
  410. }
  411. if caller.IsAdmin && user.IsAdmin {
  412. slog.Error("admin user cannot update another admin", "caller", caller.UserName, "attempted to update admin user", username)
  413. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("admin user cannot update another admin"), "forbidden"))
  414. return
  415. }
  416. if caller.IsAdmin && userchange.IsAdmin {
  417. err = errors.New("admin user cannot update role of an another user to admin")
  418. slog.Error("failed to update user", "caller", caller.UserName, "attempted to update user", username, "error", err)
  419. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  420. return
  421. }
  422. }
  423. if !ismaster && selfUpdate {
  424. if user.IsAdmin != userchange.IsAdmin || user.IsSuperAdmin != userchange.IsSuperAdmin {
  425. slog.Error("user cannot change his own role", "caller", caller.UserName, "attempted to update user role", username)
  426. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("user not allowed to self assign role"), "forbidden"))
  427. return
  428. }
  429. }
  430. if ismaster {
  431. if !user.IsSuperAdmin && userchange.IsSuperAdmin {
  432. slog.Error("operation not allowed", "caller", logic.MasterUser, "attempted to update user role to superadmin", username)
  433. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("attempted to update user role to superadmin"), "forbidden"))
  434. return
  435. }
  436. }
  437. if auth.IsOauthUser(user) == nil && userchange.Password != "" {
  438. err := fmt.Errorf("cannot update user's password for an oauth user %s", username)
  439. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
  440. return
  441. }
  442. user, err = logic.UpdateUser(&userchange, user)
  443. if err != nil {
  444. logger.Log(0, username,
  445. "failed to update user info: ", err.Error())
  446. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  447. return
  448. }
  449. logger.Log(1, username, "was updated")
  450. json.NewEncoder(w).Encode(logic.ToReturnUser(*user))
  451. }
  452. // swagger:route DELETE /api/users/{username} user deleteUser
  453. //
  454. // Delete a user.
  455. //
  456. // Schemes: https
  457. //
  458. // Security:
  459. // oauth
  460. //
  461. // Responses:
  462. // 200: userBodyResponse
  463. func deleteUser(w http.ResponseWriter, r *http.Request) {
  464. // Set header
  465. w.Header().Set("Content-Type", "application/json")
  466. // get params
  467. var params = mux.Vars(r)
  468. caller, err := logic.GetUser(r.Header.Get("user"))
  469. if err != nil {
  470. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  471. }
  472. username := params["username"]
  473. user, err := logic.GetUser(username)
  474. if err != nil {
  475. logger.Log(0, username,
  476. "failed to update user info: ", err.Error())
  477. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  478. return
  479. }
  480. if user.IsSuperAdmin {
  481. slog.Error(
  482. "failed to delete user: ", "user", username, "error", "superadmin cannot be deleted")
  483. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("superadmin cannot be deleted"), "internal"))
  484. return
  485. }
  486. if !caller.IsSuperAdmin {
  487. if caller.IsAdmin && user.IsAdmin {
  488. slog.Error(
  489. "failed to delete user: ", "user", username, "error", "admin cannot delete another admin user, including oneself")
  490. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("admin cannot delete another admin user, including oneself"), "internal"))
  491. return
  492. }
  493. }
  494. success, err := logic.DeleteUser(username)
  495. if err != nil {
  496. logger.Log(0, username,
  497. "failed to delete user: ", err.Error())
  498. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  499. return
  500. } else if !success {
  501. err := errors.New("delete unsuccessful")
  502. logger.Log(0, username, err.Error())
  503. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  504. return
  505. }
  506. // check and delete extclient with this ownerID
  507. go func() {
  508. extclients, err := logic.GetAllExtClients()
  509. if err != nil {
  510. slog.Error("failed to get extclients", "error", err)
  511. return
  512. }
  513. for _, extclient := range extclients {
  514. if extclient.OwnerID == user.UserName {
  515. err = logic.DeleteExtClient(extclient.Network, extclient.ClientID)
  516. if err != nil {
  517. slog.Error("failed to delete extclient",
  518. "id", extclient.ClientID, "owner", user.UserName, "error", err)
  519. }
  520. }
  521. }
  522. if servercfg.IsDNSMode() {
  523. logic.SetDNS()
  524. }
  525. }()
  526. logger.Log(1, username, "was deleted")
  527. json.NewEncoder(w).Encode(params["username"] + " deleted.")
  528. }
  529. // Called when vpn client dials in to start the auth flow and first stage is to get register URL itself
  530. func socketHandler(w http.ResponseWriter, r *http.Request) {
  531. // Upgrade our raw HTTP connection to a websocket based one
  532. conn, err := upgrader.Upgrade(w, r, nil)
  533. if err != nil {
  534. logger.Log(0, "error during connection upgrade for node sign-in:", err.Error())
  535. return
  536. }
  537. if conn == nil {
  538. logger.Log(0, "failed to establish web-socket connection during node sign-in")
  539. return
  540. }
  541. // Start handling the session
  542. go auth.SessionHandler(conn)
  543. }