userHandlers.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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.SSO_UserExists(userID)) {
  59. utils.SendErrorResponse(w, "user not found")
  60. return
  61. }
  62. //Load the user entry from database
  63. userEntry, err := s.SSO_GetUser(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.SSO_UserExists(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. entries, err := s.Config.Database.ListTable("sso_users")
  108. if err != nil {
  109. utils.SendErrorResponse(w, "failed to list users")
  110. return
  111. }
  112. ssoUsers := map[string]*UserEntry{}
  113. for _, keypairs := range entries {
  114. userid := string(keypairs[0])
  115. group := new(UserEntry)
  116. json.Unmarshal(keypairs[1], &group)
  117. ssoUsers[userid] = group
  118. }
  119. js, _ := json.Marshal(ssoUsers)
  120. utils.SendJSONResponse(w, string(js))
  121. }
  122. func (s *SSOHandler) HandleAddSubdomain(w http.ResponseWriter, r *http.Request) {
  123. userid, err := utils.PostPara(r, "user_id")
  124. if err != nil {
  125. utils.SendErrorResponse(w, "invalid user ID given")
  126. return
  127. }
  128. if !(s.SSO_UserExists(userid)) {
  129. utils.SendErrorResponse(w, "user not found")
  130. return
  131. }
  132. UserEntry, err := s.SSO_GetUser(userid)
  133. if err != nil {
  134. utils.SendErrorResponse(w, "failed to load user entry")
  135. return
  136. }
  137. subdomain, err := utils.PostPara(r, "subdomain")
  138. if err != nil {
  139. utils.SendErrorResponse(w, "invalid subdomain given")
  140. return
  141. }
  142. allowAccess, err := utils.PostBool(r, "allow_access")
  143. if err != nil {
  144. utils.SendErrorResponse(w, "invalid allow access value given")
  145. return
  146. }
  147. UserEntry.Subdomains[subdomain] = &SubdomainAccessRule{
  148. Subdomain: subdomain,
  149. AllowAccess: allowAccess,
  150. }
  151. err = UserEntry.Update()
  152. if err != nil {
  153. utils.SendErrorResponse(w, "failed to update user entry")
  154. return
  155. }
  156. utils.SendOK(w)
  157. }
  158. func (s *SSOHandler) HandleRemoveSubdomain(w http.ResponseWriter, r *http.Request) {
  159. userid, err := utils.PostPara(r, "user_id")
  160. if err != nil {
  161. utils.SendErrorResponse(w, "invalid user ID given")
  162. return
  163. }
  164. if !(s.SSO_UserExists(userid)) {
  165. utils.SendErrorResponse(w, "user not found")
  166. return
  167. }
  168. UserEntry, err := s.SSO_GetUser(userid)
  169. if err != nil {
  170. utils.SendErrorResponse(w, "failed to load user entry")
  171. return
  172. }
  173. subdomain, err := utils.PostPara(r, "subdomain")
  174. if err != nil {
  175. utils.SendErrorResponse(w, "invalid subdomain given")
  176. return
  177. }
  178. delete(UserEntry.Subdomains, subdomain)
  179. err = UserEntry.Update()
  180. if err != nil {
  181. utils.SendErrorResponse(w, "failed to update user entry")
  182. return
  183. }
  184. utils.SendOK(w)
  185. }
  186. func (s *SSOHandler) HandleEnable2FA(w http.ResponseWriter, r *http.Request) {
  187. userid, err := utils.PostPara(r, "user_id")
  188. if err != nil {
  189. utils.SendErrorResponse(w, "invalid user ID given")
  190. return
  191. }
  192. if !(s.SSO_UserExists(userid)) {
  193. utils.SendErrorResponse(w, "user not found")
  194. return
  195. }
  196. UserEntry, err := s.SSO_GetUser(userid)
  197. if err != nil {
  198. utils.SendErrorResponse(w, "failed to load user entry")
  199. return
  200. }
  201. UserEntry.Enable2FA = true
  202. provisionUri, err := UserEntry.ResetTotp(UserEntry.UserID, "Zoraxy-SSO")
  203. if err != nil {
  204. utils.SendErrorResponse(w, "failed to reset TOTP")
  205. return
  206. }
  207. //As the ResetTotp function will update the user entry in the database, no need to call Update here
  208. js, _ := json.Marshal(provisionUri)
  209. utils.SendJSONResponse(w, string(js))
  210. }
  211. // Handle Disable 2FA for a user
  212. func (s *SSOHandler) HandleDisable2FA(w http.ResponseWriter, r *http.Request) {
  213. userid, err := utils.PostPara(r, "user_id")
  214. if err != nil {
  215. utils.SendErrorResponse(w, "invalid user ID given")
  216. return
  217. }
  218. if !(s.SSO_UserExists(userid)) {
  219. utils.SendErrorResponse(w, "user not found")
  220. return
  221. }
  222. UserEntry, err := s.SSO_GetUser(userid)
  223. if err != nil {
  224. utils.SendErrorResponse(w, "failed to load user entry")
  225. return
  226. }
  227. UserEntry.Enable2FA = false
  228. UserEntry.TOTPCode = ""
  229. err = UserEntry.Update()
  230. if err != nil {
  231. utils.SendErrorResponse(w, "failed to update user entry")
  232. return
  233. }
  234. utils.SendOK(w)
  235. }
  236. // HandleVerify2FA verify the 2FA code for a user
  237. func (s *SSOHandler) HandleVerify2FA(w http.ResponseWriter, r *http.Request) (bool, error) {
  238. userid, err := utils.PostPara(r, "user_id")
  239. if err != nil {
  240. return false, errors.New("invalid user ID given")
  241. }
  242. if !(s.SSO_UserExists(userid)) {
  243. utils.SendErrorResponse(w, "user not found")
  244. return false, errors.New("user not found")
  245. }
  246. UserEntry, err := s.SSO_GetUser(userid)
  247. if err != nil {
  248. utils.SendErrorResponse(w, "failed to load user entry")
  249. return false, errors.New("failed to load user entry")
  250. }
  251. totpCode, _ := utils.PostPara(r, "totp_code")
  252. if !UserEntry.Enable2FA {
  253. //If 2FA is not enabled, return true
  254. return true, nil
  255. }
  256. if !UserEntry.VerifyTotp(totpCode) {
  257. return false, nil
  258. }
  259. return true, nil
  260. }