feat(server/auth): switch user identity to phone with email optional

Phone becomes the required, unique login identifier; email and name turn
optional. Login now accepts either via a single identifier field, refresh
re-checks tenant membership, and the dev seed provides phone numbers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-29 00:01:36 +08:00
parent a6b17bae62
commit ee21f512a9
11 changed files with 225 additions and 40 deletions
@@ -21,6 +21,27 @@ type AiPlatform struct {
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type AiPointUsageLog struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
OperatorID pgtype.Int8 `json:"operator_id"`
QuotaReservationID pgtype.Int8 `json:"quota_reservation_id"`
UsageType string `json:"usage_type"`
ResourceType pgtype.Text `json:"resource_type"`
ResourceID pgtype.Int8 `json:"resource_id"`
ResourceUid pgtype.Text `json:"resource_uid"`
RequestChars int32 `json:"request_chars"`
BaseChars int32 `json:"base_chars"`
Points int32 `json:"points"`
Status string `json:"status"`
Model pgtype.Text `json:"model"`
MetadataJson []byte `json:"metadata_json"`
ErrorMessage pgtype.Text `json:"error_message"`
CompletedAt pgtype.Timestamptz `json:"completed_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type Article struct {
ID int64 `json:"id"`
TenantID int64 `json:"tenant_id"`
@@ -149,6 +170,15 @@ type DesktopClient struct {
RevokedAt pgtype.Timestamptz `json:"revoked_at"`
}
type DesktopClientPrimaryLease struct {
TenantID int64 `json:"tenant_id"`
WorkspaceID int64 `json:"workspace_id"`
PrimaryClientID pgtype.UUID `json:"primary_client_id"`
LeaseExpiresAt pgtype.Timestamptz `json:"lease_expires_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type DesktopPublishJob struct {
ID int64 `json:"id"`
DesktopID pgtype.UUID `json:"desktop_id"`
@@ -708,10 +738,10 @@ type TenantQuotaLedger struct {
type User struct {
ID int64 `json:"id"`
Email string `json:"email"`
Phone pgtype.Text `json:"phone"`
Email pgtype.Text `json:"email"`
Phone string `json:"phone"`
PasswordHash string `json:"password_hash"`
Name string `json:"name"`
Name pgtype.Text `json:"name"`
AvatarUrl pgtype.Text `json:"avatar_url"`
Status string `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`