Skip to content

Commit 0945a17

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

File tree

4 files changed

+77
-11
lines changed

4 files changed

+77
-11
lines changed

share/model.go

+25-5
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,38 @@ 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 uint `gorm:"uniqueIndex;autoIncrement:false"`
47+
ShareId ShareID `gorm:"foreignKey:ID;references:ID;constraint:OnDelete:CASCADE"` //;references:ID
48+
CreatedAt time.Time
49+
UpdatedAt time.Time
50+
DeletedAt gorm.DeletedAt `gorm:"index"`
51+
}
52+
3353
// ProtoShare contains fields that are shared between PublicLinks and Shares.
3454
// Unfortunately, because these are shared, we cannot name our indexes
3555
// because then two indexes with the same name would be created
3656
type ProtoShare struct {
3757
// Including gorm.Model will embed a number of gorm-default fields
38-
gorm.Model
58+
BaseModel
3959
UIDOwner string `gorm:"size:64"`
4060
UIDInitiator string `gorm:"size:64"`
4161
ItemType ItemType `gorm:"size:16;index:"` // file | folder | reference | symlink
4262
InitialPath string
43-
Inode string `gorm:"size:32;index:"`
44-
Instance string `gorm:"size:32;index:"`
63+
Inode string `gorm:"primaryKey;size:32;index:"`
64+
Instance string `gorm:"primaryKey;size:32;index:"`
4565
Permissions uint8
4666
Orphan bool
4767
Expiration datatypes.NullTime
@@ -68,8 +88,8 @@ type PublicLink struct {
6888

6989
type ShareState struct {
7090
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
91+
ShareID uint `gorm:"uniqueIndex:i_shareid_user"` // Define the foreign key field
92+
Share Share `gorm:"foreignKey:ShareID;references:ID"` // Define the association
7393
// Can not be uid because of lw accs
7494
User string `gorm:"uniqueIndex:i_shareid_user;size:255"`
7595
Synced bool

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

+12-1
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,7 +386,7 @@ func emptyLinkWithId(id string) (*model.PublicLink, error) {
375386
}
376387
share := &model.PublicLink{
377388
ProtoShare: model.ProtoShare{
378-
Model: gorm.Model{
389+
BaseModel: model.BaseModel{
379390
ID: uint(intId),
380391
},
381392
},

share/sql/share.go

+22-2
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,16 @@ func NewShareManager(ctx context.Context, m map[string]interface{}) (revashare.M
7575
}
7676

7777
// Migrate schemas
78-
err = db.AutoMigrate(&model.Share{}, &model.ShareState{})
78+
err = db.AutoMigrate(&model.ShareID{}, &model.Share{}, &model.ShareState{})
79+
if err != nil {
80+
return nil, err
81+
}
7982

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")
8088
if err != nil {
8189
return nil, err
8290
}
@@ -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
@@ -415,7 +435,7 @@ func emptyShareWithId(id string) (*model.Share, error) {
415435
}
416436
share := &model.Share{
417437
ProtoShare: model.ProtoShare{
418-
Model: gorm.Model{
438+
BaseModel: model.BaseModel{
419439
ID: uint(intId),
420440
},
421441
},

0 commit comments

Comments
 (0)