From 82de4b68fb77836e751ffea54a4616c2be20dad6 Mon Sep 17 00:00:00 2001 From: Andrea Fazzi Date: Wed, 15 Jan 2020 13:40:35 +0100 Subject: [PATCH] Completed renderer, orm and mail sender refactoring --- config/config.go | 13 ++--- handlers/handlers.go | 38 +++++++------- handlers/handlers_test.go | 71 ++++++++++---------------- handlers/login.go | 11 ++--- handlers/testdata/config.yaml | 2 +- mail/mail.go | 56 ++++++++------------- main.go | 26 ++++++++-- orm/orm.go | 6 ++- orm/participant.go | 8 +-- orm/response.go | 5 +- orm/school.go | 29 +++++++++-- orm/useraction.go | 20 +++++--- renderer/renderer.go | 93 ++++++++++++++++++++--------------- 13 files changed, 203 insertions(+), 175 deletions(-) diff --git a/config/config.go b/config/config.go index 04c1e18a..0dff14de 100644 --- a/config/config.go +++ b/config/config.go @@ -90,6 +90,7 @@ type ConfigT struct { From string Cc string Bcc string + Subject string } Sync struct { @@ -115,13 +116,13 @@ type ConfigT struct { } } -var ( - Config *ConfigT -) +// var ( +// Config *ConfigT +// ) -func init() { - Config = new(ConfigT) -} +// func init() { +// Config = new(ConfigT) +// } // ReadFile reads the config file placed at the given path. func ReadFile(path string, config *ConfigT) error { diff --git a/handlers/handlers.go b/handlers/handlers.go index 18887863..977db7e7 100644 --- a/handlers/handlers.go +++ b/handlers/handlers.go @@ -38,6 +38,8 @@ type Handlers struct { Database *orm.Database Models []interface{} + Renderer map[string]renderer.Renderer + Login func(db *orm.Database, store *sessions.CookieStore, signingKey []byte) http.Handler Logout func(store *sessions.CookieStore) http.Handler Home func() http.Handler @@ -165,15 +167,17 @@ func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) { } -func NewHandlers(config *config.ConfigT, db *orm.Database, models []interface{}) *Handlers { +func NewHandlers(config *config.ConfigT, renderer map[string]renderer.Renderer, db *orm.Database, models []interface{}) *Handlers { handlers := new(Handlers) handlers.Config = config + + handlers.Renderer = renderer handlers.Database = db handlers.CookieStore = sessions.NewCookieStore([]byte(config.Keys.CookieStoreKey)) - handlers.Login = DefaultLoginHandler + handlers.Login = handlers.DefaultLoginHandler handlers.Logout = DefaultLogoutHandler handlers.Recover = DefaultRecoverHandler handlers.Home = DefaultHomeHandler @@ -230,7 +234,6 @@ func NewHandlers(config *config.ConfigT, db *orm.Database, models []interface{}) } func (h *Handlers) onError(w http.ResponseWriter, r *http.Request, err string) { - log.Print(err) http.Redirect(w, r, "/login?tpl_layout=login&tpl_content=login", http.StatusTemporaryRedirect) } @@ -298,21 +301,20 @@ func (h *Handlers) get(w http.ResponseWriter, r *http.Request, model string, pat getFn, err := h.Database.GetFunc(pattern.Path(model)) if err != nil { log.Println("Error:", err) - respondWithError(w, r, err) + respondWithError(h, w, r, err) } else { claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims) role := claims["role"].(string) if !hasPermission(role, pattern.Path(model)) { - log.Println("ERRORE") h.setFlashMessage(w, r, "notAuthorized") - renderer.Render[format](w, r, fmt.Errorf("%s", "Errore di autorizzazione")) + h.Renderer[format].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione")) } else { data, err := getFn(h.Database, mux.Vars(r), w, r) if err != nil { - renderer.Render[format](w, r, err) + h.Renderer[format].Render(w, r, h.CookieStore, err) } else { - renderer.Render[format](w, r, data, r.URL.Query()) + h.Renderer[format].Render(w, r, h.CookieStore, data, r.URL.Query()) } } } @@ -329,17 +331,17 @@ func (h *Handlers) post(w http.ResponseWriter, r *http.Request, model string, pa postFn, err := h.Database.GetFunc(pattern.Path(model)) if err != nil { - respondWithError(w, r, err) + respondWithError(h, w, r, err) } else { claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims) role := claims["role"].(string) if !hasPermission(role, pattern.Path(model)) { - renderer.Render[respFormat](w, r, fmt.Errorf("%s", "Errore di autorizzazione")) + h.Renderer[respFormat].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione")) } else { data, err = postFn(h.Database, mux.Vars(r), w, r) if err != nil { - respondWithError(w, r, err) + respondWithError(h, w, r, err) } else if pattern.RedirectPattern != "" { if id := mux.Vars(r)["id"]; id != "" { modelId, _ := strconv.Atoi(id) @@ -348,7 +350,7 @@ func (h *Handlers) post(w http.ResponseWriter, r *http.Request, model string, pa http.Redirect(w, r, pattern.RedirectPath(model, data.(orm.IDer).GetID()), http.StatusSeeOther) } } else { - renderer.Render[respFormat](w, r, data.(orm.IDer).GetID()) + h.Renderer[respFormat].Render(w, r, h.CookieStore, data.(orm.IDer).GetID()) } } } @@ -364,15 +366,15 @@ func (h *Handlers) delete(w http.ResponseWriter, r *http.Request, model string, role := claims["role"].(string) if !hasPermission(role, pattern.Path(model)) { - renderer.Render[respFormat](w, r, fmt.Errorf("%s", "Errore di autorizzazione")) + h.Renderer[respFormat].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione")) } else { postFn, err := h.Database.GetFunc(pattern.Path(model)) if err != nil { - renderer.Render[r.URL.Query().Get("format")](w, r, err) + h.Renderer[r.URL.Query().Get("format")].Render(w, r, h.CookieStore, err) } data, err = postFn(h.Database, mux.Vars(r), w, r) if err != nil { - renderer.Render["html"](w, r, err) + h.Renderer["html"].Render(w, r, h.CookieStore, err) } else if pattern.RedirectPattern != "" { var data struct { RedirectUrl string `json:"redirect_url"` @@ -382,15 +384,15 @@ func (h *Handlers) delete(w http.ResponseWriter, r *http.Request, model string, w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(data) } else { - renderer.Render[respFormat](w, r, data.(orm.IDer).GetID()) + h.Renderer[respFormat].Render(w, r, h.CookieStore, data.(orm.IDer).GetID()) } } } -func respondWithError(w http.ResponseWriter, r *http.Request, err error) { +func respondWithError(h *Handlers, w http.ResponseWriter, r *http.Request, err error) { respFormat := renderer.GetContentFormat(r) w.WriteHeader(http.StatusInternalServerError) - renderer.Render[respFormat](w, r, err) + h.Renderer[respFormat].Render(w, r, h.CookieStore, err) } func (h *Handlers) modelHandler(model string, pattern PathPattern) http.Handler { diff --git a/handlers/handlers_test.go b/handlers/handlers_test.go index 19374654..0b04861c 100644 --- a/handlers/handlers_test.go +++ b/handlers/handlers_test.go @@ -3,9 +3,9 @@ package handlers import ( "context" "encoding/json" + "log" "net/http" "net/http/httptest" - "net/url" "strings" "testing" "time" @@ -14,13 +14,13 @@ import ( "git.andreafazzi.eu/andrea/oef/orm" "git.andreafazzi.eu/andrea/oef/renderer" jwt "github.com/dgrijalva/jwt-go" - "github.com/jinzhu/gorm" "github.com/remogatto/prettytest" ) var ( token string handlers *Handlers + conf *config.ConfigT ) // Start of setup @@ -42,7 +42,7 @@ func authenticate(request *http.Request, tokenString string, signingKey string) } -func requestToken(handlers *Handlers) string { +func requestToken(db *orm.Database, handlers *Handlers) string { req, err := http.NewRequest("GET", "/get_token", nil) if err != nil { panic(err) @@ -52,7 +52,7 @@ func requestToken(handlers *Handlers) string { rr := httptest.NewRecorder() - handlers.GetToken([]byte(config.Config.Keys.JWTSigningKey)).ServeHTTP(rr, req) + handlers.GetToken(db, []byte(db.Config.Keys.JWTSigningKey)).ServeHTTP(rr, req) var data struct { Token string @@ -75,10 +75,9 @@ func TestRunner(t *testing.T) { func (t *testSuite) BeforeAll() { - var ( - db *gorm.DB - err error - ) + var db *orm.Database + + conf = new(config.ConfigT) models := []interface{}{ &orm.Question{}, @@ -92,25 +91,32 @@ func (t *testSuite) BeforeAll() { &orm.Region{}, } + // Load the configuration + + err := config.ReadFile("testdata/config.yaml", conf) + if err != nil { + panic(err) + } + // conf.LogLevel = config.LOG_LEVEL_OFF + // Initialize the ORM connected := false for !connected { + var err error + time.Sleep(5 * time.Second) - db, err = orm.New("oef:oef@/oef_test?charset=utf8&parseTime=True&loc=Local") + + db, err = orm.NewDatabase(conf, models) if err != nil { + log.Print(err) continue } + connected = true } - orm.Use(db) - orm.AutoMigrate() - - // Map the handlers - if err := orm.MapHandlers(models); err != nil { - panic(err) - } + db.AutoMigrate() // Initialize the renderers @@ -119,26 +125,12 @@ func (t *testSuite) BeforeAll() { panic(err) } - renderer.Render = make(map[string]func(http.ResponseWriter, *http.Request, interface{}, ...url.Values)) - - renderer.Render["html"] = func(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) { - htmlRenderer.Render(w, r, data, options...) - } - - // Load the configuration - - err = config.ReadFile("testdata/config.yaml", config.Config) - if err != nil { - panic(err) - } - config.Config.LogLevel = config.LOG_LEVEL_OFF - handlers = NewHandlers(config.Config, models) - token = requestToken(handlers) - - if err := orm.MapHandlers(models); err != nil { - panic(err) + renderer := map[string]renderer.Renderer{ + "html": htmlRenderer, } + handlers = NewHandlers(conf, renderer, db, models) + token = requestToken(db, handlers) } func (t *testSuite) TestReadAllContests() { @@ -155,16 +147,7 @@ func (t *testSuite) TestReadAllContests() { rr := httptest.NewRecorder() - req, err = authenticate(req, token, config.Config.Keys.JWTSigningKey) - // tkn, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { - // return []byte("secret"), nil - // }) - // if err != nil { - // panic(err) - // } - // ctx := req.Context() - // ctx = context.WithValue(ctx, "user", tkn) - // req = req.WithContext(ctx) + req, err = authenticate(req, token, conf.Keys.JWTSigningKey) t.Nil(err) if err != nil { diff --git a/handlers/login.go b/handlers/login.go index 53280146..fa83840d 100644 --- a/handlers/login.go +++ b/handlers/login.go @@ -7,9 +7,7 @@ import ( "strconv" "time" - "git.andreafazzi.eu/andrea/oef/config" "git.andreafazzi.eu/andrea/oef/orm" - "git.andreafazzi.eu/andrea/oef/renderer" jwt "github.com/dgrijalva/jwt-go" "github.com/gorilla/sessions" ) @@ -22,6 +20,7 @@ type UserToken struct { } var ( +// REMOVE // signingKey = []byte(config.Config.Keys.JWTSigningKey) // store = sessions.NewCookieStore([]byte(config.Config.Keys.CookieStoreKey)) @@ -59,10 +58,10 @@ func DefaultLogoutHandler(store *sessions.CookieStore) http.Handler { return http.HandlerFunc(fn) } -func DefaultLoginHandler(db *orm.Database, store *sessions.CookieStore, signingKey []byte) http.Handler { +func (h *Handlers) DefaultLoginHandler(db *orm.Database, store *sessions.CookieStore, signingKey []byte) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { - renderer.Render["html"](w, r, nil, r.URL.Query()) + h.Renderer["html"].Render(w, r, store, nil, r.URL.Query()) } if r.Method == "POST" { r.ParseForm() @@ -90,13 +89,13 @@ func DefaultLoginHandler(db *orm.Database, store *sessions.CookieStore, signingK func checkCredential(db *orm.Database, username string, password string) (*UserToken, error) { // Check if user is the administrator - if username == config.Config.Admin.Username && password == config.Config.Admin.Password { + if username == db.Config.Admin.Username && password == db.Config.Admin.Password { return &UserToken{username, true, "administrator", "0"}, nil } // Check if user is a subscriber - if password == config.Config.Subscriber.Password { + if password == db.Config.Subscriber.Password { return &UserToken{"subscriber", false, "subscriber", "0"}, nil } diff --git a/handlers/testdata/config.yaml b/handlers/testdata/config.yaml index 8bdcdd23..7a9ead06 100644 --- a/handlers/testdata/config.yaml +++ b/handlers/testdata/config.yaml @@ -6,7 +6,7 @@ keys: jwt_signing_key: "secret" orm: - connection: "oef:oef@tcp(db:3306)/oef_test" + connection: "oef:oef@tcp(localhost:3306)/oef_test" options: "charset=utf8&parseTime=True&loc=Local" automigrate: true reset: false diff --git a/mail/mail.go b/mail/mail.go index e26d0341..7e2ff95f 100644 --- a/mail/mail.go +++ b/mail/mail.go @@ -6,7 +6,6 @@ import ( "text/template" "git.andreafazzi.eu/andrea/oef/config" - "gopkg.in/gomail.v2" ) @@ -17,45 +16,32 @@ type Subscriber interface { To() string } -var ( - mail = ` -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). - -Cordialmente, -Lo Staff delle OEF 2020. -` - subject = "[OEF2020] - Credenziali di accesso della scuola" +type MailSender struct { + BodyTemplate string mailTpl *template.Template -) - -func init() { - mailTpl = template.Must(template.New("subscription_mail").Parse(mail)) + config *config.ConfigT } -func SendSubscriptionMail(rcv Subscriber) error { +func NewMailSender(config *config.ConfigT, mailBody string) *MailSender { + ms := new(MailSender) + + ms.config = config + ms.mailTpl = template.Must(template.New("subscription_mail").Parse(mailBody)) + + return ms +} + +func (ms *MailSender) SendSubscriptionMail(rcv Subscriber) error { var body bytes.Buffer m := gomail.NewMessage() - m.SetHeader("Subject", subject) - m.SetHeader("From", config.Config.Smtp.From) + m.SetHeader("Subject", ms.config.Smtp.Subject) + m.SetHeader("From", ms.config.Smtp.From) m.SetHeader("To", rcv.To()) - m.SetHeader("Bcc", config.Config.Smtp.Bcc) + m.SetHeader("Bcc", ms.config.Smtp.Bcc) - err := mailTpl.Execute(&body, rcv) + err := ms.mailTpl.Execute(&body, rcv) if err != nil { return err } @@ -63,10 +49,10 @@ func SendSubscriptionMail(rcv Subscriber) error { m.SetBody("text/plain", body.String()) dialer := gomail.NewDialer( - config.Config.Smtp.Host, - config.Config.Smtp.Port, - config.Config.Smtp.Username, - config.Config.Smtp.Password, + ms.config.Smtp.Host, + ms.config.Smtp.Port, + ms.config.Smtp.Username, + ms.config.Smtp.Password, ) dialer.TLSConfig = &tls.Config{InsecureSkipVerify: true} diff --git a/main.go b/main.go index 8b303d68..bec79410 100644 --- a/main.go +++ b/main.go @@ -12,6 +12,7 @@ import ( "git.andreafazzi.eu/andrea/oef/config" oef_handlers "git.andreafazzi.eu/andrea/oef/handlers" "git.andreafazzi.eu/andrea/oef/orm" + "git.andreafazzi.eu/andrea/oef/renderer" ) const ( @@ -41,7 +42,9 @@ func main() { flag.Parse() log.Println("Loading config file...") - err = config.ReadFile(*configFile, config.Config) + + conf := new(config.ConfigT) + err = config.ReadFile(*configFile, conf) if err != nil { panic(err) } @@ -52,7 +55,7 @@ func main() { wait := true for wait && count > 0 { - db, err = orm.NewDatabase(config.Config, models) + db, err = orm.NewDatabase(conf, models) if err != nil { count-- log.Println(err) @@ -66,7 +69,7 @@ func main() { // REMOVE // orm.Use(db) - if config.Config.Orm.AutoMigrate { + if conf.Orm.AutoMigrate { log.Print("Automigrating...") db.AutoMigrate() } @@ -78,7 +81,22 @@ func main() { orm.CreateRegions(db) log.Println("OEF is listening to port 3000...") - if err := http.ListenAndServe(":3000", handlers.LoggingHandler(os.Stdout, oef_handlers.NewHandlers(config.Config, db, models).Router)); err != nil { + + htmlRenderer, err := renderer.NewHTMLRenderer("templates") + if err != nil { + panic(err) + } + + jsonRenderer, err := renderer.NewJSONRenderer() + if err != nil { + panic(err) + } + + renderer := map[string]renderer.Renderer{ + "html": htmlRenderer, + "json": jsonRenderer, + } + if err := http.ListenAndServe(":3000", handlers.LoggingHandler(os.Stdout, oef_handlers.NewHandlers(conf, renderer, db, models).Router)); err != nil { panic(err) } diff --git a/orm/orm.go b/orm/orm.go index ad7e6223..db58684a 100644 --- a/orm/orm.go +++ b/orm/orm.go @@ -34,6 +34,8 @@ func NewDatabase(config *config.ConfigT, models []interface{}) (*Database, error db := new(Database) + db.Config = config + db.fns = make(map[string]func(*Database, map[string]string, http.ResponseWriter, *http.Request) (interface{}, error), 0) db.mapHandlers(models) @@ -52,11 +54,11 @@ func (db *Database) AutoMigrate() { } func (db *Database) GetUser(username, password string) (*User, error) { - var user *User + var user User if err := db._db.Where("username = ? AND password = ?", username, password).First(&user).Error; err != nil { return nil, errors.New("Authentication failed!") } - return user, nil + return &user, nil } func (db *Database) DB() *gorm.DB { diff --git a/orm/participant.go b/orm/participant.go index 67a62742..66867c40 100644 --- a/orm/participant.go +++ b/orm/participant.go @@ -210,7 +210,7 @@ func (model *Participant) Create(db *Database, args map[string]string, w http.Re return nil, errors.CategoryExists } - participant.UserModifierCreate = NewUserModifierCreate(r) + participant.UserModifierCreate = NewUserModifierCreate(db, r) participant, err = CreateParticipant(db, participant) if err != nil { @@ -223,7 +223,7 @@ func (model *Participant) Create(db *Database, args map[string]string, w http.Re return nil, err } - response.UserModifierCreate = NewUserModifierCreate(r) + response.UserModifierCreate = NewUserModifierCreate(db, r) if err := db._db.Save(&response).Error; err != nil { return nil, err @@ -362,7 +362,7 @@ func (model *Participant) Update(db *Database, args map[string]string, w http.Re return nil, err } - participant.(*Participant).UserModifierUpdate = NewUserModifierUpdate(r) + participant.(*Participant).UserModifierUpdate = NewUserModifierUpdate(db, r) _, err = SaveParticipant(db, participant) if err != nil { @@ -384,7 +384,7 @@ func (model *Participant) Update(db *Database, args map[string]string, w http.Re return nil, err } - response.UserModifierUpdate = NewUserModifierUpdate(r) + response.UserModifierUpdate = NewUserModifierUpdate(db, r) if err := db._db.Save(&response).Error; err != nil { return nil, err diff --git a/orm/response.go b/orm/response.go index 3474a6cf..fcf61ca6 100644 --- a/orm/response.go +++ b/orm/response.go @@ -94,7 +94,7 @@ func (model *Response) Create(db *Database, args map[string]string, w http.Respo return nil, err } - response.UserModifierCreate = NewUserModifierCreate(r) + response.UserModifierCreate = NewUserModifierCreate(db, r) response, err = CreateResponse(db, response) if err != nil { @@ -139,7 +139,6 @@ func (model *Response) Read(db *Database, args map[string]string, w http.Respons qOrder := make([]uint, 0) qIDs := strings.Split(response.QuestionsOrder, " ") - log.Print("QO", response.QuestionsOrder) for _, id := range qIDs { id, err := strconv.Atoi(id) if err != nil { @@ -212,7 +211,7 @@ func (model *Response) Update(db *Database, args map[string]string, w http.Respo return nil, err } - response.(*Response).UserModifierUpdate = NewUserModifierUpdate(r) + response.(*Response).UserModifierUpdate = NewUserModifierUpdate(db, r) _, err = SaveResponse(db, response) if err != nil { diff --git a/orm/school.go b/orm/school.go index 6646b113..2f3417b3 100644 --- a/orm/school.go +++ b/orm/school.go @@ -14,6 +14,26 @@ import ( 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). + +Cordialmente, +Lo Staff delle OEF 2020. +` + type School struct { gorm.Model @@ -41,6 +61,8 @@ type School struct { SelectedRegion map[uint]string `gorm:"-"` AllRegions []*Region `gorm:"-"` + + mailSender *mail.MailSender } func (id *RegionID) UnmarshalCSV(csv string) error { @@ -107,7 +129,7 @@ func (model *School) AfterCreate(tx *gorm.DB) error { if err := tx.Preload("User").First(model).Error; err != nil { return err } - if err := mail.SendSubscriptionMail(model); err != nil { + if err := model.mailSender.SendSubscriptionMail(model); err != nil { return err } @@ -148,8 +170,9 @@ func (model *School) Create(db *Database, args map[string]string, w http.Respons return nil, err } - school.UserModifierCreate = NewUserModifierCreate(r) + school.UserModifierCreate = NewUserModifierCreate(db, r) + school.mailSender = mail.NewMailSender(db.Config, mailBody) school, err = CreateSchool(db, school) if err != nil { return nil, err @@ -223,7 +246,7 @@ func (model *School) Update(db *Database, args map[string]string, w http.Respons return nil, err } - school.(*School).UserModifierUpdate = NewUserModifierUpdate(r) + school.(*School).UserModifierUpdate = NewUserModifierUpdate(db, r) _, err = SaveSchool(db, school) if err != nil { diff --git a/orm/useraction.go b/orm/useraction.go index 867598e8..b8a30e16 100644 --- a/orm/useraction.go +++ b/orm/useraction.go @@ -17,15 +17,19 @@ type UserModifierCreate struct { CreatorID string CreatorRole string CreatorIP string + + db *Database } type UserModifierUpdate struct { UpdaterID string UpdaterRole string UpdaterIP string + + db *Database } -func NewUserModifierCreate(r *http.Request) *UserModifierCreate { +func NewUserModifierCreate(db *Database, r *http.Request) *UserModifierCreate { var claims jwt.MapClaims if r.Context().Value("user") != nil { @@ -39,20 +43,20 @@ func NewUserModifierCreate(r *http.Request) *UserModifierCreate { } } -func (um *UserModifierCreate) CreatedBy(db *Database) (*UserAction, error) { +func (um *UserModifierCreate) CreatedBy() (*UserAction, error) { action := new(UserAction) switch um.CreatorRole { case "participant": var participant Participant - if err := db._db.Preload("User").First(&participant, um.CreatorID).Error; err != nil { + if err := um.db._db.Preload("User").First(&participant, um.CreatorID).Error; err != nil { return nil, err } action.User = *participant.User case "school": var school School - if err := db._db.Preload("User").First(&school, um.CreatorID).Error; err != nil { + if err := um.db._db.Preload("User").First(&school, um.CreatorID).Error; err != nil { return nil, err } action.User = *school.User @@ -67,7 +71,7 @@ func (um *UserModifierCreate) CreatedBy(db *Database) (*UserAction, error) { return action, nil } -func NewUserModifierUpdate(r *http.Request) *UserModifierUpdate { +func NewUserModifierUpdate(db *Database, r *http.Request) *UserModifierUpdate { var claims jwt.MapClaims if r.Context().Value("user") != nil { @@ -80,19 +84,19 @@ func NewUserModifierUpdate(r *http.Request) *UserModifierUpdate { } } -func (um *UserModifierUpdate) UpdatedBy(db *Database) (*UserAction, error) { +func (um *UserModifierUpdate) UpdatedBy() (*UserAction, error) { action := new(UserAction) switch um.UpdaterRole { case "participant": var participant Participant - if err := db._db.Preload("User").First(&participant, um.UpdaterID).Error; err != nil { + if err := um.db._db.Preload("User").First(&participant, um.UpdaterID).Error; err != nil { return nil, err } action.User = *participant.User case "school": var school School - if err := db._db.Preload("User").First(&school, um.UpdaterID).Error; err != nil { + if err := um.db._db.Preload("User").First(&school, um.UpdaterID).Error; err != nil { return nil, err } action.User = *school.User diff --git a/renderer/renderer.go b/renderer/renderer.go index 2c8f2c99..a8fc63cf 100644 --- a/renderer/renderer.go +++ b/renderer/renderer.go @@ -8,9 +8,6 @@ import ( "io" "log" - "git.andreafazzi.eu/andrea/oef/config" - "git.andreafazzi.eu/andrea/oef/errors" - "github.com/gorilla/sessions" "mime" "net/http" "net/url" @@ -21,14 +18,17 @@ import ( "strings" "time" + "git.andreafazzi.eu/andrea/oef/errors" + "github.com/gocarina/gocsv" "github.com/gorilla/schema" + "github.com/gorilla/sessions" jwt "github.com/dgrijalva/jwt-go" ) type Renderer interface { - Render(http.ResponseWriter, *http.Request, interface{}, ...url.Values) error + Render(http.ResponseWriter, *http.Request, *sessions.CookieStore, interface{}, ...url.Values) error } type JSONRenderer struct{} @@ -48,9 +48,10 @@ type JsonResponse struct { } var ( - store = sessions.NewCookieStore([]byte(config.Config.Keys.CookieStoreKey)) - currRenderer Renderer - Render map[string]func(http.ResponseWriter, *http.Request, interface{}, ...url.Values) + // REMOVE + // store = sessions.NewCookieStore([]byte(config.Config.Keys.CookieStoreKey)) + // currRenderer Renderer + // Render map[string]func(http.ResponseWriter, *http.Request, *sessions.CookieStore, interface{}, ...url.Values) contentTypeToFormat = map[string]string{ "application/x-www-form-urlencoded": "html", @@ -62,43 +63,44 @@ var ( ) func init() { - htmlRenderer, err := NewHTMLRenderer("templates/") - if err != nil { - panic(err) - } + //REMOVE + // htmlRenderer, err := NewHTMLRenderer("templates/") + // if err != nil { + // panic(err) + // } - jsonRenderer, err := NewJSONRenderer() - if err != nil { - panic(err) - } + // jsonRenderer, err := NewJSONRenderer() + // if err != nil { + // panic(err) + // } - csvRenderer, err := NewCSVRenderer() - if err != nil { - panic(err) - } + // csvRenderer, err := NewCSVRenderer() + // if err != nil { + // panic(err) + // } - pdfRenderer, err := NewPDFRenderer() - if err != nil { - panic(err) - } + // pdfRenderer, err := NewPDFRenderer() + // if err != nil { + // panic(err) + // } - Render = make(map[string]func(http.ResponseWriter, *http.Request, interface{}, ...url.Values)) + // Render = make(map[string]func(http.ResponseWriter, *http.Request, *sessions.CookieStore, interface{}, ...url.Values)) - Render["html"] = func(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) { - htmlRenderer.Render(w, r, data, options...) - } + // Render["html"] = func(w http.ResponseWriter, r *http.Request, store *sessions.CookieStore, data interface{}, options ...url.Values) { + // htmlRenderer.Render(w, r, store, data, options...) + // } - Render["json"] = func(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) { - jsonRenderer.Render(w, r, data, options...) - } + // Render["json"] = func(w http.ResponseWriter, r *http.Request, store *sessions.CookieStore, data interface{}, options ...url.Values) { + // jsonRenderer.Render(w, r, store, data, options...) + // } - Render["csv"] = func(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) { - csvRenderer.Render(w, r, data, options...) - } + // Render["csv"] = func(w http.ResponseWriter, r *http.Request, store *sessions.CookieStore, data interface{}, options ...url.Values) { + // csvRenderer.Render(w, r, data, options...) + // } - Render["pdf"] = func(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) { - pdfRenderer.Render(w, r, data, options...) - } + // Render["pdf"] = func(w http.ResponseWriter, r *http.Request, store *sessions.CookieStore, data interface{}, options ...url.Values) { + // pdfRenderer.Render(w, r, data, options...) + // } } @@ -115,7 +117,7 @@ func NewJSONRenderer() (*JSONRenderer, error) { return &JSONRenderer{}, nil } -func (rend *JSONRenderer) Render(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) error { +func (rend *JSONRenderer) Render(w http.ResponseWriter, r *http.Request, store *sessions.CookieStore, data interface{}, options ...url.Values) error { w.Header().Set("Content-Type", "application/json; charset=utf-8") if isErrorType(data) { j, err := json.Marshal(JsonResponse{nil, []byte(data.(error).Error())}) @@ -225,9 +227,10 @@ func NewHTMLRenderer(templatePath string) (*HTMLRenderer, error) { return r, nil } -func Use(r Renderer) { - currRenderer = r -} +// REMOVE +// func Use(r Renderer) { +// currRenderer = r +// } func (rend *HTMLRenderer) writeError(w http.ResponseWriter, r *http.Request, data interface{}) { var t *template.Template @@ -255,7 +258,7 @@ func (rend *HTMLRenderer) writeError(w http.ResponseWriter, r *http.Request, dat } } -func (rend *HTMLRenderer) Render(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) { +func (rend *HTMLRenderer) Render(w http.ResponseWriter, r *http.Request, store *sessions.CookieStore, data interface{}, options ...url.Values) error { var claims jwt.MapClaims if r.Context().Value("user") != nil { @@ -266,18 +269,22 @@ func (rend *HTMLRenderer) Render(w http.ResponseWriter, r *http.Request, data in session, err := store.Get(r, "flash-session") if err != nil { rend.writeError(w, r, &htmlTemplateData{err, nil, claims, nil}) + return err } fm := session.Flashes() err = session.Save(r, w) if err != nil { rend.writeError(w, r, &htmlTemplateData{err, nil, claims, fm}) + return err } rend.writeError(w, r, &htmlTemplateData{data.(error), nil, claims, fm}) + return err } else { t, ok := rend.templates[options[0]["tpl_content"][0]] if !ok { err := fmt.Errorf("Template %s not found", options[0]["tpl_content"][0]) rend.writeError(w, r, &htmlTemplateData{err, nil, claims, nil}) + return err } w.Header().Set("Content-Type", "text/html; charset=utf-8") @@ -285,18 +292,22 @@ func (rend *HTMLRenderer) Render(w http.ResponseWriter, r *http.Request, data in session, err := store.Get(r, "flash-session") if err != nil { rend.writeError(w, r, &htmlTemplateData{err, nil, claims, nil}) + return err } fm := session.Flashes() err = session.Save(r, w) if err != nil { rend.writeError(w, r, &htmlTemplateData{err, nil, claims, fm}) + return err } err = t.ExecuteTemplate(w, options[0]["tpl_layout"][0], &htmlTemplateData{data, options[0], claims, fm}) if err != nil { rend.writeError(w, r, &htmlTemplateData{err, nil, claims, fm}) + return err } } + return nil } func GetContentFormat(r *http.Request) string {