Working on participant subscription workflow of school user
This commit is contained in:
parent
4b752f2e50
commit
8f02b2eb5f
12 changed files with 177 additions and 25 deletions
|
@ -1,5 +1,12 @@
|
|||
package errors
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
var RecordExists = errors.New("Record already exists!")
|
||||
"git.andreafazzi.eu/andrea/oef/i18n"
|
||||
)
|
||||
|
||||
var (
|
||||
RecordExists = errors.New("Record already exists!")
|
||||
NotAuthorized = errors.New(i18n.Authorization["notAuthorized"]["it"])
|
||||
)
|
||||
|
|
|
@ -21,7 +21,7 @@ var (
|
|||
},
|
||||
|
||||
"school": map[string][]int{
|
||||
"Participant": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
"Participant": []int{PermissionCreate, PermissionRead, PermissionUpdate, PermissionDelete},
|
||||
"School": []int{PermissionRead, PermissionUpdate},
|
||||
},
|
||||
|
||||
|
|
|
@ -17,4 +17,9 @@ var (
|
|||
"it": "il %02d/%02d/%d alle ore %02d:%02d",
|
||||
},
|
||||
}
|
||||
Authorization = map[string]map[string]string{
|
||||
"notAuthorized": map[string]string{
|
||||
"it": "Non si è autorizzati ad accedere a questa pagina",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
|
|
@ -2,11 +2,13 @@ package orm
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"git.andreafazzi.eu/andrea/oef/config"
|
||||
"git.andreafazzi.eu/andrea/oef/errors"
|
||||
"git.andreafazzi.eu/andrea/oef/i18n"
|
||||
"git.andreafazzi.eu/andrea/oef/renderer"
|
||||
"github.com/jinzhu/gorm"
|
||||
|
@ -122,8 +124,19 @@ func (model *Participant) Create(args map[string]string, w http.ResponseWriter,
|
|||
if err := DB().Find(&participant.AllContests).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := DB().Find(&participant.AllSchools).Error; err != nil {
|
||||
return nil, err
|
||||
if isSchool(r) {
|
||||
schoolID, err := strconv.Atoi(getUserIDFromToken(r))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := DB().Find(&participant.AllSchools, schoolID).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
} else {
|
||||
if err := DB().Find(&participant.AllSchools).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return participant, nil
|
||||
} else {
|
||||
|
@ -161,6 +174,18 @@ func (model *Participant) Read(args map[string]string, w http.ResponseWriter, r
|
|||
|
||||
id := args["id"]
|
||||
|
||||
// School user can access to its participants only!
|
||||
if isSchool(r) {
|
||||
if err := DB().Preload("School").First(&participant, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if strconv.Itoa(int(participant.SchoolID)) != getUserIDFromToken(r) {
|
||||
setFlashMessage(w, r, "notAuthorized")
|
||||
return nil, errors.NotAuthorized
|
||||
}
|
||||
}
|
||||
|
||||
if err := DB().Preload("User").Preload("School").Preload("Responses").Preload("Contests").First(&participant, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -228,7 +253,7 @@ func (model *Participant) Update(args map[string]string, w http.ResponseWriter,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
participant.(*School).UserModifierUpdate = NewUserModifierUpdate(r)
|
||||
participant.(*Participant).UserModifierUpdate = NewUserModifierUpdate(r)
|
||||
|
||||
_, err = SaveParticipant(participant)
|
||||
if err != nil {
|
||||
|
@ -271,7 +296,7 @@ func CreateParticipant(participant *Participant) (*Participant, error) {
|
|||
func SaveParticipant(participant interface{}) (interface{}, error) {
|
||||
participant.(*Participant).FiscalCode = strings.ToUpper(participant.(*Participant).FiscalCode)
|
||||
|
||||
if err := DB(). /*.Omit("Something")*/ Save(participant).Error; err != nil {
|
||||
if err := DB().Omit("School").Save(participant).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return participant, nil
|
||||
|
|
38
orm/role.go
Normal file
38
orm/role.go
Normal file
|
@ -0,0 +1,38 @@
|
|||
package orm
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
)
|
||||
|
||||
func getClaims(r *http.Request) jwt.MapClaims {
|
||||
return r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
||||
}
|
||||
|
||||
func isRole(role string, r *http.Request) bool {
|
||||
if r.Context().Value("user") != nil {
|
||||
return getClaims(r)["role"].(string) == role
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isAdministrator(r *http.Request) bool {
|
||||
return isRole("administrator", r)
|
||||
}
|
||||
|
||||
func isParticipant(r *http.Request) bool {
|
||||
return isRole("participant", r)
|
||||
}
|
||||
|
||||
func isSchool(r *http.Request) bool {
|
||||
return isRole("school", r)
|
||||
}
|
||||
|
||||
func isSubscriber(r *http.Request) bool {
|
||||
return isRole("subscriber", r)
|
||||
}
|
||||
|
||||
func getUserIDFromToken(r *http.Request) string {
|
||||
return getClaims(r)["user_id"].(string)
|
||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"git.andreafazzi.eu/andrea/oef/errors"
|
||||
"git.andreafazzi.eu/andrea/oef/mail"
|
||||
"git.andreafazzi.eu/andrea/oef/renderer"
|
||||
"github.com/jinzhu/gorm"
|
||||
|
@ -69,6 +70,10 @@ func (model *School) BeforeSave(tx *gorm.DB) error {
|
|||
return err
|
||||
}
|
||||
model.UserID = user.ID
|
||||
|
||||
// School code is always uppercase
|
||||
model.Code = strings.ToUpper(model.Code)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -134,6 +139,11 @@ func (model *School) Read(args map[string]string, w http.ResponseWriter, r *http
|
|||
|
||||
id := args["id"]
|
||||
|
||||
if isSchool(r) && id != getUserIDFromToken(r) {
|
||||
setFlashMessage(w, r, "notAuthorized")
|
||||
return nil, errors.NotAuthorized
|
||||
}
|
||||
|
||||
if err := DB().Preload("User").Preload("Participants").First(&school, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -222,7 +232,7 @@ func CreateSchool(school *School) (*School, error) {
|
|||
}
|
||||
|
||||
func SaveSchool(school interface{}) (interface{}, error) {
|
||||
school.(*School).Code = strings.ToUpper(school.(*School).Code)
|
||||
// school.(*School).Code = strings.ToUpper(school.(*School).Code)
|
||||
if err := DB(). /*.Omit("Something")*/ Save(school).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ var (
|
|||
"isAdmin": isAdmin,
|
||||
"isParticipant": isParticipant,
|
||||
"isSubscriber": isSubscriber,
|
||||
"isSchool": isSchool,
|
||||
"attr": attr,
|
||||
}
|
||||
)
|
||||
|
@ -70,6 +71,10 @@ func isParticipant(claims jwt.MapClaims) bool {
|
|||
return claims["role"].(string) == "participant"
|
||||
}
|
||||
|
||||
func isSchool(claims jwt.MapClaims) bool {
|
||||
return claims["role"].(string) == "school"
|
||||
}
|
||||
|
||||
func isSubscriber(claims jwt.MapClaims) bool {
|
||||
return claims["role"].(string) == "subscriber"
|
||||
}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
{{define "base"}}
|
||||
|
||||
{{$isAdmin := .Claims|isAdmin}}
|
||||
{{$isSubscriber := .Claims|isSubscriber}}
|
||||
{{$isSchool := .Claims|isSchool}}
|
||||
{{$isParticipant := .Claims|isParticipant}}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<head>
|
||||
|
@ -12,7 +18,14 @@
|
|||
<body>
|
||||
|
||||
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-primary">
|
||||
<a class="navbar-brand" href="{{all "Contest"}}">
|
||||
|
||||
{{$homeURL := ""}}
|
||||
{{if $isAdmin}}{{$homeURL = all "Contest"}}{{end}}
|
||||
{{if $isSubscriber}}{{$homeURL = "#"}}{{end}}
|
||||
{{if $isParticipant}}{{$homeURL = "#"}}{{end}}
|
||||
{{if $isSchool}}{{$homeURL = "#"}}{{end}}
|
||||
|
||||
<a class="navbar-brand" href="{{$homeURL}}">
|
||||
<span class="fa fa-landmark"></span>
|
||||
OEF 2020
|
||||
</a>
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
<div class="col-md-4">
|
||||
<div class="btn-group float-right" role="group">
|
||||
{{template "update_button" dict "modelPath" .updatePath}}
|
||||
{{if .deletePath}}
|
||||
{{template "delete_button" dict "modelPath" .deletePath}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,18 @@
|
|||
{{ define "content" }}
|
||||
|
||||
{{$isAdmin := .Claims|isAdmin}}
|
||||
{{$isSchool := .Claims|isSchool}}
|
||||
|
||||
<div class="container">
|
||||
|
||||
{{if $isAdmin}}
|
||||
{{template "breadcrumb" toSlice "Partecipanti" (all "Participant") (.Data|string) "current"}}
|
||||
{{end}}
|
||||
|
||||
{{if $isSchool}}
|
||||
{{template "breadcrumb" toSlice (.Data.School|string) (.Data.SchoolID|show "School") (.Data|string) "current"}}
|
||||
{{end}}
|
||||
|
||||
{{template "show_header" dict "title" (.Data|string) "updatePath" (.Data.ID|update "Participant") "deletePath" (.Data.ID|delete "Participant")}}
|
||||
|
||||
<h2 class="karmen-relation-header">Informazioni generali</h2>
|
||||
|
@ -24,7 +34,6 @@
|
|||
<dd class="col-sm-9">{{.Data.UpdaterIP}}</dd>
|
||||
{{end}}
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
<div class="row">
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
{{ define "content" }}
|
||||
<div class="container">
|
||||
|
||||
{{$isAdmin := .Claims|isAdmin}}
|
||||
{{$isSubscriber := .Claims|isSubscriber}}
|
||||
{{$isSchool := .Claims|isSchool}}
|
||||
|
||||
{{$update := .Options.Get "update"}}
|
||||
|
||||
{{if not $isSubscriber}}
|
||||
|
||||
{{if $update}}
|
||||
{{if $isSchool}}
|
||||
{{template "breadcrumb" toSlice (.Data|string) (.Data.ID|show "School") "Aggiorna" "current"}}
|
||||
{{else}}
|
||||
{{template "breadcrumb" toSlice "Scuole" (all "School") (.Data|string) (.Data.ID|show "School") "Aggiorna" "current"}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{template "breadcrumb" toSlice "Scuole" (all "School") "Aggiungi" "current"}}
|
||||
{{end}}
|
||||
|
@ -31,7 +37,9 @@
|
|||
{{$options := ` { name: "Name",id: "school_name",label: "Denominazione dell'istituto",placeholder: "Inserire la denominazione",type: "text",required: "true"} `}}
|
||||
{{template "input" dict "options" ($options|yaml) "value" (.Data|field "Name") "update" $update}}
|
||||
|
||||
{{$options := `
|
||||
{{$codeOptions := ""}}
|
||||
{{if or $isAdmin $isSubscriber}}
|
||||
{{$codeOptions = `
|
||||
name: "Code"
|
||||
id: "school_code"
|
||||
label: "Codice meccanografico"
|
||||
|
@ -41,7 +49,20 @@
|
|||
otherAttrs: "maxlength=10 minlength=10"
|
||||
required: "true"
|
||||
`}}
|
||||
{{template "input" dict "options" ($options|yaml) "value" (.Data|field "Code") "update" $update}}
|
||||
{{end}}
|
||||
|
||||
{{if $isSchool}}
|
||||
{{$codeOptions = `
|
||||
name: "Code"
|
||||
id: "school_code"
|
||||
label: "Codice meccanografico"
|
||||
type: "text"
|
||||
inputClass: "form-control-plaintext"
|
||||
otherAttrs: "readonly"
|
||||
`}}
|
||||
{{end}}
|
||||
|
||||
{{template "input" dict "options" ($codeOptions|yaml) "value" (.Data|field "Code") "update" $update}}
|
||||
|
||||
{{$options := ` { name: "Email",id: "school_email",label: "Indirizzo email",placeholder: "Inserire l'indirizzo di posta istituzionale",type: "email",required: "true"} `}}
|
||||
{{template "input" dict "options" ($options|yaml) "value" (.Data|field "Email") "update" $update}}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
{{ define "content" }}
|
||||
|
||||
{{$isAdmin := .Claims|isAdmin}}
|
||||
{{$isSchool := .Claims|isSchool}}
|
||||
{{$isSubscriber := .Claims|isSubscriber}}
|
||||
|
||||
<div class="container">
|
||||
{{if .Claims|isSubscriber}}
|
||||
{{if $isSubscriber}}
|
||||
{{if .FlashMessages}}
|
||||
<p>Si è verificato un errore. Clicca <a href="/logout">qui</a> per uscire da questa sessione.</p>
|
||||
{{else}}
|
||||
|
@ -20,8 +24,16 @@
|
|||
</p>
|
||||
{{end}}
|
||||
{{else}}
|
||||
|
||||
{{$deletePath := ""}}
|
||||
{{if $isAdmin}}
|
||||
{{$deletePath = (.Data.ID|delete "School")}}
|
||||
{{end}}
|
||||
|
||||
{{if $isAdmin}}
|
||||
{{template "breadcrumb" toSlice "Scuole" (all "School") (.Data|string|trim) "current"}}
|
||||
{{template "show_header" dict "title" (.Data|string|trim) "updatePath" (.Data.ID|update "School") "deletePath" (.Data.ID|delete "School")}}
|
||||
{{end}}
|
||||
{{template "show_header" dict "title" (.Data|string|trim) "updatePath" (.Data.ID|update "School") "deletePath" $deletePath}}
|
||||
|
||||
<h2 class="karmen-relation-header">Informazioni sulla scuola</h2>
|
||||
<dl class="row">
|
||||
|
@ -41,33 +53,38 @@
|
|||
<dd class="col-sm-9">{{.Data.User.Password}}</dd>
|
||||
{{if $creatorUser:=.Data.CreatedBy}}
|
||||
<dt class="col-sm-3">Creato da</dt>
|
||||
<dd class="col-sm-9">{{$creatorUser.Username}}[{{$creatorUser.Role}}] {{$.Data.CreatedAt|prettyDateTime}}</dd>
|
||||
<dt class="col-sm-3">IP di chi ha creato la scuola</dt>
|
||||
<dd class="col-sm-9">{{.Data.CreatorIP}}</dd>
|
||||
<dd class="col-sm-9">{{$creatorUser.Username}}[{{$creatorUser.Role}}] {{$.Data.CreatedAt|prettyDateTime}} da {{.Data.CreatorIP}}</dd>
|
||||
{{end}}
|
||||
{{if $updaterUser:=.Data.UpdatedBy}}
|
||||
<dt class="col-sm-3">Modificato da</dt>
|
||||
<dd class="col-sm-9">{{$updaterUser.Username}}[{{$updaterUser.Role}}] {{$.Data.UpdatedAt|prettyDateTime}}</dd>
|
||||
<dt class="col-sm-3">IP di chi ha modificato la scuola</dt>
|
||||
<dd class="col-sm-9">{{.Data.UpdaterIP}}</dd>
|
||||
<dd class="col-sm-9">{{$updaterUser.Username}}[{{$updaterUser.Role}}] {{$.Data.UpdatedAt|prettyDateTime}} da {{.Data.UpdaterIP}}</dd>
|
||||
{{end}}
|
||||
|
||||
</dl>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
{{$options := `
|
||||
title: "Partecipanti"
|
||||
model: "Participant"
|
||||
icon: "fa fa-user"
|
||||
`}}
|
||||
|
||||
{{$noElements := "La scuola non ha iscritto alcun partecipante."}}
|
||||
{{$noElements := (printf "La scuola non ha iscritto alcun partecipante. Clicca %s per iscrivere il primo partecipante." ((create "Participant")|anchor "qui")|html)}}
|
||||
{{template "relation_list" dict "options" ($options|yaml) "data" .Data.Participants "noElements" $noElements}}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if eq (len .Data.Participants) 1}}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<p class="mt-4">
|
||||
{{(printf "Clicca %s per iscrivere il secondo partecipante." ((create "Participant")|anchor "qui")|html)}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Reference in a new issue