1
0

handlers.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. package sso
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "net/http"
  6. "github.com/gofrs/uuid"
  7. "imuslab.com/zoraxy/mod/auth"
  8. "imuslab.com/zoraxy/mod/utils"
  9. )
  10. /* Handlers for SSO user management */
  11. // HandleAddUser handle the request to add a new user to the SSO system
  12. func (s *SSOHandler) HandleAddUser(w http.ResponseWriter, r *http.Request) {
  13. username, err := utils.PostPara(r, "username")
  14. if err != nil {
  15. utils.SendErrorResponse(w, "invalid username given")
  16. return
  17. }
  18. password, err := utils.PostPara(r, "password")
  19. if err != nil {
  20. utils.SendErrorResponse(w, "invalid password given")
  21. return
  22. }
  23. newUserId, err := uuid.NewV4()
  24. if err != nil {
  25. utils.SendErrorResponse(w, "failed to generate new user ID")
  26. return
  27. }
  28. //Create a new user entry
  29. thisUserEntry := UserEntry{
  30. UserID: newUserId.String(),
  31. Username: username,
  32. PasswordHash: auth.Hash(password),
  33. TOTPCode: "",
  34. Enable2FA: false,
  35. }
  36. js, _ := json.Marshal(thisUserEntry)
  37. //Create a new user in the database
  38. err = s.Config.Database.Write("sso_users", newUserId.String(), string(js))
  39. if err != nil {
  40. utils.SendErrorResponse(w, "failed to create new user")
  41. return
  42. }
  43. utils.SendOK(w)
  44. }
  45. // Edit user information, only accept change of username, password and enabled subdomain filed
  46. func (s *SSOHandler) HandleEditUser(w http.ResponseWriter, r *http.Request) {
  47. userID, err := utils.PostPara(r, "user_id")
  48. if err != nil {
  49. utils.SendErrorResponse(w, "invalid user ID given")
  50. return
  51. }
  52. if !(s.SSO_UserExists(userID)) {
  53. utils.SendErrorResponse(w, "user not found")
  54. return
  55. }
  56. //Load the user entry from database
  57. userEntry, err := s.SSO_GetUser(userID)
  58. if err != nil {
  59. utils.SendErrorResponse(w, "failed to load user entry")
  60. return
  61. }
  62. //Update each of the fields if it is provided
  63. username, err := utils.PostPara(r, "username")
  64. if err == nil {
  65. userEntry.Username = username
  66. }
  67. password, err := utils.PostPara(r, "password")
  68. if err == nil {
  69. userEntry.PasswordHash = auth.Hash(password)
  70. }
  71. //Update the user entry in the database
  72. js, _ := json.Marshal(userEntry)
  73. err = s.Config.Database.Write("sso_users", userID, string(js))
  74. if err != nil {
  75. utils.SendErrorResponse(w, "failed to update user entry")
  76. return
  77. }
  78. utils.SendOK(w)
  79. }
  80. // HandleRemoveUser remove a user from the SSO system
  81. func (s *SSOHandler) HandleRemoveUser(w http.ResponseWriter, r *http.Request) {
  82. userID, err := utils.PostPara(r, "user_id")
  83. if err != nil {
  84. utils.SendErrorResponse(w, "invalid user ID given")
  85. return
  86. }
  87. if !(s.SSO_UserExists(userID)) {
  88. utils.SendErrorResponse(w, "user not found")
  89. return
  90. }
  91. //Remove the user from the database
  92. err = s.Config.Database.Delete("sso_users", userID)
  93. if err != nil {
  94. utils.SendErrorResponse(w, "failed to remove user")
  95. return
  96. }
  97. utils.SendOK(w)
  98. }
  99. // HandleListUser list all users in the SSO system
  100. func (s *SSOHandler) HandleListUser(w http.ResponseWriter, r *http.Request) {
  101. entries, err := s.Config.Database.ListTable("sso_users")
  102. if err != nil {
  103. utils.SendErrorResponse(w, "failed to list users")
  104. return
  105. }
  106. ssoUsers := map[string]*UserEntry{}
  107. for _, keypairs := range entries {
  108. userid := string(keypairs[0])
  109. group := new(UserEntry)
  110. json.Unmarshal(keypairs[1], &group)
  111. ssoUsers[userid] = group
  112. }
  113. js, _ := json.Marshal(ssoUsers)
  114. utils.SendJSONResponse(w, string(js))
  115. }
  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.SSO_UserExists(userid)) {
  123. utils.SendErrorResponse(w, "user not found")
  124. return
  125. }
  126. UserEntry, err := s.SSO_GetUser(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. func (s *SSOHandler) HandleRemoveSubdomain(w http.ResponseWriter, r *http.Request) {
  153. userid, err := utils.PostPara(r, "user_id")
  154. if err != nil {
  155. utils.SendErrorResponse(w, "invalid user ID given")
  156. return
  157. }
  158. if !(s.SSO_UserExists(userid)) {
  159. utils.SendErrorResponse(w, "user not found")
  160. return
  161. }
  162. UserEntry, err := s.SSO_GetUser(userid)
  163. if err != nil {
  164. utils.SendErrorResponse(w, "failed to load user entry")
  165. return
  166. }
  167. subdomain, err := utils.PostPara(r, "subdomain")
  168. if err != nil {
  169. utils.SendErrorResponse(w, "invalid subdomain given")
  170. return
  171. }
  172. delete(UserEntry.Subdomains, subdomain)
  173. err = UserEntry.Update()
  174. if err != nil {
  175. utils.SendErrorResponse(w, "failed to update user entry")
  176. return
  177. }
  178. utils.SendOK(w)
  179. }
  180. func (s *SSOHandler) HandleEnable2FA(w http.ResponseWriter, r *http.Request) {
  181. userid, err := utils.PostPara(r, "user_id")
  182. if err != nil {
  183. utils.SendErrorResponse(w, "invalid user ID given")
  184. return
  185. }
  186. if !(s.SSO_UserExists(userid)) {
  187. utils.SendErrorResponse(w, "user not found")
  188. return
  189. }
  190. UserEntry, err := s.SSO_GetUser(userid)
  191. if err != nil {
  192. utils.SendErrorResponse(w, "failed to load user entry")
  193. return
  194. }
  195. UserEntry.Enable2FA = true
  196. provisionUri, err := UserEntry.ResetTotp(UserEntry.UserID, "Zoraxy-SSO")
  197. if err != nil {
  198. utils.SendErrorResponse(w, "failed to reset TOTP")
  199. return
  200. }
  201. //As the ResetTotp function will update the user entry in the database, no need to call Update here
  202. js, _ := json.Marshal(provisionUri)
  203. utils.SendJSONResponse(w, string(js))
  204. }
  205. // Handle Disable 2FA for a user
  206. func (s *SSOHandler) HandleDisable2FA(w http.ResponseWriter, r *http.Request) {
  207. userid, err := utils.PostPara(r, "user_id")
  208. if err != nil {
  209. utils.SendErrorResponse(w, "invalid user ID given")
  210. return
  211. }
  212. if !(s.SSO_UserExists(userid)) {
  213. utils.SendErrorResponse(w, "user not found")
  214. return
  215. }
  216. UserEntry, err := s.SSO_GetUser(userid)
  217. if err != nil {
  218. utils.SendErrorResponse(w, "failed to load user entry")
  219. return
  220. }
  221. UserEntry.Enable2FA = false
  222. UserEntry.TOTPCode = ""
  223. err = UserEntry.Update()
  224. if err != nil {
  225. utils.SendErrorResponse(w, "failed to update user entry")
  226. return
  227. }
  228. utils.SendOK(w)
  229. }
  230. // HandleVerify2FA verify the 2FA code for a user
  231. func (s *SSOHandler) HandleVerify2FA(w http.ResponseWriter, r *http.Request) (bool, error) {
  232. userid, err := utils.PostPara(r, "user_id")
  233. if err != nil {
  234. return false, errors.New("invalid user ID given")
  235. }
  236. if !(s.SSO_UserExists(userid)) {
  237. utils.SendErrorResponse(w, "user not found")
  238. return false, errors.New("user not found")
  239. }
  240. UserEntry, err := s.SSO_GetUser(userid)
  241. if err != nil {
  242. utils.SendErrorResponse(w, "failed to load user entry")
  243. return false, errors.New("failed to load user entry")
  244. }
  245. totpCode, _ := utils.PostPara(r, "totp_code")
  246. if !UserEntry.Enable2FA {
  247. //If 2FA is not enabled, return true
  248. return true, nil
  249. }
  250. if !UserEntry.VerifyTotp(totpCode) {
  251. return false, nil
  252. }
  253. return true, nil
  254. }
  255. /* Handlers for SSO portal server */
  256. func (s *SSOHandler) HandleStartSSOPortal(w http.ResponseWriter, r *http.Request) {
  257. err := s.StartSSOPortal()
  258. if err != nil {
  259. s.Log("Failed to start SSO portal server", err)
  260. utils.SendErrorResponse(w, "failed to start SSO portal server")
  261. return
  262. }
  263. utils.SendOK(w)
  264. }
  265. func (s *SSOHandler) HandleStopSSOPortal(w http.ResponseWriter, r *http.Request) {
  266. err := s.ssoPortalServer.Close()
  267. if err != nil {
  268. s.Log("Failed to stop SSO portal server", err)
  269. utils.SendErrorResponse(w, "failed to stop SSO portal server")
  270. return
  271. }
  272. utils.SendOK(w)
  273. }