feat: finish the space CRUD.

This commit is contained in:
lishuang
2023-05-27 12:25:24 +08:00
parent 14ff3fea9a
commit f39bf33922
7 changed files with 164 additions and 139 deletions
+22 -123
View File
@@ -5,9 +5,8 @@ import (
"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"
)
type SpaceController struct {
@@ -71,103 +70,36 @@ func (this *SpaceController) RegisterRoutes() map[string]func(writer http.Respon
func (this *SpaceController) Create(writer http.ResponseWriter, request *http.Request) *result.WebResult {
//space's name
name := request.FormValue("name")
sizeLimitStr := request.FormValue("sizeLimit")
totalSizeLimitStr := request.FormValue("totalSizeLimit")
if name == "" {
panic("name is required")
}
//only admin can edit user's sizeLimit
var sizeLimit int64 = 0
if sizeLimitStr == "" {
panic("space'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("space's total limit size is required")
} else {
intTotalSizeLimit, err := strconv.Atoi(totalSizeLimitStr)
if err != nil {
this.PanicError(err)
}
totalSizeLimit = int64(intTotalSizeLimit)
}
//validation work.
if m, _ := regexp.MatchString(USERNAME_PATTERN, name); !m {
panic(result.BadRequestI18n(request, i18n.SpaceNameError))
}
if this.userDao.CountByUsername(name) > 0 {
panic(result.BadRequestI18n(request, i18n.SpaceNameExist, name))
}
user := this.userService.CreateUser(request, name, "", USER_ROLE_SPACE, sizeLimit, totalSizeLimit)
name := util.ExtractRequestString(request, "name", "name is required")
sizeLimit := util.ExtractRequestInt64(request, "sizeLimit", "space's limit size is required")
totalSizeLimit := util.ExtractRequestInt64(request, "totalSizeLimit", "space's total limit size is required")
//create related space.
space := this.spaceService.CreateSpace(user.Uuid)
space.User = user
space := this.spaceService.CreateSpace(request, name, nil, sizeLimit, totalSizeLimit, SPACE_TYPE_SHARED)
return this.Success(space)
}
func (this *SpaceController) Edit(writer http.ResponseWriter, request *http.Request) *result.WebResult {
//space's name
spaceUuid := request.FormValue("spaceUuid")
sizeLimitStr := request.FormValue("sizeLimit")
totalSizeLimitStr := request.FormValue("totalSizeLimit")
uuid := util.ExtractRequestString(request, "uuid", "uuid is required")
sizeLimit := util.ExtractRequestInt64(request, "sizeLimit", "space's limit size is required")
totalSizeLimit := util.ExtractRequestInt64(request, "totalSizeLimit", "space's total limit size is required")
//only admin can edit user's sizeLimit
var sizeLimit int64 = 0
if sizeLimitStr == "" {
panic("space's limit size is required")
} else {
intSizeLimit, err := strconv.Atoi(sizeLimitStr)
if err != nil {
this.PanicError(err)
}
sizeLimit = int64(intSizeLimit)
}
space := this.spaceDao.CheckByUuid(uuid)
var totalSizeLimit int64 = 0
if totalSizeLimitStr == "" {
panic("space's total limit size is required")
} else {
intTotalSizeLimit, err := strconv.Atoi(totalSizeLimitStr)
if err != nil {
this.PanicError(err)
}
totalSizeLimit = int64(intTotalSizeLimit)
}
space.SizeLimit = sizeLimit
space.TotalSizeLimit = totalSizeLimit
space := this.spaceDao.CheckByUuid(spaceUuid)
spaceUser := this.userDao.CheckByUuid(space.UserUuid)
spaceUser.SizeLimit = sizeLimit
spaceUser.TotalSizeLimit = totalSizeLimit
spaceUser = this.userDao.Save(spaceUser)
space.User = spaceUser
space = this.spaceDao.Save(space)
return this.Success(space)
}
func (this *SpaceController) Delete(writer http.ResponseWriter, request *http.Request) *result.WebResult {
uuid := request.FormValue("uuid")
if uuid == "" {
panic(result.BadRequest("uuid cannot be null"))
}
//space's name
uuid := util.ExtractRequestString(request, "uuid", "uuid is required")
space := this.spaceDao.CheckByUuid(uuid)
//when space has members, cannot delete.
@@ -176,16 +108,7 @@ func (this *SpaceController) Delete(writer http.ResponseWriter, request *http.Re
panic(result.BadRequest("space has members, cannot be deleted."))
}
spaceUser := this.userDao.CheckByUuid(space.UserUuid)
//when space has files, cannot delete.
matterCount := this.matterDao.CountByUserUuid(spaceUser.Uuid)
if matterCount > 0 {
panic(result.BadRequest("space has files, cannot be deleted."))
}
//delete related user.
this.userDao.Delete(spaceUser)
//TODO: when space has files, cannot delete.
//delete the space.
this.spaceDao.Delete(space)
@@ -195,10 +118,7 @@ func (this *SpaceController) Delete(writer http.ResponseWriter, request *http.Re
func (this *SpaceController) Detail(writer http.ResponseWriter, request *http.Request) *result.WebResult {
uuid := request.FormValue("uuid")
if uuid == "" {
panic(result.BadRequest("uuid cannot be null"))
}
uuid := util.ExtractRequestString(request, "uuid", "uuid is required")
user := this.checkUser(request)
space := this.spaceDao.CheckByUuid(uuid)
@@ -207,33 +127,19 @@ func (this *SpaceController) Detail(writer http.ResponseWriter, request *http.Re
panic(result.BadRequestI18n(request, i18n.PermissionDenied))
}
space.User = this.userDao.FindByUuid(space.UserUuid)
return this.Success(space)
}
func (this *SpaceController) Page(writer http.ResponseWriter, request *http.Request) *result.WebResult {
pageStr := request.FormValue("page")
pageSizeStr := request.FormValue("pageSize")
orderCreateTime := request.FormValue("orderCreateTime")
page := util.ExtractRequestOptionalInt(request, "page", 0)
pageSize := util.ExtractRequestOptionalInt(request, "pageSize", 20)
orderCreateTime := util.ExtractRequestOptionalString(request, "orderCreateTime", "")
spaceType := util.ExtractRequestOptionalString(request, "type", SPACE_TYPE_SHARED)
user := this.checkUser(request)
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",
@@ -243,16 +149,9 @@ func (this *SpaceController) Page(writer http.ResponseWriter, request *http.Requ
var pager *Pager
if user.Role == USER_ROLE_USER {
pager = this.spaceDao.SelfPage(page, pageSize, user.Uuid, sortArray)
pager = this.spaceDao.SelfPage(page, pageSize, user.Uuid, spaceType, sortArray)
} else if user.Role == USER_ROLE_ADMINISTRATOR {
pager = this.spaceDao.Page(page, pageSize, sortArray)
}
//fill the space's user. FIXME: user better way to get User.
if pager != nil {
for _, space := range pager.Data.([]*Space) {
space.User = this.userDao.FindByUuid(space.UserUuid)
}
pager = this.spaceDao.Page(page, pageSize, spaceType, sortArray)
}
return this.Success(pager)
+30 -10
View File
@@ -38,20 +38,40 @@ func (this *SpaceDao) CheckByUuid(uuid string) *Space {
return entity
}
// TODO:
func (this *SpaceDao) SelfPage(page int, pageSize int, userUuid string, sortArray []builder.OrderPair) *Pager {
func (this *SpaceDao) CountByName(name string) int {
var count int64
db := core.CONTEXT.GetDB().
Model(&Space{}).
Where("name = ?", name).
Count(&count)
this.PanicError(db.Error)
return int(count)
}
countSqlTemplate := fmt.Sprintf("SELECT COUNT(*) FROM `%sspace` WHERE uuid IN (SELECT space_uuid FROM `%sspace_member` WHERE user_uuid = ?)", core.TABLE_PREFIX, core.TABLE_PREFIX)
func (this *SpaceDao) CountByUserUuid(userUuid string) int {
var count int64
db := core.CONTEXT.GetDB().
Model(&Space{}).
Where("user_uuid = ?", userUuid).
Count(&count)
this.PanicError(db.Error)
return int(count)
}
// TODO:
func (this *SpaceDao) SelfPage(page int, pageSize int, userUuid string, spaceType string, sortArray []builder.OrderPair) *Pager {
countSqlTemplate := fmt.Sprintf("SELECT COUNT(*) FROM `%sspace` WHERE uuid IN (SELECT space_uuid FROM `%sspace_member` WHERE user_uuid = ?) AND type = ?", core.TABLE_PREFIX, core.TABLE_PREFIX)
var count int
core.CONTEXT.GetDB().Raw(countSqlTemplate, userUuid).Scan(&count)
core.CONTEXT.GetDB().Raw(countSqlTemplate, userUuid, spaceType).Scan(&count)
orderByString := this.GetSortString(sortArray)
if orderByString == "" {
orderByString = "uuid"
}
querySqlTemplate := fmt.Sprintf("SELECT * FROM `%sspace` WHERE uuid IN (SELECT space_uuid FROM `%sspace_member` WHERE user_uuid = ?) ORDER BY ? LIMIT ?,?", core.TABLE_PREFIX, core.TABLE_PREFIX)
querySqlTemplate := fmt.Sprintf("SELECT * FROM `%sspace` WHERE uuid IN (SELECT space_uuid FROM `%sspace_member` WHERE user_uuid = ?) AND type = ? ORDER BY ? LIMIT ?,?", core.TABLE_PREFIX, core.TABLE_PREFIX)
var spaces []*Space
core.CONTEXT.GetDB().Raw(querySqlTemplate, userUuid, orderByString, page*pageSize, pageSize).Scan(&spaces)
core.CONTEXT.GetDB().Raw(querySqlTemplate, userUuid, spaceType, orderByString, page*pageSize, pageSize).Scan(&spaces)
pager := NewPager(page, pageSize, count, spaces)
@@ -59,16 +79,16 @@ func (this *SpaceDao) SelfPage(page int, pageSize int, userUuid string, sortArra
}
func (this *SpaceDao) Page(page int, pageSize int, sortArray []builder.OrderPair) *Pager {
count, spaces := this.PlainPage(page, pageSize, sortArray)
func (this *SpaceDao) Page(page int, pageSize int, spaceType string, sortArray []builder.OrderPair) *Pager {
count, spaces := this.PlainPage(page, pageSize, spaceType, sortArray)
pager := NewPager(page, pageSize, count, spaces)
return pager
}
func (this *SpaceDao) PlainPage(page int, pageSize int, sortArray []builder.OrderPair) (int, []*Space) {
func (this *SpaceDao) PlainPage(page int, pageSize int, spaceType string, sortArray []builder.OrderPair) (int, []*Space) {
var wp = &builder.WherePair{}
var wp = &builder.WherePair{Query: "type = ?", Args: []interface{}{spaceType}}
var conditionDB *gorm.DB
conditionDB = core.CONTEXT.GetDB().Model(&Space{}).Where(wp.Query, wp.Args...)
+8 -1
View File
@@ -4,6 +4,13 @@ import (
"time"
)
const (
//private space
SPACE_TYPE_PRIVATE = "PRIVATE"
//group shared space.
SPACE_TYPE_SHARED = "SHARED"
)
/**
* shared space
*/
@@ -13,7 +20,7 @@ type Space struct {
UpdateTime time.Time `json:"updateTime" gorm:"type:timestamp not null;default:CURRENT_TIMESTAMP"`
CreateTime time.Time `json:"createTime" gorm:"type:timestamp not null;default:'2018-01-01 00:00:00'"`
Name string `json:"name" gorm:"type:varchar(100) not null;unique"`
UserUuid string `json:"userUuid" gorm:"type:char(36);index:idx_user_uuid"`
UserUuid string `json:"userUuid" gorm:"type:char(36);unique"`
SizeLimit int64 `json:"sizeLimit" gorm:"type:bigint(20) not null;default:-1"`
TotalSizeLimit int64 `json:"totalSizeLimit" gorm:"type:bigint(20) not null;default:-1"`
TotalSize int64 `json:"totalSize" gorm:"type:bigint(20) not null;default:0"`
+43 -2
View File
@@ -2,6 +2,10 @@ package rest
import (
"github.com/eyebluecn/tank/code/core"
"github.com/eyebluecn/tank/code/tool/i18n"
"github.com/eyebluecn/tank/code/tool/result"
"net/http"
"regexp"
)
// @Service
@@ -46,10 +50,47 @@ func (this *SpaceService) Detail(uuid string) *Space {
}
// create space
func (this *SpaceService) CreateSpace(userUuid string) *Space {
func (this *SpaceService) CreateSpace(
request *http.Request,
name string,
user *User,
sizeLimit int64,
totalSizeLimit int64,
spaceType string) *Space {
userUuid := ""
//validation work.
if m, _ := regexp.MatchString(USERNAME_PATTERN, name); !m {
panic(result.BadRequestI18n(request, i18n.SpaceNameError))
}
if spaceType == SPACE_TYPE_PRIVATE {
if user == nil {
panic("private space requires user.")
}
userUuid = user.Uuid
if this.spaceDao.CountByUserUuid(userUuid) > 0 {
panic(result.BadRequestI18n(request, i18n.SpaceExclusive, name))
}
} else if spaceType == SPACE_TYPE_SHARED {
} else {
panic("Not supported spaceType:" + spaceType)
}
if this.spaceDao.CountByName(name) > 0 {
panic(result.BadRequestI18n(request, i18n.SpaceNameExist, name))
}
space := &Space{
UserUuid: userUuid,
Name: name,
UserUuid: userUuid,
SizeLimit: sizeLimit,
TotalSizeLimit: totalSizeLimit,
TotalSize: 0,
Type: spaceType,
}
space = this.spaceDao.Create(space)
+1 -1
View File
@@ -7,7 +7,7 @@ import (
const (
//guest
USER_ROLE_GUEST = "GUEST"
//共享空间
//空间
USER_ROLE_SPACE = "SPACE"
//normal user
USER_ROLE_USER = "USER"
+3 -2
View File
@@ -47,8 +47,9 @@ var (
ShareCodeRequired = &Item{English: `share code required`, Chinese: `提取码必填`}
ShareCodeError = &Item{English: `share code error`, Chinese: `提取码错误`}
CronValidateError = &Item{English: `cron error. five fields needed. eg: 1 * * * *`, Chinese: `Cron表达式错误,必须为5位。例如:1 * * * *`}
SpaceNameError = &Item{English: `space's name can only be letters, numbers or _`, Chinese: `共享空间名称必填,且只能包含中文,字母,数字和'_'`}
SpaceNameExist = &Item{English: `space's name "%s" exists`, Chinese: `共享空间名称"%s"已被占用,请使用其他名字`}
SpaceNameError = &Item{English: `space's name can only be letters, numbers or _`, Chinese: `空间名称必填,且只能包含中文,字母,数字和'_'`}
SpaceNameExist = &Item{English: `space's name "%s" exists`, Chinese: `空间名称"%s"已被占用,请使用其他名字`}
SpaceExclusive = &Item{English: `user can only own ONE space`, Chinese: `一个用户只能拥有一个私有空间`}
SpaceMemberExist = &Item{English: `space member exists`, Chinese: `该用于已经是空间的成员`}
SpaceMemberRoleConflict = &Item{English: `space member cannot contain user with role space.`, Chinese: `空间成员不能是空间角色的用户`}
PermissionDenied = &Item{English: `permission denied.`, Chinese: `没有操作权限`}
+57
View File
@@ -0,0 +1,57 @@
package util
import (
"net/http"
"strconv"
)
// param is required. when missing, panic error.
func ExtractRequestString(request *http.Request, key string, errorHint string) string {
str := request.FormValue(key)
if str == "" {
panic(errorHint)
} else {
return str
}
}
// param is required. when missing, panic error.
func ExtractRequestInt64(request *http.Request, key string, errorHint string) int64 {
keyStr := request.FormValue(key)
var num int64 = 0
if keyStr == "" {
panic(errorHint)
} else {
intVal, err := strconv.Atoi(keyStr)
if err != nil {
panic(err)
}
num = int64(intVal)
return num
}
}
// param is required. when missing, panic error.
func ExtractRequestOptionalInt(request *http.Request, key string, defaultValue int) int {
str := request.FormValue(key)
if str == "" {
return defaultValue
} else {
intVal, err := strconv.Atoi(str)
if err != nil {
panic(err)
}
return intVal
}
}
// param is required. when missing, panic error.
func ExtractRequestOptionalString(request *http.Request, key string, defaultValue string) string {
str := request.FormValue(key)
if str == "" {
return defaultValue
} else {
return str
}
}