Quick prototyping of user authentication/authorization
This commit is contained in:
parent
945a2a29dd
commit
a33cd9ac2d
9 changed files with 94 additions and 474 deletions
|
@ -298,7 +298,7 @@ func modelHandler(model string, pattern PathPattern) http.Handler {
|
||||||
|
|
||||||
func homeHandler() http.Handler {
|
func homeHandler() http.Handler {
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Redirect(w, r, "/questions?format=html&tpl_layout=base&tpl_content=questions", http.StatusSeeOther)
|
http.Redirect(w, r, "/contests?format=html&tpl_layout=base&tpl_content=contests", http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
return http.HandlerFunc(fn)
|
return http.HandlerFunc(fn)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,463 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/jinzhu/gorm"
|
|
||||||
"github.com/remogatto/prettytest"
|
|
||||||
"gogs.carducci-dante.gov.it/karmen/core/config"
|
|
||||||
"gogs.carducci-dante.gov.it/karmen/core/orm"
|
|
||||||
"gogs.carducci-dante.gov.it/karmen/core/renderer"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
token string
|
|
||||||
)
|
|
||||||
|
|
||||||
// Start of setup
|
|
||||||
|
|
||||||
type testSuite struct {
|
|
||||||
prettytest.Suite
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRunner(t *testing.T) {
|
|
||||||
prettytest.Run(
|
|
||||||
t,
|
|
||||||
new(testSuite),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *testSuite) BeforeAll() {
|
|
||||||
|
|
||||||
var (
|
|
||||||
db *gorm.DB
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
|
|
||||||
// Initialize the ORM
|
|
||||||
|
|
||||||
connected := false
|
|
||||||
for !connected {
|
|
||||||
time.Sleep(10 * time.Second)
|
|
||||||
db, err = orm.New("karmen:karmen@/karmen_test?charset=utf8&parseTime=True&loc=Local")
|
|
||||||
if err != nil {
|
|
||||||
time.Sleep(5 * time.Second)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
connected = true
|
|
||||||
}
|
|
||||||
|
|
||||||
orm.Use(db)
|
|
||||||
orm.AutoMigrate()
|
|
||||||
|
|
||||||
// Initialize the renderers
|
|
||||||
|
|
||||||
htmlRenderer, err := renderer.NewHTMLRenderer("./testdata/templates/")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonRenderer, err := renderer.NewJSONRenderer()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
csvRenderer, err := renderer.NewCSVRenderer()
|
|
||||||
if err != nil {
|
|
||||||
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...)
|
|
||||||
}
|
|
||||||
|
|
||||||
renderer.Render["json"] = func(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) {
|
|
||||||
jsonRenderer.Render(w, r, data, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
renderer.Render["csv"] = func(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) {
|
|
||||||
csvRenderer.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
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", "/get_token", nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
req.SetBasicAuth("admin", "admin")
|
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
tokenHandler().ServeHTTP(rr, req)
|
|
||||||
|
|
||||||
var data struct {
|
|
||||||
Token string
|
|
||||||
UserID string
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(rr.Body.Bytes(), &data); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
token = data.Token
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *testSuite) TestGetTeachersHTML() {
|
|
||||||
req, err := http.NewRequest("GET", "/teachers?format=html&tpl_layout=base&tpl_content=teachers", nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern := PathPattern{
|
|
||||||
"/%s",
|
|
||||||
"/%s?format=html&tpl_layout=base&tpl_content=%s",
|
|
||||||
[]string{"GET"},
|
|
||||||
}
|
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
modelHandler("teachers", pattern).ServeHTTP(rr, req)
|
|
||||||
|
|
||||||
t.Equal(http.StatusOK, rr.Code)
|
|
||||||
|
|
||||||
if !t.Failed() {
|
|
||||||
t.True(strings.Contains(rr.Body.String(), "DELLE ROSE"))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *testSuite) TestGetTeachersJSON() {
|
|
||||||
var (
|
|
||||||
teachers []*orm.Teacher
|
|
||||||
response renderer.JsonResponse
|
|
||||||
)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", "/api/teachers?format=json", nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern := PathPattern{
|
|
||||||
"/api/%s",
|
|
||||||
"/%s/%d?format=json",
|
|
||||||
[]string{"GET"},
|
|
||||||
}
|
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
modelHandler("teachers", pattern).ServeHTTP(rr, req)
|
|
||||||
|
|
||||||
t.Equal(http.StatusOK, rr.Code)
|
|
||||||
|
|
||||||
if !t.Failed() {
|
|
||||||
err := json.Unmarshal(rr.Body.Bytes(), &response)
|
|
||||||
t.Nil(err)
|
|
||||||
if !t.Failed() {
|
|
||||||
err := json.Unmarshal(response.Result, &teachers)
|
|
||||||
t.Nil(err)
|
|
||||||
t.Equal("AGOSTINO", teachers[0].Surname)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *testSuite) TestDeleteActivityJSON() {
|
|
||||||
var response renderer.JsonResponse
|
|
||||||
|
|
||||||
req, err := http.NewRequest("DELETE", fmt.Sprintf("/api/activities/%d/delete?format=json", 1), nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
req.Header.Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
|
|
||||||
pattern := PathPattern{"/api/%s/{id}/delete", "", []string{"DELETE"}}
|
|
||||||
router := mux.NewRouter()
|
|
||||||
router.Handle("/api/activities/{id}/delete", modelHandler("activities", pattern))
|
|
||||||
router.ServeHTTP(rr, req)
|
|
||||||
|
|
||||||
if !t.Failed() {
|
|
||||||
err := json.Unmarshal(rr.Body.Bytes(), &response)
|
|
||||||
t.Nil(err)
|
|
||||||
if !t.Failed() {
|
|
||||||
t.Equal("1", string(response.Result))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Equal(http.StatusOK, rr.Code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *testSuite) TestGetTeacherJSON() {
|
|
||||||
var (
|
|
||||||
teacher *orm.Teacher
|
|
||||||
response renderer.JsonResponse
|
|
||||||
)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", "/api/teachers/9?format=json", nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern := PathPattern{"/api/%s/{id}", "", []string{"GET"}}
|
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
|
|
||||||
router := mux.NewRouter()
|
|
||||||
router.Handle("/api/teachers/{id}", modelHandler("teachers", pattern))
|
|
||||||
router.ServeHTTP(rr, req)
|
|
||||||
|
|
||||||
t.Equal(http.StatusOK, rr.Code)
|
|
||||||
|
|
||||||
if !t.Failed() {
|
|
||||||
err := json.Unmarshal(rr.Body.Bytes(), &response)
|
|
||||||
t.Nil(err)
|
|
||||||
if !t.Failed() {
|
|
||||||
err := json.Unmarshal(response.Result, &teacher)
|
|
||||||
t.Nil(err)
|
|
||||||
t.Equal("FRANCESCHINI", teacher.Surname)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *testSuite) TestGetTeachersCSV() {
|
|
||||||
var response renderer.JsonResponse
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", "/api/teachers?format=csv", nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern := PathPattern{
|
|
||||||
"/api/%s",
|
|
||||||
"/%s/%d?format=csv",
|
|
||||||
[]string{"GET"},
|
|
||||||
}
|
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
modelHandler("teachers", pattern).ServeHTTP(rr, req)
|
|
||||||
|
|
||||||
t.Equal(http.StatusOK, rr.Code)
|
|
||||||
|
|
||||||
if !t.Failed() {
|
|
||||||
err := json.Unmarshal(rr.Body.Bytes(), &response)
|
|
||||||
t.Nil(err)
|
|
||||||
if !t.Failed() {
|
|
||||||
t.True(strings.Contains(string(response.Result), "AGOSTINO"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *testSuite) TestGetErrorJSON() {
|
|
||||||
var (
|
|
||||||
response renderer.JsonResponse
|
|
||||||
)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", "/api/teacher/100?format=json", nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern := PathPattern{"/api/%s/{id}", "/%s?format=json", []string{"GET"}}
|
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
modelHandler("teachers", pattern).ServeHTTP(rr, req)
|
|
||||||
|
|
||||||
err = json.Unmarshal(rr.Body.Bytes(), &response)
|
|
||||||
t.Nil(err)
|
|
||||||
t.Equal("record not found", string(response.Error))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *testSuite) TestPostErrorJSON() {
|
|
||||||
var (
|
|
||||||
response renderer.JsonResponse
|
|
||||||
)
|
|
||||||
|
|
||||||
teacher := getTeacherJSON(1)
|
|
||||||
teacher.Name = "Mario"
|
|
||||||
teacher.Surname = "ROSSI"
|
|
||||||
|
|
||||||
data, err := json.Marshal(teacher)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", "/api/teachers/0/update?format=json", bytes.NewBuffer(data))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
req.Header.Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
|
|
||||||
pattern := PathPattern{"/api/%s/{id}/update", "", []string{"POST"}}
|
|
||||||
router := mux.NewRouter()
|
|
||||||
router.Handle("/api/teachers/{id}/update", modelHandler("teachers", pattern))
|
|
||||||
router.ServeHTTP(rr, req)
|
|
||||||
|
|
||||||
t.Equal(http.StatusInternalServerError, rr.Code)
|
|
||||||
|
|
||||||
err = json.Unmarshal(rr.Body.Bytes(), &response)
|
|
||||||
t.Nil(err)
|
|
||||||
t.Equal("record not found", string(response.Error))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *testSuite) TestAddTeacherJSON() {
|
|
||||||
var (
|
|
||||||
response renderer.JsonResponse
|
|
||||||
id uint
|
|
||||||
)
|
|
||||||
|
|
||||||
teacher := new(orm.Teacher)
|
|
||||||
teacher.Name = "Mario"
|
|
||||||
teacher.Surname = "ROSSI"
|
|
||||||
|
|
||||||
data, err := json.Marshal(teacher)
|
|
||||||
t.Nil(err)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", "/api/teachers/add", bytes.NewBuffer(data))
|
|
||||||
req.Header.Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern := PathPattern{
|
|
||||||
"/api/%s/add",
|
|
||||||
"",
|
|
||||||
[]string{"POST"},
|
|
||||||
}
|
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
modelHandler("teachers", pattern).ServeHTTP(rr, req)
|
|
||||||
|
|
||||||
t.Equal(http.StatusOK, rr.Code)
|
|
||||||
|
|
||||||
if !t.Failed() {
|
|
||||||
err := json.Unmarshal(rr.Body.Bytes(), &response)
|
|
||||||
t.Nil(err)
|
|
||||||
if !t.Failed() {
|
|
||||||
err := json.Unmarshal(response.Result, &id)
|
|
||||||
t.Nil(err)
|
|
||||||
t.Equal(uint(10), id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *testSuite) TestUpdateTeacherJSON() {
|
|
||||||
teacher := getTeacherJSON(1)
|
|
||||||
teacher.Name = "Mario"
|
|
||||||
teacher.Surname = "ROSSI"
|
|
||||||
|
|
||||||
data, err := json.Marshal(teacher)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", fmt.Sprintf("/api/teachers/%d/update?format=json", teacher.ID), bytes.NewBuffer(data))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
req.Header.Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
|
|
||||||
pattern := PathPattern{"/api/%s/{id}/update", "", []string{"POST"}}
|
|
||||||
router := mux.NewRouter()
|
|
||||||
router.Handle("/api/teachers/{id}/update", modelHandler("teachers", pattern))
|
|
||||||
router.ServeHTTP(rr, req)
|
|
||||||
|
|
||||||
t.Equal(http.StatusOK, rr.Code)
|
|
||||||
|
|
||||||
if !t.Failed() {
|
|
||||||
dbTeacher := getTeacherJSON(1)
|
|
||||||
t.Equal("ROSSI", dbTeacher.Surname)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTeacherJSON(id uint) *orm.Teacher {
|
|
||||||
var (
|
|
||||||
teacher *orm.Teacher
|
|
||||||
response renderer.JsonResponse
|
|
||||||
)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", fmt.Sprintf("/api/teachers/%d?format=json", id), nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern := PathPattern{"/api/%s/{id}", "", []string{"GET"}}
|
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
|
|
||||||
router := mux.NewRouter()
|
|
||||||
router.Handle("/api/teachers/{id}", modelHandler("teachers", pattern))
|
|
||||||
router.ServeHTTP(rr, req)
|
|
||||||
|
|
||||||
err = json.Unmarshal(rr.Body.Bytes(), &response)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(response.Result, &teacher)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return teacher
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *testSuite) TestGetDepartmentJSON() {
|
|
||||||
var (
|
|
||||||
department *orm.Department
|
|
||||||
response renderer.JsonResponse
|
|
||||||
)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", "/api/departments/1?format=json", nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern := PathPattern{"/api/%s/{id}", "", []string{"GET"}}
|
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
|
|
||||||
router := mux.NewRouter()
|
|
||||||
router.Handle("/api/departments/{id}", modelHandler("departments", pattern))
|
|
||||||
router.ServeHTTP(rr, req)
|
|
||||||
|
|
||||||
t.Equal(http.StatusOK, rr.Code)
|
|
||||||
|
|
||||||
if !t.Failed() {
|
|
||||||
err := json.Unmarshal(rr.Body.Bytes(), &response)
|
|
||||||
t.Nil(err)
|
|
||||||
if !t.Failed() {
|
|
||||||
err := json.Unmarshal(response.Result, &department)
|
|
||||||
t.Nil(err)
|
|
||||||
t.Equal("LINGUE STRANIERE", department.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.andreafazzi.eu/andrea/oef/config"
|
"git.andreafazzi.eu/andrea/oef/config"
|
||||||
|
"git.andreafazzi.eu/andrea/oef/orm"
|
||||||
"git.andreafazzi.eu/andrea/oef/renderer"
|
"git.andreafazzi.eu/andrea/oef/renderer"
|
||||||
jwt "github.com/dgrijalva/jwt-go"
|
jwt "github.com/dgrijalva/jwt-go"
|
||||||
)
|
)
|
||||||
|
@ -54,11 +55,20 @@ func loginHandler() http.Handler {
|
||||||
return http.HandlerFunc(fn)
|
return http.HandlerFunc(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: This is an hack for fast prototyping: users should have
|
||||||
|
// their own table on DB.
|
||||||
func checkCredential(username string, password string) (*User, error) {
|
func checkCredential(username string, password string) (*User, error) {
|
||||||
|
var participant orm.Participant
|
||||||
|
|
||||||
if username == config.Config.Admin.Username && password == config.Config.Admin.Password {
|
if username == config.Config.Admin.Username && password == config.Config.Admin.Password {
|
||||||
return &User{username, true}, nil
|
return &User{username, true}, nil
|
||||||
}
|
}
|
||||||
return nil, errors.New("Authentication failed!")
|
|
||||||
|
if err := orm.DB().Where("username = ? AND password = ?", username, password).First(&participant).Error; err != nil {
|
||||||
|
return nil, errors.New("Authentication failed!")
|
||||||
|
} else {
|
||||||
|
return &User{username, false}, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getToken(username string, password string) ([]byte, error) {
|
func getToken(username string, password string) ([]byte, error) {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.andreafazzi.eu/andrea/oef/renderer"
|
"git.andreafazzi.eu/andrea/oef/renderer"
|
||||||
|
"github.com/dgrijalva/jwt-go"
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -82,10 +83,28 @@ func (c *Contest) Read(args map[string]string, r *http.Request) (interface{}, er
|
||||||
|
|
||||||
func (c *Contest) ReadAll(args map[string]string, r *http.Request) (interface{}, error) {
|
func (c *Contest) ReadAll(args map[string]string, r *http.Request) (interface{}, error) {
|
||||||
var contests []*Contest
|
var contests []*Contest
|
||||||
if err := DB().Order("created_at").Find(&contests).Error; err != nil {
|
|
||||||
|
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
||||||
|
|
||||||
|
if claims["admin"].(bool) {
|
||||||
|
if err := DB().Order("created_at").Find(&contests).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return contests, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
participant := &Participant{}
|
||||||
|
|
||||||
|
if err := DB().Where("username = ?", claims["name"].(string)).First(&participant).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return contests, nil
|
|
||||||
|
if err := DB().Debug().Order("created_at").Find(&participant.Contests).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return participant.Contests, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Contest) Update(args map[string]string, r *http.Request) (interface{}, error) {
|
func (c *Contest) Update(args map[string]string, r *http.Request) (interface{}, error) {
|
||||||
|
|
|
@ -2,11 +2,13 @@ package orm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.andreafazzi.eu/andrea/oef/renderer"
|
"git.andreafazzi.eu/andrea/oef/renderer"
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
|
"github.com/sethvargo/go-password/password"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Participant struct {
|
type Participant struct {
|
||||||
|
@ -25,12 +27,45 @@ type Participant struct {
|
||||||
AllContests []*Contest `gorm:"-"`
|
AllContests []*Contest `gorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (model *Participant) sanitize(s string) string {
|
||||||
|
lower := strings.ToLower(s)
|
||||||
|
r := strings.NewReplacer("'", "", "-", "", " ", "", "ò", "o", "ì", "i")
|
||||||
|
return r.Replace(lower)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (model *Participant) genUsername() error {
|
||||||
|
model.Username = strings.Join([]string{model.sanitize(model.Firstname), model.sanitize(model.Lastname)}, ".")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (model *Participant) genPassword() error {
|
||||||
|
password, err := password.Generate(8, 2, 0, false, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
model.Password = password
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (model *Participant) GetID() uint { return model.ID }
|
func (model *Participant) GetID() uint { return model.ID }
|
||||||
|
|
||||||
func (model *Participant) String() string {
|
func (model *Participant) String() string {
|
||||||
return fmt.Sprintf("%s %s", strings.ToUpper(model.Lastname), strings.Title(strings.ToLower(model.Firstname)))
|
return fmt.Sprintf("%s %s", strings.ToUpper(model.Lastname), strings.Title(strings.ToLower(model.Firstname)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (model *Participant) BeforeSave(tx *gorm.DB) error {
|
||||||
|
if err := model.genUsername(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if model.Password == "" {
|
||||||
|
if err := model.genPassword(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (model *Participant) Create(args map[string]string, r *http.Request) (interface{}, error) {
|
func (model *Participant) Create(args map[string]string, r *http.Request) (interface{}, error) {
|
||||||
if r.Method == "GET" {
|
if r.Method == "GET" {
|
||||||
participant := new(Participant)
|
participant := new(Participant)
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
jwt "github.com/dgrijalva/jwt-go"
|
||||||
"github.com/jinzhu/inflection"
|
"github.com/jinzhu/inflection"
|
||||||
yml "gopkg.in/yaml.v2"
|
yml "gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
@ -46,9 +47,19 @@ var (
|
||||||
"pluralize": pluralize,
|
"pluralize": pluralize,
|
||||||
"lower": lower,
|
"lower": lower,
|
||||||
"trim": trim,
|
"trim": trim,
|
||||||
|
"username": username,
|
||||||
|
"isAdmin": isAdmin,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func username(claims jwt.MapClaims) string {
|
||||||
|
return claims["name"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAdmin(claims jwt.MapClaims) bool {
|
||||||
|
return claims["admin"].(bool)
|
||||||
|
}
|
||||||
|
|
||||||
func trim(text string) string {
|
func trim(text string) string {
|
||||||
if len(text) > MaxTextLength {
|
if len(text) > MaxTextLength {
|
||||||
return text[0:MaxTextLength] + "…"
|
return text[0:MaxTextLength] + "…"
|
||||||
|
|
|
@ -35,6 +35,7 @@ type PDFRenderer struct{}
|
||||||
type htmlTemplateData struct {
|
type htmlTemplateData struct {
|
||||||
Data interface{}
|
Data interface{}
|
||||||
Options url.Values
|
Options url.Values
|
||||||
|
Claims jwt.MapClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
type JsonResponse struct {
|
type JsonResponse struct {
|
||||||
|
@ -239,22 +240,24 @@ 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, data interface{}, options ...url.Values) {
|
||||||
if data != nil && isErrorType(data) {
|
if data != nil && isErrorType(data) {
|
||||||
rend.writeError(w, r, &htmlTemplateData{data.(error), nil})
|
rend.writeError(w, r, &htmlTemplateData{data.(error), nil, nil})
|
||||||
} else {
|
} else {
|
||||||
t, ok := rend.templates[options[0]["tpl_content"][0]]
|
t, ok := rend.templates[options[0]["tpl_content"][0]]
|
||||||
if !ok {
|
if !ok {
|
||||||
err := fmt.Errorf("Template %s not found", options[0]["tpl_content"][0])
|
err := fmt.Errorf("Template %s not found", options[0]["tpl_content"][0])
|
||||||
rend.writeError(w, r, &htmlTemplateData{err, nil})
|
rend.writeError(w, r, &htmlTemplateData{err, nil, nil})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var claims jwt.MapClaims
|
||||||
|
|
||||||
if r.Context().Value("user") != nil {
|
if r.Context().Value("user") != nil {
|
||||||
log.Println("Current user is", r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)["name"])
|
claims = r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
err := t.ExecuteTemplate(w, options[0]["tpl_layout"][0], &htmlTemplateData{data, options[0]})
|
err := t.ExecuteTemplate(w, options[0]["tpl_layout"][0], &htmlTemplateData{data, options[0], claims})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rend.writeError(w, r, &htmlTemplateData{err, nil})
|
rend.writeError(w, r, &htmlTemplateData{err, nil, nil})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,13 +23,15 @@
|
||||||
|
|
||||||
<ul class="navbar-nav mr-auto">
|
<ul class="navbar-nav mr-auto">
|
||||||
<a class="nav-item nav-link {{.Options|active "Contest"}}" href="{{all "Contest"}}">Gare</a>
|
<a class="nav-item nav-link {{.Options|active "Contest"}}" href="{{all "Contest"}}">Gare</a>
|
||||||
|
{{if (.Claims|isAdmin)}}
|
||||||
<a class="nav-item nav-link {{.Options|active "Question"}}" href="{{all "Question"}}">Domande</a>
|
<a class="nav-item nav-link {{.Options|active "Question"}}" href="{{all "Question"}}">Domande</a>
|
||||||
<a class="nav-item nav-link {{.Options|active "Answer"}}" href="{{all "Answer"}}">Risposte</a>
|
<a class="nav-item nav-link {{.Options|active "Answer"}}" href="{{all "Answer"}}">Risposte</a>
|
||||||
<a class="nav-item nav-link {{.Options|active "Participant"}}" href="{{all "Participant"}}">Partecipanti</a>
|
<a class="nav-item nav-link {{.Options|active "Participant"}}" href="{{all "Participant"}}">Partecipanti</a>
|
||||||
|
{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
<li><a class="nav-link" href="/logout">Esci</a></li>
|
<li><a class="nav-link" href="/logout">Disconnetti {{.Claims|username}}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div><!--/.nav-collapse -->
|
</div><!--/.nav-collapse -->
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
|
|
||||||
<h2 class="karmen-relation-header">Informazioni generali</h2>
|
<h2 class="karmen-relation-header">Informazioni generali</h2>
|
||||||
<p>
|
<p>
|
||||||
Questa scheda contiene la informazioni relative al partecipante <strong>{{.Data|string}}</strong>.
|
Il nome utente del partecipante è <strong>{{.Data.Username}}</strong>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
La sua password è <strong>{{.Data.Password}}</strong>
|
||||||
</p>
|
</p>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
|
Loading…
Reference in a new issue