Skip to content

Commit 41d6ad0

Browse files
committed
Merge remote-tracking branch 'giteaofficial/main'
* giteaofficial/main: Scoped label display and documentation tweaks (go-gitea#23430) Deduplicate template code for label selection menu (go-gitea#23431) Show edit/close/delete button on organization wide repositories (go-gitea#23388) Sync the class change of Edit Column Button to JS code (go-gitea#23400) Preserve file size when creating attachments (go-gitea#23406) [skip ci] Updated translations via Crowdin Use buildkit for docker builds (go-gitea#23415) Refactor branch/tag selector dropdown (first step) (go-gitea#23394) [skip ci] Updated translations via Crowdin Hide target selector if tag exists when creating new release (go-gitea#23171) Parse external request id from request headers, and print it in access log (go-gitea#22906) Add missing tabs to org projects page (go-gitea#22705) Add user webhooks (go-gitea#21563) Handle OpenID discovery URL errors a little nicer when creating/editing sources (go-gitea#23397) Split CI pipelines (go-gitea#23385)
2 parents 89e0d62 + a8e13e6 commit 41d6ad0

File tree

105 files changed

+2029
-782
lines changed

Some content is hidden

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

105 files changed

+2029
-782
lines changed

.drone.yml

+419-144
Large diffs are not rendered by default.

Makefile

+5-1
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ help:
190190
@echo " - deps install dependencies"
191191
@echo " - deps-frontend install frontend dependencies"
192192
@echo " - deps-backend install backend dependencies"
193+
@echo " - deps-tools install tool dependencies"
193194
@echo " - lint lint everything"
194195
@echo " - lint-frontend lint frontend files"
195196
@echo " - lint-backend lint backend files"
@@ -821,14 +822,17 @@ docs:
821822
cd docs; make trans-copy clean build-offline;
822823

823824
.PHONY: deps
824-
deps: deps-frontend deps-backend
825+
deps: deps-frontend deps-backend deps-tools
825826

826827
.PHONY: deps-frontend
827828
deps-frontend: node_modules
828829

829830
.PHONY: deps-backend
830831
deps-backend:
831832
$(GO) mod download
833+
834+
.PHONY: deps-tools
835+
deps-tools:
832836
$(GO) install $(AIR_PACKAGE)
833837
$(GO) install $(EDITORCONFIG_CHECKER_PACKAGE)
834838
$(GO) install $(ERRCHECK_PACKAGE)

cmd/admin.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package cmd
77
import (
88
"errors"
99
"fmt"
10+
"net/url"
1011
"os"
1112
"strings"
1213
"text/tabwriter"
@@ -469,11 +470,19 @@ func runAddOauth(c *cli.Context) error {
469470
return err
470471
}
471472

473+
config := parseOAuth2Config(c)
474+
if config.Provider == "openidConnect" {
475+
discoveryURL, err := url.Parse(config.OpenIDConnectAutoDiscoveryURL)
476+
if err != nil || (discoveryURL.Scheme != "http" && discoveryURL.Scheme != "https") {
477+
return fmt.Errorf("invalid Auto Discovery URL: %s (this must be a valid URL starting with http:// or https://)", config.OpenIDConnectAutoDiscoveryURL)
478+
}
479+
}
480+
472481
return auth_model.CreateSource(&auth_model.Source{
473482
Type: auth_model.OAuth2,
474483
Name: c.String("name"),
475484
IsActive: true,
476-
Cfg: parseOAuth2Config(c),
485+
Cfg: config,
477486
})
478487
}
479488

custom/conf/app.example.ini

+16
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,22 @@ ROUTER = console
576576
;; The routing level will default to that of the system but individual router level can be set in
577577
;; [log.<mode>.router] LEVEL
578578
;;
579+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
580+
;;
581+
;; Print request id which parsed from request headers in access log, when access log is enabled.
582+
;; * E.g:
583+
;; * In request Header: X-Request-ID: test-id-123
584+
;; * Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID
585+
;; * Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "test-id-123"
586+
;;
587+
;; If you configure more than one in the .ini file, it will match in the order of configuration,
588+
;; and the first match will be finally printed in the log.
589+
;; * E.g:
590+
;; * In reuqest Header: X-Trace-ID: trace-id-1q2w3e4r
591+
;; * Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID, X-Trace-ID, X-Req-ID
592+
;; * Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "trace-id-1q2w3e4r"
593+
;;
594+
;; REQUEST_ID_HEADERS =
579595

580596
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
581597
;;

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

+6
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,13 @@ Default templates for project boards:
881881
- `Identity`: the SignedUserName or `"-"` if not logged in.
882882
- `Start`: the start time of the request.
883883
- `ResponseWriter`: the responseWriter from the request.
884+
- `RequestID`: the value matching REQUEST_ID_HEADERS(default: `-`, if not matched).
884885
- You must be very careful to ensure that this template does not throw errors or panics as this template runs outside of the panic/recovery script.
886+
- `REQUEST_ID_HEADERS`: **\<empty\>**: You can configure multiple values that are splited by comma here. It will match in the order of configuration, and the first match will be finally printed in the access log.
887+
- e.g.
888+
- In the Request Header: X-Request-ID: **test-id-123**
889+
- Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID
890+
- Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "**test-id-123**" ...
885891

886892
### Log subsections (`log.name`, `log.name.*`)
887893

docs/content/doc/advanced/config-cheat-sheet.zh-cn.md

+16-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,22 @@ test01.xls: application/vnd.ms-excel; charset=binary
262262

263263
- `ROOT_PATH`: 日志文件根目录。
264264
- `MODE`: 日志记录模式,默认是为 `console`。如果要写到多个通道,用逗号分隔
265-
- `LEVEL`: 日志级别,默认为`Trace`
265+
- `LEVEL`: 日志级别,默认为 `Trace`
266+
- `DISABLE_ROUTER_LOG`: 关闭日志中的路由日志。
267+
- `ENABLE_ACCESS_LOG`: 是否开启 Access Log, 默认为 false。
268+
- `ACCESS_LOG_TEMPLATE`: `access.log` 输出内容的模板,默认模板:**`{{.Ctx.RemoteAddr}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.URL.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}\" \"{{.Ctx.Req.UserAgent}}"`**
269+
模板支持以下参数:
270+
- `Ctx`: 请求上下文。
271+
- `Identity`: 登录用户名,默认: “`-`”。
272+
- `Start`: 请求开始时间。
273+
- `ResponseWriter`:
274+
- `RequestID`: 从请求头中解析得到的与 `REQUEST_ID_HEADERS` 匹配的值,默认: “`-`”。
275+
- 一定要谨慎配置该模板,否则可能会引起panic.
276+
- `REQUEST_ID_HEADERS`: 从 Request Header 中匹配指定 Key,并将匹配到的值输出到 `access.log` 中(需要在 `ACCESS_LOG_TEMPLATE` 中指定输出位置)。如果在该参数中配置多个 Key, 请用逗号分割,程序将按照配置的顺序进行匹配。
277+
- 示例:
278+
- 请求头: X-Request-ID: **test-id-123**
279+
- 配置文件: REQUEST_ID_HEADERS = X-Request-ID
280+
- 日志输出: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "**test-id-123**" ...
266281

267282
## Cron (`cron`)
268283

docs/content/doc/developers/oauth2-provider.en-us.md

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Gitea supports the following scopes for tokens:
6060
| &nbsp;&nbsp;&nbsp; **write:public_key** | Grant read/write access to public keys |
6161
| &nbsp;&nbsp;&nbsp; **read:public_key** | Grant read-only access to public keys |
6262
| **admin:org_hook** | Grants full access to organizational-level hooks |
63+
| **admin:user_hook** | Grants full access to user-level hooks |
6364
| **notification** | Grants full access to notifications |
6465
| **user** | Grants full access to user profile info |
6566
| &nbsp;&nbsp;&nbsp; **read:user** | Grants read access to user's profile |

docs/content/doc/usage/labels.en-us.md

+3-5
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,15 @@ For repositories, labels can be created by going to `Issues` and clicking on `La
2323

2424
For organizations, you can define organization-wide labels that are shared with all organization repositories, including both already-existing repositories as well as newly created ones. Organization-wide labels can be created in the organization `Settings`.
2525

26-
Labels have a mandatory name, a mandatory color, an optional description, and must either be exclusive or not (see `Scoped labels` below).
26+
Labels have a mandatory name, a mandatory color, an optional description, and must either be exclusive or not (see `Scoped Labels` below).
2727

2828
When you create a repository, you can ensure certain labels exist by using the `Issue Labels` option. This option lists a number of available label sets that are [configured globally on your instance](../customizing-gitea/#labels). Its contained labels will all be created as well while creating the repository.
2929

3030
## Scoped Labels
3131

32-
A scoped label is a label that contains `/` in its name (not at either end of the name). For example labels `kind/bug` and `kind/enhancement` both have scope `kind`. Such labels will display the scope with slightly darker color.
32+
Scoped labels are used to ensure at most a single label with the same scope is assigned to an issue or pull request. For example, if labels `kind/bug` and `kind/enhancement` have the Exclusive option set, an issue can only be classified as a bug or an enhancement.
3333

34-
The scope of a label is determined based on the **last** `/`, so for example the scope of label `scope/subscope/item` is `scope/subscope`.
35-
36-
Scoped labels can be marked as exclusive. This ensures at most a single label with the same scope is assigned to an issue or pull request. For example, if `kind/bug` and `kind/enhancement` are marked exclusive, an issue can only be classified as a bug or an enhancement.
34+
A scoped label must contain `/` in its name (not at either end of the name). The scope of a label is determined based on the **last** `/`, so for example the scope of label `scope/subscope/item` is `scope/subscope`.
3735

3836
## Filtering by Label
3937

models/auth/token_scope.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ const (
3232

3333
AccessTokenScopeAdminOrgHook AccessTokenScope = "admin:org_hook"
3434

35+
AccessTokenScopeAdminUserHook AccessTokenScope = "admin:user_hook"
36+
3537
AccessTokenScopeNotification AccessTokenScope = "notification"
3638

3739
AccessTokenScopeUser AccessTokenScope = "user"
@@ -64,7 +66,7 @@ type AccessTokenScopeBitmap uint64
6466
const (
6567
// AccessTokenScopeAllBits is the bitmap of all access token scopes, except `sudo`.
6668
AccessTokenScopeAllBits AccessTokenScopeBitmap = AccessTokenScopeRepoBits |
67-
AccessTokenScopeAdminOrgBits | AccessTokenScopeAdminPublicKeyBits | AccessTokenScopeAdminOrgHookBits |
69+
AccessTokenScopeAdminOrgBits | AccessTokenScopeAdminPublicKeyBits | AccessTokenScopeAdminOrgHookBits | AccessTokenScopeAdminUserHookBits |
6870
AccessTokenScopeNotificationBits | AccessTokenScopeUserBits | AccessTokenScopeDeleteRepoBits |
6971
AccessTokenScopePackageBits | AccessTokenScopeAdminGPGKeyBits | AccessTokenScopeAdminApplicationBits
7072

@@ -86,6 +88,8 @@ const (
8688

8789
AccessTokenScopeAdminOrgHookBits AccessTokenScopeBitmap = 1 << iota
8890

91+
AccessTokenScopeAdminUserHookBits AccessTokenScopeBitmap = 1 << iota
92+
8993
AccessTokenScopeNotificationBits AccessTokenScopeBitmap = 1 << iota
9094

9195
AccessTokenScopeUserBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadUserBits | AccessTokenScopeUserEmailBits | AccessTokenScopeUserFollowBits
@@ -123,6 +127,7 @@ var allAccessTokenScopes = []AccessTokenScope{
123127
AccessTokenScopeAdminPublicKey, AccessTokenScopeWritePublicKey, AccessTokenScopeReadPublicKey,
124128
AccessTokenScopeAdminRepoHook, AccessTokenScopeWriteRepoHook, AccessTokenScopeReadRepoHook,
125129
AccessTokenScopeAdminOrgHook,
130+
AccessTokenScopeAdminUserHook,
126131
AccessTokenScopeNotification,
127132
AccessTokenScopeUser, AccessTokenScopeReadUser, AccessTokenScopeUserEmail, AccessTokenScopeUserFollow,
128133
AccessTokenScopeDeleteRepo,
@@ -147,6 +152,7 @@ var allAccessTokenScopeBits = map[AccessTokenScope]AccessTokenScopeBitmap{
147152
AccessTokenScopeWriteRepoHook: AccessTokenScopeWriteRepoHookBits,
148153
AccessTokenScopeReadRepoHook: AccessTokenScopeReadRepoHookBits,
149154
AccessTokenScopeAdminOrgHook: AccessTokenScopeAdminOrgHookBits,
155+
AccessTokenScopeAdminUserHook: AccessTokenScopeAdminUserHookBits,
150156
AccessTokenScopeNotification: AccessTokenScopeNotificationBits,
151157
AccessTokenScopeUser: AccessTokenScopeUserBits,
152158
AccessTokenScopeReadUser: AccessTokenScopeReadUserBits,
@@ -263,7 +269,7 @@ func (bitmap AccessTokenScopeBitmap) ToScope() AccessTokenScope {
263269
scope := AccessTokenScope(strings.Join(scopes, ","))
264270
scope = AccessTokenScope(strings.ReplaceAll(
265271
string(scope),
266-
"repo,admin:org,admin:public_key,admin:org_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application",
272+
"repo,admin:org,admin:public_key,admin:org_hook,admin:user_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application",
267273
"all",
268274
))
269275
return scope

models/auth/token_scope_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ func TestAccessTokenScope_Normalize(t *testing.T) {
4040
{"admin:gpg_key,write:gpg_key,user", "user,admin:gpg_key", nil},
4141
{"admin:application,write:application,user", "user,admin:application", nil},
4242
{"all", "all", nil},
43-
{"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application", "all", nil},
44-
{"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application,sudo", "all,sudo", nil},
43+
{"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,admin:user_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application", "all", nil},
44+
{"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,admin:user_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application,sudo", "all,sudo", nil},
4545
}
4646

4747
for _, test := range tests {

models/fixtures/webhook.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
-
1818
id: 3
19-
org_id: 3
19+
owner_id: 3
2020
repo_id: 3
2121
url: www.example.com/url3
2222
content_type: 1 # json

models/migrations/migrations.go

+2
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,8 @@ var migrations = []Migration{
467467

468468
// v244 -> v245
469469
NewMigration("Add NeedApproval to actions tables", v1_20.AddNeedApprovalToActionRun),
470+
// v245 -> v246
471+
NewMigration("Rename Webhook org_id to owner_id", v1_20.RenameWebhookOrgToOwner),
470472
}
471473

472474
// GetCurrentDBVersion returns the current db version

models/migrations/v1_20/v245.go

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package v1_20 //nolint
5+
6+
import (
7+
"context"
8+
"fmt"
9+
10+
"code.gitea.io/gitea/models/migrations/base"
11+
"code.gitea.io/gitea/modules/setting"
12+
13+
"xorm.io/xorm"
14+
)
15+
16+
func RenameWebhookOrgToOwner(x *xorm.Engine) error {
17+
type Webhook struct {
18+
OrgID int64 `xorm:"INDEX"`
19+
}
20+
21+
// This migration maybe rerun so that we should check if it has been run
22+
ownerExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webhook", "owner_id")
23+
if err != nil {
24+
return err
25+
}
26+
27+
if ownerExist {
28+
orgExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webhook", "org_id")
29+
if err != nil {
30+
return err
31+
}
32+
if !orgExist {
33+
return nil
34+
}
35+
}
36+
37+
sess := x.NewSession()
38+
defer sess.Close()
39+
if err := sess.Begin(); err != nil {
40+
return err
41+
}
42+
43+
if err := sess.Sync2(new(Webhook)); err != nil {
44+
return err
45+
}
46+
47+
if ownerExist {
48+
if err := base.DropTableColumns(sess, "webhook", "owner_id"); err != nil {
49+
return err
50+
}
51+
}
52+
53+
switch {
54+
case setting.Database.Type.IsMySQL():
55+
inferredTable, err := x.TableInfo(new(Webhook))
56+
if err != nil {
57+
return err
58+
}
59+
sqlType := x.Dialect().SQLType(inferredTable.GetColumn("org_id"))
60+
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `webhook` CHANGE org_id owner_id %s", sqlType)); err != nil {
61+
return err
62+
}
63+
case setting.Database.Type.IsMSSQL():
64+
if _, err := sess.Exec("sp_rename 'webhook.org_id', 'owner_id', 'COLUMN'"); err != nil {
65+
return err
66+
}
67+
default:
68+
if _, err := sess.Exec("ALTER TABLE `webhook` RENAME COLUMN org_id TO owner_id"); err != nil {
69+
return err
70+
}
71+
}
72+
73+
return sess.Commit()
74+
}

models/organization/org.go

+26
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,32 @@ func (org *Organization) CustomAvatarRelativePath() string {
239239
return org.Avatar
240240
}
241241

242+
// UnitPermission returns unit permission
243+
func (org *Organization) UnitPermission(ctx context.Context, doer *user_model.User, unitType unit.Type) perm.AccessMode {
244+
if doer != nil {
245+
teams, err := GetUserOrgTeams(ctx, org.ID, doer.ID)
246+
if err != nil {
247+
log.Error("GetUserOrgTeams: %v", err)
248+
return perm.AccessModeNone
249+
}
250+
251+
if err := teams.LoadUnits(ctx); err != nil {
252+
log.Error("LoadUnits: %v", err)
253+
return perm.AccessModeNone
254+
}
255+
256+
if len(teams) > 0 {
257+
return teams.UnitMaxAccess(unitType)
258+
}
259+
}
260+
261+
if org.Visibility.IsPublic() {
262+
return perm.AccessModeRead
263+
}
264+
265+
return perm.AccessModeNone
266+
}
267+
242268
// CreateOrganization creates record of a new organization.
243269
func CreateOrganization(org *Organization, owner *user_model.User) (err error) {
244270
if !owner.CanCreateOrganization() {

models/user/user.go

+5
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,11 @@ func (u *User) IsOrganization() bool {
393393
return u.Type == UserTypeOrganization
394394
}
395395

396+
// IsIndividual returns true if user is actually a individual user.
397+
func (u *User) IsIndividual() bool {
398+
return u.Type == UserTypeIndividual
399+
}
400+
396401
// DisplayName returns full name if it's not empty,
397402
// returns username otherwise.
398403
func (u *User) DisplayName() string {

0 commit comments

Comments
 (0)