Skip to content

Commit 68be93f

Browse files
committed
Merge branch 'main' of https://github.com/go-gitea/gitea into refactor-webhook
2 parents 784e8a0 + 9b33d18 commit 68be93f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+1462
-304
lines changed

cmd/hook.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,16 +221,16 @@ Gitea or set your environment appropriately.`, "")
221221
total++
222222
lastline++
223223

224-
// If the ref is a branch, check if it's protected
225-
if strings.HasPrefix(refFullName, git.BranchPrefix) {
224+
// If the ref is a branch or tag, check if it's protected
225+
if strings.HasPrefix(refFullName, git.BranchPrefix) || strings.HasPrefix(refFullName, git.TagPrefix) {
226226
oldCommitIDs[count] = oldCommitID
227227
newCommitIDs[count] = newCommitID
228228
refFullNames[count] = refFullName
229229
count++
230230
fmt.Fprintf(out, "*")
231231

232232
if count >= hookBatchSize {
233-
fmt.Fprintf(out, " Checking %d branches\n", count)
233+
fmt.Fprintf(out, " Checking %d references\n", count)
234234

235235
hookOptions.OldCommitIDs = oldCommitIDs
236236
hookOptions.NewCommitIDs = newCommitIDs
@@ -261,7 +261,7 @@ Gitea or set your environment appropriately.`, "")
261261
hookOptions.NewCommitIDs = newCommitIDs[:count]
262262
hookOptions.RefFullNames = refFullNames[:count]
263263

264-
fmt.Fprintf(out, " Checking %d branches\n", count)
264+
fmt.Fprintf(out, " Checking %d references\n", count)
265265

266266
statusCode, msg := private.HookPreReceive(username, reponame, hookOptions)
267267
switch statusCode {

custom/conf/app.example.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,8 @@ PATH =
705705
;;
706706
;; Minimum amount of time a user must exist before comments are kept when the user is deleted.
707707
;USER_DELETE_WITH_COMMENTS_MAX_TIME = 0
708+
;; Valid site url schemes for user profiles
709+
;VALID_SITE_URL_SCHEMES=http,https
708710

709711

710712
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

docs/content/doc/advanced/config-cheat-sheet.en-us.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ relation to port exhaustion.
519519
- `NO_REPLY_ADDRESS`: **noreply.DOMAIN** Value for the domain part of the user's email address in the git log if user has set KeepEmailPrivate to true. DOMAIN resolves to the value in server.DOMAIN.
520520
The user's email will be replaced with a concatenation of the user name in lower case, "@" and NO_REPLY_ADDRESS.
521521
- `USER_DELETE_WITH_COMMENTS_MAX_TIME`: **0** Minimum amount of time a user must exist before comments are kept when the user is deleted.
522+
- `VALID_SITE_URL_SCHEMES`: **http, https**: Valid site url schemes for user profiles
522523

523524
### Service - Expore (`service.explore`)
524525

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
date: "2021-05-14T00:00:00-00:00"
3+
title: "Protected tags"
4+
slug: "protected-tags"
5+
weight: 45
6+
toc: false
7+
draft: false
8+
menu:
9+
sidebar:
10+
parent: "advanced"
11+
name: "Protected tags"
12+
weight: 45
13+
identifier: "protected-tags"
14+
---
15+
16+
# Protected tags
17+
18+
Protected tags allow control over who has permission to create or update git tags. Each rule allows you to match either an individual tag name, or use an appropriate pattern to control multiple tags at once.
19+
20+
**Table of Contents**
21+
22+
{{< toc >}}
23+
24+
## Setting up protected tags
25+
26+
To protect a tag, you need to follow these steps:
27+
28+
1. Go to the repository’s **Settings** > **Tags** page.
29+
1. Type a pattern to match a name. You can use a single name, a [glob pattern](https://pkg.go.dev/github.com/gobwas/glob#Compile) or a regular expression.
30+
1. Choose the allowed users and/or teams. If you leave these fields empty noone is allowed to create or modify this tag.
31+
1. Select **Save** to save the configuration.
32+
33+
## Pattern protected tags
34+
35+
The pattern uses [glob](https://pkg.go.dev/github.com/gobwas/glob#Compile) or regular expressions to match a tag name. For regular expressions you need to enclose the pattern in slashes.
36+
37+
Examples:
38+
39+
| Type | Pattern Protected Tag | Possible Matching Tags |
40+
| ----- | ------------------------ | --------------------------------------- |
41+
| Glob | `v*` | `v`, `v-1`, `version2` |
42+
| Glob | `v[0-9]` | `v0`, `v1` up to `v9` |
43+
| Glob | `*-release` | `2.1-release`, `final-release` |
44+
| Glob | `gitea` | only `gitea` |
45+
| Glob | `*gitea*` | `gitea`, `2.1-gitea`, `1_gitea-release` |
46+
| Glob | `{v,rel}-*` | `v-`, `v-1`, `v-final`, `rel-`, `rel-x` |
47+
| Glob | `*` | matches all possible tag names |
48+
| Regex | `/\Av/` | `v`, `v-1`, `version2` |
49+
| Regex | `/\Av[0-9]\z/` | `v0`, `v1` up to `v9` |
50+
| Regex | `/\Av\d+\.\d+\.\d+\z/` | `v1.0.17`, `v2.1.0` |
51+
| Regex | `/\Av\d+(\.\d+){0,2}\z/` | `v1`, `v2.1`, `v1.2.34` |
52+
| Regex | `/-release\z/` | `2.1-release`, `final-release` |
53+
| Regex | `/gitea/` | `gitea`, `2.1-gitea`, `1_gitea-release` |
54+
| Regex | `/\Agitea\z/` | only `gitea` |
55+
| Regex | `/^gitea$/` | only `gitea` |
56+
| Regex | `/\A(v\|rel)-/` | `v-`, `v-1`, `v-final`, `rel-`, `rel-x` |
57+
| Regex | `/.+/` | matches all possible tag names |

docs/content/doc/usage/reverse-proxies.en-us.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ If you wish to run Gitea with IIS. You will need to setup IIS with URL Rewrite a
221221
```xml
222222
<?xml version="1.0" encoding="UTF-8"?>
223223
<configuration>
224+
<system.web>
225+
<httpRuntime requestPathInvalidCharacters="" />
226+
</system.web>
224227
<system.webServer>
225228
<security>
226229
<requestFiltering>

integrations/api_user_heatmap_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func TestUserHeatmap(t *testing.T) {
2626
var heatmap []*models.UserHeatmapData
2727
DecodeJSON(t, resp, &heatmap)
2828
var dummyheatmap []*models.UserHeatmapData
29-
dummyheatmap = append(dummyheatmap, &models.UserHeatmapData{Timestamp: 1603152000, Contributions: 1})
29+
dummyheatmap = append(dummyheatmap, &models.UserHeatmapData{Timestamp: 1603227600, Contributions: 1})
3030

3131
assert.Equal(t, dummyheatmap, heatmap)
3232
}

integrations/mirror_pull_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ func TestMirrorPull(t *testing.T) {
5959

6060
assert.NoError(t, release_service.CreateRelease(gitRepo, &models.Release{
6161
RepoID: repo.ID,
62+
Repo: repo,
6263
PublisherID: user.ID,
64+
Publisher: user,
6365
TagName: "v0.2",
6466
Target: "master",
6567
Title: "v0.2 is released",

integrations/repo_tag_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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 integrations
6+
7+
import (
8+
"io/ioutil"
9+
"net/url"
10+
"testing"
11+
12+
"code.gitea.io/gitea/models"
13+
"code.gitea.io/gitea/modules/git"
14+
"code.gitea.io/gitea/modules/util"
15+
"code.gitea.io/gitea/services/release"
16+
17+
"github.com/stretchr/testify/assert"
18+
)
19+
20+
func TestCreateNewTagProtected(t *testing.T) {
21+
defer prepareTestEnv(t)()
22+
23+
repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
24+
owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
25+
26+
t.Run("API", func(t *testing.T) {
27+
defer PrintCurrentTest(t)()
28+
29+
err := release.CreateNewTag(owner, repo, "master", "v-1", "first tag")
30+
assert.NoError(t, err)
31+
32+
err = models.InsertProtectedTag(&models.ProtectedTag{
33+
RepoID: repo.ID,
34+
NamePattern: "v-*",
35+
})
36+
assert.NoError(t, err)
37+
err = models.InsertProtectedTag(&models.ProtectedTag{
38+
RepoID: repo.ID,
39+
NamePattern: "v-1.1",
40+
AllowlistUserIDs: []int64{repo.OwnerID},
41+
})
42+
assert.NoError(t, err)
43+
44+
err = release.CreateNewTag(owner, repo, "master", "v-2", "second tag")
45+
assert.Error(t, err)
46+
assert.True(t, models.IsErrProtectedTagName(err))
47+
48+
err = release.CreateNewTag(owner, repo, "master", "v-1.1", "third tag")
49+
assert.NoError(t, err)
50+
})
51+
52+
t.Run("Git", func(t *testing.T) {
53+
onGiteaRun(t, func(t *testing.T, u *url.URL) {
54+
username := "user2"
55+
httpContext := NewAPITestContext(t, username, "repo1")
56+
57+
dstPath, err := ioutil.TempDir("", httpContext.Reponame)
58+
assert.NoError(t, err)
59+
defer util.RemoveAll(dstPath)
60+
61+
u.Path = httpContext.GitPath()
62+
u.User = url.UserPassword(username, userPassword)
63+
64+
doGitClone(dstPath, u)(t)
65+
66+
_, err = git.NewCommand("tag", "v-2").RunInDir(dstPath)
67+
assert.NoError(t, err)
68+
69+
_, err = git.NewCommand("push", "--tags").RunInDir(dstPath)
70+
assert.Error(t, err)
71+
assert.Contains(t, err.Error(), "Tag v-2 is protected")
72+
})
73+
})
74+
}

models/error.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,21 @@ func (err ErrInvalidTagName) Error() string {
985985
return fmt.Sprintf("release tag name is not valid [tag_name: %s]", err.TagName)
986986
}
987987

988+
// ErrProtectedTagName represents a "ProtectedTagName" kind of error.
989+
type ErrProtectedTagName struct {
990+
TagName string
991+
}
992+
993+
// IsErrProtectedTagName checks if an error is a ErrProtectedTagName.
994+
func IsErrProtectedTagName(err error) bool {
995+
_, ok := err.(ErrProtectedTagName)
996+
return ok
997+
}
998+
999+
func (err ErrProtectedTagName) Error() string {
1000+
return fmt.Sprintf("release tag name is protected [tag_name: %s]", err.TagName)
1001+
}
1002+
9881003
// ErrRepoFileAlreadyExists represents a "RepoFileAlreadyExist" kind of error.
9891004
type ErrRepoFileAlreadyExists struct {
9901005
Path string

models/fixtures/action.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,27 @@
3232
repo_id: 22
3333
is_private: true
3434
created_unix: 1603267920
35+
36+
- id: 5
37+
user_id: 10
38+
op_type: 1 # create repo
39+
act_user_id: 10
40+
repo_id: 6
41+
is_private: true
42+
created_unix: 1603010100
43+
44+
- id: 6
45+
user_id: 10
46+
op_type: 1 # create repo
47+
act_user_id: 10
48+
repo_id: 7
49+
is_private: true
50+
created_unix: 1603011300
51+
52+
- id: 7
53+
user_id: 10
54+
op_type: 1 # create repo
55+
act_user_id: 10
56+
repo_id: 8
57+
is_private: false
58+
created_unix: 1603011540 # grouped with id:7

models/migrations/migrations.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ var migrations = []Migration{
322322
// v185 -> v186
323323
NewMigration("Add new table repo_archiver", addRepoArchiver),
324324
// v186 -> v187
325+
NewMigration("Create protected tag table", createProtectedTagTable),
326+
// v187 -> v188
325327
NewMigration("Drop unneeded webhook related columns", dropWebhookColumns),
326328
}
327329

models/migrations/v186.go

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,22 @@
55
package migrations
66

77
import (
8+
"code.gitea.io/gitea/modules/timeutil"
9+
810
"xorm.io/xorm"
911
)
1012

11-
func dropWebhookColumns(x *xorm.Engine) error {
12-
// Make sure the columns exist before dropping them
13-
type Webhook struct {
14-
Signature string `xorm:"TEXT"`
15-
IsSSL bool `xorm:"is_ssl"`
16-
}
17-
if err := x.Sync2(new(Webhook)); err != nil {
18-
return err
19-
}
20-
21-
type HookTask struct {
22-
Typ string `xorm:"VARCHAR(16) index"`
23-
URL string `xorm:"TEXT"`
24-
Signature string `xorm:"TEXT"`
25-
HTTPMethod string `xorm:"http_method"`
26-
ContentType int
27-
IsSSL bool
28-
}
29-
if err := x.Sync2(new(HookTask)); err != nil {
30-
return err
31-
}
13+
func createProtectedTagTable(x *xorm.Engine) error {
14+
type ProtectedTag struct {
15+
ID int64 `xorm:"pk autoincr"`
16+
RepoID int64
17+
NamePattern string
18+
AllowlistUserIDs []int64 `xorm:"JSON TEXT"`
19+
AllowlistTeamIDs []int64 `xorm:"JSON TEXT"`
3220

33-
sess := x.NewSession()
34-
defer sess.Close()
35-
if err := sess.Begin(); err != nil {
36-
return err
37-
}
38-
if err := dropTableColumns(sess, "webhook", "signature", "is_ssl"); err != nil {
39-
return err
40-
}
41-
if err := dropTableColumns(sess, "hook_task", "typ", "url", "signature", "http_method", "content_type", "is_ssl"); err != nil {
42-
return err
21+
CreatedUnix timeutil.TimeStamp `xorm:"created"`
22+
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
4323
}
4424

45-
return sess.Commit()
25+
return x.Sync2(new(ProtectedTag))
4626
}

models/migrations/v187.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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 dropWebhookColumns(x *xorm.Engine) error {
12+
// Make sure the columns exist before dropping them
13+
type Webhook struct {
14+
Signature string `xorm:"TEXT"`
15+
IsSSL bool `xorm:"is_ssl"`
16+
}
17+
if err := x.Sync2(new(Webhook)); err != nil {
18+
return err
19+
}
20+
21+
type HookTask struct {
22+
Typ string `xorm:"VARCHAR(16) index"`
23+
URL string `xorm:"TEXT"`
24+
Signature string `xorm:"TEXT"`
25+
HTTPMethod string `xorm:"http_method"`
26+
ContentType int
27+
IsSSL bool
28+
}
29+
if err := x.Sync2(new(HookTask)); err != nil {
30+
return err
31+
}
32+
33+
sess := x.NewSession()
34+
defer sess.Close()
35+
if err := sess.Begin(); err != nil {
36+
return err
37+
}
38+
if err := dropTableColumns(sess, "webhook", "signature", "is_ssl"); err != nil {
39+
return err
40+
}
41+
if err := dropTableColumns(sess, "hook_task", "typ", "url", "signature", "http_method", "content_type", "is_ssl"); err != nil {
42+
return err
43+
}
44+
45+
return sess.Commit()
46+
}

models/models.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ func init() {
137137
new(IssueIndex),
138138
new(PushMirror),
139139
new(RepoArchiver),
140+
new(ProtectedTag),
140141
)
141142

142143
gonicNames := []string{"SSL", "UID"}

0 commit comments

Comments
 (0)