oef/orm/school.go

335 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://piattaforma.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 2021.
`
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
}