diff --git a/backend/box/api/types.go b/backend/box/api/types.go index e26f05286..c6e96b121 100644 --- a/backend/box/api/types.go +++ b/backend/box/api/types.go @@ -61,7 +61,7 @@ func (e *Error) Error() string { var _ error = (*Error)(nil) // ItemFields are the fields needed for FileInfo -var ItemFields = "type,id,sequence_id,etag,sha1,name,size,created_at,modified_at,content_created_at,content_modified_at,item_status" +var ItemFields = "type,id,sequence_id,etag,sha1,name,size,created_at,modified_at,content_created_at,content_modified_at,item_status,shared_link" // Types of things in Item const ( @@ -86,6 +86,10 @@ type Item struct { ContentCreatedAt Time `json:"content_created_at"` ContentModifiedAt Time `json:"content_modified_at"` ItemStatus string `json:"item_status"` // active, trashed if the file has been moved to the trash, and deleted if the file has been permanently deleted + SharedLink struct { + URL string `json:"url,omitempty"` + Access string `json:"access,omitempty"` + } `json:"shared_link"` } // ModTime returns the modification time of the item @@ -145,6 +149,14 @@ type CopyFile struct { Parent Parent `json:"parent"` } +// CreateSharedLink is the request for Public Link +type CreateSharedLink struct { + SharedLink struct { + URL string `json:"url,omitempty"` + Access string `json:"access,omitempty"` + } `json:"shared_link"` +} + // UploadSessionRequest is uses in Create Upload Session type UploadSessionRequest struct { FolderID string `json:"folder_id,omitempty"` // don't pass for update diff --git a/backend/box/box.go b/backend/box/box.go index 9ee8c9ff8..c6e9b5fc8 100644 --- a/backend/box/box.go +++ b/backend/box/box.go @@ -126,6 +126,7 @@ type Object struct { size int64 // size of the object modTime time.Time // modification time of the object id string // ID of the object + publicLink string // Public Link for the object sha1 string // SHA-1 of the object content } @@ -299,6 +300,7 @@ func NewFs(name, root string, m configmap.Mapper) (fs.Fs, error) { } return nil, err } + f.features.Fill(&newF) // return an error with an fs which points to the parent return &newF, fs.ErrorIsFile } @@ -844,6 +846,46 @@ func (f *Fs) DirMove(src fs.Fs, srcRemote, dstRemote string) error { return nil } +// PublicLink adds a "readable by anyone with link" permission on the given file or folder. +func (f *Fs) PublicLink(remote string) (string, error) { + id, err := f.dirCache.FindDir(remote, false) + var opts rest.Opts + if err == nil { + fs.Debugf(f, "attempting to share directory '%s'", remote) + + opts = rest.Opts{ + Method: "PUT", + Path: "/folders/" + id, + Parameters: fieldsValue(), + } + } else { + fs.Debugf(f, "attempting to share single file '%s'", remote) + o, err := f.NewObject(remote) + if err != nil { + return "", err + } + + if o.(*Object).publicLink != "" { + return o.(*Object).publicLink, nil + } + + opts = rest.Opts{ + Method: "PUT", + Path: "/files/" + o.(*Object).id, + Parameters: fieldsValue(), + } + } + + shareLink := api.CreateSharedLink{} + var info api.Item + var resp *http.Response + err = f.pacer.Call(func() (bool, error) { + resp, err = f.srv.CallJSON(&opts, &shareLink, &info) + return shouldRetry(resp, err) + }) + return info.SharedLink.URL, err +} + // DirCacheFlush resets the directory cache - used in testing as an // optional interface func (f *Fs) DirCacheFlush() { @@ -908,6 +950,7 @@ func (o *Object) setMetaData(info *api.Item) (err error) { o.sha1 = info.SHA1 o.modTime = info.ModTime() o.id = info.ID + o.publicLink = info.SharedLink.URL return nil } @@ -1087,6 +1130,7 @@ var ( _ fs.Mover = (*Fs)(nil) _ fs.DirMover = (*Fs)(nil) _ fs.DirCacheFlusher = (*Fs)(nil) + _ fs.PublicLinker = (*Fs)(nil) _ fs.Object = (*Object)(nil) _ fs.IDer = (*Object)(nil) ) diff --git a/docs/content/overview.md b/docs/content/overview.md index 85ea8e79b..7f24b58a5 100644 --- a/docs/content/overview.md +++ b/docs/content/overview.md @@ -131,7 +131,7 @@ operations more efficient. | Amazon Drive | Yes | No | Yes | Yes | No [#575](https://github.com/ncw/rclone/issues/575) | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | No | | Amazon S3 | No | Yes | No | No | No | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | No | | Backblaze B2 | No | No | No | No | Yes | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | No | -| Box | Yes | Yes | Yes | Yes | No [#575](https://github.com/ncw/rclone/issues/575) | No | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | No | +| Box | Yes | Yes | Yes | Yes | No [#575](https://github.com/ncw/rclone/issues/575) | No | Yes | Yes | No | | Dropbox | Yes | Yes | Yes | Yes | No [#575](https://github.com/ncw/rclone/issues/575) | No | Yes | Yes | Yes | | FTP | No | No | Yes | Yes | No | No | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | No | | Google Cloud Storage | Yes | Yes | No | No | No | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |