chore: enable forcetypeassert linter, fix issues (#38804)

Enable [`forcetypeassert`](https://github.com/gostaticanalysis/forcetypeassert)
linter to prevent unchecked type assertions. ~650 issues fixed, most
fixes were clean, some use `setting.PanicInDevOrTesting`.

The only behaviour changes are where code would previously send a 500 error
or panic, a 4xx error is now emitted.

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
silverwind
2026-08-09 12:25:06 +02:00
committed by GitHub
parent fac8bf2eca
commit 76a81b24f9
248 changed files with 1110 additions and 995 deletions
+8 -10
View File
@@ -41,17 +41,16 @@ func TwoFactor(ctx *context.Context) {
// TwoFactorPost validates a user's two-factor authentication token.
func TwoFactorPost(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.TwoFactorAuthForm)
form := web.GetForm[*forms.TwoFactorAuthForm](ctx)
ctx.Data["Title"] = ctx.Tr("twofa")
// Ensure user is in a 2FA session.
idSess := ctx.Session.Get("twofaUid")
if idSess == nil {
id, hasSession := ctx.Session.Get("twofaUid").(int64)
if !hasSession {
ctx.ServerError("UserSignIn", errors.New("not in 2FA session"))
return
}
id := idSess.(int64)
twofa, err := auth.GetTwoFactorByUID(ctx, id)
if err != nil {
ctx.ServerError("UserSignIn", err)
@@ -66,7 +65,7 @@ func TwoFactorPost(ctx *context.Context) {
}
if ok {
remember := ctx.Session.Get("twofaRemember").(bool)
remember := ctx.Session.Get("twofaRemember").(bool) //nolint:forcetypeassert // must exist
u, err := user_model.GetUserByID(ctx, id)
if err != nil {
ctx.ServerError("UserSignIn", err)
@@ -105,17 +104,16 @@ func TwoFactorScratch(ctx *context.Context) {
// TwoFactorScratchPost validates and invalidates a user's two-factor scratch token.
func TwoFactorScratchPost(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.TwoFactorScratchAuthForm)
form := web.GetForm[*forms.TwoFactorScratchAuthForm](ctx)
ctx.Data["Title"] = ctx.Tr("twofa_scratch")
// Ensure user is in a 2FA session.
idSess := ctx.Session.Get("twofaUid")
if idSess == nil {
id, hasSession := ctx.Session.Get("twofaUid").(int64)
if !hasSession {
ctx.ServerError("UserSignIn", errors.New("not in 2FA session"))
return
}
id := idSess.(int64)
twofa, err := auth.GetTwoFactorByUID(ctx, id)
if err != nil {
ctx.ServerError("UserSignIn", err)
@@ -135,7 +133,7 @@ func TwoFactorScratchPost(ctx *context.Context) {
return
}
remember := ctx.Session.Get("twofaRemember").(bool)
remember := ctx.Session.Get("twofaRemember").(bool) //nolint:forcetypeassert // must exist
u, err := user_model.GetUserByID(ctx, id)
if err != nil {
ctx.ServerError("UserSignIn", err)
+11 -8
View File
@@ -293,7 +293,7 @@ func SignInPost(ctx *context.Context) {
return
}
form := web.GetForm(ctx).(*forms.SignInForm)
form := web.GetForm[*forms.SignInForm](ctx)
if setting.Service.EnableCaptcha && setting.Service.RequireCaptchaForLogin {
context.VerifyCaptcha(ctx, tplSignIn, form)
@@ -535,7 +535,7 @@ func SignUpPost(ctx *context.Context) {
return
}
form := web.GetForm(ctx).(*forms.RegisterForm)
form := web.GetForm[*forms.RegisterForm](ctx)
// Permission denied if DisableRegistration or AllowOnlyExternalRegistration options are true
if setting.Service.DisableRegistration || setting.Service.AllowOnlyExternalRegistration {
@@ -651,6 +651,9 @@ func createUserInContext(ctx *context.Context, tpl templates.TplName, form any,
}
// handle error with template
var errNameReserved db.ErrNameReserved
var errNamePatternNotAllowed db.ErrNamePatternNotAllowed
var errNameCharsNotAllowed db.ErrNameCharsNotAllowed
switch {
case user_model.IsErrUserAlreadyExist(err):
ctx.Data["Err_UserName"] = true
@@ -664,15 +667,15 @@ func createUserInContext(ctx *context.Context, tpl templates.TplName, form any,
case user_model.IsErrEmailInvalid(err):
ctx.Data["Err_Email"] = true
ctx.RenderWithErrDeprecated(ctx.Tr("form.email_invalid"), tpl, form)
case db.IsErrNameReserved(err):
case errors.As(err, &errNameReserved):
ctx.Data["Err_UserName"] = true
ctx.RenderWithErrDeprecated(ctx.Tr("user.form.name_reserved", err.(db.ErrNameReserved).Name), tpl, form)
case db.IsErrNamePatternNotAllowed(err):
ctx.RenderWithErrDeprecated(ctx.Tr("user.form.name_reserved", errNameReserved.Name), tpl, form)
case errors.As(err, &errNamePatternNotAllowed):
ctx.Data["Err_UserName"] = true
ctx.RenderWithErrDeprecated(ctx.Tr("user.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tpl, form)
case db.IsErrNameCharsNotAllowed(err):
ctx.RenderWithErrDeprecated(ctx.Tr("user.form.name_pattern_not_allowed", errNamePatternNotAllowed.Pattern), tpl, form)
case errors.As(err, &errNameCharsNotAllowed):
ctx.Data["Err_UserName"] = true
ctx.RenderWithErrDeprecated(ctx.Tr("user.form.name_chars_not_allowed", err.(db.ErrNameCharsNotAllowed).Name), tpl, form)
ctx.RenderWithErrDeprecated(ctx.Tr("user.form.name_chars_not_allowed", errNameCharsNotAllowed.Name), tpl, form)
default:
ctx.ServerError("CreateUser", err)
}
+3 -3
View File
@@ -113,7 +113,7 @@ func handleSignInError(ctx *context.Context, userName string, ptrForm any, tmpl
// LinkAccountPostSignIn handle the coupling of external account with another account using signIn
func LinkAccountPostSignIn(ctx *context.Context) {
signInForm := web.GetForm(ctx).(*forms.SignInForm)
signInForm := web.GetForm[*forms.SignInForm](ctx)
ctx.Data["LinkAccountModeSignIn"] = true
@@ -176,7 +176,7 @@ func oauth2LinkAccount(ctx *context.Context, u *user_model.User, linkAccountData
// LinkAccountPostRegister handle the creation of a new account for an external account using signUp
func LinkAccountPostRegister(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.RegisterForm)
form := web.GetForm[*forms.RegisterForm](ctx)
ctx.Data["LinkAccountModeRegister"] = true
@@ -253,7 +253,7 @@ func LinkAccountPostRegister(ctx *context.Context) {
ctx.ServerError("GetSourceByID", err)
return
}
source := authSource.Cfg.(*oauth2.Source)
source := auth.MustSourceCfg[*oauth2.Source](authSource)
if err := syncGroupsToTeams(ctx, source, &linkAccountData.GothUser, u); err != nil {
ctx.ServerError("SyncGroupsToTeams", err)
return
+9 -7
View File
@@ -56,13 +56,15 @@ func SignInOAuth(ctx *context.Context) {
return
}
if err = authSource.Cfg.(*oauth2.Source).Callout(ctx.Req, ctx.Resp); err != nil {
oauth2Source := auth.MustSourceCfg[*oauth2.Source](authSource)
if err = oauth2Source.Callout(ctx.Req, ctx.Resp); err != nil {
if strings.Contains(err.Error(), "no provider for ") {
if err = oauth2.ResetOAuth2(ctx); err != nil {
ctx.ServerError("SignIn", err)
return
}
if err = authSource.Cfg.(*oauth2.Source).Callout(ctx.Req, ctx.Resp); err != nil {
if err = oauth2Source.Callout(ctx.Req, ctx.Resp); err != nil {
ctx.ServerError("SignIn", err)
}
return
@@ -100,8 +102,7 @@ func SignInOAuthCallback(ctx *context.Context) {
u, gothUser, err := oAuth2UserLoginCallback(ctx, authSource, ctx.Req, ctx.Resp)
if err != nil {
if user_model.IsErrUserProhibitLogin(err) {
uplerr := err.(user_model.ErrUserProhibitLogin)
if uplerr, ok := err.(user_model.ErrUserProhibitLogin); ok {
log.Info("Failed authentication attempt for %s from %s: %v", uplerr.Name, ctx.RemoteAddr(), err)
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
@@ -188,7 +189,7 @@ func SignInOAuthCallback(ctx *context.Context) {
IsActive: optional.Some(!setting.OAuth2Client.RegisterEmailConfirm && !setting.Service.RegisterManualConfirm),
}
source := authSource.Cfg.(*oauth2.Source)
source := auth.MustSourceCfg[*oauth2.Source](authSource)
linkAccountData := &LinkAccountData{authSource.ID, gothUser}
if setting.OAuth2Client.AccountLinking == setting.OAuth2AccountLinkingDisabled {
@@ -368,7 +369,8 @@ func handleOAuth2SignIn(ctx *context.Context, authSource *auth.Source, u *user_m
}
}
oauth2Source := authSource.Cfg.(*oauth2.Source)
oauth2Source := auth.MustSourceCfg[*oauth2.Source](authSource)
groupTeamMapping, err := auth_module.UnmarshalGroupTeamMapping(oauth2Source.GroupTeamMap)
if err != nil {
ctx.ServerError("UnmarshalGroupTeamMapping", err)
@@ -458,7 +460,7 @@ func handleOAuth2SignIn(ctx *context.Context, authSource *auth.Source, u *user_m
// OAuth2UserLoginCallback attempts to handle the callback from the OAuth2 provider and if successful
// login the user
func oAuth2UserLoginCallback(ctx *context.Context, authSource *auth.Source, request *http.Request, response http.ResponseWriter) (*user_model.User, goth.User, error) {
oauth2Source := authSource.Cfg.(*oauth2.Source)
oauth2Source := auth.MustSourceCfg[*oauth2.Source](authSource)
// Make sure that the response is not an error response.
errorName := request.FormValue("error")
+4 -4
View File
@@ -172,7 +172,7 @@ func IntrospectOAuth(ctx *context.Context) {
jwt.RegisteredClaims
}
form := web.GetForm(ctx).(*forms.IntrospectTokenForm)
form := web.GetForm[*forms.IntrospectTokenForm](ctx)
token, err := oauth2_provider.ParseToken(form.Token, oauth2_provider.DefaultSigningKey)
if err != nil {
// RFC 7662 returns inactive token metadata for invalid/unknown tokens.
@@ -221,7 +221,7 @@ func oauthDoerAuthorizePreCheck(ctx *context.Context, formState string) bool {
// AuthorizeOAuth manages authorize requests
func AuthorizeOAuth(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.AuthorizationForm)
form := web.GetForm[*forms.AuthorizationForm](ctx)
if !oauthDoerAuthorizePreCheck(ctx, form.State) {
return
}
@@ -399,7 +399,7 @@ func AuthorizeOAuth(ctx *context.Context) {
// GrantApplicationOAuth manages the post request submitted when a user grants access to an application
func GrantApplicationOAuth(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.GrantApplicationForm)
form := web.GetForm[*forms.GrantApplicationForm](ctx)
if !oauthDoerAuthorizePreCheck(ctx, form.State) {
return
}
@@ -498,7 +498,7 @@ func OIDCKeys(ctx *context.Context) {
// AccessTokenOAuth manages all access token requests by the client
func AccessTokenOAuth(ctx *context.Context) {
form := *web.GetForm(ctx).(*forms.AccessTokenForm)
form := *web.GetForm[*forms.AccessTokenForm](ctx)
// if there is no ClientID or ClientSecret in the request body, fill these fields by the Authorization header and ensure the provided field matches the Authorization header
if form.ClientID == "" || form.ClientSecret == "" {
if authHeader := ctx.Req.Header.Get("Authorization"); authHeader != "" {
+3 -3
View File
@@ -101,7 +101,7 @@ func allowedOpenIDURI(uri string) (err error) {
// SignInOpenIDPost response for openid sign in request
func SignInOpenIDPost(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.SignInOpenIDForm)
form := web.GetForm[*forms.SignInOpenIDForm](ctx)
ctx.Data["Title"] = ctx.Tr("sign_in")
ctx.Data["PageIsSignIn"] = true
ctx.Data["PageIsLoginOpenID"] = true
@@ -293,7 +293,7 @@ func ConnectOpenID(ctx *context.Context) {
// ConnectOpenIDPost handles submission of a form to connect an OpenID URI to an existing account
func ConnectOpenIDPost(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.ConnectOpenIDForm)
form := web.GetForm[*forms.ConnectOpenIDForm](ctx)
oid := prepareConnectOpenIDPageData(ctx)
if oid == "" {
return
@@ -366,7 +366,7 @@ func RegisterOpenIDPost(ctx *context.Context) {
return
}
form := web.GetForm(ctx).(*forms.SignUpOpenIDForm)
form := web.GetForm[*forms.SignUpOpenIDForm](ctx)
if setting.Service.AllowOnlyInternalRegistration {
ctx.HTTPError(http.StatusForbidden)
+1 -1
View File
@@ -265,7 +265,7 @@ func MustChangePassword(ctx *context.Context) {
// MustChangePasswordPost response for updating a user's password after their
// account was created by an admin
func MustChangePasswordPost(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.MustChangePasswordForm)
form := web.GetForm[*forms.MustChangePasswordForm](ctx)
ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/settings/change_password"
if ctx.HasError() {
+4 -3
View File
@@ -31,12 +31,13 @@ func WebAuthn(ctx *context.Context) {
}
// Ensure user is in a 2FA session.
if ctx.Session.Get("twofaUid") == nil {
idSess, ok := ctx.Session.Get("twofaUid").(int64)
if !ok {
ctx.ServerError("UserSignIn", errors.New("not in WebAuthn session"))
return
}
hasTwoFactor, err := auth.HasTwoFactorByUID(ctx, ctx.Session.Get("twofaUid").(int64))
hasTwoFactor, err := auth.HasTwoFactorByUID(ctx, idSess)
if err != nil {
ctx.ServerError("HasTwoFactorByUID", err)
return
@@ -265,7 +266,7 @@ func WebAuthnLoginAssertionPost(ctx *context.Context) {
return
}
remember := ctx.Session.Get("twofaRemember").(bool)
remember := ctx.Session.Get("twofaRemember").(bool) //nolint:forcetypeassert // must exist
handleSignInFull(ctx, user, remember)
_ = ctx.Session.Delete("twofaUid")
ctx.JSONRedirect(consumeAuthRedirectLink(ctx))