From a02eada324b7dd2843b78700a2274881a66d67b1 Mon Sep 17 00:00:00 2001 From: zicla Date: Sat, 4 May 2019 01:11:59 +0800 Subject: [PATCH] Finish the user register. --- code/core/config.go | 8 +- code/rest/alien_controller.go | 39 +-------- code/rest/dav_controller.go | 6 +- code/rest/install_controller.go | 35 +++----- code/rest/preference_model.go | 16 ++-- code/rest/user_controller.go | 129 ++++++++---------------------- code/rest/user_dao.go | 32 ++------ code/rest/user_model.go | 28 ------- code/rest/user_service.go | 5 ++ code/support/tank_application.go | 2 + code/tool/util/util_file.go | 15 +--- code/tool/util/util_validation.go | 9 --- 12 files changed, 82 insertions(+), 242 deletions(-) diff --git a/code/core/config.go b/code/core/config.go index 8ac3615..f25d397 100644 --- a/code/core/config.go +++ b/code/core/config.go @@ -5,14 +5,14 @@ const ( COOKIE_AUTH_KEY = "_ak" //使用用户名密码给接口授权key - USERNAME_KEY = "authUsername" - PASSWORD_KEY = "authPassword" + USERNAME_KEY = "_username" + PASSWORD_KEY = "_password" //默认端口号 DEFAULT_SERVER_PORT = 6010 - //数据库表前缀 tank200表示当前应用版本是tank:2.0.x版,数据库结构发生变化必然是中型升级 - TABLE_PREFIX = "tank20_" + //数据库表前缀 tank30_表示当前应用版本是tank:3.0.x版,数据库结构发生变化必然是中型升级 + TABLE_PREFIX = "tank30_" //当前版本 VERSION = "3.0.0.beta1" diff --git a/code/rest/alien_controller.go b/code/rest/alien_controller.go index 1c97dbb..c383686 100644 --- a/code/rest/alien_controller.go +++ b/code/rest/alien_controller.go @@ -113,37 +113,6 @@ func (this *AlienController) HandleRoutes(writer http.ResponseWriter, request *h return nil, false } -//直接从cookie中获取用户信息,或者使用邮箱和密码获取用户 -func (this *AlienController) CheckRequestUser(writer http.ResponseWriter, request *http.Request) *User { - - //根据用户登录信息取 - user := this.findUser(writer, request) - if user != nil { - return user - } - - email := request.FormValue("email") - if email == "" { - panic("邮箱必填啦") - } - - password := request.FormValue("password") - if password == "" { - panic("密码必填") - } - - //验证用户身份合法性。 - user = this.userDao.FindByEmail(email) - if user == nil { - panic(`邮箱或密码错误`) - } else { - if !util.MatchBcrypt(password, user.Password) { - panic(`邮箱或密码错误`) - } - } - return user -} - //系统中的用户x要获取一个UploadToken,用于提供给x信任的用户上传文件。 func (this *AlienController) FetchUploadToken(writer http.ResponseWriter, request *http.Request) *result.WebResult { @@ -205,7 +174,7 @@ func (this *AlienController) FetchUploadToken(writer http.ResponseWriter, reques //文件夹路径,以 / 开头。 dir := request.FormValue("dir") - user := this.CheckRequestUser(writer, request) + user := this.checkUser(writer, request) dirMatter := this.matterService.CreateDirectories(user, dir) mm, _ := time.ParseDuration(fmt.Sprintf("%ds", expire)) @@ -234,7 +203,7 @@ func (this *AlienController) Confirm(writer http.ResponseWriter, request *http.R panic("matterUuid必填") } - user := this.CheckRequestUser(writer, request) + user := this.checkUser(writer, request) matter := this.matterDao.CheckByUuid(matterUuid) if matter.UserUuid != user.Uuid { @@ -364,7 +333,7 @@ func (this *AlienController) CrawlDirect(writer http.ResponseWriter, request *ht } } - user := this.CheckRequestUser(writer, request) + user := this.checkUser(writer, request) dirMatter := this.matterService.CreateDirectories(user, dir) matter := this.matterService.AtomicCrawl(url, filename, user, dirMatter, privacy) @@ -380,7 +349,7 @@ func (this *AlienController) FetchDownloadToken(writer http.ResponseWriter, requ panic("matterUuid必填") } - user := this.CheckRequestUser(writer, request) + user := this.checkUser(writer, request) matter := this.matterDao.CheckByUuid(matterUuid) if matter.UserUuid != user.Uuid { diff --git a/code/rest/dav_controller.go b/code/rest/dav_controller.go index 0bdb19a..f5aa62a 100644 --- a/code/rest/dav_controller.go +++ b/code/rest/dav_controller.go @@ -79,17 +79,15 @@ func (this *DavController) CheckCurrentUser(writer http.ResponseWriter, request if !ok { //要求前端使用Basic的形式授权 writer.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`) - panic(result.ConstWebResult(result.LOGIN)) - } user := this.userDao.FindByUsername(username) if user == nil { - panic(result.BadRequest("邮箱或密码错误")) + panic(result.BadRequest("用户名或密码错误")) } else { if !util.MatchBcrypt(password, user.Password) { - panic(result.BadRequest("邮箱或密码错误")) + panic(result.BadRequest("用户名或密码错误")) } } diff --git a/code/rest/install_controller.go b/code/rest/install_controller.go index 655a2f2..25405c8 100644 --- a/code/rest/install_controller.go +++ b/code/rest/install_controller.go @@ -310,7 +310,6 @@ func (this *InstallController) CreateAdmin(writer http.ResponseWriter, request * defer this.closeDbConnection(db) adminUsername := request.FormValue("adminUsername") - adminEmail := request.FormValue("adminEmail") adminPassword := request.FormValue("adminPassword") //验证超级管理员的信息 @@ -322,23 +321,12 @@ func (this *InstallController) CreateAdmin(writer http.ResponseWriter, request * panic(result.BadRequest(`超级管理员密码长度至少为6位`)) } - if adminEmail == "" { - panic(result.BadRequest(`超级管理员邮箱必填`)) - } - //检查是否有重复。 - var count1 int64 - db1 := db.Model(&User{}).Where("email = ?", adminEmail).Count(&count1) - this.PanicError(db1.Error) - if count1 > 0 { - panic(result.BadRequest(`该邮箱已存在`)) - } - var count2 int64 db2 := db.Model(&User{}).Where("username = ?", adminUsername).Count(&count2) this.PanicError(db2.Error) if count2 > 0 { - panic(result.BadRequest(`该用户名已存在`)) + panic(result.BadRequest(`%s该用户名已存在`, adminUsername)) } user := &User{} @@ -351,9 +339,6 @@ func (this *InstallController) CreateAdmin(writer http.ResponseWriter, request * user.Role = USER_ROLE_ADMINISTRATOR user.Username = adminUsername user.Password = util.GetBcrypt(adminPassword) - user.Email = adminEmail - user.Phone = "" - user.Gender = USER_GENDER_UNKNOWN user.SizeLimit = -1 user.Status = USER_STATUS_OK @@ -370,28 +355,28 @@ func (this *InstallController) ValidateAdmin(writer http.ResponseWriter, request db := this.openDbConnection(writer, request) defer this.closeDbConnection(db) - adminEmail := request.FormValue("adminEmail") + adminUsername := request.FormValue("adminUsername") adminPassword := request.FormValue("adminPassword") //验证超级管理员的信息 - if adminEmail == "" { - panic(result.BadRequest(`超级管理员邮箱必填`)) + if adminUsername == "" { + panic(result.BadRequest(`超级管理员用户名必填`)) } if len(adminPassword) < 6 { panic(result.BadRequest(`超级管理员密码长度至少为6位`)) } - var existEmailUser = &User{} - db = db.Where(&User{Email: adminEmail}).First(existEmailUser) + var existUsernameUser = &User{} + db = db.Where(&User{Username: adminUsername}).First(existUsernameUser) if db.Error != nil { - panic(result.BadRequest(fmt.Sprintf("%s对应的用户不存在", adminEmail))) + panic(result.BadRequest(fmt.Sprintf("%s对应的用户不存在", adminUsername))) } - if !util.MatchBcrypt(adminPassword, existEmailUser.Password) { - panic(result.BadRequest("邮箱或密码错误")) + if !util.MatchBcrypt(adminPassword, existUsernameUser.Password) { + panic(result.BadRequest("用户名或密码错误")) } - if existEmailUser.Role != USER_ROLE_ADMINISTRATOR { + if existUsernameUser.Role != USER_ROLE_ADMINISTRATOR { panic(result.BadRequest("该账号不是管理员")) } diff --git a/code/rest/preference_model.go b/code/rest/preference_model.go index 85f5b56..3b9e13a 100644 --- a/code/rest/preference_model.go +++ b/code/rest/preference_model.go @@ -4,13 +4,15 @@ import "github.com/eyebluecn/tank/code/core" type Preference struct { Base - Name string `json:"name" gorm:"type:varchar(45)"` - LogoUrl string `json:"logoUrl" gorm:"type:varchar(255)"` - FaviconUrl string `json:"faviconUrl" gorm:"type:varchar(255)"` - Copyright string `json:"copyright" gorm:"type:varchar(1024)"` - Record string `json:"record" gorm:"type:varchar(1024)"` - DownloadDirMaxSize int64 `json:"downloadDirMaxSize" gorm:"type:bigint(20) not null;default:-1"` - DownloadDirMaxNum int64 `json:"downloadDirMaxNum" gorm:"type:bigint(20) not null;default:-1"` + Name string `json:"name" gorm:"type:varchar(45)"` + LogoUrl string `json:"logoUrl" gorm:"type:varchar(255)"` + FaviconUrl string `json:"faviconUrl" gorm:"type:varchar(255)"` + Copyright string `json:"copyright" gorm:"type:varchar(1024)"` + Record string `json:"record" gorm:"type:varchar(1024)"` + DownloadDirMaxSize int64 `json:"downloadDirMaxSize" gorm:"type:bigint(20) not null;default:-1"` + DownloadDirMaxNum int64 `json:"downloadDirMaxNum" gorm:"type:bigint(20) not null;default:-1"` + DefaultTotalSizeLimit int64 `json:"defaultTotalSizeLimit" gorm:"type:bigint(20) not null;default:-1"` + AllowRegister bool `json:"allowRegister" gorm:"type:tinyint(1) not null;default:0"` } // set File's table name to be `profiles` diff --git a/code/rest/user_controller.go b/code/rest/user_controller.go index 7fa4c2e..f825858 100644 --- a/code/rest/user_controller.go +++ b/code/rest/user_controller.go @@ -13,11 +13,17 @@ import ( type UserController struct { BaseController + preferenceService *PreferenceService } //初始化方法 func (this *UserController) Init() { this.BaseController.Init() + + b := core.CONTEXT.GetBean(this.preferenceService) + if b, ok := b.(*PreferenceService); ok { + this.preferenceService = b + } } //注册自己的路由。 @@ -26,23 +32,22 @@ func (this *UserController) RegisterRoutes() map[string]func(writer http.Respons routeMap := make(map[string]func(writer http.ResponseWriter, request *http.Request)) //每个Controller需要主动注册自己的路由。 - routeMap["/api/user/create"] = this.Wrap(this.Create, USER_ROLE_ADMINISTRATOR) + routeMap["/api/user/login"] = this.Wrap(this.Login, USER_ROLE_GUEST) + routeMap["/api/user/register"] = this.Wrap(this.Register, USER_ROLE_GUEST) routeMap["/api/user/edit"] = this.Wrap(this.Edit, USER_ROLE_USER) + routeMap["/api/user/detail"] = this.Wrap(this.Detail, USER_ROLE_USER) + routeMap["/api/user/logout"] = this.Wrap(this.Logout, USER_ROLE_GUEST) routeMap["/api/user/change/password"] = this.Wrap(this.ChangePassword, USER_ROLE_USER) routeMap["/api/user/reset/password"] = this.Wrap(this.ResetPassword, USER_ROLE_ADMINISTRATOR) - routeMap["/api/user/login"] = this.Wrap(this.Login, USER_ROLE_GUEST) - routeMap["/api/user/logout"] = this.Wrap(this.Logout, USER_ROLE_GUEST) - routeMap["/api/user/detail"] = this.Wrap(this.Detail, USER_ROLE_USER) routeMap["/api/user/page"] = this.Wrap(this.Page, USER_ROLE_ADMINISTRATOR) - routeMap["/api/user/disable"] = this.Wrap(this.Disable, USER_ROLE_ADMINISTRATOR) - routeMap["/api/user/enable"] = this.Wrap(this.Enable, USER_ROLE_ADMINISTRATOR) + routeMap["/api/user/toggle/status"] = this.Wrap(this.ToggleStatus, USER_ROLE_ADMINISTRATOR) return routeMap } //使用用户名和密码进行登录。 //参数: -// @username:用户名(也可以输入邮箱) +// @username:用户名 // @password:密码 func (this *UserController) Login(writer http.ResponseWriter, request *http.Request) *result.WebResult { @@ -56,11 +61,7 @@ func (this *UserController) Login(writer http.ResponseWriter, request *http.Requ user := this.userDao.FindByUsername(username) if user == nil { - user = this.userDao.FindByEmail(username) - if user == nil { - panic(result.BadRequest("用户名或密码错误")) - } - + panic(result.BadRequest("用户名或密码错误")) } if !util.MatchBcrypt(password, user.Password) { @@ -98,61 +99,32 @@ func (this *UserController) Login(writer http.ResponseWriter, request *http.Requ return this.Success(user) } -//创建一个用户 -func (this *UserController) Create(writer http.ResponseWriter, request *http.Request) *result.WebResult { +//用户自主注册。 +func (this *UserController) Register(writer http.ResponseWriter, request *http.Request) *result.WebResult { username := request.FormValue("username") + password := request.FormValue("password") + if m, _ := regexp.MatchString(`^[0-9a-zA-Z_]+$`, username); !m { panic(`用户名必填,且只能包含字母,数字和'_''`) } - password := request.FormValue("password") + if len(password) < 6 { panic(`密码长度至少为6位`) } - email := request.FormValue("email") - if email == "" { - panic("邮箱必填!") - } - - avatarUrl := request.FormValue("avatarUrl") - phone := request.FormValue("phone") - gender := request.FormValue("gender") - role := request.FormValue("role") - city := request.FormValue("city") - - //判断用户上传大小限制。 - sizeLimitStr := request.FormValue("sizeLimit") - var sizeLimit int64 = 0 - if sizeLimitStr == "" { - panic("用户上传限制必填!") - } else { - intsizeLimit, err := strconv.Atoi(sizeLimitStr) - if err != nil { - this.PanicError(err) - } - sizeLimit = int64(intsizeLimit) - } - //判断重名。 if this.userDao.CountByUsername(username) > 0 { - panic(username + "已经被其他用户占用。") - } - //判断邮箱重名 - if this.userDao.CountByEmail(email) > 0 { - panic(email + "已经被其他用户占用。") + panic(result.BadRequest("%s已经被其他用户占用。", username)) } + preference := this.preferenceService.Fetch() + user := &User{ - Role: GetRole(role), + Role: USER_ROLE_USER, Username: username, Password: util.GetBcrypt(password), - Email: email, - Phone: phone, - Gender: gender, - City: city, - AvatarUrl: avatarUrl, - SizeLimit: sizeLimit, + SizeLimit: preference.DefaultTotalSizeLimit, Status: USER_STATUS_OK, } @@ -166,9 +138,6 @@ func (this *UserController) Edit(writer http.ResponseWriter, request *http.Reque avatarUrl := request.FormValue("avatarUrl") uuid := request.FormValue("uuid") - phone := request.FormValue("phone") - gender := request.FormValue("gender") - city := request.FormValue("city") currentUser := this.checkUser(writer, request) user := this.userDao.CheckByUuid(uuid) @@ -195,9 +164,6 @@ func (this *UserController) Edit(writer http.ResponseWriter, request *http.Reque } user.AvatarUrl = avatarUrl - user.Phone = phone - user.Gender = GetGender(gender) - user.City = city user = this.userDao.Save(user) @@ -303,50 +269,25 @@ func (this *UserController) Page(writer http.ResponseWriter, request *http.Reque return this.Success(pager) } -//禁用用户 -func (this *UserController) Disable(writer http.ResponseWriter, request *http.Request) *result.WebResult { +//修改用户状态 +func (this *UserController) ToggleStatus(writer http.ResponseWriter, request *http.Request) *result.WebResult { uuid := request.FormValue("uuid") - - user := this.userDao.CheckByUuid(uuid) - - loginUser := this.checkUser(writer, request) - if uuid == loginUser.Uuid { - panic(result.BadRequest("你不能操作自己的状态。")) + currentUser := this.userDao.CheckByUuid(uuid) + user := this.checkUser(writer, request) + if uuid == user.Uuid { + panic(result.Unauthorized("你不能操作自己的状态。")) } - if user.Status == USER_STATUS_DISABLED { - panic(result.BadRequest("用户已经被禁用,操作无效。")) + if currentUser.Status == USER_STATUS_OK { + currentUser.Status = USER_STATUS_DISABLED + } else if currentUser.Status == USER_STATUS_DISABLED { + currentUser.Status = USER_STATUS_OK } - user.Status = USER_STATUS_DISABLED + currentUser = this.userDao.Save(currentUser) - user = this.userDao.Save(user) - - return this.Success(user) - -} - -//启用用户 -func (this *UserController) Enable(writer http.ResponseWriter, request *http.Request) *result.WebResult { - - uuid := request.FormValue("uuid") - - user := this.userDao.CheckByUuid(uuid) - loginUser := this.checkUser(writer, request) - if uuid == loginUser.Uuid { - panic(result.BadRequest("你不能操作自己的状态。")) - } - - if user.Status == USER_STATUS_OK { - panic(result.BadRequest("用户已经是正常状态,操作无效。")) - } - - user.Status = USER_STATUS_OK - - user = this.userDao.Save(user) - - return this.Success(user) + return this.Success(currentUser) } diff --git a/code/rest/user_dao.go b/code/rest/user_dao.go index 3f9ad88..c347898 100644 --- a/code/rest/user_dao.go +++ b/code/rest/user_dao.go @@ -3,6 +3,7 @@ package rest import ( "github.com/eyebluecn/tank/code/core" "github.com/eyebluecn/tank/code/tool/builder" + "github.com/eyebluecn/tank/code/tool/result" "github.com/nu7hatch/gouuid" "time" ) @@ -14,7 +15,6 @@ type UserDao struct { //初始化方法 func (this *UserDao) Init() { this.BaseDao.Init() - } //创建用户 @@ -63,24 +63,17 @@ func (this *UserDao) CheckByUuid(uuid string) *User { return user } -//按照邮箱查询用户。 +//查询用户。 func (this *UserDao) FindByUsername(username string) *User { var user = &User{} db := core.CONTEXT.GetDB().Where(&User{Username: username}).First(user) if db.Error != nil { - return nil - } - return user -} - -//按照邮箱查询用户。 -func (this *UserDao) FindByEmail(email string) *User { - - var user *User = &User{} - db := core.CONTEXT.GetDB().Where(&User{Email: email}).First(user) - if db.Error != nil { - return nil + if db.Error.Error() == result.DB_ERROR_NOT_FOUND { + return nil + } else { + panic(db.Error) + } } return user } @@ -136,17 +129,6 @@ func (this *UserDao) CountByUsername(username string) int { return count } -//查询某个邮箱是否已经有用户了 -func (this *UserDao) CountByEmail(email string) int { - var count int - db := core.CONTEXT.GetDB(). - Model(&User{}). - Where("email = ?", email). - Count(&count) - this.PanicError(db.Error) - return count -} - //保存用户 func (this *UserDao) Save(user *User) *User { diff --git a/code/rest/user_model.go b/code/rest/user_model.go index 64d5a52..4499448 100644 --- a/code/rest/user_model.go +++ b/code/rest/user_model.go @@ -14,12 +14,6 @@ const ( USER_ROLE_ADMINISTRATOR = "ADMINISTRATOR" ) -const ( - USER_GENDER_MALE = "MALE" - USER_GENDER_FEMALE = "FEMALE" - USER_GENDER_UNKNOWN = "UNKNOWN" -) - const ( //正常状态 USER_STATUS_OK = "OK" @@ -32,10 +26,6 @@ type User struct { Role string `json:"role" gorm:"type:varchar(45)"` Username string `json:"username" gorm:"type:varchar(45) not null;unique"` Password string `json:"-" gorm:"type:varchar(255)"` - Email string `json:"email" gorm:"type:varchar(45) not null;unique"` - Phone string `json:"phone" gorm:"type:varchar(45)"` - Gender string `json:"gender" gorm:"type:varchar(45)"` - City string `json:"city" gorm:"type:varchar(45)"` AvatarUrl string `json:"avatarUrl" gorm:"type:varchar(255)"` LastIp string `json:"lastIp" gorm:"type:varchar(128)"` LastTime time.Time `json:"lastTime" gorm:"type:timestamp not null;default:'2018-01-01 00:00:00'"` @@ -49,21 +39,3 @@ type User struct { func (this *User) TableName() string { return core.TABLE_PREFIX + "user" } - -//通过一个字符串获取性别 -func GetGender(genderString string) string { - if genderString == USER_GENDER_MALE || genderString == USER_GENDER_FEMALE || genderString == USER_GENDER_UNKNOWN { - return genderString - } else { - return USER_GENDER_UNKNOWN - } -} - -//通过一个字符串获取角色 -func GetRole(roleString string) string { - if roleString == USER_ROLE_GUEST || roleString == USER_ROLE_USER || roleString == USER_ROLE_ADMINISTRATOR { - return roleString - } else { - return USER_ROLE_USER - } -} diff --git a/code/rest/user_service.go b/code/rest/user_service.go index df7f439..4edc576 100644 --- a/code/rest/user_service.go +++ b/code/rest/user_service.go @@ -73,6 +73,7 @@ func (this *UserService) MatterUnlock(userUuid string) { //装载session信息,如果session没有了根据cookie去装填用户信息。 //在所有的路由最初会调用这个方法 +//1. 支持cookie形式 2.支持入参传入username和password 3.支持Basic Auth func (this *UserService) PreHandle(writer http.ResponseWriter, request *http.Request) { //登录身份有效期以数据库中记录的为准 @@ -118,6 +119,10 @@ func (this *UserService) PreHandle(writer http.ResponseWriter, request *http.Req username := request.FormValue(core.USERNAME_KEY) password := request.FormValue(core.PASSWORD_KEY) + if username == "" || password == "" { + username, password, _ = request.BasicAuth() + } + if username != "" && password != "" { user := this.userDao.FindByUsername(username) diff --git a/code/support/tank_application.go b/code/support/tank_application.go index 841cbb3..ed62954 100644 --- a/code/support/tank_application.go +++ b/code/support/tank_application.go @@ -23,6 +23,8 @@ const ( MODE_MIRROR = "mirror" //将远程的一个文件爬取到蓝眼云盘中 MODE_CRAWL = "crawl" + //TODO:查看当前蓝眼云盘版本 + MODE_VERSION = "version" ) //命令行输入相关的对象 diff --git a/code/tool/util/util_file.go b/code/tool/util/util_file.go index 78bb57c..794a07d 100644 --- a/code/tool/util/util_file.go +++ b/code/tool/util/util_file.go @@ -74,18 +74,11 @@ func GetHomePath() string { //例如:C:/Users/lishuang/AppData/Local/Temp/html func GetHtmlPath() string { - homePath := GetHomePath() - filePath := homePath + "/html" - exists := PathExists(filePath) - - if !exists { - err := os.MkdirAll(filePath, 0777) - if err != nil { - panic("创建上传文件夹时出错!") - } + //开发环境直接使用 build/html 下面的文件 + if EnvWinDevelopment() || EnvMacDevelopment() { + return GetDevHomePath() + "/build/html" } - - return filePath + return GetHomePath() + "/html" } //如果文件夹存在就不管,不存在就创建。 例如:/var/www/matter diff --git a/code/tool/util/util_validation.go b/code/tool/util/util_validation.go index 17b7de4..c7d8682 100644 --- a/code/tool/util/util_validation.go +++ b/code/tool/util/util_validation.go @@ -1,10 +1 @@ package util - -import ( - "regexp" -) - -func ValidateEmail(email string) bool { - emailRegexp := regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") - return emailRegexp.MatchString(email) -}