Skip to content

Commit a902af7

Browse files
qwerty287wxiaoguanglafriks
authored
Support instance-wide OAuth2 applications (#21335)
Support OAuth2 applications created by admins on the admin panel, they aren't owned by anybody. Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Lauris BH <lauris@nix.lv>
1 parent c41b307 commit a902af7

File tree

7 files changed

+149
-6
lines changed

7 files changed

+149
-6
lines changed

routers/web/admin/applications.go

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright 2022 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 admin
6+
7+
import (
8+
"fmt"
9+
"net/http"
10+
11+
"code.gitea.io/gitea/models/auth"
12+
"code.gitea.io/gitea/modules/base"
13+
"code.gitea.io/gitea/modules/context"
14+
"code.gitea.io/gitea/modules/setting"
15+
user_setting "code.gitea.io/gitea/routers/web/user/setting"
16+
)
17+
18+
var (
19+
tplSettingsApplications base.TplName = "admin/applications/list"
20+
tplSettingsOauth2ApplicationEdit base.TplName = "admin/applications/oauth2_edit"
21+
)
22+
23+
func newOAuth2CommonHandlers() *user_setting.OAuth2CommonHandlers {
24+
return &user_setting.OAuth2CommonHandlers{
25+
OwnerID: 0,
26+
BasePathList: fmt.Sprintf("%s/admin/applications", setting.AppSubURL),
27+
BasePathEditPrefix: fmt.Sprintf("%s/admin/applications/oauth2", setting.AppSubURL),
28+
TplAppEdit: tplSettingsOauth2ApplicationEdit,
29+
}
30+
}
31+
32+
// Applications render org applications page (for org, at the moment, there are only OAuth2 applications)
33+
func Applications(ctx *context.Context) {
34+
ctx.Data["Title"] = ctx.Tr("settings.applications")
35+
ctx.Data["PageIsAdmin"] = true
36+
ctx.Data["PageIsAdminApplications"] = true
37+
38+
apps, err := auth.GetOAuth2ApplicationsByUserID(ctx, 0)
39+
if err != nil {
40+
ctx.ServerError("GetOAuth2ApplicationsByUserID", err)
41+
return
42+
}
43+
ctx.Data["Applications"] = apps
44+
45+
ctx.HTML(http.StatusOK, tplSettingsApplications)
46+
}
47+
48+
// ApplicationsPost response for adding an oauth2 application
49+
func ApplicationsPost(ctx *context.Context) {
50+
ctx.Data["Title"] = ctx.Tr("settings.applications")
51+
ctx.Data["PageIsAdmin"] = true
52+
ctx.Data["PageIsAdminApplications"] = true
53+
54+
oa := newOAuth2CommonHandlers()
55+
oa.AddApp(ctx)
56+
}
57+
58+
// EditApplication displays the given application
59+
func EditApplication(ctx *context.Context) {
60+
ctx.Data["PageIsAdmin"] = true
61+
ctx.Data["PageIsAdminApplications"] = true
62+
63+
oa := newOAuth2CommonHandlers()
64+
oa.EditShow(ctx)
65+
}
66+
67+
// EditApplicationPost response for editing oauth2 application
68+
func EditApplicationPost(ctx *context.Context) {
69+
ctx.Data["Title"] = ctx.Tr("settings.applications")
70+
ctx.Data["PageIsAdmin"] = true
71+
ctx.Data["PageIsAdminApplications"] = true
72+
73+
oa := newOAuth2CommonHandlers()
74+
oa.EditSave(ctx)
75+
}
76+
77+
// ApplicationsRegenerateSecret handles the post request for regenerating the secret
78+
func ApplicationsRegenerateSecret(ctx *context.Context) {
79+
ctx.Data["Title"] = ctx.Tr("settings")
80+
ctx.Data["PageIsAdmin"] = true
81+
ctx.Data["PageIsAdminApplications"] = true
82+
83+
oa := newOAuth2CommonHandlers()
84+
oa.RegenerateSecret(ctx)
85+
}
86+
87+
// DeleteApplication deletes the given oauth2 application
88+
func DeleteApplication(ctx *context.Context) {
89+
oa := newOAuth2CommonHandlers()
90+
oa.DeleteApp(ctx)
91+
}
92+
93+
// TODO: revokes the grant with the given id

routers/web/auth/oauth.go

+12-5
Original file line numberDiff line numberDiff line change
@@ -380,10 +380,13 @@ func AuthorizeOAuth(ctx *context.Context) {
380380
return
381381
}
382382

383-
user, err := user_model.GetUserByID(app.UID)
384-
if err != nil {
385-
ctx.ServerError("GetUserByID", err)
386-
return
383+
var user *user_model.User
384+
if app.UID != 0 {
385+
user, err = user_model.GetUserByID(app.UID)
386+
if err != nil {
387+
ctx.ServerError("GetUserByID", err)
388+
return
389+
}
387390
}
388391

389392
if !app.ContainsRedirectURI(form.RedirectURI) {
@@ -475,7 +478,11 @@ func AuthorizeOAuth(ctx *context.Context) {
475478
ctx.Data["State"] = form.State
476479
ctx.Data["Scope"] = form.Scope
477480
ctx.Data["Nonce"] = form.Nonce
478-
ctx.Data["ApplicationUserLinkHTML"] = "<a href=\"" + html.EscapeString(user.HTMLURL()) + "\">@" + html.EscapeString(user.Name) + "</a>"
481+
if user != nil {
482+
ctx.Data["ApplicationCreatorLinkHTML"] = fmt.Sprintf(`<a href="%s">@%s</a>`, html.EscapeString(user.HomeLink()), html.EscapeString(user.Name))
483+
} else {
484+
ctx.Data["ApplicationCreatorLinkHTML"] = fmt.Sprintf(`<a href="%s">%s</a>`, html.EscapeString(setting.AppSubURL+"/"), html.EscapeString(setting.AppName))
485+
}
479486
ctx.Data["ApplicationRedirectDomainHTML"] = "<strong>" + html.EscapeString(form.RedirectURI) + "</strong>"
480487
// TODO document SESSION <=> FORM
481488
err = ctx.Session.Set("client_id", app.ClientID)

routers/web/web.go

+17
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,23 @@ func RegisterRoutes(m *web.Route) {
569569
m.Post("/delete", admin.DeleteNotices)
570570
m.Post("/empty", admin.EmptyNotices)
571571
})
572+
573+
m.Group("/applications", func() {
574+
m.Get("", admin.Applications)
575+
m.Post("/oauth2", bindIgnErr(forms.EditOAuth2ApplicationForm{}), admin.ApplicationsPost)
576+
m.Group("/oauth2/{id}", func() {
577+
m.Combo("").Get(admin.EditApplication).Post(bindIgnErr(forms.EditOAuth2ApplicationForm{}), admin.EditApplicationPost)
578+
m.Post("/regenerate_secret", admin.ApplicationsRegenerateSecret)
579+
m.Post("/delete", admin.DeleteApplication)
580+
})
581+
}, func(ctx *context.Context) {
582+
if !setting.OAuth2.Enable {
583+
ctx.Error(http.StatusForbidden)
584+
return
585+
}
586+
})
587+
}, func(ctx *context.Context) {
588+
ctx.Data["EnableOAuth2"] = setting.OAuth2.Enable
572589
}, adminReq)
573590
// ***** END: Admin *****
574591

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{{template "base/head" .}}
2+
<div class="page-content admin config">
3+
{{template "admin/navbar" .}}
4+
<div class="ui container">
5+
<div class="twelve wide column content">
6+
{{template "base/alert" .}}
7+
<h4 class="ui top attached header">
8+
{{.locale.Tr "settings.applications"}}
9+
</h4>
10+
{{template "user/settings/applications_oauth2_list" .}}
11+
</div>
12+
</div>
13+
</div>
14+
{{template "base/footer" .}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{{template "base/head" .}}
2+
<div class="page-content admin config">
3+
{{template "admin/navbar" .}}
4+
5+
{{template "user/settings/applications_oauth2_edit_form" .}}
6+
</div>
7+
{{template "base/footer" .}}

templates/admin/navbar.tmpl

+5
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626
<a class="{{if .PageIsAdminEmails}}active{{end}} item" href="{{AppSubUrl}}/admin/emails">
2727
{{.locale.Tr "admin.emails"}}
2828
</a>
29+
{{if .EnableOAuth2}}
30+
<a class="{{if .PageIsAdminApplications}}active{{end}} item" href="{{AppSubUrl}}/admin/applications">
31+
{{.locale.Tr "settings.applications"}}
32+
</a>
33+
{{end}}
2934
<a class="{{if .PageIsAdminConfig}}active{{end}} item" href="{{AppSubUrl}}/admin/config">
3035
{{.locale.Tr "admin.config"}}
3136
</a>

templates/user/auth/grant.tmpl

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
{{template "base/alert" .}}
1010
<p>
1111
<b>{{.locale.Tr "auth.authorize_application_description"}}</b><br/>
12-
{{.locale.Tr "auth.authorize_application_created_by" .ApplicationUserLinkHTML | Str2html}}
12+
{{.locale.Tr "auth.authorize_application_created_by" .ApplicationCreatorLinkHTML | Str2html}}
1313
</p>
1414
</div>
1515
<div class="ui attached segment">

0 commit comments

Comments
 (0)