334 lines
7.7 KiB
Go
334 lines
7.7 KiB
Go
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").
|
|
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
|
|
}
|