Add the deleted feature.

This commit is contained in:
lishuang 2020-07-12 17:26:15 +08:00
parent c970acbe8b
commit 82047f4504
4 changed files with 176 additions and 8 deletions

View File

@ -73,6 +73,8 @@ func (this *MatterController) RegisterRoutes() map[string]func(writer http.Respo
routeMap["/api/matter/create/directory"] = this.Wrap(this.CreateDirectory, USER_ROLE_USER) routeMap["/api/matter/create/directory"] = this.Wrap(this.CreateDirectory, USER_ROLE_USER)
routeMap["/api/matter/upload"] = this.Wrap(this.Upload, USER_ROLE_USER) routeMap["/api/matter/upload"] = this.Wrap(this.Upload, USER_ROLE_USER)
routeMap["/api/matter/crawl"] = this.Wrap(this.Crawl, USER_ROLE_USER) routeMap["/api/matter/crawl"] = this.Wrap(this.Crawl, USER_ROLE_USER)
routeMap["/api/matter/soft/delete"] = this.Wrap(this.SoftDelete, USER_ROLE_USER)
routeMap["/api/matter/soft/delete/batch"] = this.Wrap(this.SoftDeleteBatch, USER_ROLE_USER)
routeMap["/api/matter/delete"] = this.Wrap(this.Delete, USER_ROLE_USER) routeMap["/api/matter/delete"] = this.Wrap(this.Delete, USER_ROLE_USER)
routeMap["/api/matter/delete/batch"] = this.Wrap(this.DeleteBatch, USER_ROLE_USER) routeMap["/api/matter/delete/batch"] = this.Wrap(this.DeleteBatch, USER_ROLE_USER)
routeMap["/api/matter/rename"] = this.Wrap(this.Rename, USER_ROLE_USER) routeMap["/api/matter/rename"] = this.Wrap(this.Rename, USER_ROLE_USER)
@ -118,6 +120,7 @@ func (this *MatterController) Page(writer http.ResponseWriter, request *http.Req
puuid := request.FormValue("puuid") puuid := request.FormValue("puuid")
name := request.FormValue("name") name := request.FormValue("name")
dir := request.FormValue("dir") dir := request.FormValue("dir")
deleted := request.FormValue("deleted")
orderDir := request.FormValue("orderDir") orderDir := request.FormValue("orderDir")
orderSize := request.FormValue("orderSize") orderSize := request.FormValue("orderSize")
orderName := request.FormValue("orderName") orderName := request.FormValue("orderName")
@ -201,7 +204,7 @@ func (this *MatterController) Page(writer http.ResponseWriter, request *http.Req
}, },
} }
pager := this.matterDao.Page(page, pageSize, puuid, userUuid, name, dir, extensions, sortArray) pager := this.matterDao.Page(page, pageSize, puuid, userUuid, name, dir, deleted, extensions, sortArray)
return this.Success(pager) return this.Success(pager)
} }
@ -280,6 +283,57 @@ func (this *MatterController) Crawl(writer http.ResponseWriter, request *http.Re
return this.Success(matter) return this.Success(matter)
} }
//soft delete.
func (this *MatterController) SoftDelete(writer http.ResponseWriter, request *http.Request) *result.WebResult {
uuid := request.FormValue("uuid")
if uuid == "" {
panic(result.BadRequest("uuid cannot be null"))
}
matter := this.matterDao.CheckByUuid(uuid)
user := this.checkUser(request)
if matter.UserUuid != user.Uuid {
panic(result.UNAUTHORIZED)
}
this.matterService.AtomicSoftDelete(request, matter, user)
return this.Success("OK")
}
func (this *MatterController) SoftDeleteBatch(writer http.ResponseWriter, request *http.Request) *result.WebResult {
uuids := request.FormValue("uuids")
if uuids == "" {
panic(result.BadRequest("uuids cannot be null"))
}
uuidArray := strings.Split(uuids, ",")
for _, uuid := range uuidArray {
matter := this.matterDao.FindByUuid(uuid)
if matter == nil {
this.logger.Warn("%s not exist anymore", uuid)
continue
}
user := this.checkUser(request)
if matter.UserUuid != user.Uuid {
panic(result.UNAUTHORIZED)
}
this.matterService.AtomicSoftDelete(request, matter, user)
}
return this.Success("OK")
}
//complete delete.
func (this *MatterController) Delete(writer http.ResponseWriter, request *http.Request) *result.WebResult { func (this *MatterController) Delete(writer http.ResponseWriter, request *http.Request) *result.WebResult {
uuid := request.FormValue("uuid") uuid := request.FormValue("uuid")
@ -357,6 +411,10 @@ func (this *MatterController) ChangePrivacy(writer http.ResponseWriter, request
matter := this.matterDao.CheckByUuid(uuid) matter := this.matterDao.CheckByUuid(uuid)
if matter.Deleted {
panic(result.BadRequest("matter has been deleted. Cannot change privacy."))
}
if matter.Privacy == privacy { if matter.Privacy == privacy {
panic(result.BadRequest("not changed. Invalid operation.")) panic(result.BadRequest("not changed. Invalid operation."))
} }
@ -395,6 +453,10 @@ func (this *MatterController) Move(writer http.ResponseWriter, request *http.Req
panic(result.UNAUTHORIZED) panic(result.UNAUTHORIZED)
} }
if destMatter.Deleted {
panic(result.BadRequest("dest matter has been deleted. Cannot move."))
}
var srcMatters []*Matter var srcMatters []*Matter
for _, uuid := range srcUuids { for _, uuid := range srcUuids {
srcMatter := this.matterDao.CheckByUuid(uuid) srcMatter := this.matterDao.CheckByUuid(uuid)
@ -403,6 +465,10 @@ func (this *MatterController) Move(writer http.ResponseWriter, request *http.Req
panic(result.BadRequest("no move, invalid operation")) panic(result.BadRequest("no move, invalid operation"))
} }
if srcMatter.Deleted {
panic(result.BadRequest("src matter has been deleted. Cannot move."))
}
//check whether there are files with the same name. //check whether there are files with the same name.
count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, destMatter.Uuid, srcMatter.Dir, srcMatter.Name) count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, destMatter.Uuid, srcMatter.Dir, srcMatter.Name)
@ -461,6 +527,13 @@ func (this *MatterController) Zip(writer http.ResponseWriter, request *http.Requ
if matters == nil || len(matters) == 0 { if matters == nil || len(matters) == 0 {
panic(result.BadRequest("matters cannot be nil.")) panic(result.BadRequest("matters cannot be nil."))
} }
for _, matter := range matters {
if matter.Deleted {
panic(result.BadRequest("matter has been deleted. Cannot download batch."))
}
}
user := this.checkUser(request) user := this.checkUser(request)
puuid := matters[0].Puuid puuid := matters[0].Puuid

View File

@ -246,7 +246,7 @@ func (this *MatterDao) FindByUuids(uuids []string, sortArray []builder.OrderPair
return matters return matters
} }
func (this *MatterDao) PlainPage(page int, pageSize int, puuid string, userUuid string, name string, dir string, extensions []string, sortArray []builder.OrderPair) (int, []*Matter) { func (this *MatterDao) PlainPage(page int, pageSize int, puuid string, userUuid string, name string, dir string, deleted string, extensions []string, sortArray []builder.OrderPair) (int, []*Matter) {
var wp = &builder.WherePair{} var wp = &builder.WherePair{}
@ -268,6 +268,12 @@ func (this *MatterDao) PlainPage(page int, pageSize int, puuid string, userUuid
wp = wp.And(&builder.WherePair{Query: "dir = ?", Args: []interface{}{0}}) wp = wp.And(&builder.WherePair{Query: "dir = ?", Args: []interface{}{0}})
} }
if deleted == TRUE {
wp = wp.And(&builder.WherePair{Query: "deleted = ?", Args: []interface{}{1}})
} else if deleted == FALSE {
wp = wp.And(&builder.WherePair{Query: "deleted = ?", Args: []interface{}{0}})
}
var conditionDB *gorm.DB var conditionDB *gorm.DB
if extensions != nil && len(extensions) > 0 { if extensions != nil && len(extensions) > 0 {
var orWp = &builder.WherePair{} var orWp = &builder.WherePair{}
@ -291,16 +297,16 @@ func (this *MatterDao) PlainPage(page int, pageSize int, puuid string, userUuid
return count, matters return count, matters
} }
func (this *MatterDao) Page(page int, pageSize int, puuid string, userUuid string, name string, dir string, extensions []string, sortArray []builder.OrderPair) *Pager { func (this *MatterDao) Page(page int, pageSize int, puuid string, userUuid string, name string, dir string, deleted string, extensions []string, sortArray []builder.OrderPair) *Pager {
count, matters := this.PlainPage(page, pageSize, puuid, userUuid, name, dir, extensions, sortArray) count, matters := this.PlainPage(page, pageSize, puuid, userUuid, name, dir, deleted, extensions, sortArray)
pager := NewPager(page, pageSize, count, matters) pager := NewPager(page, pageSize, count, matters)
return pager return pager
} }
//handle matter page by page. //handle matter page by page.
func (this *MatterDao) PageHandle(puuid string, userUuid string, name string, dir string, fun func(matter *Matter)) { func (this *MatterDao) PageHandle(puuid string, userUuid string, name string, dir string, deleted string, fun func(matter *Matter)) {
//delete share and bridges. //delete share and bridges.
pageSize := 1000 pageSize := 1000
@ -310,13 +316,13 @@ func (this *MatterDao) PageHandle(puuid string, userUuid string, name string, di
Value: DIRECTION_ASC, Value: DIRECTION_ASC,
}, },
} }
count, _ := this.PlainPage(0, pageSize, puuid, userUuid, name, dir, nil, sortArray) count, _ := this.PlainPage(0, pageSize, puuid, userUuid, name, dir, deleted, nil, sortArray)
if count > 0 { if count > 0 {
var totalPages = int(math.Ceil(float64(count) / float64(pageSize))) var totalPages = int(math.Ceil(float64(count) / float64(pageSize)))
var page int var page int
for page = 0; page < totalPages; page++ { for page = 0; page < totalPages; page++ {
_, matters := this.PlainPage(0, pageSize, puuid, userUuid, name, dir, nil, sortArray) _, matters := this.PlainPage(0, pageSize, puuid, userUuid, name, dir, deleted, nil, sortArray)
for _, matter := range matters { for _, matter := range matters {
fun(matter) fun(matter)
} }
@ -411,6 +417,37 @@ func (this *MatterDao) Delete(matter *Matter) {
} }
} }
//soft delete a file from db and disk.
func (this *MatterDao) SoftDelete(matter *Matter) {
// recursive if dir
if matter.Dir {
matters := this.FindByPuuidAndUserUuid(matter.Uuid, matter.UserUuid, nil)
for _, f := range matters {
this.SoftDelete(f)
}
//soft delete from db.
db := core.CONTEXT.GetDB().Model(&Matter{}).Where("uuid = ?", matter.Uuid).Update(map[string]interface{}{"deleted": 1})
this.PanicError(db.Error)
} else {
//soft delete from db.
db := core.CONTEXT.GetDB().Model(&Matter{}).Where("uuid = ?", matter.Uuid).Update(map[string]interface{}{"deleted": 1})
this.PanicError(db.Error)
//no need to delete its image cache.
//delete all the share.
this.bridgeDao.DeleteByMatterUuid(matter.Uuid)
//no need to delete from disk.
}
}
func (this *MatterDao) DeleteByUserUuid(userUuid string) { func (this *MatterDao) DeleteByUserUuid(userUuid string) {
db := core.CONTEXT.GetDB().Where("user_uuid = ?", userUuid).Delete(Matter{}) db := core.CONTEXT.GetDB().Where("user_uuid = ?", userUuid).Delete(Matter{})

View File

@ -45,6 +45,7 @@ type Matter struct {
Children []*Matter `json:"-" gorm:"-"` Children []*Matter `json:"-" gorm:"-"`
Prop string `json:"prop" gorm:"type:varchar(1024) not null;default:'{}'"` 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'"` 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;default:0"`
} }
// set File's table name to be `profiles` // set File's table name to be `profiles`

View File

@ -255,6 +255,21 @@ func (this *MatterService) Delete(request *http.Request, matter *Matter, user *U
this.ComputeRouteSize(matter.Puuid, user) this.ComputeRouteSize(matter.Puuid, user)
} }
//soft delete files.
func (this *MatterService) SoftDelete(request *http.Request, matter *Matter, user *User) {
if matter == nil {
panic(result.BadRequest("matter cannot be nil"))
}
if matter.Deleted {
panic(result.BadRequest("matter has been deleted"))
}
this.matterDao.SoftDelete(matter)
//no need to recompute size.
}
//atomic delete files //atomic delete files
func (this *MatterService) AtomicDelete(request *http.Request, matter *Matter, user *User) { func (this *MatterService) AtomicDelete(request *http.Request, matter *Matter, user *User) {
@ -269,6 +284,24 @@ func (this *MatterService) AtomicDelete(request *http.Request, matter *Matter, u
this.Delete(request, matter, user) this.Delete(request, matter, user)
} }
//atomic soft delete files
func (this *MatterService) AtomicSoftDelete(request *http.Request, matter *Matter, user *User) {
if matter == nil {
panic(result.BadRequest("matter cannot be nil"))
}
if matter.Deleted {
panic(result.BadRequest("matter has been deleted"))
}
//lock
this.userService.MatterLock(matter.UserUuid)
defer this.userService.MatterUnlock(matter.UserUuid)
this.SoftDelete(request, matter, user)
}
//upload files. //upload files.
func (this *MatterService) Upload(request *http.Request, file io.Reader, user *User, dirMatter *Matter, filename string, privacy bool) *Matter { func (this *MatterService) Upload(request *http.Request, file io.Reader, user *User, dirMatter *Matter, filename string, privacy bool) *Matter {
@ -280,6 +313,10 @@ func (this *MatterService) Upload(request *http.Request, file io.Reader, user *U
panic(result.BadRequest("dirMatter cannot be nil.")) panic(result.BadRequest("dirMatter cannot be nil."))
} }
if dirMatter.Deleted {
panic(result.BadRequest("Dir has been deleted. Cannot upload under it."))
}
if len(filename) > MATTER_NAME_MAX_LENGTH { if len(filename) > MATTER_NAME_MAX_LENGTH {
panic(result.BadRequestI18n(request, i18n.MatterNameLengthExceedLimit, len(filename), MATTER_NAME_MAX_LENGTH)) panic(result.BadRequestI18n(request, i18n.MatterNameLengthExceedLimit, len(filename), MATTER_NAME_MAX_LENGTH))
} }
@ -479,6 +516,10 @@ func (this *MatterService) createDirectory(request *http.Request, dirMatter *Mat
panic(result.BadRequest("dirMatter must be directory")) panic(result.BadRequest("dirMatter must be directory"))
} }
if dirMatter.Deleted {
panic(result.BadRequest("Dir has been deleted. Cannot create dir under it."))
}
if dirMatter.UserUuid != user.Uuid { if dirMatter.UserUuid != user.Uuid {
panic(result.BadRequest("file's user not the same")) panic(result.BadRequest("file's user not the same"))
@ -537,6 +578,10 @@ func (this *MatterService) createDirectory(request *http.Request, dirMatter *Mat
func (this *MatterService) AtomicCreateDirectory(request *http.Request, dirMatter *Matter, name string, user *User) *Matter { func (this *MatterService) AtomicCreateDirectory(request *http.Request, dirMatter *Matter, name string, user *User) *Matter {
if dirMatter.Deleted {
panic(result.BadRequest("Dir has been deleted. Cannot create sub dir under it."))
}
this.userService.MatterLock(user.Uuid) this.userService.MatterLock(user.Uuid)
defer this.userService.MatterUnlock(user.Uuid) defer this.userService.MatterUnlock(user.Uuid)
@ -782,6 +827,10 @@ func (this *MatterService) AtomicRename(request *http.Request, matter *Matter, n
panic(result.BadRequest("user cannot be nil")) panic(result.BadRequest("user cannot be nil"))
} }
if matter.Deleted {
panic(result.BadRequest("matter has been deleted. Cannot rename."))
}
this.userService.MatterLock(user.Uuid) this.userService.MatterLock(user.Uuid)
defer this.userService.MatterUnlock(user.Uuid) defer this.userService.MatterUnlock(user.Uuid)
@ -869,6 +918,10 @@ func (this *MatterService) AtomicMirror(request *http.Request, srcPath string, d
destDirMatter := this.CreateDirectories(request, user, destPath) destDirMatter := this.CreateDirectories(request, user, destPath)
if destDirMatter.Deleted {
panic(result.BadRequest("dest matter has been deleted. Cannot mirror."))
}
this.mirror(request, srcPath, destDirMatter, overwrite, user) this.mirror(request, srcPath, destDirMatter, overwrite, user)
} }
@ -1036,6 +1089,10 @@ func (this *MatterService) AtomicCrawl(request *http.Request, url string, filena
panic(result.BadRequest("user cannot be nil.")) panic(result.BadRequest("user cannot be nil."))
} }
if dirMatter.Deleted {
panic(result.BadRequest("Dir has been deleted. Cannot crawl under it."))
}
this.userService.MatterLock(user.Uuid) this.userService.MatterLock(user.Uuid)
defer this.userService.MatterUnlock(user.Uuid) defer this.userService.MatterUnlock(user.Uuid)
@ -1138,7 +1195,7 @@ func (this *MatterService) scanPhysicsFolder(request *http.Request, dirInfo os.F
} }
//fetch all matters under this folder. //fetch all matters under this folder.
_, matters := this.matterDao.PlainPage(0, 1000, dirMatter.Uuid, user.Uuid, "", "", nil, nil) _, matters := this.matterDao.PlainPage(0, 1000, dirMatter.Uuid, user.Uuid, "", "", "", nil, nil)
nameMatterMap := make(map[string]*Matter) nameMatterMap := make(map[string]*Matter)
for _, m := range matters { for _, m := range matters {
nameMatterMap[m.Name] = m nameMatterMap[m.Name] = m