1dc96e86fc
- User blocking (with reason) now closes the auth gap immediately — a
blocked user's still-valid access token stops working on the next
request, not just on their next OTP/refresh.
- Admin-created reports (moderation notes) per user, viewable in a history
list independent of block status.
- GET /admin/users: full paginated, searchable user list with report counts.
- GET /admin/matches: all matches across the app ("friends" who mutually
liked each other), for admin visibility.
- GET/DELETE /admin/photos: paginated feed of every uploaded photo with
uploader info, so admins can review and remove content without going
user-by-user.
- Per-user activity: monitoring requests can now be filtered by user_id, so
a user's detail page can show their recent API activity.
- Batched the profile-selections query in fullProfilePayload (was 6 queries
per view, now 1) for consistency with the earlier N+1 fixes.
117 lines
4.1 KiB
Go
117 lines
4.1 KiB
Go
package models
|
|
|
|
import "time"
|
|
|
|
// Gender جنسیت کاربر
|
|
type Gender string
|
|
|
|
const (
|
|
GenderMale Gender = "male"
|
|
GenderFemale Gender = "female"
|
|
)
|
|
|
|
// UserState وضعیت کلی کاربر
|
|
type UserState string
|
|
|
|
const (
|
|
UserStateInactive UserState = "inactive"
|
|
UserStateActive UserState = "active"
|
|
UserStateBlocked UserState = "blocked"
|
|
)
|
|
|
|
// OnboardingStep مرحلهی فعلی کاربر در فرآیند تکمیل پروفایل.
|
|
// هر مقدار یعنی «این مرحله هنوز باید تکمیل بشه». وقتی به StepCompleted
|
|
// میرسه یعنی کاربر تمام مراحل رو طی کرده.
|
|
type OnboardingStep int
|
|
|
|
const (
|
|
StepBasicInfo OnboardingStep = iota + 1
|
|
StepPhotos
|
|
StepBodyInfo
|
|
StepProfileQuestions
|
|
StepEducation
|
|
StepOccupations
|
|
StepRelationshipImportance
|
|
StepInterests
|
|
StepLookingFor
|
|
StepCompleted
|
|
)
|
|
|
|
// ApprovalStatus وضعیت بررسی پروفایل توسط ادمین (بعد از تکمیل آنبوردینگ)
|
|
type ApprovalStatus string
|
|
|
|
const (
|
|
ApprovalPending ApprovalStatus = "pending"
|
|
ApprovalApproved ApprovalStatus = "approved"
|
|
ApprovalRejected ApprovalStatus = "rejected"
|
|
)
|
|
|
|
// StepInfo برای پاسخهای API که وضعیت هر مرحله رو توضیح میده
|
|
type StepInfo struct {
|
|
Step OnboardingStep `json:"step"`
|
|
Key string `json:"key"`
|
|
Done bool `json:"done"`
|
|
}
|
|
|
|
// ordered لیست ترتیب مراحل آنبوردینگ (برای ساخت وضعیت کامل)
|
|
var OnboardingStepOrder = []struct {
|
|
Step OnboardingStep
|
|
Key string
|
|
}{
|
|
{StepBasicInfo, "basic_info"},
|
|
{StepPhotos, "photos"},
|
|
{StepBodyInfo, "body_info"},
|
|
{StepProfileQuestions, "profile_questions"},
|
|
{StepEducation, "education"},
|
|
{StepOccupations, "occupations"},
|
|
{StepRelationshipImportance, "relationship_importance"},
|
|
{StepInterests, "interests"},
|
|
{StepLookingFor, "looking_for"},
|
|
}
|
|
|
|
// User کاربر اصلی سیستم. احراز هویت فقط با شماره موبایل + OTP انجام میشود.
|
|
type User struct {
|
|
ID uint `gorm:"primaryKey" json:"id"`
|
|
Phone string `gorm:"size:11;uniqueIndex;not null" json:"phone"`
|
|
State UserState `gorm:"size:10;default:inactive;not null" json:"state"`
|
|
IsAdmin bool `gorm:"default:false;not null" json:"is_admin"`
|
|
IsActive bool `gorm:"default:true;not null" json:"is_active"`
|
|
|
|
// -------- بلاک شدن توسط ادمین --------
|
|
BlockedReason *string `json:"blocked_reason,omitempty"`
|
|
BlockedAt *time.Time `json:"blocked_at,omitempty"`
|
|
|
|
// فیلدهای OTP - هش میشوند و هرگز در پاسخ API برنمیگردند
|
|
OTPCode *string `gorm:"size:128" json:"-"`
|
|
OTPExpiry *time.Time `json:"-"`
|
|
|
|
// -------- اطلاعات پروفایل (پر میشوند طی فرآیند آنبوردینگ) --------
|
|
Gender *Gender `gorm:"size:10" json:"gender,omitempty"`
|
|
FirstName string `gorm:"size:100" json:"first_name,omitempty"`
|
|
BirthDate *time.Time `json:"birth_date,omitempty"`
|
|
HeightCM *int `json:"height_cm,omitempty"`
|
|
WeightKG *int `json:"weight_kg,omitempty"`
|
|
|
|
// -------- موقعیت مکانی (برای محاسبهی فاصلهی تقریبی در دوستیابی) --------
|
|
Latitude *float64 `json:"-"`
|
|
Longitude *float64 `json:"-"`
|
|
|
|
// -------- وضعیت آنبوردینگ --------
|
|
CurrentStep OnboardingStep `gorm:"default:1;not null" json:"current_step"`
|
|
IsOnboarded bool `gorm:"default:false;not null" json:"is_onboarded"`
|
|
|
|
// -------- بررسی ادمین (بعد از تکمیل آنبوردینگ) --------
|
|
// تا وقتی approved نشه، کاربر اجازهی ورود به صفحهی دوستیابی رو نداره.
|
|
ApprovalStatus ApprovalStatus `gorm:"size:10;default:pending;not null" json:"approval_status"`
|
|
RejectionReason *string `json:"rejection_reason,omitempty"`
|
|
ReviewedAt *time.Time `json:"reviewed_at,omitempty"`
|
|
|
|
LastLogin *time.Time `json:"last_login,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|
|
func (User) TableName() string {
|
|
return "users"
|
|
}
|