Skip to content

Commit 7bd7aee

Browse files
committed
follow #30454
1 parent e865de1 commit 7bd7aee

File tree

6 files changed

+44
-44
lines changed

6 files changed

+44
-44
lines changed

models/user/user.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -501,19 +501,19 @@ func GetUserSalt() (string, error) {
501501
// Note: The set of characters here can safely expand without a breaking change,
502502
// but characters removed from this set can cause user account linking to break
503503
var (
504-
customCharsReplacement = strings.NewReplacer("Æ", "AE")
505-
removeCharsRE = regexp.MustCompile(`['´\x60]`)
506-
removeDiacriticsTransform = transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC)
507-
replaceCharsHyphenRE = regexp.MustCompile(`[\s~+]`)
504+
customCharsReplacement = strings.NewReplacer("Æ", "AE")
505+
removeCharsRE = regexp.MustCompile(`['´\x60]`)
506+
transformDiacritics = transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC)
507+
replaceCharsHyphenRE = regexp.MustCompile(`[\s~+]`)
508508
)
509509

510-
// normalizeUserName returns a string with single-quotes and diacritics
511-
// removed, and any other non-supported username characters replaced with
512-
// a `-` character
510+
// NormalizeUserName only takes the name part if it is an email address, transforms it diacritics to ASCII characters.
511+
// It returns a string with all quotes removed, and any other non-supported username characters are replaced with a `-` character
513512
func NormalizeUserName(s string) (string, error) {
514-
strDiacriticsRemoved, n, err := transform.String(removeDiacriticsTransform, customCharsReplacement.Replace(s))
513+
s, _, _ = strings.Cut(s, "@")
514+
strDiacriticsRemoved, n, err := transform.String(transformDiacritics, customCharsReplacement.Replace(s))
515515
if err != nil {
516-
return "", fmt.Errorf("Failed to normalize character `%v` in provided username `%v`", s[n], s)
516+
return "", fmt.Errorf("failed to normalize the string of provided username %q at position %d", s, n)
517517
}
518518
return replaceCharsHyphenRE.ReplaceAllLiteralString(removeCharsRE.ReplaceAllLiteralString(strDiacriticsRemoved, ""), "-"), nil
519519
}

models/user/user_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -506,15 +506,16 @@ func Test_NormalizeUserFromEmail(t *testing.T) {
506506
Expected string
507507
IsNormalizedValid bool
508508
}{
509+
{"[email protected]", "name", true},
509510
{"test", "test", true},
510511
{"Sinéad.O'Connor", "Sinead.OConnor", true},
511512
{"Æsir", "AEsir", true},
512-
// \u00e9\u0065\u0301
513-
{"éé", "ee", true},
513+
{"éé", "ee", true}, // \u00e9\u0065\u0301
514514
{"Awareness Hub", "Awareness-Hub", true},
515515
{"double__underscore", "double__underscore", false}, // We should consider squashing double non-alpha characters
516516
{".bad.", ".bad.", false},
517517
{"new😀user", "new😀user", false}, // No plans to support
518+
{`"quoted"`, `"quoted"`, false}, // No plans to support
518519
}
519520
for _, testCase := range testCases {
520521
normalizedName, err := user_model.NormalizeUserName(testCase.Input)

modules/setting/oauth2.go

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,10 @@ import (
1616
type OAuth2UsernameType string
1717

1818
const (
19-
// OAuth2UsernameUserid oauth2 userid field will be used as gitea name
20-
OAuth2UsernameUserid OAuth2UsernameType = "userid"
21-
// OAuth2UsernameNickname oauth2 nickname field will be used as gitea name
22-
OAuth2UsernameNickname OAuth2UsernameType = "nickname"
23-
// OAuth2UsernameEmail username of oauth2 email field will be used as gitea name
24-
OAuth2UsernameEmail OAuth2UsernameType = "email"
25-
// OAuth2UsernameEmail username of oauth2 preferred_username field will be used as gitea name
26-
OAuth2UsernamePreferredUsername OAuth2UsernameType = "preferred_username"
19+
OAuth2UsernameUserid OAuth2UsernameType = "userid" // use user id (sub) field as gitea's username
20+
OAuth2UsernameNickname OAuth2UsernameType = "nickname" // use nickname field
21+
OAuth2UsernameEmail OAuth2UsernameType = "email" // use email field
22+
OAuth2UsernamePreferredUsername OAuth2UsernameType = "preferred_username" // use preferred_username field
2723
)
2824

2925
func (username OAuth2UsernameType) isValid() bool {
@@ -71,8 +67,8 @@ func loadOAuth2ClientFrom(rootCfg ConfigProvider) {
7167
OAuth2Client.EnableAutoRegistration = sec.Key("ENABLE_AUTO_REGISTRATION").MustBool()
7268
OAuth2Client.Username = OAuth2UsernameType(sec.Key("USERNAME").MustString(string(OAuth2UsernameNickname)))
7369
if !OAuth2Client.Username.isValid() {
74-
log.Warn("Username setting is not valid: '%s', will fallback to '%s'", OAuth2Client.Username, OAuth2UsernameNickname)
7570
OAuth2Client.Username = OAuth2UsernameNickname
71+
log.Warn("[oauth2_client].USERNAME setting is invalid, falls back to %q", OAuth2Client.Username)
7672
}
7773
OAuth2Client.UpdateAvatar = sec.Key("UPDATE_AVATAR").MustBool()
7874
OAuth2Client.AccountLinking = OAuth2AccountLinkingType(sec.Key("ACCOUNT_LINKING").MustString(string(OAuth2AccountLinkingLogin)))

routers/web/auth/auth.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -382,17 +382,17 @@ func handleSignInFull(ctx *context.Context, u *user_model.User, remember, obeyRe
382382
return setting.AppSubURL + "/"
383383
}
384384

385-
func getUserName(gothUser *goth.User) (string, error) {
385+
// extractUserNameFromOAuth2 tries to extract a normalized username from the given OAuth2 user.
386+
// It returns ("", nil) if the required field doesn't exist.
387+
func extractUserNameFromOAuth2(gothUser *goth.User) (string, error) {
386388
switch setting.OAuth2Client.Username {
387389
case setting.OAuth2UsernameEmail:
388-
return user_model.NormalizeUserName(strings.Split(gothUser.Email, "@")[0])
390+
return user_model.NormalizeUserName(gothUser.Email)
389391
case setting.OAuth2UsernamePreferredUsername:
390-
preferredUsername, exists := gothUser.RawData["preferred_username"]
391-
if exists {
392-
return user_model.NormalizeUserName(preferredUsername.(string))
393-
} else {
394-
return "", fmt.Errorf("preferred_username is missing in received user data but configured as username source for user_id %q. Check if OPENID_CONNECT_SCOPES contains profile", gothUser.UserID)
392+
if preferredUsername, ok := gothUser.RawData["preferred_username"].(string); ok {
393+
return user_model.NormalizeUserName(preferredUsername)
395394
}
395+
return "", nil
396396
case setting.OAuth2UsernameNickname:
397397
return user_model.NormalizeUserName(gothUser.NickName)
398398
default: // OAuth2UsernameUserid

routers/web/auth/linkaccount.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,23 +48,22 @@ func LinkAccount(ctx *context.Context) {
4848
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/link_account_signin"
4949
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/link_account_signup"
5050

51-
gothUser := ctx.Session.Get("linkAccountGothUser")
52-
if gothUser == nil {
51+
gothUser, ok := ctx.Session.Get("linkAccountGothUser").(goth.User)
52+
if !ok {
5353
ctx.ServerError("UserSignIn", errors.New("not in LinkAccount session"))
5454
return
5555
}
5656

57-
gu, _ := gothUser.(goth.User)
58-
uname, err := getUserName(&gu)
57+
uname, err := extractUserNameFromOAuth2(&gothUser)
5958
if err != nil {
6059
ctx.ServerError("UserSignIn", err)
6160
return
6261
}
63-
email := gu.Email
62+
email := gothUser.Email
6463
ctx.Data["user_name"] = uname
6564
ctx.Data["email"] = email
6665

67-
if len(email) != 0 {
66+
if email != "" {
6867
u, err := user_model.GetUserByEmail(ctx, email)
6968
if err != nil && !user_model.IsErrUserNotExist(err) {
7069
ctx.ServerError("UserSignIn", err)
@@ -73,7 +72,7 @@ func LinkAccount(ctx *context.Context) {
7372
if u != nil {
7473
ctx.Data["user_exists"] = true
7574
}
76-
} else if len(uname) != 0 {
75+
} else if uname != "" {
7776
u, err := user_model.GetUserByName(ctx, uname)
7877
if err != nil && !user_model.IsErrUserNotExist(err) {
7978
ctx.ServerError("UserSignIn", err)

routers/web/auth/oauth.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -952,23 +952,27 @@ func SignInOAuthCallback(ctx *context.Context) {
952952
if gothUser.Email == "" {
953953
missingFields = append(missingFields, "email")
954954
}
955-
if setting.OAuth2Client.Username == setting.OAuth2UsernameNickname && gothUser.NickName == "" {
956-
missingFields = append(missingFields, "nickname")
955+
uname, err := extractUserNameFromOAuth2(&gothUser)
956+
if err != nil {
957+
ctx.ServerError("UserSignIn", err)
958+
return
959+
}
960+
if uname == "" {
961+
if setting.OAuth2Client.Username == setting.OAuth2UsernameNickname {
962+
missingFields = append(missingFields, "nickname")
963+
} else if setting.OAuth2Client.Username == setting.OAuth2UsernamePreferredUsername {
964+
missingFields = append(missingFields, "preferred_username")
965+
} // else: "UserID" and "Email" have been handled above separately
957966
}
958967
if len(missingFields) > 0 {
959-
log.Error("OAuth2 Provider %s returned empty or missing fields: %s", authSource.Name, missingFields)
968+
err := fmt.Errorf("OAuth2 Provider %q returned empty or missing fields: %s", authSource.Name, strings.Join(missingFields, ","))
960969
if authSource.IsOAuth2() && authSource.Cfg.(*oauth2.Source).Provider == "openidConnect" {
961-
log.Error("You may need to change the 'OPENID_CONNECT_SCOPES' setting to request all required fields")
970+
err = fmt.Errorf("you may need to change the '[oauth2_client].OPENID_CONNECT_SCOPES' setting to request all required fields: %w", err)
962971
}
963-
err = fmt.Errorf("OAuth2 Provider %s returned empty or missing fields: %s", authSource.Name, missingFields)
972+
ctx.Flash.Error(err.Error(), true)
964973
ctx.ServerError("CreateUser", err)
965974
return
966975
}
967-
uname, err := getUserName(&gothUser)
968-
if err != nil {
969-
ctx.ServerError("UserSignIn", err)
970-
return
971-
}
972976
u = &user_model.User{
973977
Name: uname,
974978
FullName: gothUser.Name,

0 commit comments

Comments
 (0)