package orm import ( "fmt" "net/http" "os" "strings" "time" "git.andreafazzi.eu/andrea/oef/errors" "git.andreafazzi.eu/andrea/oef/mail" "git.andreafazzi.eu/andrea/oef/renderer" "github.com/dchest/captcha" "github.com/jinzhu/gorm" ) type RegionID uint var mailBody = ` Spettabile {{.NameForMail}}, grazie per l'interesse manifestato per le Olimpiadi di Economia e Finanza. Di seguito riportiamo le credenziali di accesso tramite le quali potrà gestire le iscrizioni dei suoi studenti alla competizione (Fase Regionale). username: {{.Username}} password: {{.Password}} Per accedere alla pagina di login occorrerà seguire questo link https://iscrizioni.olimpiadi-economiaefinanza.it/ ed inserire le credenziali riportate sopra (si consiglia di effettuare un copia/incolla). Questa mail è stata generata da un sistema automatico, si prega di non rispondere. Cordialmente, Lo Staff delle OEF 2020. ` type School struct { gorm.Model UserModifier Name string Address string Email string Code string EmailSentDate time.Time SchoolContactPersonLastname string SchoolContactPersonFirstname string ContestDirectorLastname string ContestDirectorFirstname string UserID uint RegionID RegionID `schema:"region_id"` Region *Region User *User Participants []*Participant SelectedRegion map[uint]string `gorm:"-"` AllRegions []*Region `gorm:"-"` CaptchaID string `gorm:"-",schema:"-"` CaptchaSolution string `gorm:"-",schema:"-"` mailSender *mail.MailSender } func (id *RegionID) UnmarshalCSV(csv string) error { *id = RegionID(regionsMap[strings.Title(strings.ToLower(csv))]) return nil } func (model *School) GetID() uint { return model.ID } func (model *School) String() string { return fmt.Sprintf("%s (%s)", model.Code, model.Name) } func (model *School) NameForMail() string { return fmt.Sprintf("%s (%s)", model.Name, model.Code) } func (model *School) Username() string { return strings.ToUpper(model.Code) } func (model *School) Password() string { return model.User.Password } func (model *School) To() string { return model.Email } func (model *School) SetCreatorID(id uint) { model.CreatorID = id } func (model *School) SetCreatorRole(role string) { model.CreatorRole = role } func (model *School) SetCreatorIP(addr string) { model.CreatorIP = addr } func (model *School) SetUpdaterID(id uint) { model.UpdaterID = id } func (model *School) SetUpdaterRole(role string) { model.UpdaterRole = role } func (model *School) SetUpdaterIP(addr string) { model.UpdaterIP = addr } func (model *School) exists(db *Database) (*User, error) { var user User if err := db._db.First(&user, &User{Username: model.Username()}).Error; err != nil && err != gorm.ErrRecordNotFound { return nil, err } else if err == gorm.ErrRecordNotFound { return nil, nil } return &user, nil } func (model *School) BeforeSave(tx *gorm.DB) error { var user User if err := tx.FirstOrCreate(&user, &User{ Username: model.Username(), Role: "school", }).Error; err != nil { return err } model.UserID = user.ID // School code is always uppercase model.Code = strings.ToUpper(model.Code) return nil } func (model *School) AfterDelete(tx *gorm.DB) error { if err := tx.Unscoped().Delete(model.User).Error; err != nil { return err } return nil } func (model *School) AfterCreate(tx *gorm.DB) error { if err := tx.Preload("User").First(model).Error; err != nil { return err } if err := model.mailSender.SendSubscriptionMail(model); err != nil { return err } if err := tx.Model(model).Update("email_sent_date", time.Now()).Error; err != nil { return err } return nil } func (model *School) Create(db *Database, args map[string]string, w http.ResponseWriter, r *http.Request) (interface{}, error) { if r.Method == "GET" { school := new(School) if err := db._db.Find(&school.AllRegions).Error; err != nil { return nil, err } return school, nil } else { if isSubscriber(r) && os.Getenv("OEF_REGRESSION_TEST") != "1" { if !captcha.VerifyString(r.FormValue("CaptchaID"), r.FormValue("CaptchaSolution")) { return nil, errors.WrongCaptcha } } school := new(School) err := renderer.Decode(school, r) if err != nil { return nil, err } // Check if this user already exists in the users table. if user, err := school.exists(db); err == nil && user != nil { if err := db._db.Where("user_id = ?", user.ID).Find(&school).Error; err != nil { return nil, err } return nil, errors.SchoolExists } else if err != nil { return nil, err } WriteCreator(r, school) school.mailSender = mail.NewMailSender(db.Config, mailBody) school, err = CreateSchool(db, school) if err != nil { return nil, err } return school, nil } } func (model *School) Read(db *Database, args map[string]string, w http.ResponseWriter, r *http.Request) (interface{}, error) { var school School id := args["id"] if isSchool(r) && id != getModelIDFromToken(r) { return nil, errors.NotAuthorized } if err := db._db. Preload("Participants"). Preload("Participants.Category"). Preload("Region"). Preload("User"). Preload("Creator"). Preload("Updater"). First(&school, id).Error; err != nil { return nil, err } return &school, nil } func (model *School) ReadAll(db *Database, args map[string]string, w http.ResponseWriter, r *http.Request) (interface{}, error) { var schools []*School if err := db._db. Preload("Participants"). Preload("Participants.Category"). Preload("Region"). Order("code"). Find(&schools).Error; err != nil { return nil, err } return schools, nil } func (model *School) Update(db *Database, args map[string]string, w http.ResponseWriter, r *http.Request) (interface{}, error) { if r.Method == "GET" { result, err := model.Read(db, args, w, r) if err != nil { return nil, err } school := result.(*School) if err := db._db.Find(&school.AllRegions).Error; err != nil { return nil, err } school.SelectedRegion = make(map[uint]string) school.SelectedRegion[uint(school.RegionID)] = "selected" return school, nil } else { school, err := model.Read(db, args, w, r) if err != nil { return nil, err } err = renderer.Decode(school, r) if err != nil { return nil, err } // Check if the modified school code belong to an existing school. if user, err := school.(*School).exists(db); err == nil && user != nil { if user.ID != school.(*School).UserID { return nil, errors.SchoolExists } } else if err != nil { return nil, err } WriteUpdater(r, school.(*School)) _, err = SaveSchool(db, school) if err != nil { return nil, err } school, err = model.Read(db, args, w, r) if err != nil { return nil, err } return school.(*School), nil } } func (model *School) Delete(db *Database, args map[string]string, w http.ResponseWriter, r *http.Request) (interface{}, error) { school, err := model.Read(db, args, w, r) if err != nil { return nil, err } if err := db._db.Unscoped().Delete(school.(*School)).Error; err != nil { return nil, err } return school.(*School), nil } func CreateSchool(db *Database, school *School) (*School, error) { if err := db._db.Create(school).Error; err != nil { return nil, err } return school, nil } func SaveSchool(db *Database, school interface{}) (interface{}, error) { if err := db._db.Omit("Region", "Creator", "Updater").Save(school).Error; err != nil { return nil, err } return school, nil } func (model *School) HasCategory(db *Database, participant *Participant) (bool, error) { var participants []*Participant if err := db._db. Where("category_id = ? AND school_id = ? AND id <> ?", participant.CategoryID, model.ID, participant.ID). Find(&participants).Error; err != nil { return false, err } return len(participants) > 0, nil }