Skip to content

Commit ee56bd5

Browse files
committed
Merge branch 'main' into deps-api
2 parents 21dd56d + d5f9a4e commit ee56bd5

File tree

14 files changed

+230
-94
lines changed

14 files changed

+230
-94
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
---
2+
date: "2019-04-19:44:00+01:00"
3+
title: "OAuth2 提供者"
4+
slug: "oauth2-provider"
5+
weight: 41
6+
toc: false
7+
draft: false
8+
menu:
9+
sidebar:
10+
parent: "development"
11+
name: "OAuth2 提供者"
12+
weight: 41
13+
identifier: "oauth2-provider"
14+
---
15+
16+
# OAuth2 提供者
17+
18+
**目录**
19+
20+
{{< toc >}}
21+
22+
Gitea 支持作为 OAuth2 提供者,允许第三方应用程序在用户同意的情况下访问其资源。此功能自 1.8.0 版起可用。
23+
24+
## 端点
25+
26+
| 端点 | URL |
27+
| ------------------------ | ----------------------------------- |
28+
| OpenID Connect Discovery | `/.well-known/openid-configuration` |
29+
| Authorization Endpoint | `/login/oauth/authorize` |
30+
| Access Token Endpoint | `/login/oauth/access_token` |
31+
| OpenID Connect UserInfo | `/login/oauth/userinfo` |
32+
| JSON Web Key Set | `/login/oauth/keys` |
33+
34+
## 支持的 OAuth2 授权
35+
36+
目前 Gitea 仅支持 [**Authorization Code Grant**](https://tools.ietf.org/html/rfc6749#section-1.3.1) 标准,并额外支持以下扩展:
37+
38+
- [Proof Key for Code Exchange (PKCE)](https://tools.ietf.org/html/rfc7636)
39+
- [OpenID Connect (OIDC)](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth)
40+
41+
要将 Authorization Code Grant 作为第三方应用程序,您需要通过在设置中添加一个新的 "应用程序" (`/user/settings/applications`)。
42+
43+
## 范围
44+
45+
Gitea 支持以下令牌范围:
46+
47+
| 名称 | 介绍 |
48+
| ---- | ----------- |
49+
| **(no scope)** | 授予对公共用户配置文件和公共存储库的只读访问权限 |
50+
| **repo** | 完全控制所有存储库 |
51+
| &nbsp;&nbsp;&nbsp; **repo:status** | 授予对所有存储库中提交状态的读/写访问权限 |
52+
| &nbsp;&nbsp;&nbsp; **public_repo** | 仅授予对公共存储库的读/写访问权限 |
53+
| **admin:repo_hook** | 授予对所有存储库的 Hooks 访问权限,该权限已包含在 `repo` 范围中 |
54+
| &nbsp;&nbsp;&nbsp; **write:repo_hook** | 授予对存储库 Hooks 的读/写访问权限 |
55+
| &nbsp;&nbsp;&nbsp; **read:repo_hook** | 授予对存储库 Hooks 的只读访问权限 |
56+
| **admin:org** | 授予对组织设置的完全访问权限 |
57+
| &nbsp;&nbsp;&nbsp; **write:org** | 授予对组织设置的读/写访问权限 |
58+
| &nbsp;&nbsp;&nbsp; **read:org** | 授予对组织设置的只读访问权限 |
59+
| **admin:public_key** | 授予公钥管理的完全访问权限 |
60+
| &nbsp;&nbsp;&nbsp; **write:public_key** | 授予对公钥的读/写访问权限 |
61+
| &nbsp;&nbsp;&nbsp; **read:public_key** | 授予对公钥的只读访问权限 |
62+
| **admin:org_hook** | 授予对组织级别 Hooks 的完全访问权限 |
63+
| **admin:user_hook** | 授予对用户级别 Hooks 的完全访问权限 |
64+
| **notification** | 授予对通知的完全访问权限 |
65+
| **user** | 授予对用户个人资料信息的完全访问权限 |
66+
| &nbsp;&nbsp;&nbsp; **read:user** | 授予对用户个人资料的读取权限 |
67+
| &nbsp;&nbsp;&nbsp; **user:email** | 授予对用户电子邮件地址的读取权限 |
68+
| &nbsp;&nbsp;&nbsp; **user:follow** | 授予访问权限以关注/取消关注用户 |
69+
| **delete_repo** | 授予删除存储库的权限 |
70+
| **package** | 授予对托管包的完全访问权限 |
71+
| &nbsp;&nbsp;&nbsp; **write:package** | 授予对包的读/写访问权限 |
72+
| &nbsp;&nbsp;&nbsp; **read:package** | 授予对包的读取权限 |
73+
| &nbsp;&nbsp;&nbsp; **delete:package** | 授予对包的删除权限 |
74+
| **admin:gpg_key** | 授予 GPG 密钥管理的完全访问权限 |
75+
| &nbsp;&nbsp;&nbsp; **write:gpg_key** | 授予对 GPG 密钥的读/写访问权限 |
76+
| &nbsp;&nbsp;&nbsp; **read:gpg_key** | 授予对 GPG 密钥的只读访问权限 |
77+
| **admin:application** | 授予应用程序管理的完全访问权限 |
78+
| &nbsp;&nbsp;&nbsp; **write:application** | 授予应用程序管理的读/写访问权限 |
79+
| &nbsp;&nbsp;&nbsp; **read:application** | 授予应用程序管理的读取权限 |
80+
| **sudo** | 允许以站点管理员身份执行操作 |
81+
82+
## 客户端类型
83+
84+
Gitea 支持私密和公共客户端类型,[参见 RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749#section-2.1).
85+
86+
对于公共客户端, 允许在本地回环地址的重定向 URI 中使用任意端口,例如 `http://127.0.0.1/`。根据 [RFC 8252 的建议](https://datatracker.ietf.org/doc/html/rfc8252#section-8.3),请避免使用 `localhost`
87+
88+
## 示例
89+
90+
**注意:** 该示例中尚未使用 PKCE。
91+
92+
1. 将用户重定向到授权端点,以获得他们的访问资源授权:
93+
94+
```curl
95+
https://[YOUR-GITEA-URL]/login/oauth/authorize?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI& response_type=code&state=STATE
96+
```
97+
98+
在设置中注册应用程序以获得 `CLIENT_ID``STATE` 是一个随机字符串,它将在获得用户授权后发送回您的应用程序。`state` 参数是可选的,但您应该使用它来防止 CSRF 攻击。
99+
100+
![Authorization Page](/authorize.png)
101+
102+
用户将会被询问是否授权给您的应用程序。如果他们同意了授权,用户将会被重定向到 `REDIRECT_URL`,例如:
103+
104+
```curl
105+
https://[REDIRECT_URI]?code=RETURNED_CODE&state=STATE
106+
```
107+
108+
2. 使用重定向提供的 `code`,您可以请求一个新的应用程序和 Refresh Token。Access Token Endpoint 接受 `application/json``application/x-www-form-urlencoded` 类型的 POST 请求,例如:
109+
110+
```curl
111+
POST https://[YOUR-GITEA-URL]/login/oauth/access_token
112+
```
113+
114+
```json
115+
{
116+
"client_id": "YOUR_CLIENT_ID",
117+
"client_secret": "YOUR_CLIENT_SECRET",
118+
"code": "RETURNED_CODE",
119+
"grant_type": "authorization_code",
120+
"redirect_uri": "REDIRECT_URI"
121+
}
122+
```
123+
124+
返回:
125+
126+
```json
127+
{
128+
"access_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJnbnQiOjIsInR0IjowLCJleHAiOjE1NTUxNzk5MTIsImlhdCI6MTU1NTE3NjMxMn0.0-iFsAwBtxuckA0sNZ6QpBQmywVPz129u75vOM7wPJecw5wqGyBkmstfJHAjEOqrAf_V5Z-1QYeCh_Cz4RiKug",
129+
"token_type": "bearer",
130+
"expires_in": 3600,
131+
"refresh_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJnbnQiOjIsInR0IjoxLCJjbnQiOjEsImV4cCI6MTU1NzgwNDMxMiwiaWF0IjoxNTU1MTc2MzEyfQ.S_HZQBy4q9r5SEzNGNIoFClT43HPNDbUdHH-GYNYYdkRfft6XptJBkUQscZsGxOW975Yk6RbgtGvq1nkEcklOw"
132+
}
133+
```
134+
135+
`CLIENT_SECRET` 是生成给应用程序的唯一密钥。请注意,该密钥只会在您使用 Gitea 创建/注册应用程序后出现一次。如果您丢失了密钥,您必须在应用程序设置中重新生成密钥。
136+
137+
`access_token` 请求中的 `REDIRECT_URI` 必须与 `authorize` 请求中的 `REDIRECT_URI` 相符。
138+
139+
3. 使用 `access_token` 来构造 [API 请求](https://docs.gitea.io/en-us/api-usage#oauth2) 以读写用户的资源。

templates/base/footer_content.tmpl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@
1919
{{if .ShowFooterBranding}}
2020
<a target="_blank" rel="noopener noreferrer" href="https://github.com/go-gitea/gitea">{{svg "octicon-mark-github"}}<span class="sr-only">GitHub</span></a>
2121
{{end}}
22-
<div class="ui language bottom floating slide up dropdown link item">
23-
{{svg "octicon-globe"}}
24-
<span>{{.locale.LangName}}</span>
22+
<div class="ui dropdown upward language">
23+
<span>{{svg "octicon-globe"}} {{.locale.LangName}}</span>
2524
<div class="menu language-menu">
2625
{{range .AllLangs}}
2726
<a lang="{{.Lang}}" data-url="{{AppSubUrl}}/?lang={{.Lang}}" class="item {{if eq $.locale.Lang .Lang}}active selected{{end}}">{{.Name}}</a>

templates/repo/diff/options_dropdown.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div class="ui dropdown tiny basic button icon-button" data-tooltip-content="{{.locale.Tr "repo.diff.options_button"}}">
22
{{svg "octicon-kebab-horizontal"}}
33
<div class="menu">
4-
<a class="item tiny basic toggle button" id="show-file-list-btn">{{.locale.Tr "repo.diff.show_diff_stats"}}</a>
4+
<a class="item" id="show-file-list-btn">{{.locale.Tr "repo.diff.show_diff_stats"}}</a>
55
{{if .Issue.Index}}
66
<a class="item" href="{{$.RepoLink}}/pulls/{{.Issue.Index}}.patch" download="{{.Issue.Index}}.patch">{{.locale.Tr "repo.diff.download_patch"}}</a>
77
<a class="item" href="{{$.RepoLink}}/pulls/{{.Issue.Index}}.diff" download="{{.Issue.Index}}.diff">{{.locale.Tr "repo.diff.download_diff"}}</a>

templates/repo/diff/whitespace_dropdown.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@
2828
</a>
2929
</div>
3030
</div>
31-
<a class="ui tiny basic toggle button icon-button" href="?style={{if .IsSplitStyle}}unified{{else}}split{{end}}&whitespace={{$.WhitespaceBehavior}}" data-tooltip-content="{{if .IsSplitStyle}}{{.locale.Tr "repo.diff.show_unified_view"}}{{else}}{{.locale.Tr "repo.diff.show_split_view"}}{{end}}">{{if .IsSplitStyle}}{{svg "gitea-join"}}{{else}}{{svg "gitea-split"}}{{end}}</a>
31+
<a class="ui tiny basic button icon-button" href="?style={{if .IsSplitStyle}}unified{{else}}split{{end}}&whitespace={{$.WhitespaceBehavior}}" data-tooltip-content="{{if .IsSplitStyle}}{{.locale.Tr "repo.diff.show_unified_view"}}{{else}}{{.locale.Tr "repo.diff.show_split_view"}}{{end}}">{{if .IsSplitStyle}}{{svg "gitea-join"}}{{else}}{{svg "gitea-split"}}{{end}}</a>

templates/repo/home.tmpl

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,29 @@
2828
</div>
2929
{{end}}
3030
</div>
31-
<div class="gt-mt-3" id="repo-topics">
32-
{{range .Topics}}<a class="ui repo-topic large label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=1">{{.Name}}</a>{{end}}
33-
{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}<a id="manage_topic" class="muted">{{.locale.Tr "repo.topic.manage_topics"}}</a>{{end}}
31+
<div class="gt-df gt-ac gt-fw gt-mt-3" id="repo-topics">
32+
{{range .Topics}}<a class="ui repo-topic large label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=1">{{.Name}}</a>{{end}}
33+
{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}<button id="manage_topic" class="ui button tiny tertiary gt-ml-2">{{.locale.Tr "repo.topic.manage_topics"}}</button>{{end}}
3434
</div>
3535
{{end}}
3636
{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}
37-
<div class="ui repo-topic-edit grid form gt-hidden" id="topic_edit">
38-
<div class="fourteen wide column">
39-
<div class="field">
40-
<div class="ui fluid multiple search selection dropdown">
41-
<input type="hidden" name="topics" value="{{range $i, $v := .Topics}}{{.Name}}{{if lt (Add $i 1) (len $.Topics)}},{{end}}{{end}}">
42-
{{range .Topics}}
43-
<div class="ui small label topic transition visible" data-value="{{.Name}}" style="display: inline-block !important; cursor: default;">{{.Name}}{{svg "octicon-x" 16 "delete icon gt-ml-3 gt-mt-1"}}</div>
44-
{{end}}
45-
<div class="text"></div>
46-
</div>
37+
<div class="ui form gt-hidden gt-df gt-mt-4" id="topic_edit">
38+
<div class="field gt-f1 gt-mr-3">
39+
<div class="ui fluid multiple search selection dropdown" data-text-count-prompt="{{.locale.Tr "repo.topic.count_prompt"}}" data-text-format-prompt="{{.locale.Tr "repo.topic.format_prompt"}}">
40+
<input type="hidden" name="topics" value="{{range $i, $v := .Topics}}{{.Name}}{{if lt (Add $i 1) (len $.Topics)}},{{end}}{{end}}">
41+
{{range .Topics}}
42+
{{/* keey the same layout as Fomantic UI generated labels */}}
43+
<a class="ui label transition visible gt-cursor-default" data-value="{{.Name}}" style="display: inline-block !important;">{{.Name}}{{svg "octicon-x" 16 "delete icon"}}</a>
44+
{{end}}
45+
<div class="text"></div>
4746
</div>
4847
</div>
49-
<div class="two wide column">
50-
<a class="ui button primary" role="button" tabindex="0" id="save_topic"
51-
data-link="{{.RepoLink}}/topics">{{.locale.Tr "repo.topic.done"}}</a>
48+
<div>
49+
<button class="ui basic button secondary" id="cancel_topic_edit">{{.locale.Tr "cancel"}}</button>
50+
<button class="ui primary button" id="save_topic" data-link="{{.RepoLink}}/topics">{{.locale.Tr "save"}}</button>
5251
</div>
5352
</div>
5453
{{end}}
55-
<div class="gt-hidden" id="validate_prompt">
56-
<span id="count_prompt">{{.locale.Tr "repo.topic.count_prompt"}}</span>
57-
<span id="format_prompt">{{.locale.Tr "repo.topic.format_prompt"}}</span>
58-
</div>
5954
{{if .Repository.IsArchived}}
6055
<div class="ui warning message">
6156
{{.locale.Tr "repo.archive.title"}}

templates/repo/settings/webhook/history.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
{{else}}
1919
<span class="text red">{{svg "octicon-alert"}}</span>
2020
{{end}}
21-
<a class="ui primary sha label toggle button" data-target="#info-{{.ID}}">{{.UUID}}</a>
21+
<a class="ui primary sha label toggle button show-panel" data-panel="#info-{{.ID}}">{{.UUID}}</a>
2222
<div class="ui right">
2323
<span class="text grey time">
2424
{{.DeliveredString}}

web_src/css/base.css

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1854,15 +1854,15 @@ footer .container .links > *:first-child {
18541854
}
18551855

18561856
footer .ui.language .menu {
1857-
max-height: 500px;
1857+
height: 500px;
1858+
max-height: calc(100vh - 60px);
18581859
overflow-y: auto;
18591860
margin-bottom: 7px;
18601861
}
18611862

18621863
footer .ui.language .svg {
18631864
margin-right: 0.15em;
1864-
vertical-align: top;
1865-
margin-top: calc(2em - 16px);
1865+
margin-top: 1px;
18661866
}
18671867

18681868
footer .ui.left,
@@ -2387,6 +2387,10 @@ a.ui.label:hover {
23872387
color: var(--color-text);
23882388
}
23892389

2390+
.ui.tertiary.button:focus {
2391+
color: var(--color-text-dark);
2392+
}
2393+
23902394
.ui.primary.label,
23912395
.ui.primary.labels .label {
23922396
background-color: var(--color-primary) !important;

web_src/css/helpers.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
.gt-pointer-events-none { pointer-events: none !important; }
2424
.gt-relative { position: relative !important; }
2525
.gt-overflow-x-scroll { overflow-x: scroll !important; }
26+
.gt-cursor-default { cursor: default !important; }
2627

2728
.gt-mono {
2829
font-family: var(--fonts-monospace) !important;

web_src/css/repository.css

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3062,21 +3062,10 @@ tbody.commit-list {
30623062
top: -2px;
30633063
}
30643064

3065-
#topic_edit {
3066-
margin-top: 5px;
3067-
}
3068-
3069-
#repo-topics {
3070-
margin-top: 5px;
3071-
display: flex;
3072-
align-items: center;
3073-
flex-wrap: wrap;
3074-
}
3075-
3076-
.repo-topic {
3077-
font-weight: normal !important;
3065+
#repo-topics .repo-topic {
3066+
font-weight: normal;
30783067
cursor: pointer;
3079-
margin: 2px !important;
3068+
margin: 2px;
30803069
}
30813070

30823071
#new-dependency-drop-list.ui.selection.dropdown {
@@ -3092,18 +3081,6 @@ tbody.commit-list {
30923081
overflow: hidden;
30933082
}
30943083

3095-
#manage_topic {
3096-
font-size: 12px;
3097-
}
3098-
3099-
.label + #manage_topic {
3100-
margin-left: 5px;
3101-
}
3102-
3103-
.ui.small.label.topic {
3104-
margin-bottom: 4px;
3105-
}
3106-
31073084
.repo-header {
31083085
display: flex;
31093086
align-items: center;

web_src/js/components/DashboardRepoList.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div>
3-
<div v-if="!isOrganization" class="ui two item tabable menu">
3+
<div v-if="!isOrganization" class="ui two item menu">
44
<a :class="{item: true, active: tab === 'repos'}" @click="changeTab('repos')">{{ textRepository }}</a>
55
<a :class="{item: true, active: tab === 'organizations'}" @click="changeTab('organizations')">{{ textOrganization }}</a>
66
</div>

web_src/js/features/common-global.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export function initGlobalCommon() {
8383
const $uiDropdowns = $('.ui.dropdown');
8484

8585
// do not init "custom" dropdowns, "custom" dropdowns are managed by their own code.
86-
$uiDropdowns.filter(':not(.custom)').dropdown({fullTextSearch: 'exact'});
86+
$uiDropdowns.filter(':not(.custom)').dropdown();
8787

8888
// The "jump" means this dropdown is mainly used for "menu" purpose,
8989
// clicking an item will jump to somewhere else or trigger an action/function.
@@ -111,18 +111,12 @@ export function initGlobalCommon() {
111111
},
112112
});
113113

114-
// special animations/popup-directions
115-
$uiDropdowns.filter('.slide.up').dropdown({transition: 'slide up'});
116-
$uiDropdowns.filter('.upward').dropdown({direction: 'upward'});
114+
// special popup-directions
115+
$uiDropdowns.filter('.upward').dropdown('setting', 'direction', 'upward');
117116

118117
$('.ui.checkbox').checkbox();
119118

120119
$('.tabular.menu .item').tab();
121-
$('.tabable.menu .item').tab();
122-
123-
$('.toggle.button').on('click', function () {
124-
toggleElem($($(this).data('target')));
125-
});
126120

127121
// prevent multiple form submissions on forms containing .loading-button
128122
document.addEventListener('submit', (e) => {
@@ -312,8 +306,15 @@ export function initGlobalButtons() {
312306
});
313307

314308
$('.show-panel.button').on('click', function (e) {
309+
// a '.show-panel.button' can show a panel, by `data-panel="selector"`
310+
// if the button is a "toggle" button, it toggles the panel
315311
e.preventDefault();
316-
showElem($(this).data('panel'));
312+
const sel = $(this).attr('data-panel');
313+
if (this.classList.contains('toggle')) {
314+
toggleElem(sel);
315+
} else {
316+
showElem(sel);
317+
}
317318
});
318319

319320
$('.hide-panel.button').on('click', function (e) {

0 commit comments

Comments
 (0)