523 lines
14 KiB
Go
523 lines
14 KiB
Go
package rest
|
|
|
|
import (
|
|
"github.com/eyebluecn/tank/code/core"
|
|
"github.com/eyebluecn/tank/code/tool/builder"
|
|
"github.com/eyebluecn/tank/code/tool/i18n"
|
|
"github.com/eyebluecn/tank/code/tool/result"
|
|
"github.com/eyebluecn/tank/code/tool/util"
|
|
"net/http"
|
|
"regexp"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
type UserController struct {
|
|
BaseController
|
|
preferenceService *PreferenceService
|
|
userService *UserService
|
|
matterService *MatterService
|
|
}
|
|
|
|
func (this *UserController) Init() {
|
|
this.BaseController.Init()
|
|
|
|
b := core.CONTEXT.GetBean(this.preferenceService)
|
|
if b, ok := b.(*PreferenceService); ok {
|
|
this.preferenceService = b
|
|
}
|
|
|
|
b = core.CONTEXT.GetBean(this.userService)
|
|
if b, ok := b.(*UserService); ok {
|
|
this.userService = b
|
|
}
|
|
|
|
b = core.CONTEXT.GetBean(this.matterService)
|
|
if b, ok := b.(*MatterService); ok {
|
|
this.matterService = b
|
|
}
|
|
|
|
}
|
|
|
|
func (this *UserController) RegisterRoutes() map[string]func(writer http.ResponseWriter, request *http.Request) {
|
|
|
|
routeMap := make(map[string]func(writer http.ResponseWriter, request *http.Request))
|
|
|
|
routeMap["/api/user/info"] = this.Wrap(this.Info, USER_ROLE_GUEST)
|
|
routeMap["/api/user/login"] = this.Wrap(this.Login, USER_ROLE_GUEST)
|
|
routeMap["/api/user/authentication/login"] = this.Wrap(this.AuthenticationLogin, USER_ROLE_GUEST)
|
|
routeMap["/api/user/register"] = this.Wrap(this.Register, USER_ROLE_GUEST)
|
|
routeMap["/api/user/create"] = this.Wrap(this.Create, USER_ROLE_ADMINISTRATOR)
|
|
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/page"] = this.Wrap(this.Page, USER_ROLE_ADMINISTRATOR)
|
|
routeMap["/api/user/toggle/status"] = this.Wrap(this.ToggleStatus, USER_ROLE_ADMINISTRATOR)
|
|
routeMap["/api/user/transfiguration"] = this.Wrap(this.Transfiguration, USER_ROLE_ADMINISTRATOR)
|
|
routeMap["/api/user/scan"] = this.Wrap(this.Scan, USER_ROLE_ADMINISTRATOR)
|
|
routeMap["/api/user/delete"] = this.Wrap(this.Delete, USER_ROLE_ADMINISTRATOR)
|
|
|
|
return routeMap
|
|
}
|
|
|
|
func (this *UserController) innerLogin(writer http.ResponseWriter, request *http.Request, user *User) {
|
|
|
|
if user.Status == USER_STATUS_DISABLED {
|
|
panic(result.BadRequestI18n(request, i18n.UserDisabled))
|
|
}
|
|
|
|
//set cookie. expire after 30 days.
|
|
expiration := time.Now()
|
|
expiration = expiration.AddDate(0, 0, 30)
|
|
|
|
//save session to db.
|
|
session := &Session{
|
|
UserUuid: user.Uuid,
|
|
Ip: util.GetIpAddress(request),
|
|
ExpireTime: expiration,
|
|
}
|
|
session.UpdateTime = time.Now()
|
|
session.CreateTime = time.Now()
|
|
session = this.sessionDao.Create(session)
|
|
|
|
//set cookie
|
|
cookie := http.Cookie{
|
|
Name: core.COOKIE_AUTH_KEY,
|
|
Path: "/",
|
|
Value: session.Uuid,
|
|
Expires: expiration}
|
|
http.SetCookie(writer, &cookie)
|
|
|
|
//update lastTime and lastIp
|
|
user.LastTime = time.Now()
|
|
user.LastIp = util.GetIpAddress(request)
|
|
this.userDao.Save(user)
|
|
}
|
|
|
|
//login by username and password
|
|
func (this *UserController) Login(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
|
|
username := request.FormValue("username")
|
|
password := request.FormValue("password")
|
|
|
|
if "" == username || "" == password {
|
|
panic(result.BadRequestI18n(request, i18n.UsernameOrPasswordCannotNull))
|
|
}
|
|
|
|
user := this.userDao.FindByUsername(username)
|
|
if user == nil {
|
|
panic(result.BadRequestI18n(request, i18n.UsernameOrPasswordError))
|
|
}
|
|
|
|
if !util.MatchBcrypt(password, user.Password) {
|
|
panic(result.BadRequestI18n(request, i18n.UsernameOrPasswordError))
|
|
}
|
|
this.innerLogin(writer, request, user)
|
|
|
|
return this.Success(user)
|
|
}
|
|
|
|
//login by authentication.
|
|
func (this *UserController) AuthenticationLogin(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
|
|
authentication := request.FormValue("authentication")
|
|
if authentication == "" {
|
|
panic(result.BadRequest("authentication cannot be null"))
|
|
}
|
|
session := this.sessionDao.FindByUuid(authentication)
|
|
if session == nil {
|
|
panic(result.BadRequest("authentication error"))
|
|
}
|
|
duration := session.ExpireTime.Sub(time.Now())
|
|
if duration <= 0 {
|
|
panic(result.BadRequest("login info has expired"))
|
|
}
|
|
|
|
user := this.userDao.CheckByUuid(session.UserUuid)
|
|
this.innerLogin(writer, request, user)
|
|
return this.Success(user)
|
|
}
|
|
|
|
//fetch current user's info.
|
|
func (this *UserController) Info(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
user := this.checkUser(request)
|
|
return this.Success(user)
|
|
}
|
|
|
|
//register by username and password. After registering, will auto login.
|
|
func (this *UserController) Register(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
|
|
username := request.FormValue("username")
|
|
password := request.FormValue("password")
|
|
|
|
preference := this.preferenceService.Fetch()
|
|
if !preference.AllowRegister {
|
|
panic(result.BadRequestI18n(request, i18n.UserRegisterNotAllowd))
|
|
}
|
|
|
|
if m, _ := regexp.MatchString(USERNAME_PATTERN, username); !m {
|
|
panic(result.BadRequestI18n(request, i18n.UsernameError))
|
|
}
|
|
|
|
if len(password) < 6 {
|
|
panic(result.BadRequestI18n(request, i18n.UserPasswordLengthError))
|
|
}
|
|
|
|
if this.userDao.CountByUsername(username) > 0 {
|
|
panic(result.BadRequestI18n(request, i18n.UsernameExist, username))
|
|
}
|
|
|
|
user := &User{
|
|
Role: USER_ROLE_USER,
|
|
Username: username,
|
|
Password: util.GetBcrypt(password),
|
|
TotalSizeLimit: preference.DefaultTotalSizeLimit,
|
|
Status: USER_STATUS_OK,
|
|
}
|
|
|
|
user = this.userDao.Create(user)
|
|
|
|
//auto login
|
|
this.innerLogin(writer, request, user)
|
|
|
|
return this.Success(user)
|
|
}
|
|
|
|
func (this *UserController) Create(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
|
|
username := request.FormValue("username")
|
|
password := request.FormValue("password")
|
|
role := request.FormValue("role")
|
|
sizeLimitStr := request.FormValue("sizeLimit")
|
|
totalSizeLimitStr := request.FormValue("totalSizeLimit")
|
|
|
|
//only admin can edit user's sizeLimit
|
|
var sizeLimit int64 = 0
|
|
if sizeLimitStr == "" {
|
|
panic("user's limit size is required")
|
|
} else {
|
|
intSizeLimit, err := strconv.Atoi(sizeLimitStr)
|
|
if err != nil {
|
|
this.PanicError(err)
|
|
}
|
|
sizeLimit = int64(intSizeLimit)
|
|
}
|
|
|
|
var totalSizeLimit int64 = 0
|
|
if totalSizeLimitStr == "" {
|
|
panic("user's total limit size is required")
|
|
} else {
|
|
intTotalSizeLimit, err := strconv.Atoi(totalSizeLimitStr)
|
|
if err != nil {
|
|
this.PanicError(err)
|
|
}
|
|
totalSizeLimit = int64(intTotalSizeLimit)
|
|
}
|
|
|
|
if m, _ := regexp.MatchString(USERNAME_PATTERN, username); !m {
|
|
panic(result.BadRequestI18n(request, i18n.UsernameError))
|
|
}
|
|
|
|
if len(password) < 6 {
|
|
panic(result.BadRequestI18n(request, i18n.UserPasswordLengthError))
|
|
}
|
|
|
|
if this.userDao.CountByUsername(username) > 0 {
|
|
panic(result.BadRequestI18n(request, i18n.UsernameExist, username))
|
|
}
|
|
|
|
if role != USER_ROLE_USER && role != USER_ROLE_ADMINISTRATOR {
|
|
role = USER_ROLE_USER
|
|
}
|
|
|
|
user := &User{
|
|
Username: username,
|
|
Password: util.GetBcrypt(password),
|
|
Role: role,
|
|
SizeLimit: sizeLimit,
|
|
TotalSizeLimit: totalSizeLimit,
|
|
Status: USER_STATUS_OK,
|
|
}
|
|
|
|
user = this.userDao.Create(user)
|
|
|
|
return this.Success(user)
|
|
}
|
|
|
|
func (this *UserController) Edit(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
|
|
uuid := request.FormValue("uuid")
|
|
avatarUrl := request.FormValue("avatarUrl")
|
|
sizeLimitStr := request.FormValue("sizeLimit")
|
|
totalSizeLimitStr := request.FormValue("totalSizeLimit")
|
|
role := request.FormValue("role")
|
|
|
|
user := this.checkUser(request)
|
|
currentUser := this.userDao.CheckByUuid(uuid)
|
|
|
|
currentUser.AvatarUrl = avatarUrl
|
|
|
|
if user.Role == USER_ROLE_ADMINISTRATOR {
|
|
//only admin can edit user's sizeLimit
|
|
var sizeLimit int64 = 0
|
|
if sizeLimitStr == "" {
|
|
panic("user's limit size is required")
|
|
} else {
|
|
intSizeLimit, err := strconv.Atoi(sizeLimitStr)
|
|
if err != nil {
|
|
this.PanicError(err)
|
|
}
|
|
sizeLimit = int64(intSizeLimit)
|
|
}
|
|
currentUser.SizeLimit = sizeLimit
|
|
|
|
var totalSizeLimit int64 = 0
|
|
if totalSizeLimitStr == "" {
|
|
panic("user's total limit size is required")
|
|
} else {
|
|
intTotalSizeLimit, err := strconv.Atoi(totalSizeLimitStr)
|
|
if err != nil {
|
|
this.PanicError(err)
|
|
}
|
|
totalSizeLimit = int64(intTotalSizeLimit)
|
|
}
|
|
currentUser.TotalSizeLimit = totalSizeLimit
|
|
|
|
if role == USER_ROLE_USER || role == USER_ROLE_ADMINISTRATOR {
|
|
currentUser.Role = role
|
|
}
|
|
|
|
} else if user.Uuid != uuid {
|
|
panic(result.UNAUTHORIZED)
|
|
}
|
|
|
|
currentUser = this.userDao.Save(currentUser)
|
|
|
|
//remove cache user.
|
|
this.userService.RemoveCacheUserByUuid(currentUser.Uuid)
|
|
|
|
return this.Success(currentUser)
|
|
}
|
|
|
|
func (this *UserController) Detail(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
|
|
uuid := request.FormValue("uuid")
|
|
|
|
user := this.userDao.CheckByUuid(uuid)
|
|
|
|
return this.Success(user)
|
|
|
|
}
|
|
|
|
func (this *UserController) Logout(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
|
|
//try to find from SessionCache.
|
|
sessionId := util.GetSessionUuidFromRequest(request, core.COOKIE_AUTH_KEY)
|
|
if sessionId == "" {
|
|
return nil
|
|
}
|
|
|
|
user := this.findUser(request)
|
|
if user != nil {
|
|
session := this.sessionDao.FindByUuid(sessionId)
|
|
session.ExpireTime = time.Now()
|
|
this.sessionDao.Save(session)
|
|
}
|
|
|
|
//delete session.
|
|
_, err := core.CONTEXT.GetSessionCache().Delete(sessionId)
|
|
if err != nil {
|
|
this.logger.Error("error while deleting session.")
|
|
}
|
|
|
|
//clear cookie.
|
|
expiration := time.Now()
|
|
expiration = expiration.AddDate(-1, 0, 0)
|
|
cookie := http.Cookie{
|
|
Name: core.COOKIE_AUTH_KEY,
|
|
Path: "/",
|
|
Value: sessionId,
|
|
Expires: expiration}
|
|
http.SetCookie(writer, &cookie)
|
|
|
|
return this.Success("OK")
|
|
}
|
|
|
|
func (this *UserController) Page(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
|
|
pageStr := request.FormValue("page")
|
|
pageSizeStr := request.FormValue("pageSize")
|
|
orderCreateTime := request.FormValue("orderCreateTime")
|
|
orderUpdateTime := request.FormValue("orderUpdateTime")
|
|
orderSort := request.FormValue("orderSort")
|
|
|
|
username := request.FormValue("username")
|
|
status := request.FormValue("status")
|
|
orderLastTime := request.FormValue("orderLastTime")
|
|
|
|
var page int
|
|
if pageStr != "" {
|
|
page, _ = strconv.Atoi(pageStr)
|
|
}
|
|
|
|
pageSize := 200
|
|
if pageSizeStr != "" {
|
|
tmp, err := strconv.Atoi(pageSizeStr)
|
|
if err == nil {
|
|
pageSize = tmp
|
|
}
|
|
}
|
|
|
|
sortArray := []builder.OrderPair{
|
|
{
|
|
Key: "create_time",
|
|
Value: orderCreateTime,
|
|
},
|
|
{
|
|
Key: "update_time",
|
|
Value: orderUpdateTime,
|
|
},
|
|
{
|
|
Key: "sort",
|
|
Value: orderSort,
|
|
},
|
|
{
|
|
Key: "last_time",
|
|
Value: orderLastTime,
|
|
},
|
|
}
|
|
|
|
pager := this.userDao.Page(page, pageSize, username, status, sortArray)
|
|
|
|
return this.Success(pager)
|
|
}
|
|
|
|
func (this *UserController) ToggleStatus(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
|
|
uuid := request.FormValue("uuid")
|
|
currentUser := this.userDao.CheckByUuid(uuid)
|
|
user := this.checkUser(request)
|
|
if uuid == user.Uuid {
|
|
panic(result.BadRequest("You cannot disable yourself."))
|
|
}
|
|
|
|
if currentUser.Status == USER_STATUS_OK {
|
|
currentUser.Status = USER_STATUS_DISABLED
|
|
} else if currentUser.Status == USER_STATUS_DISABLED {
|
|
currentUser.Status = USER_STATUS_OK
|
|
}
|
|
|
|
currentUser = this.userDao.Save(currentUser)
|
|
|
|
//remove cache user.
|
|
this.userService.RemoveCacheUserByUuid(currentUser.Uuid)
|
|
|
|
return this.Success(currentUser)
|
|
|
|
}
|
|
|
|
func (this *UserController) Transfiguration(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
|
|
uuid := request.FormValue("uuid")
|
|
currentUser := this.userDao.CheckByUuid(uuid)
|
|
|
|
//expire after 10 minutes.
|
|
expiration := time.Now()
|
|
expiration = expiration.Add(10 * time.Minute)
|
|
|
|
session := &Session{
|
|
UserUuid: currentUser.Uuid,
|
|
Ip: util.GetIpAddress(request),
|
|
ExpireTime: expiration,
|
|
}
|
|
session.UpdateTime = time.Now()
|
|
session.CreateTime = time.Now()
|
|
session = this.sessionDao.Create(session)
|
|
|
|
return this.Success(session.Uuid)
|
|
}
|
|
|
|
//scan user's physics files. create index into EyeblueTank
|
|
func (this *UserController) Scan(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
|
|
uuid := request.FormValue("uuid")
|
|
currentUser := this.userDao.CheckByUuid(uuid)
|
|
this.matterService.DeleteByPhysics(request, currentUser)
|
|
this.matterService.ScanPhysics(request, currentUser)
|
|
|
|
return this.Success("OK")
|
|
}
|
|
|
|
func (this *UserController) Delete(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
|
|
uuid := request.FormValue("uuid")
|
|
currentUser := this.userDao.CheckByUuid(uuid)
|
|
user := this.checkUser(request)
|
|
|
|
if currentUser.Status != USER_STATUS_DISABLED {
|
|
panic(result.BadRequest("Only disabled user can be deleted."))
|
|
}
|
|
if currentUser.Uuid == user.Uuid {
|
|
panic(result.BadRequest("You cannot delete yourself."))
|
|
}
|
|
|
|
this.userService.DeleteUser(request, currentUser)
|
|
|
|
return this.Success("OK")
|
|
}
|
|
|
|
func (this *UserController) ChangePassword(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
|
|
oldPassword := request.FormValue("oldPassword")
|
|
newPassword := request.FormValue("newPassword")
|
|
if oldPassword == "" || newPassword == "" {
|
|
panic(result.BadRequest("oldPassword and newPassword cannot be null"))
|
|
}
|
|
|
|
user := this.checkUser(request)
|
|
|
|
//if username is demo, cannot change password.
|
|
if user.Username == USERNAME_DEMO {
|
|
return this.Success(user)
|
|
}
|
|
|
|
if !util.MatchBcrypt(oldPassword, user.Password) {
|
|
panic(result.BadRequestI18n(request, i18n.UserOldPasswordError))
|
|
}
|
|
|
|
user.Password = util.GetBcrypt(newPassword)
|
|
|
|
user = this.userDao.Save(user)
|
|
|
|
return this.Success(user)
|
|
}
|
|
|
|
//admin reset password.
|
|
func (this *UserController) ResetPassword(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
|
|
userUuid := request.FormValue("userUuid")
|
|
password := request.FormValue("password")
|
|
if userUuid == "" {
|
|
panic(result.BadRequest("userUuid cannot be null"))
|
|
}
|
|
if password == "" {
|
|
panic(result.BadRequest("password cannot be null"))
|
|
}
|
|
|
|
currentUser := this.checkUser(request)
|
|
|
|
if currentUser.Role != USER_ROLE_ADMINISTRATOR {
|
|
panic(result.UNAUTHORIZED)
|
|
}
|
|
|
|
user := this.userDao.CheckByUuid(userUuid)
|
|
|
|
user.Password = util.GetBcrypt(password)
|
|
|
|
user = this.userDao.Save(user)
|
|
|
|
return this.Success(currentUser)
|
|
}
|