mirror of https://github.com/cloudreve/Cloudreve
feat(dbfs): set default share shortcut for new users
parent
9f5ebe11b6
commit
c6ee3e5dcd
|
@ -246,4 +246,5 @@ var DefaultSettings = map[string]string{
|
||||||
"qq_login": `0`,
|
"qq_login": `0`,
|
||||||
"qq_login_config": `{"direct_sign_in":false}`,
|
"qq_login_config": `{"direct_sign_in":false}`,
|
||||||
"license": "",
|
"license": "",
|
||||||
|
"default_symbolics": "[]",
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,8 @@ var (
|
||||||
type (
|
type (
|
||||||
ShareClient interface {
|
ShareClient interface {
|
||||||
TxOperator
|
TxOperator
|
||||||
|
// GetByIDs returns the shares with given ids.
|
||||||
|
GetByIDs(ctx context.Context, ids []int) ([]*ent.Share, error)
|
||||||
// GetByID returns the share with given id.
|
// GetByID returns the share with given id.
|
||||||
GetByID(ctx context.Context, id int) (*ent.Share, error)
|
GetByID(ctx context.Context, id int) (*ent.Share, error)
|
||||||
// GetByIDUser returns the share with given id and user id.
|
// GetByIDUser returns the share with given id and user id.
|
||||||
|
@ -67,6 +69,7 @@ type (
|
||||||
UserID int
|
UserID int
|
||||||
FileID int
|
FileID int
|
||||||
PublicOnly bool
|
PublicOnly bool
|
||||||
|
ShareIDs []int
|
||||||
}
|
}
|
||||||
ListShareResult struct {
|
ListShareResult struct {
|
||||||
*PaginationResults
|
*PaginationResults
|
||||||
|
@ -168,6 +171,15 @@ func (c *shareClient) GetByIDUser(ctx context.Context, id, uid int) (*ent.Share,
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *shareClient) GetByIDs(ctx context.Context, ids []int) ([]*ent.Share, error) {
|
||||||
|
s, err := withShareEagerLoading(ctx, c.client.Share.Query().Where(share.IDIn(ids...))).All(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to query shares %v: %w", ids, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *shareClient) DeleteBatch(ctx context.Context, shareIds []int) error {
|
func (c *shareClient) DeleteBatch(ctx context.Context, shareIds []int) error {
|
||||||
_, err := c.client.Share.Delete().Where(share.IDIn(shareIds...)).Exec(ctx)
|
_, err := c.client.Share.Delete().Where(share.IDIn(shareIds...)).Exec(ctx)
|
||||||
return err
|
return err
|
||||||
|
@ -332,6 +344,10 @@ func (c *shareClient) listQuery(args *ListShareArgs) *ent.ShareQuery {
|
||||||
query.Where(share.HasFileWith(file.ID(args.FileID)))
|
query.Where(share.HasFileWith(file.ID(args.FileID)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(args.ShareIDs) > 0 {
|
||||||
|
query.Where(share.IDIn(args.ShareIDs...))
|
||||||
|
}
|
||||||
|
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -719,7 +719,7 @@ func (f *DBFS) getFileByPath(ctx context.Context, navigator Navigator, path *fs.
|
||||||
// initFs initializes the file system for the user.
|
// initFs initializes the file system for the user.
|
||||||
func (f *DBFS) initFs(ctx context.Context, uid int) error {
|
func (f *DBFS) initFs(ctx context.Context, uid int) error {
|
||||||
f.l.Info("Initialize database file system for user %q", f.user.Email)
|
f.l.Info("Initialize database file system for user %q", f.user.Email)
|
||||||
_, err := f.fileClient.CreateFolder(ctx, nil,
|
parent, err := f.fileClient.CreateFolder(ctx, nil,
|
||||||
&inventory.CreateFolderParameters{
|
&inventory.CreateFolderParameters{
|
||||||
Owner: uid,
|
Owner: uid,
|
||||||
Name: inventory.RootFolderName,
|
Name: inventory.RootFolderName,
|
||||||
|
@ -728,6 +728,58 @@ func (f *DBFS) initFs(ctx context.Context, uid int) error {
|
||||||
return fmt.Errorf("failed to create root folder: %w", err)
|
return fmt.Errorf("failed to create root folder: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create default symbolics
|
||||||
|
symbolics := f.settingClient.DefaultSymbolics(ctx)
|
||||||
|
if len(symbolics) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := f.userClient.GetLoginUserByID(ctx, uid)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get user: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.SetOwner(user)
|
||||||
|
|
||||||
|
ctx = context.WithValue(ctx, inventory.LoadShareFile{}, true)
|
||||||
|
ctx = context.WithValue(ctx, inventory.LoadShareUser{}, true)
|
||||||
|
shares, err := f.shareClient.GetByIDs(ctx, symbolics)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get shares: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, share := range shares {
|
||||||
|
if share.Edges.File == nil || share.Edges.User == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
shareOwner := hashid.EncodeUserID(f.hasher, share.Edges.User.ID)
|
||||||
|
shareUri := fs.NewShareUri(hashid.EncodeShareID(f.hasher, share.ID), share.Password)
|
||||||
|
shareUriParsed, err := fs.NewUriFromString(shareUri)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if share.Edges.File.Type == int(types.FileTypeFile) {
|
||||||
|
shareUriParsed.Join(share.Edges.File.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
parentFile := newFile(nil, parent)
|
||||||
|
parentFile.OwnerModel = user
|
||||||
|
if _, err := f.createFile(ctx, parentFile, share.Edges.File.Name, types.FileType(share.Edges.File.Type), &dbfsOption{
|
||||||
|
FsOption: &fs.FsOption{
|
||||||
|
Metadata: map[string]string{
|
||||||
|
MetadataSharedRedirect: shareUriParsed.String(),
|
||||||
|
MetadataSharedOwner: shareOwner,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
errOnConflict: true,
|
||||||
|
isSymbolicLink: true,
|
||||||
|
}); err != nil {
|
||||||
|
f.l.Warning("Failed to create default symbolic link %q for user %q: %s", shareUriParsed, uid, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ const (
|
||||||
MetadataSharedRedirect = MetadataSysPrefix + "shared_redirect"
|
MetadataSharedRedirect = MetadataSysPrefix + "shared_redirect"
|
||||||
MetadataRestoreUri = MetadataSysPrefix + "restore_uri"
|
MetadataRestoreUri = MetadataSysPrefix + "restore_uri"
|
||||||
MetadataExpectedCollectTime = MetadataSysPrefix + "expected_collect_time"
|
MetadataExpectedCollectTime = MetadataSysPrefix + "expected_collect_time"
|
||||||
|
MetadataSharedOwner = MetadataSysPrefix + "shared_owner"
|
||||||
|
|
||||||
ThumbMetadataPrefix = "thumb:"
|
ThumbMetadataPrefix = "thumb:"
|
||||||
ThumbDisabledKey = ThumbMetadataPrefix + "disabled"
|
ThumbDisabledKey = ThumbMetadataPrefix + "disabled"
|
||||||
|
|
|
@ -184,6 +184,8 @@ type (
|
||||||
AvatarProcess(ctx context.Context) *AvatarProcess
|
AvatarProcess(ctx context.Context) *AvatarProcess
|
||||||
// UseFirstSiteUrl returns the first site URL.
|
// UseFirstSiteUrl returns the first site URL.
|
||||||
AllSiteURLs(ctx context.Context) []*url.URL
|
AllSiteURLs(ctx context.Context) []*url.URL
|
||||||
|
// DefaultSymbolics returns the default symbolics for new users.
|
||||||
|
DefaultSymbolics(ctx context.Context) []int
|
||||||
}
|
}
|
||||||
UseFirstSiteUrlCtxKey = struct{}
|
UseFirstSiteUrlCtxKey = struct{}
|
||||||
)
|
)
|
||||||
|
@ -211,6 +213,16 @@ type (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (s *settingProvider) DefaultSymbolics(ctx context.Context) []int {
|
||||||
|
raw := s.getString(ctx, "default_symbolics", "[]")
|
||||||
|
var symbolics []int
|
||||||
|
if err := json.Unmarshal([]byte(raw), &symbolics); err != nil {
|
||||||
|
return []int{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return symbolics
|
||||||
|
}
|
||||||
|
|
||||||
func (s *settingProvider) License(ctx context.Context) string {
|
func (s *settingProvider) License(ctx context.Context) string {
|
||||||
return s.getString(ctx, "license", "")
|
return s.getString(ctx, "license", "")
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package admin
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/cloudreve/Cloudreve/v4/application/dependency"
|
"github.com/cloudreve/Cloudreve/v4/application/dependency"
|
||||||
"github.com/cloudreve/Cloudreve/v4/ent"
|
"github.com/cloudreve/Cloudreve/v4/ent"
|
||||||
|
@ -17,6 +18,7 @@ import (
|
||||||
const (
|
const (
|
||||||
shareUserIDCondition = "share_user_id"
|
shareUserIDCondition = "share_user_id"
|
||||||
shareFileIDCondition = "share_file_id"
|
shareFileIDCondition = "share_file_id"
|
||||||
|
shareIDCondition = "share_id"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *AdminListService) Shares(c *gin.Context) (*ListShareResponse, error) {
|
func (s *AdminListService) Shares(c *gin.Context) (*ListShareResponse, error) {
|
||||||
|
@ -25,9 +27,10 @@ func (s *AdminListService) Shares(c *gin.Context) (*ListShareResponse, error) {
|
||||||
hasher := dep.HashIDEncoder()
|
hasher := dep.HashIDEncoder()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
userID int
|
userID int
|
||||||
fileID int
|
fileID int
|
||||||
|
shareIDs []int
|
||||||
)
|
)
|
||||||
|
|
||||||
if s.Conditions[shareUserIDCondition] != "" {
|
if s.Conditions[shareUserIDCondition] != "" {
|
||||||
|
@ -44,6 +47,18 @@ func (s *AdminListService) Shares(c *gin.Context) (*ListShareResponse, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.Conditions[shareIDCondition] != "" {
|
||||||
|
shareIdStrs := strings.Split(s.Conditions[shareIDCondition], ",")
|
||||||
|
for _, shareIdStr := range shareIdStrs {
|
||||||
|
shareID, err := strconv.Atoi(shareIdStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, serializer.NewError(serializer.CodeParamErr, "Invalid share ID", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
shareIDs = append(shareIDs, shareID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctx := context.WithValue(c, inventory.LoadShareFile{}, true)
|
ctx := context.WithValue(c, inventory.LoadShareFile{}, true)
|
||||||
ctx = context.WithValue(ctx, inventory.LoadShareUser{}, true)
|
ctx = context.WithValue(ctx, inventory.LoadShareUser{}, true)
|
||||||
|
|
||||||
|
@ -54,8 +69,9 @@ func (s *AdminListService) Shares(c *gin.Context) (*ListShareResponse, error) {
|
||||||
OrderBy: s.OrderBy,
|
OrderBy: s.OrderBy,
|
||||||
Order: inventory.OrderDirection(s.OrderDirection),
|
Order: inventory.OrderDirection(s.OrderDirection),
|
||||||
},
|
},
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
FileID: fileID,
|
FileID: fileID,
|
||||||
|
ShareIDs: shareIDs,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -261,7 +261,6 @@ func (service *WopiService) PutContent(c *gin.Context, isPutRelative bool) error
|
||||||
if isPutRelative {
|
if isPutRelative {
|
||||||
c.JSON(http.StatusOK, PutRelativeResponse{
|
c.JSON(http.StatusOK, PutRelativeResponse{
|
||||||
Name: res.Name,
|
Name: res.Name,
|
||||||
Url: "http://docker.host.internal:5212/explorer/viewer?uri=",
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in New Issue