Skip to content

Commit cd0dad4

Browse files
committed
Implement shared ID for public links and shares
1 parent d4c5866 commit cd0dad4

File tree

4 files changed

+87
-19
lines changed

4 files changed

+87
-19
lines changed

share/model.go

+31-9
Original file line numberDiff line numberDiff line change
@@ -30,33 +30,55 @@ func (i ItemType) String() string {
3030
return string(i)
3131
}
3232

33+
// ShareID only contains IDs of shares and public links. This is because OCIS requires
34+
// that shares and public links do not share an ID, so we need a shared table to make sure
35+
// that there are no duplicates.
36+
// This is implemented by having ShareID have an ID that is auto-increment, and shares and
37+
// public links will have their ID be a foreign key to ShareID
38+
// When creating a new share, we will then first create an ID entry and use this for the ID
39+
40+
type ShareID struct {
41+
ID uint `gorm:"primarykey"`
42+
}
43+
44+
// We cannot use gorm.Model, because we want our ID to be a foreign key to ShareID
45+
type BaseModel struct {
46+
// Id has to be called Id and not ID, otherwise the foreign key will not work
47+
// ID is a special field in GORM, which it uses as the default Primary Key
48+
Id uint `gorm:"uniqueIndex"`
49+
ShareId ShareID `gorm:"foreignKey:Id;references:ID;constraint:OnDelete:CASCADE"` //;references:ID
50+
CreatedAt time.Time
51+
UpdatedAt time.Time
52+
DeletedAt gorm.DeletedAt `gorm:"index"`
53+
}
54+
3355
// ProtoShare contains fields that are shared between PublicLinks and Shares.
3456
// Unfortunately, because these are shared, we cannot name our indexes
3557
// because then two indexes with the same name would be created
3658
type ProtoShare struct {
3759
// Including gorm.Model will embed a number of gorm-default fields
38-
gorm.Model
60+
BaseModel
3961
UIDOwner string `gorm:"size:64"`
4062
UIDInitiator string `gorm:"size:64"`
4163
ItemType ItemType `gorm:"size:16;index:"` // file | folder | reference | symlink
4264
InitialPath string
43-
Inode string `gorm:"size:32;index:"`
44-
Instance string `gorm:"size:32;index:"`
65+
Inode string `gorm:"primaryKey;size:32;index:"`
66+
Instance string `gorm:"primaryKey;size:32;index:"`
4567
Permissions uint8
4668
Orphan bool
4769
Expiration datatypes.NullTime
4870
}
4971

5072
type Share struct {
5173
ProtoShare
52-
ShareWith string `gorm:"size:255;index:i_share_with"` // 255 because this can be a lw account, which are mapped from email addresses / ...
74+
ShareWith string `gorm:"primaryKey;size:255;index:i_share_with"` // 255 because this can be a lw account, which are mapped from email addresses / ...
5375
SharedWithIsGroup bool
5476
Description string `gorm:"size:1024"`
5577
}
5678

5779
type PublicLink struct {
5880
ProtoShare
59-
Token string `gorm:"index:i_token"`
81+
Token string `gorm:"primaryKey;index:i_token"`
6082
// Enforce uniqueness in db re: Itemsource
6183
Quicklink bool
6284
NotifyUploads bool
@@ -68,8 +90,8 @@ type PublicLink struct {
6890

6991
type ShareState struct {
7092
gorm.Model
71-
ShareID uint `gorm:"foreignKey:ShareID;references:ID;uniqueIndex:i_shareid_user"` // Define the foreign key field
72-
Share Share // Define the association
93+
ShareID uint `gorm:"uniqueIndex:i_shareid_user"` // Define the foreign key field
94+
Share Share `gorm:"foreignKey:ShareID;references:Id"` // Define the association
7395
// Can not be uid because of lw accs
7496
User string `gorm:"uniqueIndex:i_shareid_user;size:255"`
7597
Synced bool
@@ -86,7 +108,7 @@ func (s *Share) AsCS3Share(granteeType userpb.UserType) *collaboration.Share {
86108
}
87109
return &collaboration.Share{
88110
Id: &collaboration.ShareId{
89-
OpaqueId: strconv.FormatUint(uint64(s.ID), 10),
111+
OpaqueId: strconv.FormatUint(uint64(s.Id), 10),
90112
},
91113
//ResourceId: &provider.Reference{StorageId: s.Prefix, NodeId: s.ItemSource},
92114
ResourceId: &provider.ResourceId{
@@ -139,7 +161,7 @@ func (p *PublicLink) AsCS3PublicShare() *link.PublicShare {
139161
}
140162
return &link.PublicShare{
141163
Id: &link.PublicShareId{
142-
OpaqueId: strconv.Itoa(int(p.ID)),
164+
OpaqueId: strconv.Itoa(int(p.Id)),
143165
},
144166
ResourceId: &provider.ResourceId{
145167
StorageId: p.Instance,

share/sql/common.go

+18-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package sql
33
import (
44
"fmt"
55

6+
model "github.com/cernbox/reva-plugins/share"
67
"github.com/cs3org/reva"
78
"gorm.io/driver/mysql"
89
"gorm.io/driver/sqlite"
@@ -33,14 +34,28 @@ func init() {
3334
}
3435

3536
func getDb(c config) (*gorm.DB, error) {
37+
gormCfg := &gorm.Config{
38+
DisableForeignKeyConstraintWhenMigrating: false,
39+
}
3640
switch c.Engine {
3741
case "sqlite":
38-
return gorm.Open(sqlite.Open(c.DBName), &gorm.Config{})
42+
return gorm.Open(sqlite.Open(c.DBName), gormCfg)
3943
case "mysql":
4044
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?parseTime=true", c.DBUsername, c.DBPassword, c.DBHost, c.DBPort, c.DBName)
41-
return gorm.Open(mysql.Open(dsn), &gorm.Config{})
45+
return gorm.Open(mysql.Open(dsn), gormCfg)
4246
default: // default is mysql
4347
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?parseTime=true", c.DBUsername, c.DBPassword, c.DBHost, c.DBPort, c.DBName)
44-
return gorm.Open(mysql.Open(dsn), &gorm.Config{})
48+
return gorm.Open(mysql.Open(dsn), gormCfg)
49+
}
50+
}
51+
52+
func createID(db *gorm.DB) (uint, error) {
53+
id := &model.ShareID{}
54+
55+
res := db.Create(&id)
56+
if res.Error != nil {
57+
return 0, res.Error
58+
} else {
59+
return id.ID, nil
4560
}
4661
}

share/sql/public_link.go

+13-2
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,17 @@ func (m *publicShareMgr) CreatePublicShare(ctx context.Context, u *user.User, md
106106
NotifyUploadsExtraRecipients: notifyUploadsExtraRecipients,
107107
}
108108

109+
// Create Shared ID
110+
id, err := createID(m.db)
111+
if err != nil {
112+
return nil, errors.Wrap(err, "failed to create id for PublicShare")
113+
}
114+
115+
publiclink.BaseModel = model.BaseModel{
116+
Id: id,
117+
ShareId: model.ShareID{ID: id},
118+
}
119+
109120
publiclink.UIDOwner = conversions.FormatUserID(md.Owner)
110121
publiclink.UIDInitiator = conversions.FormatUserID(user.Id)
111122
publiclink.InitialPath = md.Path
@@ -375,8 +386,8 @@ func emptyLinkWithId(id string) (*model.PublicLink, error) {
375386
}
376387
share := &model.PublicLink{
377388
ProtoShare: model.ProtoShare{
378-
Model: gorm.Model{
379-
ID: uint(intId),
389+
BaseModel: model.BaseModel{
390+
Id: uint(intId),
380391
},
381392
},
382393
}

share/sql/share.go

+25-5
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,20 @@ func NewShareManager(ctx context.Context, m map[string]interface{}) (revashare.M
7575
}
7676

7777
// Migrate schemas
78-
err = db.AutoMigrate(&model.Share{}, &model.ShareState{})
79-
78+
err = db.AutoMigrate(&model.ShareID{}, &model.Share{}, &model.ShareState{})
8079
if err != nil {
8180
return nil, err
8281
}
8382

83+
// err = db.Migrator().CreateConstraint(&model.ShareID{}, "ID")
84+
// if err != nil {
85+
// return nil, err
86+
// }
87+
// err = db.Migrator().CreateConstraint(&model.Share{}, "fk_shares_share_ids")
88+
// if err != nil {
89+
// return nil, err
90+
// }
91+
8492
mgr := &shareMgr{
8593
c: &c,
8694
db: db,
@@ -125,6 +133,18 @@ func (m *shareMgr) Share(ctx context.Context, md *provider.ResourceInfo, g *coll
125133
ShareWith: shareWith,
126134
SharedWithIsGroup: g.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_GROUP,
127135
}
136+
137+
// Create Shared ID
138+
id, err := createID(m.db)
139+
if err != nil {
140+
return nil, errors.Wrap(err, "failed to create id for PublicShare")
141+
}
142+
143+
share.BaseModel = model.BaseModel{
144+
Id: id,
145+
ShareId: model.ShareID{ID: id},
146+
}
147+
128148
share.UIDOwner = conversions.FormatUserID(md.Owner)
129149
share.UIDInitiator = conversions.FormatUserID(user.Id)
130150
share.InitialPath = md.Path
@@ -390,7 +410,7 @@ func (m *shareMgr) ListReceivedShares(ctx context.Context, filters []*collaborat
390410
func (m *shareMgr) getShareState(ctx context.Context, share *model.Share, user *userpb.User) (*model.ShareState, error) {
391411
var shareState model.ShareState
392412
query := m.db.Model(&shareState).
393-
Where("share_id = ?", share.ID).
413+
Where("share_id = ?", share.Id).
394414
Where("user = ?", user.Username)
395415

396416
res := query.First(&shareState)
@@ -415,8 +435,8 @@ func emptyShareWithId(id string) (*model.Share, error) {
415435
}
416436
share := &model.Share{
417437
ProtoShare: model.ProtoShare{
418-
Model: gorm.Model{
419-
ID: uint(intId),
438+
BaseModel: model.BaseModel{
439+
Id: uint(intId),
420440
},
421441
},
422442
}

0 commit comments

Comments
 (0)