| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 | package main/*	User Management System	Entry points for handler user functions*/import (	"encoding/json"	"log"	"net/http"	"strconv"	"strings"	uuid "github.com/satori/go.uuid"	auth "imuslab.com/arozos/mod/auth"	module "imuslab.com/arozos/mod/modules"	prout "imuslab.com/arozos/mod/prouter"	user "imuslab.com/arozos/mod/user")func UserSystemInit() {	//Create a new User Handler	uh, err := user.NewUserHandler(sysdb, authAgent, permissionHandler, baseStoragePool, &shareEntryTable)	if err != nil {		panic(err)	}	userHandler = uh	router := prout.NewModuleRouter(prout.RouterOption{		ModuleName:  "System Settings",		AdminOnly:   false,		UserHandler: userHandler,		DeniedHandler: func(w http.ResponseWriter, r *http.Request) {			sendErrorResponse(w, "Permission Denied")		},	})	//Create Endpoint Listeners	router.HandleFunc("/system/users/list", user_handleList)	//Everyone logged in should have permission to view their profile and change their password	http.HandleFunc("/system/users/userinfo", func(w http.ResponseWriter, r *http.Request) {		authAgent.HandleCheckAuth(w, r, user_handleUserInfo)	})	//Interface info should be able to view by everyone logged in	http.HandleFunc("/system/users/interfaceinfo", func(w http.ResponseWriter, r *http.Request) {		authAgent.HandleCheckAuth(w, r, user_getInterfaceInfo)	})	//Register setting interface for module configuration	registerSetting(settingModule{		Name:         "My Account",		Desc:         "Manage your account and password",		IconPath:     "SystemAO/users/img/small_icon.png",		Group:        "Users",		StartDir:     "SystemAO/users/account.html",		RequireAdmin: false,	})	registerSetting(settingModule{		Name:         "User List",		Desc:         "A list of users registered on this system",		IconPath:     "SystemAO/users/img/small_icon.png",		Group:        "Users",		StartDir:     "SystemAO/users/userList.html",		RequireAdmin: true,	})	//Register auth management events that requires user handler	adminRouter := prout.NewModuleRouter(prout.RouterOption{		ModuleName:  "System Settings",		AdminOnly:   true,		UserHandler: userHandler,		DeniedHandler: func(w http.ResponseWriter, r *http.Request) {			sendErrorResponse(w, "Permission Denied")		},	})	//Handle Authentication Unregister Handler	adminRouter.HandleFunc("/system/auth/unregister", authAgent.HandleUnregister)	adminRouter.HandleFunc("/system/users/editUser", user_handleUserEdit)	adminRouter.HandleFunc("/system/users/removeUser", user_handleUserRemove)}//Remove a user from the systemfunc user_handleUserRemove(w http.ResponseWriter, r *http.Request) {	username, err := mv(r, "username", true)	if err != nil {		sendErrorResponse(w, "Username not defined")		return	}	if !authAgent.UserExists(username) {		sendErrorResponse(w, "User not exists")		return	}	userinfo, err := userHandler.GetUserInfoFromUsername(username)	if err != nil {		sendErrorResponse(w, err.Error())		return	}	currentUserinfo, err := userHandler.GetUserInfoFromRequest(w, r)	if err != nil {		//This user has not logged in		sendErrorResponse(w, "User not logged in")		return	}	if currentUserinfo.Username == userinfo.Username {		//This user has not logged in		sendErrorResponse(w, "You can't remove yourself")		return	}	//Clear Core User Data	userinfo.RemoveUser()	//Clearn Up FileSystem preferences	system_fs_removeUserPreferences(username)	sendOK(w)}func user_handleUserEdit(w http.ResponseWriter, r *http.Request) {	userinfo, err := userHandler.GetUserInfoFromRequest(w, r)	if err != nil {		//This user has not logged in		sendErrorResponse(w, "User not logged in")		return	}	if userinfo.IsAdmin() == false {		//Require admin access		sendErrorResponse(w, "Permission Denied")		return	}	opr, _ := mv(r, "opr", true)	username, _ := mv(r, "username", true)	if !authAgent.UserExists(username) {		sendErrorResponse(w, "User not exists")		return	}	if opr == "" {		//List this user information		type returnValue struct {			Username  string			Icondata  string			Usergroup []string			Quota     int64		}		iconData := getUserIcon(username)		userGroup, err := permissionHandler.GetUsersPermissionGroup(username)		if err != nil {			sendErrorResponse(w, "Unable to get user group")			return		}		//Parse the user permission groupts		userGroupNames := []string{}		for _, gp := range userGroup {			userGroupNames = append(userGroupNames, gp.Name)		}		//Get the user's storaeg quota		userinfo, _ := userHandler.GetUserInfoFromUsername(username)		jsonString, _ := json.Marshal(returnValue{			Username:  username,			Icondata:  iconData,			Usergroup: userGroupNames,			Quota:     userinfo.StorageQuota.GetUserStorageQuota(),		})		sendJSONResponse(w, string(jsonString))	} else if opr == "updateUserGroup" {		//Update the target user's group		newgroup, err := mv(r, "newgroup", true)		if err != nil {			log.Println(err.Error())			sendErrorResponse(w, "New Group not defined")			return		}		newQuota, err := mv(r, "quota", true)		if err != nil {			log.Println(err.Error())			sendErrorResponse(w, "Quota not defined")			return		}		quotaInt, err := strconv.Atoi(newQuota)		if err != nil {			log.Println(err.Error())			sendErrorResponse(w, "Invalid Quota Value")			return		}		newGroupKeys := []string{}		err = json.Unmarshal([]byte(newgroup), &newGroupKeys)		if err != nil {			log.Println(err.Error())			sendErrorResponse(w, "Unable to parse new groups")			return		}		if len(newGroupKeys) == 0 {			sendErrorResponse(w, "User must be in at least one user permission group")			return		}		//Check if each group exists		for _, thisgp := range newGroupKeys {			if !permissionHandler.GroupExists(thisgp) {				sendErrorResponse(w, "Group not exists, given: "+thisgp)				return			}		}		//OK to proceed		userinfo, err := userHandler.GetUserInfoFromUsername(username)		if err != nil {			sendErrorResponse(w, err.Error())			return		}		//Check if the current user is the only one admin in the administrator group and he is leaving the group		allAdministratorGroupUsers, err := userHandler.GetUsersInPermissionGroup("administrator")		if err == nil {			//Skip checking if error			if len(allAdministratorGroupUsers) == 1 && userinfo.UserIsInOneOfTheGroupOf([]string{"administrator"}) && !stringInSlice("administrator", newGroupKeys) {				//Current administrator group only contain 1 user				//This user is in the administrator group				//The user want to unset himself from administrator group				//Reject the operation as this will cause system lockdown				sendErrorResponse(w, "You are the only administrator. You cannot remove yourself from the administrator group.")				return			}		}		//Get the permission groups by their ids		newPermissioGroups := userHandler.GetPermissionHandler().GetPermissionGroupByNameList(newGroupKeys)		//Set the user's permission to these groups		userinfo.SetUserPermissionGroup(newPermissioGroups)		if err != nil {			sendErrorResponse(w, err.Error())			return		}		//Write to quota handler		userinfo.StorageQuota.SetUserStorageQuota(int64(quotaInt))		sendOK(w)	} else if opr == "resetPassword" {		//Reset password for this user		//Generate a random password for this user		tmppassword := uuid.NewV4().String()		hashedPassword := auth.Hash(tmppassword)		err := sysdb.Write("auth", "passhash/"+username, hashedPassword)		if err != nil {			sendErrorResponse(w, err.Error())			return		}		//Finish. Send back the reseted password		sendJSONResponse(w, "\""+tmppassword+"\"")	} else {		sendErrorResponse(w, "Not supported opr")		return	}}//Get the user interface info for the user to launch intofunc user_getInterfaceInfo(w http.ResponseWriter, r *http.Request) {	userinfo, err := userHandler.GetUserInfoFromRequest(w, r)	if err != nil {		//User not logged in		sendErrorResponse(w, "User not logged in")		return	}	interfacingModules := userinfo.GetInterfaceModules()	interfaceModuleInfos := []module.ModuleInfo{}	for _, im := range interfacingModules {		interfaceModuleInfos = append(interfaceModuleInfos, *moduleHandler.GetModuleInfoByID(im))	}	jsonString, _ := json.Marshal(interfaceModuleInfos)	sendJSONResponse(w, string(jsonString))}func user_handleUserInfo(w http.ResponseWriter, r *http.Request) {	username, err := authAgent.GetUserName(w, r)	if err != nil {		sendErrorResponse(w, "User not logged in")		return	}	opr, _ := mv(r, "opr", true)	if opr == "" {		//Listing mode		iconData := getUserIcon(username)		userGroup, err := permissionHandler.GetUsersPermissionGroup(username)		if err != nil {			sendErrorResponse(w, "Unable to get user group")			return		}		userGroupNames := []string{}		for _, group := range userGroup {			userGroupNames = append(userGroupNames, group.Name)		}		type returnValue struct {			Username  string			Icondata  string			Usergroup []string		}		jsonString, _ := json.Marshal(returnValue{			Username:  username,			Icondata:  iconData,			Usergroup: userGroupNames,		})		sendJSONResponse(w, string(jsonString))		return	} else if opr == "changepw" {		oldpw, _ := mv(r, "oldpw", true)		newpw, _ := mv(r, "newpw", true)		if oldpw == "" || newpw == "" {			sendErrorResponse(w, "Password cannot be empty")			return		}		//valid the old password		hashedPassword := auth.Hash(oldpw)		var passwordInDB string		err = sysdb.Read("auth", "passhash/"+username, &passwordInDB)		if hashedPassword != passwordInDB {			//Old password entry invalid.			sendErrorResponse(w, "Invalid old password.")			return		}		//OK! Change user password		newHashedPassword := auth.Hash(newpw)		sysdb.Write("auth", "passhash/"+username, newHashedPassword)		sendOK(w)	} else if opr == "changeprofilepic" {		picdata, _ := mv(r, "picdata", true)		if picdata != "" {			setUserIcon(username, picdata)			sendOK(w)		} else {			sendErrorResponse(w, "Empty image data received.")			return		}	} else {		sendErrorResponse(w, "Not supported opr")		return	}}func user_handleList(w http.ResponseWriter, r *http.Request) {	userinfo, err := userHandler.GetUserInfoFromRequest(w, r)	if err != nil {		//This user has not logged in		sendErrorResponse(w, "User not logged in")		return	}	if userinfo.IsAdmin() == true {		entries, _ := sysdb.ListTable("auth")		var results [][]interface{}		for _, keypairs := range entries {			if strings.Contains(string(keypairs[0]), "group/") {				username := strings.Split(string(keypairs[0]), "/")[1]				group := []string{}				//Get user icon if it exists in the database				userIcon := getUserIcon(username)				json.Unmarshal(keypairs[1], &group)				var thisUserInfo []interface{}				thisUserInfo = append(thisUserInfo, username)				thisUserInfo = append(thisUserInfo, group)				thisUserInfo = append(thisUserInfo, userIcon)				thisUserInfo = append(thisUserInfo, username == userinfo.Username)				results = append(results, thisUserInfo)			}		}		jsonString, _ := json.Marshal(results)		sendJSONResponse(w, string(jsonString))	} else {		sendErrorResponse(w, "Permission denied")		return	}}func getUserIcon(username string) string {	var userIconpath []byte	sysdb.Read("auth", "profilepic/"+username, &userIconpath)	return string(userIconpath)}func setUserIcon(username string, base64data string) {	sysdb.Write("auth", "profilepic/"+username, []byte(base64data))	return}
 |