Skip to content

Commit 4f60c31

Browse files
committed
feat: extend share lifecycle controls
1 parent bd725d5 commit 4f60c31

5 files changed

Lines changed: 369 additions & 89 deletions

File tree

‎internal/db/share.go‎

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/alist-org/alist/v3/internal/model"
77
"gorm.io/gorm"
8+
"gorm.io/gorm/clause"
89
)
910

1011
func GetShareByShareID(shareID string) (*model.Share, error) {
@@ -15,6 +16,14 @@ func GetShareByShareID(shareID string) (*model.Share, error) {
1516
return &share, nil
1617
}
1718

19+
func GetShareByCreatorAndShareID(creatorID uint, shareID string) (*model.Share, error) {
20+
var share model.Share
21+
if err := db.Where("creator_id = ? AND share_id = ?", creatorID, shareID).Take(&share).Error; err != nil {
22+
return nil, err
23+
}
24+
return &share, nil
25+
}
26+
1827
func ShareIDExists(shareID string) bool {
1928
var count int64
2029
if err := db.Model(&model.Share{}).Where("share_id = ?", shareID).Count(&count).Error; err != nil {
@@ -23,6 +32,14 @@ func ShareIDExists(shareID string) bool {
2332
return count > 0
2433
}
2534

35+
func ShareIDExistsExceptID(shareID string, id uint) bool {
36+
var count int64
37+
if err := db.Model(&model.Share{}).Where("share_id = ? AND id <> ?", shareID, id).Count(&count).Error; err != nil {
38+
return false
39+
}
40+
return count > 0
41+
}
42+
2643
func CreateShare(share *model.Share) error {
2744
return db.Create(share).Error
2845
}
@@ -45,6 +62,12 @@ func DeleteShareByShareID(creatorID uint, shareID string) error {
4562
return db.Where("creator_id = ? AND share_id = ?", creatorID, shareID).Delete(&model.Share{}).Error
4663
}
4764

65+
func DisableShareByShareID(creatorID uint, shareID string) error {
66+
return db.Model(&model.Share{}).
67+
Where("creator_id = ? AND share_id = ?", creatorID, shareID).
68+
Update("enabled", false).Error
69+
}
70+
4871
func TouchShareView(shareID string) error {
4972
now := time.Now()
5073
return db.Model(&model.Share{}).
@@ -65,13 +88,37 @@ func TouchShareDownload(shareID string) error {
6588
}).Error
6689
}
6790

68-
func ConsumeShare(shareID string) error {
69-
now := time.Now()
70-
return db.Model(&model.Share{}).
71-
Where("share_id = ? AND burn_after_read = ? AND consumed_at IS NULL", shareID, true).
72-
Updates(map[string]interface{}{
73-
"enabled": false,
74-
"consumed_at": now,
91+
func RecordShareAccess(shareID string) (*model.Share, error) {
92+
var updated model.Share
93+
err := db.Transaction(func(tx *gorm.DB) error {
94+
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
95+
Where("share_id = ?", shareID).
96+
Take(&updated).Error; err != nil {
97+
return err
98+
}
99+
100+
now := time.Now()
101+
updated.AccessCount++
102+
updated.LastAccessAt = &now
103+
updates := map[string]interface{}{
104+
"access_count": updated.AccessCount,
75105
"last_access_at": now,
76-
}).Error
106+
}
107+
108+
limit := updated.EffectiveAccessLimit()
109+
if limit > 0 && updated.AccessCount >= limit {
110+
updated.Enabled = false
111+
updated.ConsumedAt = &now
112+
updates["enabled"] = false
113+
updates["consumed_at"] = now
114+
}
115+
116+
return tx.Model(&model.Share{}).
117+
Where("id = ?", updated.ID).
118+
Updates(updates).Error
119+
})
120+
if err != nil {
121+
return nil, err
122+
}
123+
return &updated, nil
77124
}

‎internal/model/share.go‎

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ type Share struct {
1212
PasswordHash string `json:"-" gorm:"size:64"`
1313
PasswordSalt string `json:"-" gorm:"size:32"`
1414
BurnAfterRead bool `json:"burn_after_read" gorm:"default:false"`
15+
AccessLimit int64 `json:"access_limit"`
16+
AccessCount int64 `json:"access_count"`
1517
AllowPreview bool `json:"allow_preview" gorm:"default:true"`
1618
AllowDownload bool `json:"allow_download" gorm:"default:true"`
1719
Enabled bool `json:"enabled" gorm:"default:true;index"`
@@ -28,6 +30,33 @@ func (s Share) HasPassword() bool {
2830
return s.PasswordHash != ""
2931
}
3032

33+
func (s Share) EffectiveAccessLimit() int64 {
34+
if s.AccessLimit > 0 {
35+
return s.AccessLimit
36+
}
37+
if s.BurnAfterRead {
38+
return 1
39+
}
40+
return 0
41+
}
42+
43+
func (s Share) RemainingAccesses() int64 {
44+
limit := s.EffectiveAccessLimit()
45+
if limit <= 0 {
46+
return 0
47+
}
48+
remaining := limit - s.AccessCount
49+
if remaining < 0 {
50+
return 0
51+
}
52+
return remaining
53+
}
54+
55+
func (s Share) IsConsumed() bool {
56+
limit := s.EffectiveAccessLimit()
57+
return s.ConsumedAt != nil || (limit > 0 && s.AccessCount >= limit)
58+
}
59+
3160
func (s Share) IsExpired(now time.Time) bool {
32-
return s.ExpiresAt != nil && s.ExpiresAt.Before(now)
61+
return s.ExpiresAt != nil && !s.ExpiresAt.After(now)
3362
}

0 commit comments

Comments
 (0)