add skip secondary authorization option for public oauth2 clients (#31454)
This commit is contained in:
		
							parent
							
								
									e9aa39bda4
								
							
						
					
					
						commit
						a8d0c879c3
					
				| @ -37,10 +37,11 @@ type OAuth2Application struct { | |||||||
| 	// https://datatracker.ietf.org/doc/html/rfc6749#section-2.1 | 	// https://datatracker.ietf.org/doc/html/rfc6749#section-2.1 | ||||||
| 	// "Authorization servers MUST record the client type in the client registration details" | 	// "Authorization servers MUST record the client type in the client registration details" | ||||||
| 	// https://datatracker.ietf.org/doc/html/rfc8252#section-8.4 | 	// https://datatracker.ietf.org/doc/html/rfc8252#section-8.4 | ||||||
| 	ConfidentialClient bool               `xorm:"NOT NULL DEFAULT TRUE"` | 	ConfidentialClient         bool               `xorm:"NOT NULL DEFAULT TRUE"` | ||||||
| 	RedirectURIs       []string           `xorm:"redirect_uris JSON TEXT"` | 	SkipSecondaryAuthorization bool               `xorm:"NOT NULL DEFAULT FALSE"` | ||||||
| 	CreatedUnix        timeutil.TimeStamp `xorm:"INDEX created"` | 	RedirectURIs               []string           `xorm:"redirect_uris JSON TEXT"` | ||||||
| 	UpdatedUnix        timeutil.TimeStamp `xorm:"INDEX updated"` | 	CreatedUnix                timeutil.TimeStamp `xorm:"INDEX created"` | ||||||
|  | 	UpdatedUnix                timeutil.TimeStamp `xorm:"INDEX updated"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
| @ -251,21 +252,23 @@ func GetOAuth2ApplicationByID(ctx context.Context, id int64) (app *OAuth2Applica | |||||||
| 
 | 
 | ||||||
| // CreateOAuth2ApplicationOptions holds options to create an oauth2 application | // CreateOAuth2ApplicationOptions holds options to create an oauth2 application | ||||||
| type CreateOAuth2ApplicationOptions struct { | type CreateOAuth2ApplicationOptions struct { | ||||||
| 	Name               string | 	Name                       string | ||||||
| 	UserID             int64 | 	UserID                     int64 | ||||||
| 	ConfidentialClient bool | 	ConfidentialClient         bool | ||||||
| 	RedirectURIs       []string | 	SkipSecondaryAuthorization bool | ||||||
|  | 	RedirectURIs               []string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // CreateOAuth2Application inserts a new oauth2 application | // CreateOAuth2Application inserts a new oauth2 application | ||||||
| func CreateOAuth2Application(ctx context.Context, opts CreateOAuth2ApplicationOptions) (*OAuth2Application, error) { | func CreateOAuth2Application(ctx context.Context, opts CreateOAuth2ApplicationOptions) (*OAuth2Application, error) { | ||||||
| 	clientID := uuid.New().String() | 	clientID := uuid.New().String() | ||||||
| 	app := &OAuth2Application{ | 	app := &OAuth2Application{ | ||||||
| 		UID:                opts.UserID, | 		UID:                        opts.UserID, | ||||||
| 		Name:               opts.Name, | 		Name:                       opts.Name, | ||||||
| 		ClientID:           clientID, | 		ClientID:                   clientID, | ||||||
| 		RedirectURIs:       opts.RedirectURIs, | 		RedirectURIs:               opts.RedirectURIs, | ||||||
| 		ConfidentialClient: opts.ConfidentialClient, | 		ConfidentialClient:         opts.ConfidentialClient, | ||||||
|  | 		SkipSecondaryAuthorization: opts.SkipSecondaryAuthorization, | ||||||
| 	} | 	} | ||||||
| 	if err := db.Insert(ctx, app); err != nil { | 	if err := db.Insert(ctx, app); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| @ -275,11 +278,12 @@ func CreateOAuth2Application(ctx context.Context, opts CreateOAuth2ApplicationOp | |||||||
| 
 | 
 | ||||||
| // UpdateOAuth2ApplicationOptions holds options to update an oauth2 application | // UpdateOAuth2ApplicationOptions holds options to update an oauth2 application | ||||||
| type UpdateOAuth2ApplicationOptions struct { | type UpdateOAuth2ApplicationOptions struct { | ||||||
| 	ID                 int64 | 	ID                         int64 | ||||||
| 	Name               string | 	Name                       string | ||||||
| 	UserID             int64 | 	UserID                     int64 | ||||||
| 	ConfidentialClient bool | 	ConfidentialClient         bool | ||||||
| 	RedirectURIs       []string | 	SkipSecondaryAuthorization bool | ||||||
|  | 	RedirectURIs               []string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // UpdateOAuth2Application updates an oauth2 application | // UpdateOAuth2Application updates an oauth2 application | ||||||
| @ -305,6 +309,7 @@ func UpdateOAuth2Application(ctx context.Context, opts UpdateOAuth2ApplicationOp | |||||||
| 	app.Name = opts.Name | 	app.Name = opts.Name | ||||||
| 	app.RedirectURIs = opts.RedirectURIs | 	app.RedirectURIs = opts.RedirectURIs | ||||||
| 	app.ConfidentialClient = opts.ConfidentialClient | 	app.ConfidentialClient = opts.ConfidentialClient | ||||||
|  | 	app.SkipSecondaryAuthorization = opts.SkipSecondaryAuthorization | ||||||
| 
 | 
 | ||||||
| 	if err = updateOAuth2Application(ctx, app); err != nil { | 	if err = updateOAuth2Application(ctx, app); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| @ -315,7 +320,7 @@ func UpdateOAuth2Application(ctx context.Context, opts UpdateOAuth2ApplicationOp | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func updateOAuth2Application(ctx context.Context, app *OAuth2Application) error { | func updateOAuth2Application(ctx context.Context, app *OAuth2Application) error { | ||||||
| 	if _, err := db.GetEngine(ctx).ID(app.ID).UseBool("confidential_client").Update(app); err != nil { | 	if _, err := db.GetEngine(ctx).ID(app.ID).UseBool("confidential_client", "skip_secondary_authorization").Update(app); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
|  | |||||||
| @ -593,6 +593,8 @@ var migrations = []Migration{ | |||||||
| 	NewMigration("Add content version to issue and comment table", v1_23.AddContentVersionToIssueAndComment), | 	NewMigration("Add content version to issue and comment table", v1_23.AddContentVersionToIssueAndComment), | ||||||
| 	// v300 -> v301 | 	// v300 -> v301 | ||||||
| 	NewMigration("Add force-push branch protection support", v1_23.AddForcePushBranchProtection), | 	NewMigration("Add force-push branch protection support", v1_23.AddForcePushBranchProtection), | ||||||
|  | 	// v301 -> v302 | ||||||
|  | 	NewMigration("Add skip_secondary_authorization option to oauth2 application table", v1_23.AddSkipSecondaryAuthColumnToOAuth2ApplicationTable), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetCurrentDBVersion returns the current db version | // GetCurrentDBVersion returns the current db version | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								models/migrations/v1_23/v301.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								models/migrations/v1_23/v301.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | // Copyright 2024 The Gitea Authors. All rights reserved. | ||||||
|  | // SPDX-License-Identifier: MIT | ||||||
|  | 
 | ||||||
|  | package v1_23 //nolint | ||||||
|  | 
 | ||||||
|  | import "xorm.io/xorm" | ||||||
|  | 
 | ||||||
|  | // AddSkipSeconderyAuthToOAuth2ApplicationTable: add SkipSecondaryAuthorization column, setting existing rows to false | ||||||
|  | func AddSkipSecondaryAuthColumnToOAuth2ApplicationTable(x *xorm.Engine) error { | ||||||
|  | 	type oauth2Application struct { | ||||||
|  | 		SkipSecondaryAuthorization bool `xorm:"NOT NULL DEFAULT FALSE"` | ||||||
|  | 	} | ||||||
|  | 	return x.Sync(new(oauth2Application)) | ||||||
|  | } | ||||||
| @ -31,21 +31,23 @@ type CreateAccessTokenOption struct { | |||||||
| 
 | 
 | ||||||
| // CreateOAuth2ApplicationOptions holds options to create an oauth2 application | // CreateOAuth2ApplicationOptions holds options to create an oauth2 application | ||||||
| type CreateOAuth2ApplicationOptions struct { | type CreateOAuth2ApplicationOptions struct { | ||||||
| 	Name               string   `json:"name" binding:"Required"` | 	Name                       string   `json:"name" binding:"Required"` | ||||||
| 	ConfidentialClient bool     `json:"confidential_client"` | 	ConfidentialClient         bool     `json:"confidential_client"` | ||||||
| 	RedirectURIs       []string `json:"redirect_uris" binding:"Required"` | 	SkipSecondaryAuthorization bool     `json:"skip_secondary_authorization"` | ||||||
|  | 	RedirectURIs               []string `json:"redirect_uris" binding:"Required"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // OAuth2Application represents an OAuth2 application. | // OAuth2Application represents an OAuth2 application. | ||||||
| // swagger:response OAuth2Application | // swagger:response OAuth2Application | ||||||
| type OAuth2Application struct { | type OAuth2Application struct { | ||||||
| 	ID                 int64     `json:"id"` | 	ID                         int64     `json:"id"` | ||||||
| 	Name               string    `json:"name"` | 	Name                       string    `json:"name"` | ||||||
| 	ClientID           string    `json:"client_id"` | 	ClientID                   string    `json:"client_id"` | ||||||
| 	ClientSecret       string    `json:"client_secret"` | 	ClientSecret               string    `json:"client_secret"` | ||||||
| 	ConfidentialClient bool      `json:"confidential_client"` | 	ConfidentialClient         bool      `json:"confidential_client"` | ||||||
| 	RedirectURIs       []string  `json:"redirect_uris"` | 	SkipSecondaryAuthorization bool      `json:"skip_secondary_authorization"` | ||||||
| 	Created            time.Time `json:"created"` | 	RedirectURIs               []string  `json:"redirect_uris"` | ||||||
|  | 	Created                    time.Time `json:"created"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // OAuth2ApplicationList represents a list of OAuth2 applications. | // OAuth2ApplicationList represents a list of OAuth2 applications. | ||||||
|  | |||||||
| @ -914,6 +914,7 @@ create_oauth2_application_success = You have successfully created a new OAuth2 a | |||||||
| update_oauth2_application_success = You have successfully updated the OAuth2 application. | update_oauth2_application_success = You have successfully updated the OAuth2 application. | ||||||
| oauth2_application_name = Application Name | oauth2_application_name = Application Name | ||||||
| oauth2_confidential_client = Confidential Client. Select for apps that keep the secret confidential, such as web apps. Do not select for native apps including desktop and mobile apps. | oauth2_confidential_client = Confidential Client. Select for apps that keep the secret confidential, such as web apps. Do not select for native apps including desktop and mobile apps. | ||||||
|  | oauth2_skip_secondary_authorization = Skip authorization for public clients after granting access once. <strong>May pose a security risk.</strong> | ||||||
| oauth2_redirect_uris = Redirect URIs. Please use a new line for every URI. | oauth2_redirect_uris = Redirect URIs. Please use a new line for every URI. | ||||||
| save_application = Save | save_application = Save | ||||||
| oauth2_client_id = Client ID | oauth2_client_id = Client ID | ||||||
|  | |||||||
| @ -223,10 +223,11 @@ func CreateOauth2Application(ctx *context.APIContext) { | |||||||
| 	data := web.GetForm(ctx).(*api.CreateOAuth2ApplicationOptions) | 	data := web.GetForm(ctx).(*api.CreateOAuth2ApplicationOptions) | ||||||
| 
 | 
 | ||||||
| 	app, err := auth_model.CreateOAuth2Application(ctx, auth_model.CreateOAuth2ApplicationOptions{ | 	app, err := auth_model.CreateOAuth2Application(ctx, auth_model.CreateOAuth2ApplicationOptions{ | ||||||
| 		Name:               data.Name, | 		Name:                       data.Name, | ||||||
| 		UserID:             ctx.Doer.ID, | 		UserID:                     ctx.Doer.ID, | ||||||
| 		RedirectURIs:       data.RedirectURIs, | 		RedirectURIs:               data.RedirectURIs, | ||||||
| 		ConfidentialClient: data.ConfidentialClient, | 		ConfidentialClient:         data.ConfidentialClient, | ||||||
|  | 		SkipSecondaryAuthorization: data.SkipSecondaryAuthorization, | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusBadRequest, "", "error creating oauth2 application") | 		ctx.Error(http.StatusBadRequest, "", "error creating oauth2 application") | ||||||
| @ -381,11 +382,12 @@ func UpdateOauth2Application(ctx *context.APIContext) { | |||||||
| 	data := web.GetForm(ctx).(*api.CreateOAuth2ApplicationOptions) | 	data := web.GetForm(ctx).(*api.CreateOAuth2ApplicationOptions) | ||||||
| 
 | 
 | ||||||
| 	app, err := auth_model.UpdateOAuth2Application(ctx, auth_model.UpdateOAuth2ApplicationOptions{ | 	app, err := auth_model.UpdateOAuth2Application(ctx, auth_model.UpdateOAuth2ApplicationOptions{ | ||||||
| 		Name:               data.Name, | 		Name:                       data.Name, | ||||||
| 		UserID:             ctx.Doer.ID, | 		UserID:                     ctx.Doer.ID, | ||||||
| 		ID:                 appID, | 		ID:                         appID, | ||||||
| 		RedirectURIs:       data.RedirectURIs, | 		RedirectURIs:               data.RedirectURIs, | ||||||
| 		ConfidentialClient: data.ConfidentialClient, | 		ConfidentialClient:         data.ConfidentialClient, | ||||||
|  | 		SkipSecondaryAuthorization: data.SkipSecondaryAuthorization, | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if auth_model.IsErrOauthClientIDInvalid(err) || auth_model.IsErrOAuthApplicationNotFound(err) { | 		if auth_model.IsErrOauthClientIDInvalid(err) || auth_model.IsErrOAuthApplicationNotFound(err) { | ||||||
|  | |||||||
| @ -469,9 +469,9 @@ func AuthorizeOAuth(ctx *context.Context) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Redirect if user already granted access and the application is confidential. | 	// Redirect if user already granted access and the application is confidential or trusted otherwise | ||||||
| 	// I.e. always require authorization for public clients as recommended by RFC 6749 Section 10.2 | 	// I.e. always require authorization for untrusted public clients as recommended by RFC 6749 Section 10.2 | ||||||
| 	if app.ConfidentialClient && grant != nil { | 	if (app.ConfidentialClient || app.SkipSecondaryAuthorization) && grant != nil { | ||||||
| 		code, err := grant.GenerateNewAuthorizationCode(ctx, form.RedirectURI, form.CodeChallenge, form.CodeChallengeMethod) | 		code, err := grant.GenerateNewAuthorizationCode(ctx, form.RedirectURI, form.CodeChallenge, form.CodeChallengeMethod) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			handleServerError(ctx, form.State, form.RedirectURI) | 			handleServerError(ctx, form.State, form.RedirectURI) | ||||||
|  | |||||||
| @ -49,10 +49,11 @@ func (oa *OAuth2CommonHandlers) AddApp(ctx *context.Context) { | |||||||
| 
 | 
 | ||||||
| 	// TODO validate redirect URI | 	// TODO validate redirect URI | ||||||
| 	app, err := auth.CreateOAuth2Application(ctx, auth.CreateOAuth2ApplicationOptions{ | 	app, err := auth.CreateOAuth2Application(ctx, auth.CreateOAuth2ApplicationOptions{ | ||||||
| 		Name:               form.Name, | 		Name:                       form.Name, | ||||||
| 		RedirectURIs:       util.SplitTrimSpace(form.RedirectURIs, "\n"), | 		RedirectURIs:               util.SplitTrimSpace(form.RedirectURIs, "\n"), | ||||||
| 		UserID:             oa.OwnerID, | 		UserID:                     oa.OwnerID, | ||||||
| 		ConfidentialClient: form.ConfidentialClient, | 		ConfidentialClient:         form.ConfidentialClient, | ||||||
|  | 		SkipSecondaryAuthorization: form.SkipSecondaryAuthorization, | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.ServerError("CreateOAuth2Application", err) | 		ctx.ServerError("CreateOAuth2Application", err) | ||||||
| @ -102,11 +103,12 @@ func (oa *OAuth2CommonHandlers) EditSave(ctx *context.Context) { | |||||||
| 	// TODO validate redirect URI | 	// TODO validate redirect URI | ||||||
| 	var err error | 	var err error | ||||||
| 	if ctx.Data["App"], err = auth.UpdateOAuth2Application(ctx, auth.UpdateOAuth2ApplicationOptions{ | 	if ctx.Data["App"], err = auth.UpdateOAuth2Application(ctx, auth.UpdateOAuth2ApplicationOptions{ | ||||||
| 		ID:                 ctx.PathParamInt64("id"), | 		ID:                         ctx.PathParamInt64("id"), | ||||||
| 		Name:               form.Name, | 		Name:                       form.Name, | ||||||
| 		RedirectURIs:       util.SplitTrimSpace(form.RedirectURIs, "\n"), | 		RedirectURIs:               util.SplitTrimSpace(form.RedirectURIs, "\n"), | ||||||
| 		UserID:             oa.OwnerID, | 		UserID:                     oa.OwnerID, | ||||||
| 		ConfidentialClient: form.ConfidentialClient, | 		ConfidentialClient:         form.ConfidentialClient, | ||||||
|  | 		SkipSecondaryAuthorization: form.SkipSecondaryAuthorization, | ||||||
| 	}); err != nil { | 	}); err != nil { | ||||||
| 		ctx.ServerError("UpdateOAuth2Application", err) | 		ctx.ServerError("UpdateOAuth2Application", err) | ||||||
| 		return | 		return | ||||||
|  | |||||||
| @ -455,13 +455,14 @@ func ToTopicResponse(topic *repo_model.Topic) *api.TopicResponse { | |||||||
| // ToOAuth2Application convert from auth.OAuth2Application to api.OAuth2Application | // ToOAuth2Application convert from auth.OAuth2Application to api.OAuth2Application | ||||||
| func ToOAuth2Application(app *auth.OAuth2Application) *api.OAuth2Application { | func ToOAuth2Application(app *auth.OAuth2Application) *api.OAuth2Application { | ||||||
| 	return &api.OAuth2Application{ | 	return &api.OAuth2Application{ | ||||||
| 		ID:                 app.ID, | 		ID:                         app.ID, | ||||||
| 		Name:               app.Name, | 		Name:                       app.Name, | ||||||
| 		ClientID:           app.ClientID, | 		ClientID:                   app.ClientID, | ||||||
| 		ClientSecret:       app.ClientSecret, | 		ClientSecret:               app.ClientSecret, | ||||||
| 		ConfidentialClient: app.ConfidentialClient, | 		ConfidentialClient:         app.ConfidentialClient, | ||||||
| 		RedirectURIs:       app.RedirectURIs, | 		SkipSecondaryAuthorization: app.SkipSecondaryAuthorization, | ||||||
| 		Created:            app.CreatedUnix.AsTime(), | 		RedirectURIs:               app.RedirectURIs, | ||||||
|  | 		Created:                    app.CreatedUnix.AsTime(), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -365,9 +365,10 @@ func (f *NewAccessTokenForm) GetScope() (auth_model.AccessTokenScope, error) { | |||||||
| 
 | 
 | ||||||
| // EditOAuth2ApplicationForm form for editing oauth2 applications | // EditOAuth2ApplicationForm form for editing oauth2 applications | ||||||
| type EditOAuth2ApplicationForm struct { | type EditOAuth2ApplicationForm struct { | ||||||
| 	Name               string `binding:"Required;MaxSize(255)" form:"application_name"` | 	Name                       string `binding:"Required;MaxSize(255)" form:"application_name"` | ||||||
| 	RedirectURIs       string `binding:"Required" form:"redirect_uris"` | 	RedirectURIs               string `binding:"Required" form:"redirect_uris"` | ||||||
| 	ConfidentialClient bool   `form:"confidential_client"` | 	ConfidentialClient         bool   `form:"confidential_client"` | ||||||
|  | 	SkipSecondaryAuthorization bool   `form:"skip_secondary_authorization"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Validate validates the fields | // Validate validates the fields | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								templates/swagger/v1_json.tmpl
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								templates/swagger/v1_json.tmpl
									
									
									
										generated
									
									
									
								
							| @ -19875,6 +19875,10 @@ | |||||||
|             "type": "string" |             "type": "string" | ||||||
|           }, |           }, | ||||||
|           "x-go-name": "RedirectURIs" |           "x-go-name": "RedirectURIs" | ||||||
|  |         }, | ||||||
|  |         "skip_secondary_authorization": { | ||||||
|  |           "type": "boolean", | ||||||
|  |           "x-go-name": "SkipSecondaryAuthorization" | ||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       "x-go-package": "code.gitea.io/gitea/modules/structs" |       "x-go-package": "code.gitea.io/gitea/modules/structs" | ||||||
| @ -23002,6 +23006,10 @@ | |||||||
|             "type": "string" |             "type": "string" | ||||||
|           }, |           }, | ||||||
|           "x-go-name": "RedirectURIs" |           "x-go-name": "RedirectURIs" | ||||||
|  |         }, | ||||||
|  |         "skip_secondary_authorization": { | ||||||
|  |           "type": "boolean", | ||||||
|  |           "x-go-name": "SkipSecondaryAuthorization" | ||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       "x-go-package": "code.gitea.io/gitea/modules/structs" |       "x-go-package": "code.gitea.io/gitea/modules/structs" | ||||||
|  | |||||||
| @ -44,7 +44,13 @@ | |||||||
| 		<div class="field {{if .Err_ConfidentialClient}}error{{end}}"> | 		<div class="field {{if .Err_ConfidentialClient}}error{{end}}"> | ||||||
| 			<div class="ui checkbox"> | 			<div class="ui checkbox"> | ||||||
| 				<label>{{ctx.Locale.Tr "settings.oauth2_confidential_client"}}</label> | 				<label>{{ctx.Locale.Tr "settings.oauth2_confidential_client"}}</label> | ||||||
| 				<input type="checkbox" name="confidential_client" {{if .App.ConfidentialClient}}checked{{end}}> | 				<input class="disable-setting" type="checkbox" name="confidential_client" data-target="#skip-secondary-authorization" {{if .App.ConfidentialClient}}checked{{end}}> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 		<div class="field {{if .Err_SkipSecondaryAuthorization}}error{{end}} {{if .App.ConfidentialClient}}disabled{{end}}" id="skip-secondary-authorization"> | ||||||
|  | 			<div class="ui checkbox"> | ||||||
|  | 				<label>{{ctx.Locale.Tr "settings.oauth2_skip_secondary_authorization"}}</label> | ||||||
|  | 				<input type="checkbox" name="skip_secondary_authorization" {{if .App.SkipSecondaryAuthorization}}checked{{end}}> | ||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
| 		<button class="ui primary button"> | 		<button class="ui primary button"> | ||||||
|  | |||||||
| @ -64,7 +64,13 @@ | |||||||
| 		<div class="field {{if .Err_ConfidentialClient}}error{{end}}"> | 		<div class="field {{if .Err_ConfidentialClient}}error{{end}}"> | ||||||
| 			<div class="ui checkbox"> | 			<div class="ui checkbox"> | ||||||
| 				<label>{{ctx.Locale.Tr "settings.oauth2_confidential_client"}}</label> | 				<label>{{ctx.Locale.Tr "settings.oauth2_confidential_client"}}</label> | ||||||
| 				<input type="checkbox" name="confidential_client" checked> | 				<input class="disable-setting" type="checkbox" name="confidential_client" data-target="#skip-secondary-authorization" checked> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 		<div class="field {{if .Err_SkipSecondaryAuthorization}}error{{end}} disabled" id="skip-secondary-authorization"> | ||||||
|  | 			<div class="ui checkbox"> | ||||||
|  | 				<label>{{ctx.Locale.Tr "settings.oauth2_skip_secondary_authorization"}}</label> | ||||||
|  | 				<input type="checkbox" name="skip_secondary_authorization"> | ||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
| 		<button class="ui primary button"> | 		<button class="ui primary button"> | ||||||
|  | |||||||
							
								
								
									
										5
									
								
								web_src/js/features/oauth2-settings.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								web_src/js/features/oauth2-settings.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | export function initOAuth2SettingsDisableCheckbox() { | ||||||
|  |   for (const e of document.querySelectorAll('.disable-setting')) e.addEventListener('change', ({target}) => { | ||||||
|  |     document.querySelector(e.getAttribute('data-target')).classList.toggle('disabled', target.checked); | ||||||
|  |   }); | ||||||
|  | } | ||||||
| @ -78,6 +78,7 @@ import {initDirAuto} from './modules/dirauto.ts'; | |||||||
| import {initRepositorySearch} from './features/repo-search.ts'; | import {initRepositorySearch} from './features/repo-search.ts'; | ||||||
| import {initColorPickers} from './features/colorpicker.ts'; | import {initColorPickers} from './features/colorpicker.ts'; | ||||||
| import {initAdminSelfCheck} from './features/admin/selfcheck.ts'; | import {initAdminSelfCheck} from './features/admin/selfcheck.ts'; | ||||||
|  | import {initOAuth2SettingsDisableCheckbox} from './features/oauth2-settings.ts'; | ||||||
| import {initGlobalFetchAction} from './features/common-fetch-action.ts'; | import {initGlobalFetchAction} from './features/common-fetch-action.ts'; | ||||||
| import { | import { | ||||||
|   initFootLanguageMenu, |   initFootLanguageMenu, | ||||||
| @ -225,5 +226,7 @@ onDomReady(() => { | |||||||
|     initPdfViewer, |     initPdfViewer, | ||||||
|     initScopedAccessTokenCategories, |     initScopedAccessTokenCategories, | ||||||
|     initColorPickers, |     initColorPickers, | ||||||
|  | 
 | ||||||
|  |     initOAuth2SettingsDisableCheckbox, | ||||||
|   ]); |   ]); | ||||||
| }); | }); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user