Skip to content

Commit

Permalink
support deleting multiple file records at once
Browse files Browse the repository at this point in the history
  • Loading branch information
or-else committed Jun 10, 2018
1 parent 1affd61 commit 89796b8
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 26 deletions.
34 changes: 28 additions & 6 deletions server/db/mysql/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ func (a *adapter) UserGetAll(ids ...t.Uid) ([]t.User, error) {

users := []t.User{}
q, _, _ := sqlx.In("SELECT * FROM users WHERE id IN (?)", uids)
q = a.db.Rebind(q)
rows, err := a.db.Queryx(q, uids...)
if err != nil {
return nil, err
Expand Down Expand Up @@ -861,6 +862,7 @@ func (a *adapter) TopicsForUser(uid t.Uid, keepDeleted bool, opts *t.QueryOpt) (
q, _, _ := sqlx.In(
"SELECT createdat,updatedat,deletedat,touchedat,name AS id,access,seqid,delid,public,tags "+
"FROM topics WHERE name IN (?)", topq)
q = a.db.Rebind(q)
rows, err = a.db.Queryx(q, topq...)
if err != nil {
return nil, err
Expand Down Expand Up @@ -1813,13 +1815,33 @@ func (a *adapter) FileGet(fid string) (*t.FileDef, error) {

}

// FileDelete deletes a record of a file
func (a *adapter) FileDelete(fid string) error {
uid := t.ParseUid(fid)
if uid.IsZero() {
return t.ErrMalformed
// FileDelete deletes records of a files if uid matches the owner.
// If uid is zero, delete the records regardless of the owner.
// If fids is not provided, delete all record of a given user.
func (a *adapter) FileDelete(uid t.Uid, fids ...string) error {
var args []interface{}
query := "DELETE FROM fileuploads WHERE "
if len(fids) > 0 {
query += "id IN (?" + strings.Repeat(",?", len(fids)-1) + ") "
for _, fid := range fids {
id := t.ParseUid(fid)
if id.IsZero() {
return t.ErrMalformed
}
args = append(args, id)
}
}
_, err := a.db.Exec("DELETE FROM fileuploads WHERE id=?", store.DecodeUid(uid))
if !uid.IsZero() {
if len(args) > 0 {
query += "AND "
}
query += "userid=?"
args = append(args, store.DecodeUid(uid))
}
if len(args) == 0 {
return errors.New("FileDelete: no arguments provided")
}
_, err := a.db.Exec(query, args...)
return err
}

Expand Down
24 changes: 9 additions & 15 deletions server/hdl_files.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,6 @@ func largeFileServe(wrt http.ResponseWriter, req *http.Request) {
enc.Encode(msg)
}

// Check if this is a GET request
if req.Method != http.MethodGet {
writeHttpResponse(ErrOperationNotAllowed("", "", now))
return
}

// Check for API key presence
if isValid, _ := checkAPIKey(getAPIKey(req)); !isValid {
writeHttpResponse(ErrAPIKeyRequired(now))
Expand Down Expand Up @@ -97,7 +91,7 @@ func largeFileServe(wrt http.ResponseWriter, req *http.Request) {
return
}

// FIXME: The following code is dependent on storage method.
// FIXME: The following code is dependent on the storage method.
log.Println("Opening file", fd.Location)
file, err := os.Open(fd.Location)
if err != nil {
Expand Down Expand Up @@ -159,16 +153,16 @@ func largeFileUpload(wrt http.ResponseWriter, req *http.Request) {
if strings.Contains(err.Error(), "request body too large") {
log.Println("Uploaded file is too large", err)
writeHttpResponse(ErrTooLarge("", "", now))
if strings.Contains(err.Error(), "unexpected EOF") {
log.Println("Upload interrupted by client", err)
writeHttpResponse(ErrMalformed("", "", now))
} else {
log.Println("Upload error", err)
writeHttpResponse(ErrMalformed("", "", now))
if strings.Contains(err.Error(), "unexpected EOF") {
log.Println("Upload interrupted by client", err)
writeHttpResponse(ErrMalformed("", "", now))
} else {
log.Println("Upload error", err)
writeHttpResponse(ErrMalformed("", "", now))
}
return
}
return
}

fdef := types.FileDef{}
fdef.Id = store.GetUidString()
fdef.InitTimes()
Expand Down
5 changes: 3 additions & 2 deletions server/store/adapter/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ type Adapter interface {
FilesForUser(uid t.Uid, opts *t.QueryOpt) ([]t.FileDef, error)
// FileGet fetches a record of a specific file
FileGet(fid string) (*t.FileDef, error)
// FileDelete deletes a record of a file
FileDelete(fid string) error
// FileDelete deletes records of a file if file owner matched the uid.
// If uid is zero, the ownership is not checked.
FileDelete(uid t.Uid, fid ...string) error
}
7 changes: 4 additions & 3 deletions server/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,8 @@ func (FileMapper) Get(fid string) (*types.FileDef, error) {
return adp.FileGet(fid)
}

// Delete file record by unique ID.
func (FileMapper) Delete(fid string) error {
return adp.FileDelete(fid)
// Delete deletes file records by a list of file IDs. If uid is not zero, only
// files owned by the given user are deleted. If fids are missing, delete all files for the given uid.
func (FileMapper) Delete(uid types.Uid, fid ...string) error {
return adp.FileDelete(uid, fid...)
}

0 comments on commit 89796b8

Please sign in to comment.