diff --git a/code/rest/matter_dao.go b/code/rest/matter_dao.go index 6a0aaea..b297a45 100644 --- a/code/rest/matter_dao.go +++ b/code/rest/matter_dao.go @@ -46,7 +46,7 @@ func (this *MatterDao) FindByUuid(uuid string) *Matter { return entity } -//find by uuid. if not found panic NotFound error +// find by uuid. if not found panic NotFound error func (this *MatterDao) CheckByUuid(uuid string) *Matter { entity := this.FindByUuid(uuid) if entity == nil { @@ -328,7 +328,7 @@ func (this *MatterDao) Page(page int, pageSize int, puuid string, userUuid strin return pager } -//handle matter page by page. +// handle matter page by page. func (this *MatterDao) PageHandle( puuid string, userUuid string, @@ -385,7 +385,7 @@ func (this *MatterDao) Save(matter *Matter) *Matter { return matter } -//download time add 1 +// download time add 1 func (this *MatterDao) TimesIncrement(matterUuid string) { db := core.CONTEXT.GetDB().Model(&Matter{}).Where("uuid = ?", matterUuid).Updates(map[string]interface{}{"times": gorm.Expr("times + 1"), "visit_time": time.Now()}) this.PanicError(db.Error) @@ -411,7 +411,7 @@ func (this *MatterDao) SizeByPuuidAndUserUuid(matterUuid string, userUuid string return sumSize } -//delete a file from db and disk. +// delete a file from db and disk. func (this *MatterDao) Delete(matter *Matter) { // recursive if dir @@ -450,7 +450,7 @@ func (this *MatterDao) Delete(matter *Matter) { } } -//soft delete a file or dir +// soft delete a file or dir func (this *MatterDao) SoftDelete(matter *Matter) { //soft delete from db. @@ -459,7 +459,7 @@ func (this *MatterDao) SoftDelete(matter *Matter) { } -//recovery a file +// recovery a file func (this *MatterDao) Recovery(matter *Matter) { //recovery from db. @@ -501,7 +501,7 @@ func (this *MatterDao) SizeBetweenTime(startTime time.Time, endTime time.Time) i return size } -//find by userUuid and path. if not found, return nil +// find by userUuid and path. if not found, return nil func (this *MatterDao) findByUserUuidAndPath(userUuid string, path string) *Matter { var wp = &builder.WherePair{Query: "user_uuid = ? AND path = ?", Args: []interface{}{userUuid, path}} @@ -520,7 +520,7 @@ func (this *MatterDao) findByUserUuidAndPath(userUuid string, path string) *Matt return matter } -//find by userUuid and path. if not found, panic +// find by userUuid and path. if not found, panic func (this *MatterDao) checkByUserUuidAndPath(userUuid string, path string) *Matter { if path == "" { @@ -567,7 +567,19 @@ func (this *MatterDao) CountByUserUuidAndPath(userUuid string, path string) int6 } -//统计总共有多少条。 +func (this *MatterDao) CountByUserUuid(userUuid string) int64 { + + var wp = &builder.WherePair{Query: "user_uuid = ?", Args: []interface{}{userUuid}} + + var count int64 + db := core.CONTEXT.GetDB().Model(&Matter{}).Where(wp.Query, wp.Args...).Count(&count) + core.PanicError(db.Error) + + return count + +} + +// 统计总共有多少条。 func (this *MatterDao) Count() int64 { var count int64 @@ -578,7 +590,7 @@ func (this *MatterDao) Count() int64 { } -//System cleanup. +// System cleanup. func (this *MatterDao) Cleanup() { this.logger.Info("[MatterDao] clean up. Delete all Matter record in db and on disk.") db := core.CONTEXT.GetDB().Where("uuid is not null").Delete(Matter{}) diff --git a/code/rest/matter_model.go b/code/rest/matter_model.go index 85c0c46..2805980 100644 --- a/code/rest/matter_model.go +++ b/code/rest/matter_model.go @@ -30,26 +30,27 @@ const ( * file is too common. so we use matter as file. */ type Matter struct { - Uuid string `json:"uuid" gorm:"type:char(36);primary_key;unique"` - Sort int64 `json:"sort" gorm:"type:bigint(20) not null"` - 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'"` - Puuid string `json:"puuid" gorm:"type:char(36);index:idx_matter_puuid"` //index should unique globally. - UserUuid string `json:"userUuid" gorm:"type:char(36);index:idx_matter_uu"` - Username string `json:"username" gorm:"type:varchar(45) not null"` - Dir bool `json:"dir" gorm:"type:tinyint(1) not null;default:0"` - Name string `json:"name" gorm:"type:varchar(255) not null"` - Md5 string `json:"md5" gorm:"type:varchar(45)"` - Size int64 `json:"size" gorm:"type:bigint(20) not null;default:0"` - Privacy bool `json:"privacy" gorm:"type:tinyint(1) not null;default:0"` - Path string `json:"path" gorm:"type:varchar(1024)"` - Times int64 `json:"times" gorm:"type:bigint(20) not null;default:0"` - Parent *Matter `json:"parent" gorm:"-"` - Children []*Matter `json:"-" gorm:"-"` - Prop string `json:"prop" gorm:"type:varchar(1024) not null;default:'{}'"` - VisitTime time.Time `json:"visitTime" gorm:"type:timestamp not null;default:'2018-01-01 00:00:00'"` - Deleted bool `json:"deleted" gorm:"type:tinyint(1) not null;index:idx_matter_del;default:0"` - DeleteTime time.Time `json:"deleteTime" gorm:"type:timestamp not null;index:idx_matter_delt;default:'2018-01-01 00:00:00'"` + Uuid string `json:"uuid" gorm:"type:char(36);primary_key;unique"` + Sort int64 `json:"sort" gorm:"type:bigint(20) not null"` + 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'"` + Puuid string `json:"puuid" gorm:"type:char(36);index:idx_matter_puuid"` //index should unique globally. + UserUuid string `json:"userUuid" gorm:"type:char(36);index:idx_matter_uu"` + Username string `json:"username" gorm:"type:varchar(45) not null"` + Dir bool `json:"dir" gorm:"type:tinyint(1) not null;default:0"` + Name string `json:"name" gorm:"type:varchar(255) not null"` + Md5 string `json:"md5" gorm:"type:varchar(45)"` + Size int64 `json:"size" gorm:"type:bigint(20) not null;default:0"` + Privacy bool `json:"privacy" gorm:"type:tinyint(1) not null;default:0"` + Path string `json:"path" gorm:"type:varchar(1024)"` + Times int64 `json:"times" gorm:"type:bigint(20) not null;default:0"` + Parent *Matter `json:"parent" gorm:"-"` + Children []*Matter `json:"-" gorm:"-"` + Prop string `json:"prop" gorm:"type:varchar(1024) not null;default:'{}'"` + VisitTime time.Time `json:"visitTime" gorm:"type:timestamp not null;default:'2018-01-01 00:00:00'"` + Deleted bool `json:"deleted" gorm:"type:tinyint(1) not null;index:idx_matter_del;default:0"` + DeleteTime time.Time `json:"deleteTime" gorm:"type:timestamp not null;index:idx_matter_delt;default:'2018-01-01 00:00:00'"` + MemberUserUuid string `json:"memberUserUuid" gorm:"type:char(36);index:idx_member_uu"` } // get matter's absolute path. the Path property is relative path in db. @@ -61,7 +62,7 @@ func (this *Matter) MimeType() string { return util.GetMimeType(util.GetExtension(this.Name)) } -//Create a root matter. It's convenient for copy and move +// Create a root matter. It's convenient for copy and move func NewRootMatter(user *User) *Matter { matter := &Matter{} matter.Uuid = MATTER_ROOT @@ -76,7 +77,7 @@ func NewRootMatter(user *User) *Matter { return matter } -//get user's space absolute path +// get user's space absolute path func GetUserSpaceRootDir(username string) (rootDirPath string) { rootDirPath = fmt.Sprintf("%s/%s", core.CONFIG.MatterPath(), username) @@ -84,7 +85,7 @@ func GetUserSpaceRootDir(username string) (rootDirPath string) { return rootDirPath } -//get user's root absolute path +// get user's root absolute path func GetUserMatterRootDir(username string) (rootDirPath string) { rootDirPath = fmt.Sprintf("%s/%s/%s", core.CONFIG.MatterPath(), username, MATTER_ROOT) @@ -92,7 +93,7 @@ func GetUserMatterRootDir(username string) (rootDirPath string) { return rootDirPath } -//get user's cache absolute path +// get user's cache absolute path func GetUserCacheRootDir(username string) (rootDirPath string) { rootDirPath = fmt.Sprintf("%s/%s/%s", core.CONFIG.MatterPath(), username, MATTER_CACHE) @@ -100,7 +101,7 @@ func GetUserCacheRootDir(username string) (rootDirPath string) { return rootDirPath } -//get user's zip absolute path +// get user's zip absolute path func GetUserZipRootDir(username string) (rootDirPath string) { rootDirPath = fmt.Sprintf("%s/%s/%s", core.CONFIG.MatterPath(), username, MATTER_ZIP) @@ -108,7 +109,7 @@ func GetUserZipRootDir(username string) (rootDirPath string) { return rootDirPath } -//check matter's name. If error, panic. +// check matter's name. If error, panic. func CheckMatterName(request *http.Request, name string) string { if name == "" { @@ -127,7 +128,7 @@ func CheckMatterName(request *http.Request, name string) string { return name } -//fetch the props +// fetch the props func (this *Matter) FetchPropMap() map[string]string { m := make(map[string]string) @@ -144,7 +145,7 @@ func (this *Matter) FetchPropMap() map[string]string { return m } -//fetch the props +// fetch the props func (this *Matter) SetPropMap(propMap map[string]string) { b, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(propMap) diff --git a/code/rest/space_controller.go b/code/rest/space_controller.go index 256f358..c95de2d 100644 --- a/code/rest/space_controller.go +++ b/code/rest/space_controller.go @@ -12,11 +12,13 @@ import ( type SpaceController struct { BaseController - spaceDao *SpaceDao - matterDao *MatterDao - matterService *MatterService - spaceService *SpaceService - userService *UserService + spaceDao *SpaceDao + spaceMemberDao *SpaceMemberDao + spaceMemberService *SpaceMemberService + matterDao *MatterDao + matterService *MatterService + spaceService *SpaceService + userService *UserService } func (this *SpaceController) Init() { @@ -27,6 +29,11 @@ func (this *SpaceController) Init() { this.spaceDao = b } + b = core.CONTEXT.GetBean(this.spaceMemberDao) + if b, ok := b.(*SpaceMemberDao); ok { + this.spaceMemberDao = b + } + b = core.CONTEXT.GetBean(this.matterDao) if b, ok := b.(*MatterDao); ok { this.matterDao = b @@ -54,7 +61,7 @@ func (this *SpaceController) RegisterRoutes() map[string]func(writer http.Respon routeMap := make(map[string]func(writer http.ResponseWriter, request *http.Request)) routeMap["/api/space/create"] = this.Wrap(this.Create, USER_ROLE_ADMINISTRATOR) - routeMap["/api/space/delete"] = this.Wrap(this.Delete, USER_ROLE_USER) + routeMap["/api/space/delete"] = this.Wrap(this.Delete, USER_ROLE_ADMINISTRATOR) routeMap["/api/space/detail"] = this.Wrap(this.Detail, USER_ROLE_USER) routeMap["/api/space/page"] = this.Wrap(this.Page, USER_ROLE_USER) @@ -119,13 +126,28 @@ func (this *SpaceController) Delete(writer http.ResponseWriter, request *http.Re panic(result.BadRequest("uuid cannot be null")) } - space := this.spaceDao.FindByUuid(uuid) + space := this.spaceDao.CheckByUuid(uuid) - if space != nil { - - this.spaceDao.Delete(space) + //when space has members, cannot delete. + memberCount := this.spaceMemberDao.CountBySpaceUuid(uuid) + if memberCount > 0 { + 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) + + //delete the space. + this.spaceDao.Delete(space) + return this.Success(nil) } @@ -136,14 +158,15 @@ func (this *SpaceController) Detail(writer http.ResponseWriter, request *http.Re panic(result.BadRequest("uuid cannot be null")) } - space := this.spaceDao.CheckByUuid(uuid) - user := this.checkUser(request) - - if space.UserUuid != user.Uuid { - panic(result.UNAUTHORIZED) + space := this.spaceDao.CheckByUuid(uuid) + canRead := this.spaceMemberService.canRead(user, space.Uuid) + if !canRead { + panic(result.BadRequestI18n(request, i18n.PermissionDenied)) } + space.User = this.userDao.FindByUuid(space.UserUuid) + return this.Success(space) } diff --git a/code/rest/space_member_controller.go b/code/rest/space_member_controller.go index 6f7865f..1a24427 100644 --- a/code/rest/space_member_controller.go +++ b/code/rest/space_member_controller.go @@ -106,8 +106,8 @@ func (this *SpaceMemberController) Create(writer http.ResponseWriter, request *h func (this *SpaceMemberController) Delete(writer http.ResponseWriter, request *http.Request) *result.WebResult { - spaceMemberUuid := request.FormValue("spaceMemberUuid") - spaceMember := this.spaceMemberDao.CheckByUuid(spaceMemberUuid) + uuid := request.FormValue("uuid") + spaceMember := this.spaceMemberDao.CheckByUuid(uuid) user := this.checkUser(request) canManage := this.spaceMemberService.canManageBySpaceMember(user, spaceMember) if !canManage { diff --git a/code/rest/space_member_dao.go b/code/rest/space_member_dao.go index 8025745..09c326d 100644 --- a/code/rest/space_member_dao.go +++ b/code/rest/space_member_dao.go @@ -111,6 +111,26 @@ func (this *SpaceMemberDao) Delete(spaceMember *SpaceMember) { } +func (this *SpaceMemberDao) DeleteBySpaceUuid(spaceUuid string) { + + var wp = &builder.WherePair{} + + wp = wp.And(&builder.WherePair{Query: "space_uuid = ?", Args: []interface{}{spaceUuid}}) + + db := core.CONTEXT.GetDB().Where(wp.Query, wp.Args).Delete(SpaceMember{}) + this.PanicError(db.Error) +} + +func (this *SpaceMemberDao) CountBySpaceUuid(spaceUuid string) int { + var count int64 + db := core.CONTEXT.GetDB(). + Model(&SpaceMember{}). + Where("space_uuid = ?", spaceUuid). + Count(&count) + this.PanicError(db.Error) + return int(count) +} + // System cleanup. func (this *SpaceMemberDao) Cleanup() { this.logger.Info("[SpaceMemberDao] clean up. Delete all SpaceMember") diff --git a/code/tool/i18n/i18n.go b/code/tool/i18n/i18n.go index bf53591..ae64dd9 100644 --- a/code/tool/i18n/i18n.go +++ b/code/tool/i18n/i18n.go @@ -48,7 +48,7 @@ var ( 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"已存在`} + SpaceNameExist = &Item{English: `space's name "%s" exists`, Chinese: `共享空间名称"%s"已被占用,请使用其他名字`} 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: `没有操作权限`}