Spaces:
Configuration error
Configuration error
| package validation | |
| import ( | |
| "strings" | |
| "sync" | |
| v10 "github.com/go-playground/validator/v10" | |
| "gorm.io/gorm" | |
| ) | |
| type ValidOptionSource interface { | |
| GetValidOptions(key string) ([]string, error) | |
| GetValidKeys() []string | |
| } | |
| // -------------------- | |
| // InMemoryOptionSource | |
| // -------------------- | |
| type InMemoryOptionSource struct{} | |
| var inMemoryOptions = map[string][]string{ | |
| "last_education": {"SD", "SMP", "SMA", "D1", "D2", "D3", "D4", "D5", "S1", "S2", "S3"}, | |
| "marital_status": {"Belum Menikah", "Duda", "Janda"}, | |
| "gender": {"Laki-laki", "Perempuan"}, | |
| "monthly_expenses": {"< 2 Juta", "2-5 Juta", "5-20 Juta", "> 10 Juta"}, | |
| "monthly_income": {"< 3 Juta", "3-5 Juta", "5-10 Juta", "> 10 Juta"}, | |
| "religion": {"Islam", "Non-Islam"}, | |
| "family_role": {"Ayah", "Ibu", "Kakak", "Adik", "Anak"}, | |
| "life_status": {"Hidup", "Wafat"}, | |
| "body_shape": {"Ideal", "Kurus", "Berisi", "Gemuk"}, | |
| "skin_color": {"Putih", "Kuning Langsat", "Sawo Matang"}, | |
| "hair_type": {"Lurus", "Bergelombang", "Keriting"}, | |
| "frequently": {"Selalu", "Sering", "Kadang", "Jarang"}, | |
| "quran_reading_ability": {"Lancar", "Menengah", "Perlu Bimbingan"}, | |
| } | |
| func (s *InMemoryOptionSource) GetValidOptions(key string) ([]string, error) { | |
| return inMemoryOptions[key], nil | |
| } | |
| func (s *InMemoryOptionSource) GetValidKeys() []string { | |
| keys := make([]string, 0, len(inMemoryOptions)) | |
| for k := range inMemoryOptions { | |
| keys = append(keys, k) | |
| } | |
| return keys | |
| } | |
| // -------------------- | |
| // DBOptionSource | |
| // -------------------- | |
| type DBOptionSource struct { | |
| options map[string][]string | |
| mu sync.RWMutex | |
| } | |
| type ( | |
| OptionCategory struct { | |
| ID int64 `gorm:"primaryKey" json:"id"` | |
| OptionName string `json:"option_name"` | |
| OptionSlug string `json:"option_slug" gorm:"uniqueIndex"` | |
| } | |
| OptionValues struct { | |
| ID int64 `gorm:"primaryKey" json:"id"` | |
| OptionCategoryID int64 `json:"option_category_id"` | |
| OptionValue string `json:"option_value"` | |
| } | |
| ) | |
| func NewDBOptionSource(db *gorm.DB) (*DBOptionSource, error) { | |
| var categories []OptionCategory | |
| if err := db.Find(&categories).Error; err != nil { | |
| return nil, err | |
| } | |
| options := make(map[string][]string) | |
| for _, cat := range categories { | |
| var values []OptionValues | |
| if err := db.Where("option_category_id = ?", cat.ID).Find(&values).Error; err != nil { | |
| return nil, err | |
| } | |
| for _, val := range values { | |
| options[cat.OptionSlug] = append(options[cat.OptionSlug], val.OptionValue) | |
| } | |
| } | |
| return &DBOptionSource{options: options}, nil | |
| } | |
| func (s *DBOptionSource) GetValidOptions(key string) ([]string, error) { | |
| s.mu.RLock() | |
| defer s.mu.RUnlock() | |
| return s.options[key], nil | |
| } | |
| func (s *DBOptionSource) GetValidKeys() []string { | |
| s.mu.RLock() | |
| defer s.mu.RUnlock() | |
| keys := make([]string, 0, len(s.options)) | |
| for k := range s.options { | |
| keys = append(keys, k) | |
| } | |
| return keys | |
| } | |
| // -------------------- | |
| // Validator | |
| // -------------------- | |
| type Validator struct { | |
| source ValidOptionSource | |
| } | |
| func NewValidatorRules(source ValidOptionSource) *Validator { | |
| return &Validator{source: source} | |
| } | |
| func (v *Validator) GenericOptionRule(key string) func(fl v10.FieldLevel) bool { | |
| return func(fl v10.FieldLevel) bool { | |
| value := fl.Field().String() | |
| if value == "" { | |
| return true | |
| } | |
| validOptions, err := v.source.GetValidOptions(key) | |
| if err != nil { | |
| return false | |
| } | |
| for _, opt := range validOptions { | |
| if opt == value { | |
| return true | |
| } | |
| } | |
| return false | |
| } | |
| } | |
| func (v *Validator) RegisterAllCustomRules(validate *v10.Validate) error { | |
| for _, key := range v.source.GetValidKeys() { | |
| err := validate.RegisterValidation(key, v.GenericOptionRule(key)) | |
| if err != nil { | |
| return err | |
| } | |
| } | |
| err := validate.RegisterValidation("password", v.PasswordRule) | |
| if err != nil { | |
| return err | |
| } | |
| return nil | |
| } | |
| func (v *Validator) PasswordRule(fl v10.FieldLevel) bool { | |
| password := fl.Field().String() | |
| return len(password) >= 8 && | |
| strings.ContainsAny(password, "abcdefghijklmnopqrstuvwxyz") && | |
| strings.ContainsAny(password, "ABCDEFGHIJKLMNOPQRSTUVWXYZ") && | |
| strings.ContainsAny(password, "0123456789") | |
| } | |