From a902af75f480a5629f0747cd65531107e4897e4e Mon Sep 17 00:00:00 2001 From: qwerty287 <80460567+qwerty287@users.noreply.github.com> Date: Wed, 12 Oct 2022 16:08:29 +0200 Subject: [PATCH] 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 Co-authored-by: Lauris BH --- routers/web/admin/applications.go | 93 +++++++++++++++++++ routers/web/auth/oauth.go | 17 +++- routers/web/web.go | 17 ++++ templates/admin/applications/list.tmpl | 14 +++ templates/admin/applications/oauth2_edit.tmpl | 7 ++ templates/admin/navbar.tmpl | 5 + templates/user/auth/grant.tmpl | 2 +- 7 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 routers/web/admin/applications.go create mode 100644 templates/admin/applications/list.tmpl create mode 100644 templates/admin/applications/oauth2_edit.tmpl diff --git a/routers/web/admin/applications.go b/routers/web/admin/applications.go new file mode 100644 index 0000000000..c7a9c3100f --- /dev/null +++ b/routers/web/admin/applications.go @@ -0,0 +1,93 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package admin + +import ( + "fmt" + "net/http" + + "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/setting" + user_setting "code.gitea.io/gitea/routers/web/user/setting" +) + +var ( + tplSettingsApplications base.TplName = "admin/applications/list" + tplSettingsOauth2ApplicationEdit base.TplName = "admin/applications/oauth2_edit" +) + +func newOAuth2CommonHandlers() *user_setting.OAuth2CommonHandlers { + return &user_setting.OAuth2CommonHandlers{ + OwnerID: 0, + BasePathList: fmt.Sprintf("%s/admin/applications", setting.AppSubURL), + BasePathEditPrefix: fmt.Sprintf("%s/admin/applications/oauth2", setting.AppSubURL), + TplAppEdit: tplSettingsOauth2ApplicationEdit, + } +} + +// Applications render org applications page (for org, at the moment, there are only OAuth2 applications) +func Applications(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("settings.applications") + ctx.Data["PageIsAdmin"] = true + ctx.Data["PageIsAdminApplications"] = true + + apps, err := auth.GetOAuth2ApplicationsByUserID(ctx, 0) + if err != nil { + ctx.ServerError("GetOAuth2ApplicationsByUserID", err) + return + } + ctx.Data["Applications"] = apps + + ctx.HTML(http.StatusOK, tplSettingsApplications) +} + +// ApplicationsPost response for adding an oauth2 application +func ApplicationsPost(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("settings.applications") + ctx.Data["PageIsAdmin"] = true + ctx.Data["PageIsAdminApplications"] = true + + oa := newOAuth2CommonHandlers() + oa.AddApp(ctx) +} + +// EditApplication displays the given application +func EditApplication(ctx *context.Context) { + ctx.Data["PageIsAdmin"] = true + ctx.Data["PageIsAdminApplications"] = true + + oa := newOAuth2CommonHandlers() + oa.EditShow(ctx) +} + +// EditApplicationPost response for editing oauth2 application +func EditApplicationPost(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("settings.applications") + ctx.Data["PageIsAdmin"] = true + ctx.Data["PageIsAdminApplications"] = true + + oa := newOAuth2CommonHandlers() + oa.EditSave(ctx) +} + +// ApplicationsRegenerateSecret handles the post request for regenerating the secret +func ApplicationsRegenerateSecret(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("settings") + ctx.Data["PageIsAdmin"] = true + ctx.Data["PageIsAdminApplications"] = true + + oa := newOAuth2CommonHandlers() + oa.RegenerateSecret(ctx) +} + +// DeleteApplication deletes the given oauth2 application +func DeleteApplication(ctx *context.Context) { + oa := newOAuth2CommonHandlers() + oa.DeleteApp(ctx) +} + +// TODO: revokes the grant with the given id diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go index e6112b4276..c172215b90 100644 --- a/routers/web/auth/oauth.go +++ b/routers/web/auth/oauth.go @@ -380,10 +380,13 @@ func AuthorizeOAuth(ctx *context.Context) { return } - user, err := user_model.GetUserByID(app.UID) - if err != nil { - ctx.ServerError("GetUserByID", err) - return + var user *user_model.User + if app.UID != 0 { + user, err = user_model.GetUserByID(app.UID) + if err != nil { + ctx.ServerError("GetUserByID", err) + return + } } if !app.ContainsRedirectURI(form.RedirectURI) { @@ -475,7 +478,11 @@ func AuthorizeOAuth(ctx *context.Context) { ctx.Data["State"] = form.State ctx.Data["Scope"] = form.Scope ctx.Data["Nonce"] = form.Nonce - ctx.Data["ApplicationUserLinkHTML"] = "@" + html.EscapeString(user.Name) + "" + if user != nil { + ctx.Data["ApplicationCreatorLinkHTML"] = fmt.Sprintf(`@%s`, html.EscapeString(user.HomeLink()), html.EscapeString(user.Name)) + } else { + ctx.Data["ApplicationCreatorLinkHTML"] = fmt.Sprintf(`%s`, html.EscapeString(setting.AppSubURL+"/"), html.EscapeString(setting.AppName)) + } ctx.Data["ApplicationRedirectDomainHTML"] = "" + html.EscapeString(form.RedirectURI) + "" // TODO document SESSION <=> FORM err = ctx.Session.Set("client_id", app.ClientID) diff --git a/routers/web/web.go b/routers/web/web.go index c74343c8cf..c01a2bce40 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -569,6 +569,23 @@ func RegisterRoutes(m *web.Route) { m.Post("/delete", admin.DeleteNotices) m.Post("/empty", admin.EmptyNotices) }) + + m.Group("/applications", func() { + m.Get("", admin.Applications) + m.Post("/oauth2", bindIgnErr(forms.EditOAuth2ApplicationForm{}), admin.ApplicationsPost) + m.Group("/oauth2/{id}", func() { + m.Combo("").Get(admin.EditApplication).Post(bindIgnErr(forms.EditOAuth2ApplicationForm{}), admin.EditApplicationPost) + m.Post("/regenerate_secret", admin.ApplicationsRegenerateSecret) + m.Post("/delete", admin.DeleteApplication) + }) + }, func(ctx *context.Context) { + if !setting.OAuth2.Enable { + ctx.Error(http.StatusForbidden) + return + } + }) + }, func(ctx *context.Context) { + ctx.Data["EnableOAuth2"] = setting.OAuth2.Enable }, adminReq) // ***** END: Admin ***** diff --git a/templates/admin/applications/list.tmpl b/templates/admin/applications/list.tmpl new file mode 100644 index 0000000000..6d627129df --- /dev/null +++ b/templates/admin/applications/list.tmpl @@ -0,0 +1,14 @@ +{{template "base/head" .}} +
+ {{template "admin/navbar" .}} +
+
+ {{template "base/alert" .}} +

+ {{.locale.Tr "settings.applications"}} +

+ {{template "user/settings/applications_oauth2_list" .}} +
+
+
+{{template "base/footer" .}} diff --git a/templates/admin/applications/oauth2_edit.tmpl b/templates/admin/applications/oauth2_edit.tmpl new file mode 100644 index 0000000000..84d821ecca --- /dev/null +++ b/templates/admin/applications/oauth2_edit.tmpl @@ -0,0 +1,7 @@ +{{template "base/head" .}} +
+ {{template "admin/navbar" .}} + + {{template "user/settings/applications_oauth2_edit_form" .}} +
+{{template "base/footer" .}} diff --git a/templates/admin/navbar.tmpl b/templates/admin/navbar.tmpl index 0db1aab079..b138eb79ba 100644 --- a/templates/admin/navbar.tmpl +++ b/templates/admin/navbar.tmpl @@ -26,6 +26,11 @@ {{.locale.Tr "admin.emails"}} + {{if .EnableOAuth2}} + + {{.locale.Tr "settings.applications"}} + + {{end}} {{.locale.Tr "admin.config"}} diff --git a/templates/user/auth/grant.tmpl b/templates/user/auth/grant.tmpl index 0ba32c550f..682614dee5 100644 --- a/templates/user/auth/grant.tmpl +++ b/templates/user/auth/grant.tmpl @@ -9,7 +9,7 @@ {{template "base/alert" .}}

{{.locale.Tr "auth.authorize_application_description"}}
- {{.locale.Tr "auth.authorize_application_created_by" .ApplicationUserLinkHTML | Str2html}} + {{.locale.Tr "auth.authorize_application_created_by" .ApplicationCreatorLinkHTML | Str2html}}