Skip to content

Commit

Permalink
Delete public links on GET (#1364) (#1374)
Browse files Browse the repository at this point in the history
Co-authored-by: Alex Unger <6905948+refs@users.noreply.github.com>
  • Loading branch information
labkode and refs authored Dec 16, 2020
1 parent 8be3976 commit 5207197
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 4 deletions.
5 changes: 5 additions & 0 deletions changelog/unreleased/delete-public-link-on-get-operations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Enhancement: Remove expired Link on Get

There is the scenario in which a public link has expired but ListPublicLink has not run, accessing a technically expired public share is still possible.

https://github.com/cs3org/reva/pull/1364
67 changes: 63 additions & 4 deletions pkg/publicshare/manager/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ import (
"io/ioutil"
"math/rand"
"os"
"os/signal"
"path/filepath"
"sync"
"syscall"
"time"

"github.com/rs/zerolog/log"
Expand All @@ -46,6 +48,30 @@ import (
"go.opencensus.io/trace"
)

type janitor struct {
m *manager
interval time.Duration
}

func (j *janitor) run() {
ticker := time.NewTicker(j.interval)
work := make(chan os.Signal, 1)
signal.Notify(work, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT)

for {
select {
case <-work:
return
case <-ticker.C:
j.m.cleanupExpiredShares()
}
}
}

var j = janitor{
interval: time.Minute, // TODO we want this interval configurable
}

func init() {
registry.Register("json", New)
}
Expand Down Expand Up @@ -86,6 +112,9 @@ func New(c map[string]interface{}) (publicshare.Manager, error) {
}
}

j.m = &m
go j.run()

return &m, nil
}

Expand Down Expand Up @@ -292,6 +321,12 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu
}

if ref.GetId().GetOpaqueId() == ps.Id.OpaqueId {
if !notExpired(ps) {
if err := m.revokeExpiredPublicShare(ctx, ps, u); err != nil {
return nil, err
}
return nil, errors.New("no shares found by id:" + ref.GetId().String())
}
return ps, nil
}

Expand Down Expand Up @@ -353,6 +388,25 @@ func notExpired(s *link.PublicShare) bool {
return false
}

func (m *manager) cleanupExpiredShares() {
m.mutex.Lock()
defer m.mutex.Unlock()

db, _ := m.readDb()

for _, v := range db {
d := v.(map[string]interface{})["share"]

ps := &link.PublicShare{}
r := bytes.NewBuffer([]byte(d.(string)))
_ = m.unmarshaler.Unmarshal(r, ps)

if !notExpired(ps) {
_ = m.revokeExpiredPublicShare(context.Background(), ps, nil)
}
}
}

func (m *manager) revokeExpiredPublicShare(ctx context.Context, s *link.PublicShare, u *user.User) error {
m.mutex.Unlock()
defer m.mutex.Lock()
Expand Down Expand Up @@ -452,15 +506,20 @@ func (m *manager) GetPublicShareByToken(ctx context.Context, token, password str
}

if local.Token == token {
// validate if it is password protected
if !notExpired(local) {
// TODO user is not needed at all in this API.
if err := m.revokeExpiredPublicShare(ctx, local, nil); err != nil {
return nil, err
}
break
}

if local.PasswordProtected {
password = base64.StdEncoding.EncodeToString([]byte(password))
// check sent password matches stored one
if passDB == password {
return local, nil
}
// TODO(refs): custom permission denied error to catch up
// in upper layers

return nil, errors.New("json: invalid password")
}
return local, nil
Expand Down

0 comments on commit 5207197

Please sign in to comment.