Completed renderer, orm and mail sender refactoring

This commit is contained in:
Andrea Fazzi 2020-01-15 13:40:35 +01:00
parent 3bb8dde670
commit 82de4b68fb
13 changed files with 203 additions and 175 deletions

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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
}

View file

@ -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

View file

@ -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}

26
main.go
View file

@ -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)
}

View file

@ -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 {

View file

@ -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

View file

@ -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 {

View file

@ -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 {

View file

@ -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

View file

@ -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 {