feat: reject emails that are not shaped like name@example.com when updating a profile
This commit is contained in:
1 parent
773ec302a7
commit
98a1605a83
4 files changed
+37
-1
No files matched your search
@@ -278,6 +278,7 @@ var knownErrors = []struct {
|
||||
{admin.ErrUnrecognizedCookies, protocol.ErrorCodeInvalidArgument},
|
||||
{identity.ErrInvalidTicket, protocol.ErrorCodeUnauthorized},
|
||||
{identity.ErrBotSession, protocol.ErrorCodeUnauthorized},
|
||||
{identity.ErrInvalidEmail, protocol.ErrorCodeInvalidArgument},
|
||||
{realtime.ErrRequesterNotAllowed, protocol.ErrorCodeInvalidArgument},
|
||||
{site.ErrInvalidBrandName, protocol.ErrorCodeInvalidArgument},
|
||||
{realtime.ErrUnavailable, protocol.ErrorCodeUnavailable},
|
||||
|
||||
@@ -3,6 +3,8 @@ package identity
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/dihemoe/alisten/internal/app/port"
|
||||
"github.com/dihemoe/alisten/internal/app/realtime"
|
||||
@@ -15,8 +17,11 @@ var (
|
||||
ErrInvalidTicket = errors.New("票据无效")
|
||||
ErrWrongPassword = errors.New("房间密码错误")
|
||||
ErrBotSession = errors.New("API Key 只能用于 HTTP 接口")
|
||||
ErrInvalidEmail = errors.New("email:格式不正确,应形如 name@example.com")
|
||||
)
|
||||
|
||||
var emailPattern = regexp.MustCompile(`^[^@\s]+@[^@\s]+\.[^@\s]+$`)
|
||||
|
||||
type Service struct {
|
||||
members port.Members
|
||||
rooms port.RoomDirectory
|
||||
@@ -62,7 +67,11 @@ type Profile struct {
|
||||
func (s *Service) UpdateProfile(ctx context.Context, memberID string, p Profile) (member.Member, error) {
|
||||
var avatar *string
|
||||
if p.Email != nil {
|
||||
hash := avatarHash(*p.Email)
|
||||
email := strings.TrimSpace(*p.Email)
|
||||
if email != "" && !emailPattern.MatchString(email) {
|
||||
return member.Member{}, ErrInvalidEmail
|
||||
}
|
||||
hash := avatarHash(email)
|
||||
avatar = &hash
|
||||
}
|
||||
m, err := s.members.UpdateMember(ctx, memberID, p.Name, avatar)
|
||||
|
||||
@@ -95,6 +95,23 @@ func TestUpdateProfile(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateProfileRejectsMalformedEmail(t *testing.T) {
|
||||
s, _ := newService(t)
|
||||
id := createMember(t, s).Member.ID
|
||||
if _, err := s.UpdateProfile(t.Context(), id, Profile{Email: ptr("alice@example.com")}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, email := range []string{"a@b@c.com", "alice@example", "a lice@example.com", "alice@exa mple.com", "@", "@example.com", "alice@.", "alice"} {
|
||||
if _, err := s.UpdateProfile(t.Context(), id, Profile{Email: ptr(email)}); !errors.Is(err, ErrInvalidEmail) {
|
||||
t.Errorf("邮箱 %q 的错误 = %v,期望 ErrInvalidEmail", email, err)
|
||||
}
|
||||
}
|
||||
if m, _ := s.UpdateProfile(t.Context(), id, Profile{}); m.AvatarHash != "c160f8cc69a4f0bf2b0362752353d060" {
|
||||
t.Errorf("被拒绝的邮箱不应改动头像:%#v", m)
|
||||
}
|
||||
}
|
||||
|
||||
type noMemberBroadcast struct {
|
||||
port.Bus
|
||||
}
|
||||
|
||||
@@ -36,6 +36,15 @@ Authorization: Bearer $alice
|
||||
PATCH /api/me
|
||||
Authorization: Bearer $alice
|
||||
|
||||
{"email": "alice@example"}
|
||||
-- response --
|
||||
400
|
||||
{"error": {"code": "INVALID_ARGUMENT", "message": "email:格式不正确,应形如 name@example.com"}}
|
||||
|
||||
-- request --
|
||||
PATCH /api/me
|
||||
Authorization: Bearer $alice
|
||||
|
||||
{}
|
||||
-- response --
|
||||
200
|
||||
|
||||
Reference in new issue
Block a user