Skip to content

Commit ddc709f

Browse files
lunny6543
andauthoredSep 8, 2021
Add repo_id for attachment (#16958)
When create a new issue or comment and paste/upload an attachment/image, it will not assign an issue id before submit. So if user give up the creating, the attachments will lost key feature and become dirty content. We don't know if we need to delete the attachment even if the repository deleted. This PR add a repo_id in attachment table so that even if a new upload attachment with no issue_id or release_id but should have repo_id. When deleting a repository, they could also be deleted. Co-authored-by: 6543 <6543@obermui.de>
1 parent f55cd03 commit ddc709f

File tree

15 files changed

+306
-124
lines changed

15 files changed

+306
-124
lines changed
 

‎models/attachment.go

+3-22
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,23 @@
55
package models
66

77
import (
8-
"bytes"
98
"fmt"
10-
"io"
119
"path"
1210

1311
"code.gitea.io/gitea/modules/setting"
1412
"code.gitea.io/gitea/modules/storage"
1513
"code.gitea.io/gitea/modules/timeutil"
1614

17-
gouuid "github.com/google/uuid"
1815
"xorm.io/xorm"
1916
)
2017

2118
// Attachment represent a attachment of issue/comment/release.
2219
type Attachment struct {
2320
ID int64 `xorm:"pk autoincr"`
2421
UUID string `xorm:"uuid UNIQUE"`
25-
IssueID int64 `xorm:"INDEX"`
26-
ReleaseID int64 `xorm:"INDEX"`
22+
RepoID int64 `xorm:"INDEX"` // this should not be zero
23+
IssueID int64 `xorm:"INDEX"` // maybe zero when creating
24+
ReleaseID int64 `xorm:"INDEX"` // maybe zero when creating
2725
UploaderID int64 `xorm:"INDEX DEFAULT 0"` // Notice: will be zero before this column added
2826
CommentID int64
2927
Name string
@@ -81,23 +79,6 @@ func (a *Attachment) LinkedRepository() (*Repository, UnitType, error) {
8179
return nil, -1, nil
8280
}
8381

84-
// NewAttachment creates a new attachment object.
85-
func NewAttachment(attach *Attachment, buf []byte, file io.Reader) (_ *Attachment, err error) {
86-
attach.UUID = gouuid.New().String()
87-
88-
size, err := storage.Attachments.Save(attach.RelativePath(), io.MultiReader(bytes.NewReader(buf), file), -1)
89-
if err != nil {
90-
return nil, fmt.Errorf("Create: %v", err)
91-
}
92-
attach.Size = size
93-
94-
if _, err := x.Insert(attach); err != nil {
95-
return nil, err
96-
}
97-
98-
return attach, nil
99-
}
100-
10182
// GetAttachmentByID returns attachment by given id
10283
func GetAttachmentByID(id int64) (*Attachment, error) {
10384
return getAttachmentByID(x, id)

‎models/attachment_test.go

-29
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,11 @@
55
package models
66

77
import (
8-
"os"
9-
"path/filepath"
108
"testing"
119

1210
"github.com/stretchr/testify/assert"
1311
)
1412

15-
func TestUploadAttachment(t *testing.T) {
16-
assert.NoError(t, PrepareTestDatabase())
17-
18-
user := AssertExistsAndLoadBean(t, &User{ID: 1}).(*User)
19-
20-
fPath := "./attachment_test.go"
21-
f, err := os.Open(fPath)
22-
assert.NoError(t, err)
23-
defer f.Close()
24-
25-
buf := make([]byte, 1024)
26-
n, err := f.Read(buf)
27-
assert.NoError(t, err)
28-
buf = buf[:n]
29-
30-
attach, err := NewAttachment(&Attachment{
31-
UploaderID: user.ID,
32-
Name: filepath.Base(fPath),
33-
}, buf, f)
34-
assert.NoError(t, err)
35-
36-
attachment, err := GetAttachmentByUUID(attach.UUID)
37-
assert.NoError(t, err)
38-
assert.EqualValues(t, user.ID, attachment.UploaderID)
39-
assert.Equal(t, int64(0), attachment.DownloadCount)
40-
}
41-
4213
func TestIncreaseDownloadCount(t *testing.T) {
4314
assert.NoError(t, PrepareTestDatabase())
4415

‎models/context.go

+6
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,9 @@ func Iterate(ctx DBContext, tableBean interface{}, cond builder.Cond, fun func(i
6666
BufferSize(setting.Database.IterateBufferSize).
6767
Iterate(tableBean, fun)
6868
}
69+
70+
// Insert inserts records into database
71+
func Insert(ctx DBContext, beans ...interface{}) error {
72+
_, err := ctx.e.Insert(beans...)
73+
return err
74+
}

‎models/fixtures/attachment.yml

+11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
-
22
id: 1
33
uuid: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11
4+
repo_id: 1
45
issue_id: 1
56
comment_id: 0
67
name: attach1
@@ -10,6 +11,7 @@
1011
-
1112
id: 2
1213
uuid: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12
14+
repo_id: 2
1315
issue_id: 4
1416
comment_id: 0
1517
name: attach2
@@ -19,6 +21,7 @@
1921
-
2022
id: 3
2123
uuid: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a13
24+
repo_id: 1
2225
issue_id: 2
2326
comment_id: 1
2427
name: attach1
@@ -28,6 +31,7 @@
2831
-
2932
id: 4
3033
uuid: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14
34+
repo_id: 1
3135
issue_id: 3
3236
comment_id: 1
3337
name: attach2
@@ -37,6 +41,7 @@
3741
-
3842
id: 5
3943
uuid: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a15
44+
repo_id: 2
4045
issue_id: 4
4146
comment_id: 0
4247
name: attach1
@@ -46,6 +51,7 @@
4651
-
4752
id: 6
4853
uuid: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a16
54+
repo_id: 1
4955
issue_id: 5
5056
comment_id: 2
5157
name: attach1
@@ -55,6 +61,7 @@
5561
-
5662
id: 7
5763
uuid: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17
64+
repo_id: 1
5865
issue_id: 5
5966
comment_id: 2
6067
name: attach1
@@ -64,6 +71,7 @@
6471
-
6572
id: 8
6673
uuid: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18
74+
repo_id: 3
6775
issue_id: 6
6876
comment_id: 0
6977
name: attach1
@@ -73,6 +81,7 @@
7381
-
7482
id: 9
7583
uuid: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a19
84+
repo_id: 1
7685
release_id: 1
7786
name: attach1
7887
download_count: 0
@@ -81,6 +90,7 @@
8190
-
8291
id: 10
8392
uuid: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a20
93+
repo_id: 0 # TestGetAttachment/NotLinked
8494
uploader_id: 8
8595
name: attach1
8696
download_count: 0
@@ -89,6 +99,7 @@
8999
-
90100
id: 11
91101
uuid: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a21
102+
repo_id: 40
92103
release_id: 2
93104
name: attach1
94105
download_count: 0

‎models/migrations/migrations.go

+2
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,8 @@ var migrations = []Migration{
338338
NewMigration("Alter issue/comment table TEXT fields to LONGTEXT", alterIssueAndCommentTextFieldsToLongText),
339339
// v192 -> v193
340340
NewMigration("RecreateIssueResourceIndexTable to have a primary key instead of an unique index", recreateIssueResourceIndexTable),
341+
// v193 -> v194
342+
NewMigration("Add repo id column for attachment table", addRepoIDForAttachment),
341343
}
342344

343345
// GetCurrentDBVersion returns the current db version

‎models/migrations/v193.go

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package migrations
6+
7+
import (
8+
"xorm.io/xorm"
9+
)
10+
11+
func addRepoIDForAttachment(x *xorm.Engine) error {
12+
type Attachment struct {
13+
ID int64 `xorm:"pk autoincr"`
14+
UUID string `xorm:"uuid UNIQUE"`
15+
RepoID int64 `xorm:"INDEX"` // this should not be zero
16+
IssueID int64 `xorm:"INDEX"` // maybe zero when creating
17+
ReleaseID int64 `xorm:"INDEX"` // maybe zero when creating
18+
UploaderID int64 `xorm:"INDEX DEFAULT 0"`
19+
}
20+
if err := x.Sync2(new(Attachment)); err != nil {
21+
return err
22+
}
23+
24+
if _, err := x.Exec("UPDATE `attachment` set repo_id = (SELECT repo_id FROM `issue` WHERE `issue`.id = `attachment`.issue_id) WHERE `attachment`.issue_id > 0"); err != nil {
25+
return err
26+
}
27+
28+
if _, err := x.Exec("UPDATE `attachment` set repo_id = (SELECT repo_id FROM `release` WHERE `release`.id = `attachment`.release_id) WHERE `attachment`.release_id > 0"); err != nil {
29+
return err
30+
}
31+
32+
return nil
33+
}

‎models/migrations/v193_test.go

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package migrations
6+
7+
import (
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func Test_addRepoIDForAttachment(t *testing.T) {
14+
type Attachment struct {
15+
ID int64 `xorm:"pk autoincr"`
16+
UUID string `xorm:"uuid UNIQUE"`
17+
RepoID int64 `xorm:"INDEX"` // this should not be zero
18+
IssueID int64 `xorm:"INDEX"` // maybe zero when creating
19+
ReleaseID int64 `xorm:"INDEX"` // maybe zero when creating
20+
UploaderID int64 `xorm:"INDEX DEFAULT 0"`
21+
}
22+
23+
type Issue struct {
24+
ID int64
25+
RepoID int64
26+
}
27+
28+
type Release struct {
29+
ID int64
30+
RepoID int64
31+
}
32+
33+
// Prepare and load the testing database
34+
x, deferrable := prepareTestEnv(t, 0, new(Attachment), new(Issue), new(Release))
35+
defer deferrable()
36+
if x == nil || t.Failed() {
37+
return
38+
}
39+
40+
// Run the migration
41+
if err := addRepoIDForAttachment(x); err != nil {
42+
assert.NoError(t, err)
43+
return
44+
}
45+
46+
var issueAttachments []*Attachment
47+
err := x.Where("issue_id > 0").Find(&issueAttachments)
48+
assert.NoError(t, err)
49+
for _, attach := range issueAttachments {
50+
assert.Greater(t, attach.RepoID, 0)
51+
assert.Greater(t, attach.IssueID, 0)
52+
var issue Issue
53+
has, err := x.ID(attach.IssueID).Get(&issue)
54+
assert.NoError(t, err)
55+
assert.True(t, has)
56+
assert.EqualValues(t, attach.RepoID, issue.RepoID)
57+
}
58+
59+
var releaseAttachments []*Attachment
60+
err = x.Where("release_id > 0").Find(&releaseAttachments)
61+
assert.NoError(t, err)
62+
for _, attach := range releaseAttachments {
63+
assert.Greater(t, attach.RepoID, 0)
64+
assert.Greater(t, attach.IssueID, 0)
65+
var release Release
66+
has, err := x.ID(attach.ReleaseID).Get(&release)
67+
assert.NoError(t, err)
68+
assert.True(t, has)
69+
assert.EqualValues(t, attach.RepoID, release.RepoID)
70+
}
71+
}

0 commit comments

Comments
 (0)
Please sign in to comment.