Finish the user register.

This commit is contained in:
zicla 2019-05-04 01:11:59 +08:00
parent bda9339299
commit a02eada324
12 changed files with 82 additions and 242 deletions

View File

@ -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"

View File

@ -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 {

View File

@ -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("用户名或密码错误"))
}
}

View File

@ -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("该账号不是管理员"))
}

View File

@ -11,6 +11,8 @@ type Preference struct {
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`

View File

@ -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 {
@ -55,14 +60,10 @@ 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("用户名或密码错误"))
}
}
if !util.MatchBcrypt(password, user.Password) {
panic(result.BadRequest("用户名或密码错误"))
@ -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)
}

View File

@ -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 {
if db.Error.Error() == result.DB_ERROR_NOT_FOUND {
return nil
} else {
panic(db.Error)
}
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
}
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 {

View File

@ -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
}
}

View File

@ -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)

View File

@ -23,6 +23,8 @@ const (
MODE_MIRROR = "mirror"
//将远程的一个文件爬取到蓝眼云盘中
MODE_CRAWL = "crawl"
//TODO:查看当前蓝眼云盘版本
MODE_VERSION = "version"
)
//命令行输入相关的对象

View File

@ -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

View File

@ -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)
}