MIF_E31222379_BE/internal/authentication/authentication_dto.go

364 lines
12 KiB
Go

package authentication
import (
"rijig/utils"
"strings"
"time"
)
type LoginorRegistRequest struct {
Phone string `json:"phone" validate:"required,min=10,max=15"`
RoleName string `json:"role_name"`
}
type VerifyOtpRequest struct {
DeviceID string `json:"device_id" validate:"required"`
RoleName string `json:"role_name" validate:"required,oneof=masyarakat pengepul pengelola"`
Phone string `json:"phone" validate:"required"`
Otp string `json:"otp" validate:"required,len=6"`
}
type CreatePINRequest struct {
PIN string `json:"pin" validate:"required,len=6,numeric"`
ConfirmPIN string `json:"confirm_pin" validate:"required,len=6,numeric"`
}
type VerifyPINRequest struct {
PIN string `json:"pin" validate:"required,len=6,numeric"`
DeviceID string `json:"device_id" validate:"required"`
}
type RefreshTokenRequest struct {
RefreshToken string `json:"refresh_token" validate:"required"`
DeviceID string `json:"device_id" validate:"required"`
UserID string `json:"user_id" validate:"required"`
}
type LogoutRequest struct {
DeviceID string `json:"device_id" validate:"required"`
}
type OTPResponse struct {
Message string `json:"message"`
ExpiresIn int `json:"expires_in"`
Phone string `json:"phone"`
}
type AuthResponse struct {
Message string `json:"message"`
AccessToken string `json:"access_token,omitempty"`
RefreshToken string `json:"refresh_token,omitempty"`
TokenType string `json:"token_type,omitempty"`
ExpiresIn int64 `json:"expires_in,omitempty"`
User *UserResponse `json:"user,omitempty"`
RegistrationStatus string `json:"registration_status,omitempty"`
NextStep string `json:"next_step,omitempty"`
SessionID string `json:"session_id,omitempty"`
}
type UserResponse struct {
ID string `json:"id"`
Name string `json:"name"`
Phone string `json:"phone"`
Email string `json:"email,omitempty"`
Role string `json:"role"`
RegistrationStatus string `json:"registration_status"`
RegistrationProgress int8 `json:"registration_progress"`
PhoneVerified bool `json:"phone_verified"`
Avatar *string `json:"avatar,omitempty"`
Gender string `json:"gender,omitempty"`
DateOfBirth string `json:"date_of_birth,omitempty"`
PlaceOfBirth string `json:"place_of_birth,omitempty"`
}
type RegistrationStatusResponse struct {
CurrentStep int `json:"current_step"`
TotalSteps int `json:"total_steps"`
CompletedSteps []RegistrationStep `json:"completed_steps"`
NextStep *RegistrationStep `json:"next_step,omitempty"`
RegistrationStatus string `json:"registration_status"`
IsComplete bool `json:"is_complete"`
RequiresApproval bool `json:"requires_approval"`
ApprovalMessage string `json:"approval_message,omitempty"`
}
type RegistrationStep struct {
StepNumber int `json:"step_number"`
Title string `json:"title"`
Description string `json:"description"`
IsRequired bool `json:"is_required"`
IsCompleted bool `json:"is_completed"`
IsActive bool `json:"is_active"`
}
type OTPData struct {
Phone string `json:"phone"`
OTP string `json:"otp"`
UserID string `json:"user_id,omitempty"`
Role string `json:"role"`
RoleID string `json:"role_id,omitempty"`
Type string `json:"type"`
ExpiresAt time.Time `json:"expires_at"`
Attempts int `json:"attempts"`
}
type SessionData struct {
UserID string `json:"user_id"`
DeviceID string `json:"device_id"`
Role string `json:"role"`
CreatedAt time.Time `json:"created_at"`
LastSeen time.Time `json:"last_seen"`
IsActive bool `json:"is_active"`
}
type ErrorResponse struct {
Error string `json:"error"`
Message string `json:"message"`
Code string `json:"code,omitempty"`
Details interface{} `json:"details,omitempty"`
}
type ValidationErrorResponse struct {
Error string `json:"error"`
Message string `json:"message"`
Fields map[string]string `json:"fields"`
}
type ApproveRegistrationRequest struct {
UserID string `json:"user_id" validate:"required"`
Message string `json:"message,omitempty"`
}
type RejectRegistrationRequest struct {
UserID string `json:"user_id" validate:"required"`
Reason string `json:"reason" validate:"required"`
}
type PendingRegistrationResponse struct {
ID string `json:"id"`
Name string `json:"name"`
Phone string `json:"phone"`
Role string `json:"role"`
RegistrationData RegistrationData `json:"registration_data"`
SubmittedAt time.Time `json:"submitted_at"`
DocumentsUploaded []DocumentInfo `json:"documents_uploaded"`
}
type RegistrationData struct {
KTPNumber string `json:"ktp_number,omitempty"`
KTPImage string `json:"ktp_image,omitempty"`
FullName string `json:"full_name,omitempty"`
Address string `json:"address,omitempty"`
BusinessName string `json:"business_name,omitempty"`
BusinessType string `json:"business_type,omitempty"`
BusinessAddress string `json:"business_address,omitempty"`
BusinessPhone string `json:"business_phone,omitempty"`
TaxNumber string `json:"tax_number,omitempty"`
BusinessLicense string `json:"business_license,omitempty"`
}
type DocumentInfo struct {
Type string `json:"type"`
FileName string `json:"file_name"`
UploadedAt time.Time `json:"uploaded_at"`
Status string `json:"status"`
FileSize int64 `json:"file_size"`
ContentType string `json:"content_type"`
}
type AuthStatsResponse struct {
TotalUsers int64 `json:"total_users"`
ActiveUsers int64 `json:"active_users"`
PendingRegistrations int64 `json:"pending_registrations"`
UsersByRole map[string]int64 `json:"users_by_role"`
RegistrationStats RegistrationStatsData `json:"registration_stats"`
LoginStats LoginStatsData `json:"login_stats"`
}
type RegistrationStatsData struct {
TotalRegistrations int64 `json:"total_registrations"`
CompletedToday int64 `json:"completed_today"`
CompletedThisWeek int64 `json:"completed_this_week"`
CompletedThisMonth int64 `json:"completed_this_month"`
PendingApproval int64 `json:"pending_approval"`
RejectedRegistrations int64 `json:"rejected_registrations"`
}
type LoginStatsData struct {
TotalLogins int64 `json:"total_logins"`
LoginsToday int64 `json:"logins_today"`
LoginsThisWeek int64 `json:"logins_this_week"`
LoginsThisMonth int64 `json:"logins_this_month"`
UniqueUsersToday int64 `json:"unique_users_today"`
UniqueUsersWeek int64 `json:"unique_users_week"`
UniqueUsersMonth int64 `json:"unique_users_month"`
}
type PaginationRequest struct {
Page int `json:"page" query:"page" validate:"min=1"`
Limit int `json:"limit" query:"limit" validate:"min=1,max=100"`
Sort string `json:"sort" query:"sort"`
Order string `json:"order" query:"order" validate:"oneof=asc desc"`
Search string `json:"search" query:"search"`
Filter string `json:"filter" query:"filter"`
}
type PaginationResponse struct {
Page int `json:"page"`
Limit int `json:"limit"`
Total int64 `json:"total"`
TotalPages int `json:"total_pages"`
HasNext bool `json:"has_next"`
HasPrev bool `json:"has_prev"`
}
type PaginatedResponse struct {
Data interface{} `json:"data"`
Pagination PaginationResponse `json:"pagination"`
}
type SMSWebhookRequest struct {
MessageID string `json:"message_id"`
Phone string `json:"phone"`
Status string `json:"status"`
Timestamp string `json:"timestamp"`
}
type RateLimitInfo struct {
Limit int `json:"limit"`
Remaining int `json:"remaining"`
ResetTime time.Time `json:"reset_time"`
RetryAfter time.Duration `json:"retry_after,omitempty"`
}
type StepResponse struct {
UserID string `json:"user_id"`
Role string `json:"role"`
RegistrationStatus string `json:"registration_status"`
RegistrationProgress int `json:"registration_progress"`
NextStep string `json:"next_step"`
}
type RegisterAdminRequest struct {
Name string `json:"name"`
Gender string `json:"gender"`
DateOfBirth string `json:"dateofbirth"`
PlaceOfBirth string `json:"placeofbirth"`
Phone string `json:"phone"`
Email string `json:"email"`
Password string `json:"password"`
PasswordConfirm string `json:"password_confirm"`
}
type LoginAdminRequest struct {
Email string `json:"email"`
Password string `json:"password"`
DeviceID string `json:"device_id"`
}
func (r *LoginorRegistRequest) ValidateLoginorRegistRequest() (map[string][]string, bool) {
errors := make(map[string][]string)
if !utils.IsValidPhoneNumber(r.Phone) {
errors["phone"] = append(errors["phone"], "nomor harus dimulai 62.. dan 8-14 digit")
}
if len(errors) > 0 {
return errors, false
}
return nil, true
}
func (r *VerifyOtpRequest) ValidateVerifyOtpRequest() (map[string][]string, bool) {
errors := make(map[string][]string)
if len(strings.TrimSpace(r.DeviceID)) < 10 {
errors["device_id"] = append(errors["device_id"], "Device ID must be at least 10 characters")
}
validRoles := map[string]bool{"masyarakat": true, "pengepul": true, "pengelola": true}
if _, ok := validRoles[r.RoleName]; !ok {
errors["role"] = append(errors["role"], "Role tidak valid, hanya masyarakat, pengepul, atau pengelola")
}
if !utils.IsValidPhoneNumber(r.Phone) {
errors["phone"] = append(errors["phone"], "nomor harus dimulai 62.. dan 8-14 digit")
}
if len(r.Otp) != 4 || !utils.IsNumeric(r.Otp) {
errors["otp"] = append(errors["otp"], "OTP must be 4-digit number")
}
if len(errors) > 0 {
return errors, false
}
return nil, true
}
func (r *LoginAdminRequest) ValidateLoginAdminRequest() (map[string][]string, bool) {
errors := make(map[string][]string)
if !utils.IsValidEmail(r.Email) {
errors["email"] = append(errors["email"], "Invalid email format")
}
if strings.TrimSpace(r.Password) == "" {
errors["password"] = append(errors["password"], "Password is required")
}
if len(strings.TrimSpace(r.DeviceID)) < 10 {
errors["device_id"] = append(errors["device_id"], "Device ID must be at least 10 characters")
}
if len(errors) > 0 {
return errors, false
}
return nil, true
}
func (r *RegisterAdminRequest) ValidateRegisterAdminRequest() (map[string][]string, bool) {
errors := make(map[string][]string)
if strings.TrimSpace(r.Name) == "" {
errors["name"] = append(errors["name"], "Name is required")
}
genderLower := strings.ToLower(strings.TrimSpace(r.Gender))
if genderLower != "laki-laki" && genderLower != "perempuan" {
errors["gender"] = append(errors["gender"], "Gender must be either 'laki-laki' or 'perempuan'")
}
if strings.TrimSpace(r.DateOfBirth) == "" {
errors["dateofbirth"] = append(errors["dateofbirth"], "Date of birth is required")
} else {
_, err := time.Parse("02-01-2006", r.DateOfBirth)
if err != nil {
errors["dateofbirth"] = append(errors["dateofbirth"], "Date of birth must be in DD-MM-YYYY format")
}
}
if strings.TrimSpace(r.PlaceOfBirth) == "" {
errors["placeofbirth"] = append(errors["placeofbirth"], "Place of birth is required")
}
if !utils.IsValidPhoneNumber(r.Phone) {
errors["phone"] = append(errors["phone"], "Phone must be valid, has 8-14 digit and start with '62..'")
}
if !utils.IsValidEmail(r.Email) {
errors["email"] = append(errors["email"], "Invalid email format")
}
if !utils.IsValidPassword(r.Password) {
errors["password"] = append(errors["password"], "Password must be at least 8 characters, with uppercase, number, and special character")
}
if r.Password != r.PasswordConfirm {
errors["password_confirm"] = append(errors["password_confirm"], "Passwords do not match")
}
if len(errors) > 0 {
return errors, false
}
return nil, true
}