mirror of
https://github.com/rclone/rclone.git
synced 2024-12-22 15:11:56 +01:00
seafile: renew library password - fixes #6662
Passwords for encrypted libraries are kept in memory in the server and flushed after an hour. This MR fixes an issue when the library password expires after 1 hour.
This commit is contained in:
parent
f08bb5bf66
commit
f31ab6d178
54
backend/seafile/renew.go
Normal file
54
backend/seafile/renew.go
Normal file
@ -0,0 +1,54 @@
|
||||
package seafile
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/rclone/rclone/fs"
|
||||
)
|
||||
|
||||
// Renew allows tokens to be renewed on expiry.
|
||||
type Renew struct {
|
||||
ts *time.Ticker // timer indicating when it's time to renew the token
|
||||
run func() error // the callback to do the renewal
|
||||
done chan interface{} // channel to end the go routine
|
||||
shutdown *sync.Once
|
||||
}
|
||||
|
||||
// NewRenew creates a new Renew struct and starts a background process
|
||||
// which renews the token whenever it expires. It uses the run() call
|
||||
// to do the renewal.
|
||||
func NewRenew(every time.Duration, run func() error) *Renew {
|
||||
r := &Renew{
|
||||
ts: time.NewTicker(every),
|
||||
run: run,
|
||||
done: make(chan interface{}),
|
||||
shutdown: &sync.Once{},
|
||||
}
|
||||
go r.renewOnExpiry()
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Renew) renewOnExpiry() {
|
||||
for {
|
||||
select {
|
||||
case <-r.ts.C:
|
||||
err := r.run()
|
||||
if err != nil {
|
||||
fs.Errorf(nil, "error while refreshing decryption token: %s", err)
|
||||
}
|
||||
|
||||
case <-r.done:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shutdown stops the ticker and no more renewal will take place.
|
||||
func (r *Renew) Shutdown() {
|
||||
// closing a channel can only be done once
|
||||
r.shutdown.Do(func() {
|
||||
r.ts.Stop()
|
||||
close(r.done)
|
||||
})
|
||||
}
|
35
backend/seafile/renew_test.go
Normal file
35
backend/seafile/renew_test.go
Normal file
@ -0,0 +1,35 @@
|
||||
package seafile
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestShouldAllowShutdownTwice(t *testing.T) {
|
||||
renew := NewRenew(time.Hour, func() error {
|
||||
return nil
|
||||
})
|
||||
renew.Shutdown()
|
||||
renew.Shutdown()
|
||||
}
|
||||
|
||||
func TestRenewal(t *testing.T) {
|
||||
var count int64
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(2) // run the renewal twice
|
||||
renew := NewRenew(time.Millisecond, func() error {
|
||||
atomic.AddInt64(&count, 1)
|
||||
wg.Done()
|
||||
return nil
|
||||
})
|
||||
wg.Wait()
|
||||
renew.Shutdown()
|
||||
|
||||
// it is technically possible that a third renewal gets triggered between Wait() and Shutdown()
|
||||
assert.GreaterOrEqual(t, atomic.LoadInt64(&count), int64(2))
|
||||
}
|
@ -143,6 +143,7 @@ type Fs struct {
|
||||
createDirMutex sync.Mutex // Protect creation of directories
|
||||
useOldDirectoryAPI bool // Use the old API v2 if seafile < 7
|
||||
moveDirNotAvailable bool // Version < 7.0 don't have an API to move a directory
|
||||
renew *Renew // Renew an encrypted library token
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
@ -268,6 +269,11 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
|
||||
}
|
||||
// And remove the public link feature
|
||||
f.features.PublicLink = nil
|
||||
|
||||
// renew the library password every 45 minutes
|
||||
f.renew = NewRenew(45*time.Minute, func() error {
|
||||
return f.authorizeLibrary(context.Background(), libraryID)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// Deactivate the cleaner feature since there's no library selected
|
||||
@ -383,6 +389,15 @@ func Config(ctx context.Context, name string, m configmap.Mapper, config fs.Conf
|
||||
return nil, fmt.Errorf("unknown state %q", config.State)
|
||||
}
|
||||
|
||||
// Shutdown the Fs
|
||||
func (f *Fs) Shutdown(ctx context.Context) error {
|
||||
if f.renew == nil {
|
||||
return nil
|
||||
}
|
||||
f.renew.Shutdown()
|
||||
return nil
|
||||
}
|
||||
|
||||
// sets the AuthorizationToken up
|
||||
func (f *Fs) setAuthorizationToken(token string) {
|
||||
f.srv.SetHeader("Authorization", "Token "+token)
|
||||
@ -1331,6 +1346,7 @@ var (
|
||||
_ fs.PutStreamer = &Fs{}
|
||||
_ fs.PublicLinker = &Fs{}
|
||||
_ fs.UserInfoer = &Fs{}
|
||||
_ fs.Shutdowner = &Fs{}
|
||||
_ fs.Object = &Object{}
|
||||
_ fs.IDer = &Object{}
|
||||
)
|
||||
|
@ -8,9 +8,10 @@ versionIntroduced: "v1.52"
|
||||
|
||||
This is a backend for the [Seafile](https://www.seafile.com/) storage service:
|
||||
- It works with both the free community edition or the professional edition.
|
||||
- Seafile versions 6.x and 7.x are all supported.
|
||||
- Seafile versions 6.x, 7.x, 8.x and 9.x are all supported.
|
||||
- Encrypted libraries are also supported.
|
||||
- It supports 2FA enabled users
|
||||
- Using a Library API Token is **not** supported
|
||||
|
||||
## Configuration
|
||||
|
||||
@ -256,14 +257,17 @@ that has already been shared, you will get the exact same link.
|
||||
|
||||
### Compatibility
|
||||
|
||||
It has been actively tested using the [seafile docker image](https://github.com/haiwen/seafile-docker) of these versions:
|
||||
It has been actively developed using the [seafile docker image](https://github.com/haiwen/seafile-docker) of these versions:
|
||||
- 6.3.4 community edition
|
||||
- 7.0.5 community edition
|
||||
- 7.1.3 community edition
|
||||
- 9.0.10 community edition
|
||||
|
||||
Versions below 6.0 are not supported.
|
||||
Versions between 6.0 and 6.3 haven't been tested and might not work properly.
|
||||
|
||||
Each new version of `rclone` is automatically tested against the [latest docker image](https://hub.docker.com/r/seafileltd/seafile-mc/) of the seafile community server.
|
||||
|
||||
{{< rem autogenerated options start" - DO NOT EDIT - instead edit fs.RegInfo in backend/seafile/seafile.go then run make backenddocs" >}}
|
||||
### Standard options
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
version: '2.0'
|
||||
services:
|
||||
db:
|
||||
image: mariadb:10.1
|
||||
image: mariadb:10.5
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
|
||||
- MYSQL_LOG_CONSOLE=true
|
||||
@ -9,7 +9,7 @@ services:
|
||||
- ${SEAFILE_TEST_DATA}/${NAME}/seafile-mysql/db:/var/lib/mysql
|
||||
|
||||
memcached:
|
||||
image: memcached:1.5.6
|
||||
image: memcached:1.6.9
|
||||
entrypoint: memcached -m 256
|
||||
|
||||
seafile:
|
||||
|
Loading…
Reference in New Issue
Block a user