Fix windows build error (#14263)
* fix build * take flash error message back and fix more windows lint error * performance optimization * own step to check lint for windows Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
		
							parent
							
								
									4ef5f17a7e
								
							
						
					
					
						commit
						a1c9e8f266
					
				
					 12 changed files with 61 additions and 44 deletions
				
			
		
							
								
								
									
										12
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								.drone.yml
									
									
									
									
									
								
							|  | @ -33,6 +33,18 @@ steps: | |||
|       GOSUMDB: sum.golang.org | ||||
|       TAGS: bindata sqlite sqlite_unlock_notify | ||||
| 
 | ||||
|   - name: lint-backend-windows | ||||
|     pull: always | ||||
|     image: golang:1.15 | ||||
|     commands: | ||||
|       - make golangci-lint vet | ||||
|     environment: | ||||
|       GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not | ||||
|       GOSUMDB: sum.golang.org | ||||
|       TAGS: bindata sqlite sqlite_unlock_notify | ||||
|       GOOS: windows | ||||
|       GOARCH: amd64 | ||||
| 
 | ||||
|   - name: lint-backend-gogit | ||||
|     pull: always | ||||
|     image: golang:1.15 | ||||
|  |  | |||
|  | @ -47,7 +47,7 @@ func (b *Basic) IsEnabled() bool { | |||
| // "Authorization" header of the request and returns the corresponding user object for that
 | ||||
| // name/token on successful validation.
 | ||||
| // Returns nil if header is empty or validation fails.
 | ||||
| func (b *Basic) VerifyAuthData(req *http.Request, store DataStore, sess SessionStore) *models.User { | ||||
| func (b *Basic) VerifyAuthData(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *models.User { | ||||
| 	baHead := req.Header.Get("Authorization") | ||||
| 	if len(baHead) == 0 { | ||||
| 		return nil | ||||
|  |  | |||
|  | @ -40,5 +40,5 @@ type SingleSignOn interface { | |||
| 	// or a new user object (with id = 0) populated with the information that was found
 | ||||
| 	// in the authentication data (username or email).
 | ||||
| 	// Returns nil if verification fails.
 | ||||
| 	VerifyAuthData(http *http.Request, store DataStore, sess SessionStore) *models.User | ||||
| 	VerifyAuthData(http *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *models.User | ||||
| } | ||||
|  |  | |||
|  | @ -114,7 +114,7 @@ func (o *OAuth2) IsEnabled() bool { | |||
| // or the "Authorization" header and returns the corresponding user object for that ID.
 | ||||
| // If verification is successful returns an existing user object.
 | ||||
| // Returns nil if verification fails.
 | ||||
| func (o *OAuth2) VerifyAuthData(req *http.Request, store DataStore, sess SessionStore) *models.User { | ||||
| func (o *OAuth2) VerifyAuthData(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *models.User { | ||||
| 	if !models.HasEngine { | ||||
| 		return nil | ||||
| 	} | ||||
|  |  | |||
|  | @ -60,7 +60,7 @@ func (r *ReverseProxy) IsEnabled() bool { | |||
| // If a username is available in the "setting.ReverseProxyAuthUser" header an existing
 | ||||
| // user object is returned (populated with username or email found in header).
 | ||||
| // Returns nil if header is empty.
 | ||||
| func (r *ReverseProxy) VerifyAuthData(req *http.Request, store DataStore, sess SessionStore) *models.User { | ||||
| func (r *ReverseProxy) VerifyAuthData(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *models.User { | ||||
| 	username := r.getUserName(req) | ||||
| 	if len(username) == 0 { | ||||
| 		return nil | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ func (s *Session) IsEnabled() bool { | |||
| // VerifyAuthData checks if there is a user uid stored in the session and returns the user
 | ||||
| // object for that uid.
 | ||||
| // Returns nil if there is no user uid stored in the session.
 | ||||
| func (s *Session) VerifyAuthData(req *http.Request, store DataStore, sess SessionStore) *models.User { | ||||
| func (s *Session) VerifyAuthData(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *models.User { | ||||
| 	user := SessionUser(sess) | ||||
| 	if user != nil { | ||||
| 		return user | ||||
|  |  | |||
|  | @ -7,19 +7,17 @@ package sso | |||
| import ( | ||||
| 	"errors" | ||||
| 	"net/http" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/models" | ||||
| 	"code.gitea.io/gitea/modules/base" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| 
 | ||||
| 	"gitea.com/macaron/macaron" | ||||
| 	"gitea.com/macaron/session" | ||||
| 	"code.gitea.io/gitea/modules/templates" | ||||
| 
 | ||||
| 	gouuid "github.com/google/uuid" | ||||
| 	"github.com/quasoft/websspi" | ||||
| 	"github.com/unrolled/render" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
|  | @ -41,6 +39,7 @@ var ( | |||
| // On successful authentication returns a valid user object.
 | ||||
| // Returns nil if authentication fails.
 | ||||
| type SSPI struct { | ||||
| 	rnd *render.Render | ||||
| } | ||||
| 
 | ||||
| // Init creates a new global websspi.Authenticator object
 | ||||
|  | @ -48,7 +47,18 @@ func (s *SSPI) Init() error { | |||
| 	config := websspi.NewConfig() | ||||
| 	var err error | ||||
| 	sspiAuth, err = websspi.New(config) | ||||
| 	return err | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	s.rnd = render.New(render.Options{ | ||||
| 		Extensions:    []string{".tmpl"}, | ||||
| 		Directory:     "templates", | ||||
| 		Funcs:         templates.NewFuncMap(), | ||||
| 		Asset:         templates.GetAsset, | ||||
| 		AssetNames:    templates.GetAssetNames, | ||||
| 		IsDevelopment: setting.RunMode != "prod", | ||||
| 	}) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Free releases resources used by the global websspi.Authenticator object
 | ||||
|  | @ -65,8 +75,8 @@ func (s *SSPI) IsEnabled() bool { | |||
| // If authentication is successful, returs the corresponding user object.
 | ||||
| // If negotiation should continue or authentication fails, immediately returns a 401 HTTP
 | ||||
| // response code, as required by the SPNEGO protocol.
 | ||||
| func (s *SSPI) VerifyAuthData(req *http.Request, store DataStore, sess SessionStore) *models.User { | ||||
| 	if !s.shouldAuthenticate(ctx) { | ||||
| func (s *SSPI) VerifyAuthData(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *models.User { | ||||
| 	if !s.shouldAuthenticate(req) { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
|  | @ -76,22 +86,29 @@ func (s *SSPI) VerifyAuthData(req *http.Request, store DataStore, sess SessionSt | |||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	userInfo, outToken, err := sspiAuth.Authenticate(req, ctx.Resp) | ||||
| 	userInfo, outToken, err := sspiAuth.Authenticate(req, w) | ||||
| 	if err != nil { | ||||
| 		log.Warn("Authentication failed with error: %v\n", err) | ||||
| 		sspiAuth.AppendAuthenticateHeader(ctx.Resp, outToken) | ||||
| 		sspiAuth.AppendAuthenticateHeader(w, outToken) | ||||
| 
 | ||||
| 		// Include the user login page in the 401 response to allow the user
 | ||||
| 		// to login with another authentication method if SSPI authentication
 | ||||
| 		// fails
 | ||||
| 		addFlashErr(ctx, ctx.Tr("auth.sspi_auth_failed")) | ||||
| 		ctx.Data["EnableOpenIDSignIn"] = setting.Service.EnableOpenIDSignIn | ||||
| 		ctx.Data["EnableSSPI"] = true | ||||
| 		ctx.HTML(401, string(tplSignIn)) | ||||
| 		store.GetData()["Flash"] = map[string]string{ | ||||
| 			"ErrMsg": err.Error(), | ||||
| 		} | ||||
| 		store.GetData()["EnableOpenIDSignIn"] = setting.Service.EnableOpenIDSignIn | ||||
| 		store.GetData()["EnableSSPI"] = true | ||||
| 
 | ||||
| 		err := s.rnd.HTML(w, 401, string(tplSignIn), templates.BaseVars().Merge(store.GetData())) | ||||
| 		if err != nil { | ||||
| 			log.Error("%v", err) | ||||
| 		} | ||||
| 
 | ||||
| 		return nil | ||||
| 	} | ||||
| 	if outToken != "" { | ||||
| 		sspiAuth.AppendAuthenticateHeader(ctx.Resp, outToken) | ||||
| 		sspiAuth.AppendAuthenticateHeader(w, outToken) | ||||
| 	} | ||||
| 
 | ||||
| 	username := sanitizeUsername(userInfo.Username, cfg) | ||||
|  | @ -110,7 +127,7 @@ func (s *SSPI) VerifyAuthData(req *http.Request, store DataStore, sess SessionSt | |||
| 			log.Error("User '%s' not found", username) | ||||
| 			return nil | ||||
| 		} | ||||
| 		user, err = s.newUser(ctx, username, cfg) | ||||
| 		user, err = s.newUser(username, cfg) | ||||
| 		if err != nil { | ||||
| 			log.Error("CreateUser: %v", err) | ||||
| 			return nil | ||||
|  | @ -118,8 +135,8 @@ func (s *SSPI) VerifyAuthData(req *http.Request, store DataStore, sess SessionSt | |||
| 	} | ||||
| 
 | ||||
| 	// Make sure requests to API paths and PWA resources do not create a new session
 | ||||
| 	if !isAPIPath(ctx) && !isAttachmentDownload(ctx) { | ||||
| 		handleSignIn(ctx, sess, user) | ||||
| 	if !isAPIPath(req) && !isAttachmentDownload(req) { | ||||
| 		handleSignIn(w, req, sess, user) | ||||
| 	} | ||||
| 
 | ||||
| 	return user | ||||
|  | @ -146,7 +163,7 @@ func (s *SSPI) shouldAuthenticate(req *http.Request) (shouldAuth bool) { | |||
| 	if path == "/user/login" { | ||||
| 		if req.FormValue("user_name") != "" && req.FormValue("password") != "" { | ||||
| 			shouldAuth = false | ||||
| 		} else if ctx.Req.FormValue("auth_with_sspi") == "1" { | ||||
| 		} else if req.FormValue("auth_with_sspi") == "1" { | ||||
| 			shouldAuth = true | ||||
| 		} | ||||
| 	} else if isInternalPath(req) { | ||||
|  | @ -217,20 +234,6 @@ func sanitizeUsername(username string, cfg *models.SSPIConfig) string { | |||
| 	return username | ||||
| } | ||||
| 
 | ||||
| // addFlashErr adds an error message to the Flash object mapped to a macaron.Context
 | ||||
| func addFlashErr(ctx *macaron.Context, err string) { | ||||
| 	fv := ctx.GetVal(reflect.TypeOf(&session.Flash{})) | ||||
| 	if !fv.IsValid() { | ||||
| 		return | ||||
| 	} | ||||
| 	flash, ok := fv.Interface().(*session.Flash) | ||||
| 	if !ok { | ||||
| 		return | ||||
| 	} | ||||
| 	flash.Error(err) | ||||
| 	ctx.Data["Flash"] = flash | ||||
| } | ||||
| 
 | ||||
| // init registers the SSPI auth method as the last method in the list.
 | ||||
| // The SSPI plugin is expected to be executed last, as it returns 401 status code if negotiation
 | ||||
| // fails (or if negotiation should continue), which would prevent other authentication methods
 | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ import ( | |||
| 
 | ||||
| // SignedInUser returns the user object of signed user.
 | ||||
| // It returns a bool value to indicate whether user uses basic auth or not.
 | ||||
| func SignedInUser(req *http.Request, ds DataStore, sess SessionStore) (*models.User, bool) { | ||||
| func SignedInUser(req *http.Request, w http.ResponseWriter, ds DataStore, sess SessionStore) (*models.User, bool) { | ||||
| 	if !models.HasEngine { | ||||
| 		return nil, false | ||||
| 	} | ||||
|  | @ -22,7 +22,7 @@ func SignedInUser(req *http.Request, ds DataStore, sess SessionStore) (*models.U | |||
| 		if !ssoMethod.IsEnabled() { | ||||
| 			continue | ||||
| 		} | ||||
| 		user := ssoMethod.VerifyAuthData(req, ds, sess) | ||||
| 		user := ssoMethod.VerifyAuthData(req, w, ds, sess) | ||||
| 		if user != nil { | ||||
| 			_, isBasic := ssoMethod.(*Basic) | ||||
| 			return user, isBasic | ||||
|  |  | |||
|  | @ -309,7 +309,7 @@ func Contexter() macaron.Handler { | |||
| 		} | ||||
| 
 | ||||
| 		// Get user from session if logged in.
 | ||||
| 		ctx.User, ctx.IsBasicAuth = sso.SignedInUser(ctx.Req.Request, ctx, ctx.Session) | ||||
| 		ctx.User, ctx.IsBasicAuth = sso.SignedInUser(ctx.Req.Request, c.Resp, ctx, ctx.Session) | ||||
| 
 | ||||
| 		if ctx.User != nil { | ||||
| 			ctx.IsSigned = true | ||||
|  |  | |||
|  | @ -73,7 +73,7 @@ func (g *Manager) start() { | |||
| 
 | ||||
| 	// Make SVC process
 | ||||
| 	run := svc.Run | ||||
| 	isInteractive, err := svc.IsAnInteractiveSession() | ||||
| 	isInteractive, err := svc.IsWindowsService() | ||||
| 	if err != nil { | ||||
| 		log.Error("Unable to ascertain if running as an Interactive Session: %v", err) | ||||
| 		return | ||||
|  | @ -81,7 +81,9 @@ func (g *Manager) start() { | |||
| 	if isInteractive { | ||||
| 		run = debug.Run | ||||
| 	} | ||||
| 	go run(WindowsServiceName, g) | ||||
| 	go func() { | ||||
| 		_ = run(WindowsServiceName, g) | ||||
| 	}() | ||||
| } | ||||
| 
 | ||||
| // Execute makes Manager implement svc.Handler
 | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ func enableVTMode(console windows.Handle) bool { | |||
| 	// https://docs.microsoft.com/en-us/windows/console/setconsolemode
 | ||||
| 	// It only works on windows 10. Earlier terminals will fail with an err which we will
 | ||||
| 	// handle to say don't color
 | ||||
| 	mode = mode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING | ||||
| 	mode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING | ||||
| 	err = windows.SetConsoleMode(console, mode) | ||||
| 	return err == nil | ||||
| } | ||||
|  |  | |||
|  | @ -75,7 +75,7 @@ func Recovery() func(next http.Handler) http.Handler { | |||
| 					} | ||||
| 
 | ||||
| 					// Get user from session if logged in.
 | ||||
| 					user, _ := sso.SignedInUser(req, &store, sess) | ||||
| 					user, _ := sso.SignedInUser(req, w, &store, sess) | ||||
| 					if user != nil { | ||||
| 						store.Data["IsSigned"] = true | ||||
| 						store.Data["SignedUser"] = user | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue