userHandlers.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. package sso
  2. /*
  3. userHandlers.go
  4. Handlers for SSO user management
  5. If you are looking for handlers that changes the settings
  6. of the SSO portal (e.g. authURL or port), please refer to
  7. handlers.go.
  8. */
  9. import (
  10. "encoding/json"
  11. "errors"
  12. "net/http"
  13. "github.com/gofrs/uuid"
  14. "imuslab.com/zoraxy/mod/auth"
  15. "imuslab.com/zoraxy/mod/utils"
  16. )
  17. // HandleAddUser handle the request to add a new user to the SSO system
  18. func (s *SSOHandler) HandleAddUser(w http.ResponseWriter, r *http.Request) {
  19. username, err := utils.PostPara(r, "username")
  20. if err != nil {
  21. utils.SendErrorResponse(w, "invalid username given")
  22. return
  23. }
  24. password, err := utils.PostPara(r, "password")
  25. if err != nil {
  26. utils.SendErrorResponse(w, "invalid password given")
  27. return
  28. }
  29. newUserId, err := uuid.NewV4()
  30. if err != nil {
  31. utils.SendErrorResponse(w, "failed to generate new user ID")
  32. return
  33. }
  34. //Create a new user entry
  35. thisUserEntry := UserEntry{
  36. UserID: newUserId.String(),
  37. Username: username,
  38. PasswordHash: auth.Hash(password),
  39. TOTPCode: "",
  40. Enable2FA: false,
  41. }
  42. js, _ := json.Marshal(thisUserEntry)
  43. //Create a new user in the database
  44. err = s.Config.Database.Write("sso_users", newUserId.String(), string(js))
  45. if err != nil {
  46. utils.SendErrorResponse(w, "failed to create new user")
  47. return
  48. }
  49. utils.SendOK(w)
  50. }
  51. // Edit user information, only accept change of username, password and enabled subdomain filed
  52. func (s *SSOHandler) HandleEditUser(w http.ResponseWriter, r *http.Request) {
  53. userID, err := utils.PostPara(r, "user_id")
  54. if err != nil {
  55. utils.SendErrorResponse(w, "invalid user ID given")
  56. return
  57. }
  58. if !(s.SSOUserExists(userID)) {
  59. utils.SendErrorResponse(w, "user not found")
  60. return
  61. }
  62. //Load the user entry from database
  63. userEntry, err := s.GetSSOUser(userID)
  64. if err != nil {
  65. utils.SendErrorResponse(w, "failed to load user entry")
  66. return
  67. }
  68. //Update each of the fields if it is provided
  69. username, err := utils.PostPara(r, "username")
  70. if err == nil {
  71. userEntry.Username = username
  72. }
  73. password, err := utils.PostPara(r, "password")
  74. if err == nil {
  75. userEntry.PasswordHash = auth.Hash(password)
  76. }
  77. //Update the user entry in the database
  78. js, _ := json.Marshal(userEntry)
  79. err = s.Config.Database.Write("sso_users", userID, string(js))
  80. if err != nil {
  81. utils.SendErrorResponse(w, "failed to update user entry")
  82. return
  83. }
  84. utils.SendOK(w)
  85. }
  86. // HandleRemoveUser remove a user from the SSO system
  87. func (s *SSOHandler) HandleRemoveUser(w http.ResponseWriter, r *http.Request) {
  88. userID, err := utils.PostPara(r, "user_id")
  89. if err != nil {
  90. utils.SendErrorResponse(w, "invalid user ID given")
  91. return
  92. }
  93. if !(s.SSOUserExists(userID)) {
  94. utils.SendErrorResponse(w, "user not found")
  95. return
  96. }
  97. //Remove the user from the database
  98. err = s.Config.Database.Delete("sso_users", userID)
  99. if err != nil {
  100. utils.SendErrorResponse(w, "failed to remove user")
  101. return
  102. }
  103. utils.SendOK(w)
  104. }
  105. // HandleListUser list all users in the SSO system
  106. func (s *SSOHandler) HandleListUser(w http.ResponseWriter, r *http.Request) {
  107. ssoUsers, err := s.ListSSOUsers()
  108. if err != nil {
  109. utils.SendErrorResponse(w, "failed to list users")
  110. return
  111. }
  112. js, _ := json.Marshal(ssoUsers)
  113. utils.SendJSONResponse(w, string(js))
  114. }
  115. // HandleAddSubdomain add a subdomain to a user
  116. func (s *SSOHandler) HandleAddSubdomain(w http.ResponseWriter, r *http.Request) {
  117. userid, err := utils.PostPara(r, "user_id")
  118. if err != nil {
  119. utils.SendErrorResponse(w, "invalid user ID given")
  120. return
  121. }
  122. if !(s.SSOUserExists(userid)) {
  123. utils.SendErrorResponse(w, "user not found")
  124. return
  125. }
  126. UserEntry, err := s.GetSSOUser(userid)
  127. if err != nil {
  128. utils.SendErrorResponse(w, "failed to load user entry")
  129. return
  130. }
  131. subdomain, err := utils.PostPara(r, "subdomain")
  132. if err != nil {
  133. utils.SendErrorResponse(w, "invalid subdomain given")
  134. return
  135. }
  136. allowAccess, err := utils.PostBool(r, "allow_access")
  137. if err != nil {
  138. utils.SendErrorResponse(w, "invalid allow access value given")
  139. return
  140. }
  141. UserEntry.Subdomains[subdomain] = &SubdomainAccessRule{
  142. Subdomain: subdomain,
  143. AllowAccess: allowAccess,
  144. }
  145. err = UserEntry.Update()
  146. if err != nil {
  147. utils.SendErrorResponse(w, "failed to update user entry")
  148. return
  149. }
  150. utils.SendOK(w)
  151. }
  152. // HandleRemoveSubdomain remove a subdomain from a user
  153. func (s *SSOHandler) HandleRemoveSubdomain(w http.ResponseWriter, r *http.Request) {
  154. userid, err := utils.PostPara(r, "user_id")
  155. if err != nil {
  156. utils.SendErrorResponse(w, "invalid user ID given")
  157. return
  158. }
  159. if !(s.SSOUserExists(userid)) {
  160. utils.SendErrorResponse(w, "user not found")
  161. return
  162. }
  163. UserEntry, err := s.GetSSOUser(userid)
  164. if err != nil {
  165. utils.SendErrorResponse(w, "failed to load user entry")
  166. return
  167. }
  168. subdomain, err := utils.PostPara(r, "subdomain")
  169. if err != nil {
  170. utils.SendErrorResponse(w, "invalid subdomain given")
  171. return
  172. }
  173. delete(UserEntry.Subdomains, subdomain)
  174. err = UserEntry.Update()
  175. if err != nil {
  176. utils.SendErrorResponse(w, "failed to update user entry")
  177. return
  178. }
  179. utils.SendOK(w)
  180. }
  181. // HandleEnable2FA enable 2FA for a user
  182. func (s *SSOHandler) HandleEnable2FA(w http.ResponseWriter, r *http.Request) {
  183. userid, err := utils.PostPara(r, "user_id")
  184. if err != nil {
  185. utils.SendErrorResponse(w, "invalid user ID given")
  186. return
  187. }
  188. if !(s.SSOUserExists(userid)) {
  189. utils.SendErrorResponse(w, "user not found")
  190. return
  191. }
  192. UserEntry, err := s.GetSSOUser(userid)
  193. if err != nil {
  194. utils.SendErrorResponse(w, "failed to load user entry")
  195. return
  196. }
  197. UserEntry.Enable2FA = true
  198. provisionUri, err := UserEntry.ResetTotp(UserEntry.UserID, "Zoraxy-SSO")
  199. if err != nil {
  200. utils.SendErrorResponse(w, "failed to reset TOTP")
  201. return
  202. }
  203. //As the ResetTotp function will update the user entry in the database, no need to call Update here
  204. js, _ := json.Marshal(provisionUri)
  205. utils.SendJSONResponse(w, string(js))
  206. }
  207. // Handle Disable 2FA for a user
  208. func (s *SSOHandler) HandleDisable2FA(w http.ResponseWriter, r *http.Request) {
  209. userid, err := utils.PostPara(r, "user_id")
  210. if err != nil {
  211. utils.SendErrorResponse(w, "invalid user ID given")
  212. return
  213. }
  214. if !(s.SSOUserExists(userid)) {
  215. utils.SendErrorResponse(w, "user not found")
  216. return
  217. }
  218. UserEntry, err := s.GetSSOUser(userid)
  219. if err != nil {
  220. utils.SendErrorResponse(w, "failed to load user entry")
  221. return
  222. }
  223. UserEntry.Enable2FA = false
  224. UserEntry.TOTPCode = ""
  225. err = UserEntry.Update()
  226. if err != nil {
  227. utils.SendErrorResponse(w, "failed to update user entry")
  228. return
  229. }
  230. utils.SendOK(w)
  231. }
  232. // HandleVerify2FA verify the 2FA code for a user
  233. func (s *SSOHandler) HandleVerify2FA(w http.ResponseWriter, r *http.Request) (bool, error) {
  234. userid, err := utils.PostPara(r, "user_id")
  235. if err != nil {
  236. return false, errors.New("invalid user ID given")
  237. }
  238. if !(s.SSOUserExists(userid)) {
  239. utils.SendErrorResponse(w, "user not found")
  240. return false, errors.New("user not found")
  241. }
  242. UserEntry, err := s.GetSSOUser(userid)
  243. if err != nil {
  244. utils.SendErrorResponse(w, "failed to load user entry")
  245. return false, errors.New("failed to load user entry")
  246. }
  247. totpCode, _ := utils.PostPara(r, "totp_code")
  248. if !UserEntry.Enable2FA {
  249. //If 2FA is not enabled, return true
  250. return true, nil
  251. }
  252. if !UserEntry.VerifyTotp(totpCode) {
  253. return false, nil
  254. }
  255. return true, nil
  256. }