feat: reject emails that are not shaped like name@example.com when updating a profile

This commit is contained in:
DiheChen committed 2026-11-09 21:17:42 +08:00
1 parent 729e5861f5
commit 90a3b26c77
4 files changed
+37 -1

No files matched your search

+1
View File
@@ -282,6 +282,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},
+10 -1
View File
@@ -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)
+17
View File
@@ -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
}
+9
View File
@@ -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