Cloudreve/pkg/filemanager/manager/viewer.go

93 lines
2.3 KiB
Go

package manager
import (
"context"
"encoding/gob"
"fmt"
"time"
"github.com/cloudreve/Cloudreve/v4/inventory/types"
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs"
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs/dbfs"
"github.com/cloudreve/Cloudreve/v4/pkg/util"
"github.com/gofrs/uuid"
)
type (
ViewerSession struct {
ID string `json:"id"`
AccessToken string `json:"access_token"`
Expires int64 `json:"expires"`
File fs.File `json:"-"`
}
ViewerSessionCache struct {
ID string
Uri string
UserID int
FileID int
ViewerID string
Version string
Token string
}
ViewerSessionCacheCtx struct{}
ViewerCtx struct{}
)
const (
ViewerSessionCachePrefix = "viewer_session_"
sessionExpiresPadding = 10
)
func init() {
gob.Register(ViewerSessionCache{})
}
func (m *manager) CreateViewerSession(ctx context.Context, uri *fs.URI, version string, viewer *types.Viewer) (*ViewerSession, error) {
file, err := m.fs.Get(ctx, uri, dbfs.WithFileEntities(), dbfs.WithNotRoot())
if err != nil {
return nil, err
}
versionType := types.EntityTypeVersion
found, desired := fs.FindDesiredEntity(file, version, m.hasher, &versionType)
if !found {
return nil, fs.ErrEntityNotExist
}
if desired.Size() > m.settings.MaxOnlineEditSize(ctx) {
return nil, fs.ErrFileSizeTooBig
}
sessionID := uuid.Must(uuid.NewV4()).String()
token := util.RandStringRunes(128)
sessionCache := &ViewerSessionCache{
ID: sessionID,
Uri: file.Uri(false).String(),
UserID: m.user.ID,
ViewerID: viewer.ID,
FileID: file.ID(),
Version: version,
Token: fmt.Sprintf("%s.%s", sessionID, token),
}
ttl := m.settings.ViewerSessionTTL(ctx)
if err := m.kv.Set(ViewerSessionCachePrefix+sessionID, *sessionCache, ttl); err != nil {
return nil, err
}
return &ViewerSession{
File: file,
ID: sessionID,
AccessToken: sessionCache.Token,
Expires: time.Now().Add(time.Duration(ttl-sessionExpiresPadding) * time.Second).UnixMilli(),
}, nil
}
func ViewerSessionFromContext(ctx context.Context) *ViewerSessionCache {
return ctx.Value(ViewerSessionCacheCtx{}).(*ViewerSessionCache)
}
func ViewerFromContext(ctx context.Context) *types.Viewer {
return ctx.Value(ViewerCtx{}).(*types.Viewer)
}