1e5ef02bdf
Messages between matched users are now encrypted client-side with each user's own key pair before they ever reach the server; the backend only ever stores/relays opaque ciphertext + nonce and cannot read message content, including for the last-message preview on the matches list. - User gains a PublicKey field, registered/rotated via PUT /profile/public-key - Message gains CipherText/Nonce; legacy plaintext Text is kept as-is for messages sent before this change - MatchView exposes the partner's public key and the last message's ciphertext/nonce so the client can decrypt previews itself - Removed the now-dead plaintext SanitizeMessageText utility — the server can no longer sanitize message content since it's opaque ciphertext Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
90 lines
4.6 KiB
Go
90 lines
4.6 KiB
Go
package dto
|
|
|
|
// DiscoverCandidate یک پروفایل پیشنهادی توی صفحهی دوستیابی
|
|
type DiscoverCandidate struct {
|
|
ID uint `json:"id"`
|
|
FirstName string `json:"first_name"`
|
|
Age int `json:"age"`
|
|
Bio string `json:"bio,omitempty"`
|
|
Photos []string `json:"photos"`
|
|
DistanceKM *float64 `json:"distance_km,omitempty"`
|
|
Interests []string `json:"interests,omitempty"`
|
|
}
|
|
|
|
// SwipeRequest بدنهی درخواست ثبت لایک/ردّ
|
|
type SwipeRequest struct {
|
|
Action string `json:"action" binding:"required,oneof=like pass superlike"`
|
|
}
|
|
|
|
// SwipeResponse نتیجهی یک سواپ؛ اگه Matched=true باشه یعنی مچ تازه (یا از قبل) ساخته شده
|
|
type SwipeResponse struct {
|
|
Matched bool `json:"matched"`
|
|
Match *MatchView `json:"match,omitempty"`
|
|
}
|
|
|
|
// MatchView خلاصهی یک مچ برای نمایش در لیست مچها/گفتگوها. برای پیشنمایش
|
|
// آخرین پیام، سرور رمزگشایی نمیکنه (نمیتونه) — CipherText/Nonce خودِ آخرین
|
|
// پیام رو برمیگردونه تا کلاینت خودش رمزگشایی کنه؛ LastMessage فقط برای
|
|
// پیامهای قدیمیِ قبل از E2EE پر میشه.
|
|
type MatchView struct {
|
|
ID uint `json:"id"`
|
|
UserID uint `json:"user_id"`
|
|
FirstName string `json:"first_name"`
|
|
Photos []string `json:"photos"`
|
|
CreatedAt string `json:"created_at"`
|
|
LastMessage *string `json:"last_message,omitempty"`
|
|
LastMessageCipherText *string `json:"last_message_cipher_text,omitempty"`
|
|
LastMessageNonce *string `json:"last_message_nonce,omitempty"`
|
|
LastAt *string `json:"last_at,omitempty"`
|
|
// PartnerPublicKey کلید عمومی X25519 طرف مقابل (base64) برای رمزنگاری
|
|
// سرتاسری؛ اگه طرف مقابل هنوز کلیدی ثبت نکرده باشه خالیه.
|
|
PartnerPublicKey *string `json:"partner_public_key,omitempty"`
|
|
}
|
|
|
|
// MessageView یک پیام در یک گفتگو. یا Text (پیام قدیمیِ قبل از E2EE) پر
|
|
// میشه، یا CipherText+Nonce (پیام رمزنگاریشده) — سرور خودش نمیدونه محتوای
|
|
// رمزنگاریشده چیه، فقط بین دو طرف مچ ردوبدلش میکنه.
|
|
type MessageView struct {
|
|
ID uint `json:"id"`
|
|
MatchID uint `json:"match_id"`
|
|
SenderID uint `json:"sender_id"`
|
|
Text string `json:"text,omitempty"`
|
|
CipherText *string `json:"cipher_text,omitempty"`
|
|
Nonce *string `json:"nonce,omitempty"`
|
|
CreatedAt string `json:"created_at"`
|
|
IsMine bool `json:"is_mine"`
|
|
}
|
|
|
|
// SendMessageRequest بدنهی درخواست ارسال پیام رمزنگاریشده. متن خام پیام
|
|
// هیچوقت به سرور نمیرسه؛ کلاینت قبل از ارسال با کلید عمومی طرف مقابل
|
|
// رمزنگاریش میکنه.
|
|
type SendMessageRequest struct {
|
|
CipherText string `json:"cipher_text" binding:"required,min=1,max=12000"`
|
|
Nonce string `json:"nonce" binding:"required,len=32"`
|
|
}
|
|
|
|
// CandidateAnswer پاسخ یک سوال پروفایل، برای نمایش عمومی
|
|
type CandidateAnswer struct {
|
|
Question string `json:"question"`
|
|
Answer string `json:"answer"`
|
|
}
|
|
|
|
// CandidateDetail پروفایل کامل یک کاربر دیگه (برای نمایش صفحهی جزئیات پروفایل)
|
|
type CandidateDetail struct {
|
|
ID uint `json:"id"`
|
|
FirstName string `json:"first_name"`
|
|
Age int `json:"age"`
|
|
Bio string `json:"bio,omitempty"`
|
|
Photos []string `json:"photos"`
|
|
DistanceKM *float64 `json:"distance_km,omitempty"`
|
|
HeightCM *int `json:"height_cm,omitempty"`
|
|
WeightKG *int `json:"weight_kg,omitempty"`
|
|
Education string `json:"education,omitempty"`
|
|
FieldOfStudy string `json:"field_of_study,omitempty"`
|
|
Occupations []string `json:"occupations,omitempty"`
|
|
Interests []string `json:"interests,omitempty"`
|
|
ImportantInRelationship []string `json:"important_in_relationship,omitempty"`
|
|
LookingFor string `json:"looking_for,omitempty"`
|
|
Answers []CandidateAnswer `json:"profile_answers,omitempty"`
|
|
}
|