user.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. package main
  2. /*
  3. User Management System
  4. Entry points for handler user functions
  5. */
  6. import (
  7. "encoding/base64"
  8. "encoding/json"
  9. "image"
  10. "image/gif"
  11. "image/jpeg"
  12. "image/png"
  13. "net/http"
  14. "strconv"
  15. "strings"
  16. uuid "github.com/satori/go.uuid"
  17. auth "imuslab.com/arozos/mod/auth"
  18. module "imuslab.com/arozos/mod/modules"
  19. prout "imuslab.com/arozos/mod/prouter"
  20. user "imuslab.com/arozos/mod/user"
  21. "imuslab.com/arozos/mod/utils"
  22. )
  23. func UserSystemInit() {
  24. //Create a new User Handler
  25. uh, err := user.NewUserHandler(sysdb, authAgent, permissionHandler, baseStoragePool, &shareEntryTable)
  26. if err != nil {
  27. panic(err)
  28. }
  29. userHandler = uh
  30. /*
  31. router := prout.NewModuleRouter(prout.RouterOption{
  32. ModuleName: "System Settings",
  33. AdminOnly: false,
  34. UserHandler: userHandler,
  35. DeniedHandler: func(w http.ResponseWriter, r *http.Request) {
  36. utils.SendErrorResponse(w, "Permission Denied")
  37. },
  38. })
  39. */
  40. //Create Endpoint Listeners
  41. http.HandleFunc("/system/users/list", user_handleList)
  42. //Everyone logged in should have permission to view their profile and change their password
  43. http.HandleFunc("/system/users/userinfo", func(w http.ResponseWriter, r *http.Request) {
  44. authAgent.HandleCheckAuth(w, r, user_handleUserInfo)
  45. })
  46. //Interface info should be able to view by everyone logged in
  47. http.HandleFunc("/system/users/interfaceinfo", func(w http.ResponseWriter, r *http.Request) {
  48. authAgent.HandleCheckAuth(w, r, user_getInterfaceInfo)
  49. })
  50. //API for loading other users thumbnail as image file
  51. http.HandleFunc("/system/users/profilepic", func(w http.ResponseWriter, r *http.Request) {
  52. authAgent.HandleCheckAuth(w, r, user_getProfilePic)
  53. })
  54. //Register setting interface for module configuration
  55. registerSetting(settingModule{
  56. Name: "My Account",
  57. Desc: "Manage your account and password",
  58. IconPath: "SystemAO/users/img/small_icon.png",
  59. Group: "Users",
  60. StartDir: "SystemAO/users/account.html",
  61. RequireAdmin: false,
  62. })
  63. registerSetting(settingModule{
  64. Name: "User List",
  65. Desc: "A list of users registered on this system",
  66. IconPath: "SystemAO/users/img/small_icon.png",
  67. Group: "Users",
  68. StartDir: "SystemAO/users/userList.html",
  69. RequireAdmin: true,
  70. })
  71. //Register auth management events that requires user handler
  72. adminRouter := prout.NewModuleRouter(prout.RouterOption{
  73. ModuleName: "System Settings",
  74. AdminOnly: true,
  75. UserHandler: userHandler,
  76. DeniedHandler: func(w http.ResponseWriter, r *http.Request) {
  77. utils.SendErrorResponse(w, "Permission Denied")
  78. },
  79. })
  80. //Handle Authentication Unregister Handler
  81. adminRouter.HandleFunc("/system/auth/unregister", authAgent.HandleUnregister)
  82. adminRouter.HandleFunc("/system/users/editUser", user_handleUserEdit)
  83. adminRouter.HandleFunc("/system/users/removeUser", user_handleUserRemove)
  84. }
  85. // Remove a user from the system
  86. func user_handleUserRemove(w http.ResponseWriter, r *http.Request) {
  87. username, err := utils.PostPara(r, "username")
  88. if err != nil {
  89. utils.SendErrorResponse(w, "Username not defined")
  90. return
  91. }
  92. if !authAgent.UserExists(username) {
  93. utils.SendErrorResponse(w, "User not exists")
  94. return
  95. }
  96. userinfo, err := userHandler.GetUserInfoFromUsername(username)
  97. if err != nil {
  98. utils.SendErrorResponse(w, err.Error())
  99. return
  100. }
  101. currentUserinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  102. if err != nil {
  103. //This user has not logged in
  104. utils.SendErrorResponse(w, "User not logged in")
  105. return
  106. }
  107. if currentUserinfo.Username == userinfo.Username {
  108. //This user has not logged in
  109. utils.SendErrorResponse(w, "You can't remove yourself")
  110. return
  111. }
  112. //Clear Core User Data
  113. userinfo.RemoveUser()
  114. //Clearn Up FileSystem preferences
  115. system_fs_removeUserPreferences(username)
  116. utils.SendOK(w)
  117. }
  118. func user_handleUserEdit(w http.ResponseWriter, r *http.Request) {
  119. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  120. if err != nil {
  121. //This user has not logged in
  122. utils.SendErrorResponse(w, "User not logged in")
  123. return
  124. }
  125. if userinfo.IsAdmin() == false {
  126. //Require admin access
  127. utils.SendErrorResponse(w, "Permission Denied")
  128. return
  129. }
  130. opr, _ := utils.PostPara(r, "opr")
  131. username, _ := utils.PostPara(r, "username")
  132. if !authAgent.UserExists(username) {
  133. utils.SendErrorResponse(w, "User not exists")
  134. return
  135. }
  136. if opr == "" {
  137. //List this user information
  138. type returnValue struct {
  139. Username string
  140. Icondata string
  141. Usergroup []string
  142. Quota int64
  143. }
  144. iconData := getUserIcon(username)
  145. userGroup, err := permissionHandler.GetUsersPermissionGroup(username)
  146. if err != nil {
  147. utils.SendErrorResponse(w, "Unable to get user group")
  148. return
  149. }
  150. //Parse the user permission groupts
  151. userGroupNames := []string{}
  152. for _, gp := range userGroup {
  153. userGroupNames = append(userGroupNames, gp.Name)
  154. }
  155. //Get the user's storaeg quota
  156. userinfo, _ := userHandler.GetUserInfoFromUsername(username)
  157. jsonString, _ := json.Marshal(returnValue{
  158. Username: username,
  159. Icondata: iconData,
  160. Usergroup: userGroupNames,
  161. Quota: userinfo.StorageQuota.GetUserStorageQuota(),
  162. })
  163. utils.SendJSONResponse(w, string(jsonString))
  164. } else if opr == "updateUserGroup" {
  165. //Update the target user's group
  166. newgroup, err := utils.PostPara(r, "newgroup")
  167. if err != nil {
  168. systemWideLogger.PrintAndLog("User", err.Error(), err)
  169. utils.SendErrorResponse(w, "New Group not defined")
  170. return
  171. }
  172. newQuota, err := utils.PostPara(r, "quota")
  173. if err != nil {
  174. systemWideLogger.PrintAndLog("User", err.Error(), err)
  175. utils.SendErrorResponse(w, "Quota not defined")
  176. return
  177. }
  178. quotaInt, err := strconv.Atoi(newQuota)
  179. if err != nil {
  180. systemWideLogger.PrintAndLog("User", err.Error(), err)
  181. utils.SendErrorResponse(w, "Invalid Quota Value")
  182. return
  183. }
  184. newGroupKeys := []string{}
  185. err = json.Unmarshal([]byte(newgroup), &newGroupKeys)
  186. if err != nil {
  187. systemWideLogger.PrintAndLog("User", err.Error(), err)
  188. utils.SendErrorResponse(w, "Unable to parse new groups")
  189. return
  190. }
  191. if len(newGroupKeys) == 0 {
  192. utils.SendErrorResponse(w, "User must be in at least one user permission group")
  193. return
  194. }
  195. //Check if each group exists
  196. for _, thisgp := range newGroupKeys {
  197. if !permissionHandler.GroupExists(thisgp) {
  198. utils.SendErrorResponse(w, "Group not exists, given: "+thisgp)
  199. return
  200. }
  201. }
  202. //OK to proceed
  203. userinfo, err := userHandler.GetUserInfoFromUsername(username)
  204. if err != nil {
  205. utils.SendErrorResponse(w, err.Error())
  206. return
  207. }
  208. //Check if the current user is the only one admin in the administrator group and he is leaving the group
  209. allAdministratorGroupUsers, err := userHandler.GetUsersInPermissionGroup("administrator")
  210. if err == nil {
  211. //Skip checking if error
  212. if len(allAdministratorGroupUsers) == 1 && userinfo.UserIsInOneOfTheGroupOf([]string{"administrator"}) && !utils.StringInArray(newGroupKeys, "administrator") {
  213. //Current administrator group only contain 1 user
  214. //This user is in the administrator group
  215. //The user want to unset himself from administrator group
  216. //Reject the operation as this will cause system lockdown
  217. utils.SendErrorResponse(w, "You are the only administrator. You cannot remove yourself from the administrator group.")
  218. return
  219. }
  220. }
  221. //Get the permission groups by their ids
  222. newPermissioGroups := userHandler.GetPermissionHandler().GetPermissionGroupByNameList(newGroupKeys)
  223. //Set the user's permission to these groups
  224. userinfo.SetUserPermissionGroup(newPermissioGroups)
  225. if err != nil {
  226. utils.SendErrorResponse(w, err.Error())
  227. return
  228. }
  229. //Write to quota handler
  230. userinfo.StorageQuota.SetUserStorageQuota(int64(quotaInt))
  231. utils.SendOK(w)
  232. } else if opr == "resetPassword" {
  233. //Reset password for this user
  234. //Generate a random password for this user
  235. tmppassword := uuid.NewV4().String()
  236. hashedPassword := auth.Hash(tmppassword)
  237. err := sysdb.Write("auth", "passhash/"+username, hashedPassword)
  238. if err != nil {
  239. utils.SendErrorResponse(w, err.Error())
  240. return
  241. }
  242. //Finish. Send back the reseted password
  243. utils.SendJSONResponse(w, "\""+tmppassword+"\"")
  244. } else {
  245. utils.SendErrorResponse(w, "Not supported opr")
  246. return
  247. }
  248. }
  249. // Get the user interface info for the user to launch into
  250. func user_getInterfaceInfo(w http.ResponseWriter, r *http.Request) {
  251. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  252. if err != nil {
  253. //User not logged in
  254. utils.SendErrorResponse(w, "User not logged in")
  255. return
  256. }
  257. interfacingModules := userinfo.GetInterfaceModules()
  258. interfaceModuleInfos := []module.ModuleInfo{}
  259. for _, im := range interfacingModules {
  260. interfaceModuleInfos = append(interfaceModuleInfos, *moduleHandler.GetModuleInfoByID(im))
  261. }
  262. jsonString, _ := json.Marshal(interfaceModuleInfos)
  263. utils.SendJSONResponse(w, string(jsonString))
  264. }
  265. // return the user profile picture as image file
  266. func user_getProfilePic(w http.ResponseWriter, r *http.Request) {
  267. thisUsername, err := authAgent.GetUserName(w, r)
  268. if err != nil {
  269. utils.SendErrorResponse(w, "User not logged in")
  270. return
  271. }
  272. targetUsername, err := utils.GetPara(r, "user")
  273. if err != nil {
  274. targetUsername = thisUsername
  275. }
  276. base64Image := getUserIcon(targetUsername)
  277. if base64Image == "" && utils.FileExists("./web/img/system/close.png") {
  278. //There are no profile image for this user
  279. http.ServeFile(w, r, "./web/img/system/close.png")
  280. return
  281. }
  282. // Remove the data:image/...;base64, part if it exists
  283. if commaIndex := strings.Index(base64Image, ","); commaIndex != -1 {
  284. base64Image = base64Image[commaIndex+1:]
  285. }
  286. imgBytes, err := base64.StdEncoding.DecodeString(base64Image)
  287. if err != nil {
  288. http.Error(w, "Failed to decode base64 string", http.StatusInternalServerError)
  289. return
  290. }
  291. img, format, err := image.Decode(strings.NewReader(string(imgBytes)))
  292. if err != nil {
  293. http.Error(w, "Failed to decode image", http.StatusInternalServerError)
  294. return
  295. }
  296. switch format {
  297. case "jpeg":
  298. w.Header().Set("Content-Type", "image/jpeg")
  299. err = jpeg.Encode(w, img, nil)
  300. case "png":
  301. w.Header().Set("Content-Type", "image/png")
  302. err = png.Encode(w, img)
  303. case "gif":
  304. w.Header().Set("Content-Type", "image/gif")
  305. err = gif.Encode(w, img, nil)
  306. default:
  307. http.Error(w, "Unsupported image format", http.StatusInternalServerError)
  308. return
  309. }
  310. if err != nil {
  311. utils.SendErrorResponse(w, err.Error())
  312. }
  313. }
  314. func user_handleUserInfo(w http.ResponseWriter, r *http.Request) {
  315. username, err := authAgent.GetUserName(w, r)
  316. if err != nil {
  317. utils.SendErrorResponse(w, "User not logged in")
  318. return
  319. }
  320. opr, _ := utils.PostPara(r, "opr")
  321. if opr == "" {
  322. //Listing mode
  323. iconData := getUserIcon(username)
  324. userGroup, err := permissionHandler.GetUsersPermissionGroup(username)
  325. if err != nil {
  326. utils.SendErrorResponse(w, "Unable to get user group")
  327. return
  328. }
  329. userGroupNames := []string{}
  330. for _, group := range userGroup {
  331. userGroupNames = append(userGroupNames, group.Name)
  332. }
  333. type returnValue struct {
  334. Username string
  335. Icondata string
  336. Usergroup []string
  337. }
  338. jsonString, _ := json.Marshal(returnValue{
  339. Username: username,
  340. Icondata: iconData,
  341. Usergroup: userGroupNames,
  342. })
  343. utils.SendJSONResponse(w, string(jsonString))
  344. return
  345. } else if opr == "changepw" {
  346. oldpw, _ := utils.PostPara(r, "oldpw")
  347. newpw, _ := utils.PostPara(r, "newpw")
  348. if oldpw == "" || newpw == "" {
  349. utils.SendErrorResponse(w, "Password cannot be empty")
  350. return
  351. }
  352. //valid the old password
  353. hashedPassword := auth.Hash(oldpw)
  354. var passwordInDB string
  355. err = sysdb.Read("auth", "passhash/"+username, &passwordInDB)
  356. if hashedPassword != passwordInDB {
  357. //Old password entry invalid.
  358. utils.SendErrorResponse(w, "Invalid old password.")
  359. return
  360. }
  361. //Logout users from all switchable accounts
  362. authAgent.SwitchableAccountManager.ExpireUserFromAllSwitchableAccountPool(username)
  363. //OK! Change user password
  364. newHashedPassword := auth.Hash(newpw)
  365. sysdb.Write("auth", "passhash/"+username, newHashedPassword)
  366. utils.SendOK(w)
  367. } else if opr == "changeprofilepic" {
  368. picdata, _ := utils.PostPara(r, "picdata")
  369. if picdata != "" {
  370. setUserIcon(username, picdata)
  371. utils.SendOK(w)
  372. } else {
  373. utils.SendErrorResponse(w, "Empty image data received.")
  374. return
  375. }
  376. } else {
  377. utils.SendErrorResponse(w, "Not supported opr")
  378. return
  379. }
  380. }
  381. func user_handleList(w http.ResponseWriter, r *http.Request) {
  382. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  383. if err != nil {
  384. //This user has not logged in
  385. utils.SendErrorResponse(w, "User not logged in")
  386. return
  387. }
  388. if authAgent.CheckAuth(r) {
  389. entries, _ := sysdb.ListTable("auth")
  390. var results [][]interface{}
  391. for _, keypairs := range entries {
  392. if strings.Contains(string(keypairs[0]), "group/") {
  393. username := strings.Split(string(keypairs[0]), "/")[1]
  394. group := []string{}
  395. //Get user icon if it exists in the database
  396. userIcon := getUserIcon(username)
  397. json.Unmarshal(keypairs[1], &group)
  398. var thisUserInfo []interface{}
  399. thisUserInfo = append(thisUserInfo, username)
  400. thisUserInfo = append(thisUserInfo, group)
  401. thisUserInfo = append(thisUserInfo, userIcon)
  402. thisUserInfo = append(thisUserInfo, username == userinfo.Username)
  403. results = append(results, thisUserInfo)
  404. }
  405. }
  406. jsonString, _ := json.Marshal(results)
  407. utils.SendJSONResponse(w, string(jsonString))
  408. } else {
  409. utils.SendErrorResponse(w, "Permission Denied")
  410. }
  411. }
  412. func getUserIcon(username string) string {
  413. var userIconpath []byte
  414. sysdb.Read("auth", "profilepic/"+username, &userIconpath)
  415. return string(userIconpath)
  416. }
  417. func setUserIcon(username string, base64data string) {
  418. sysdb.Write("auth", "profilepic/"+username, []byte(base64data))
  419. return
  420. }