From bcd4dbe80593d3e934d945ffb1b4651c9be0dd9e Mon Sep 17 00:00:00 2001 From: mytja Date: Thu, 28 Apr 2022 20:32:14 +0200 Subject: [PATCH] Fully implement system settings - Resolves https://github.com/MeetPlan/MeetPlanFrontend/issues/10 --- config.json | 2 +- httphandlers/config.go | 19 +++++++++++++++++++ httphandlers/helpers.go | 6 +++++- httphandlers/interface.go | 1 + httphandlers/meals.go | 37 +++++++++++++++++++++++++++++++++++++ httphandlers/user.go | 27 +++++++++++++++++++++++++-- main.go | 1 + sql/absence.go | 4 ++-- sql/classes.go | 2 +- sql/communication.go | 2 +- sql/config.go | 29 ++++++++++++++++------------- sql/grades.go | 4 ++-- sql/homework.go | 4 ++-- sql/jwt.go | 9 ++++++--- sql/meals.go | 2 +- sql/meeting.go | 8 ++++---- sql/message.go | 4 ++-- sql/selftesting.go | 2 +- sql/student_homework.go | 2 +- sql/subject.go | 4 ++-- 20 files changed, 130 insertions(+), 39 deletions(-) diff --git a/config.json b/config.json index 4778ac6..4e7b7ee 100644 --- a/config.json +++ b/config.json @@ -1 +1 @@ -{"database_name":"sqlite3","database_config":"MeetPlanDB/meetplan.db","debug":true,"host":"127.0.0.1:8000","school_name":"Testna šola","school_address":"Testna ulica 1","school_city":"Ljubljana","school_country":"Slovenija","school_post_code":1000,"parent_view_grades":false,"parent_view_absences":true,"parent_view_homework":true,"parent_view_gradings":true} \ No newline at end of file +{"database_name":"sqlite3","database_config":"MeetPlanDB/meetplan.db","debug":true,"host":"127.0.0.1:8000","school_name":"Testna šola","school_address":"Testna ulica 1","school_city":"Ljubljana","school_country":"Slovenija","school_post_code":1000,"parent_view_grades":false,"parent_view_absences":true,"parent_view_homework":true,"parent_view_gradings":true,"block_registrations":false,"block_meals":false,"school_free_days":["2022-02-02"]} \ No newline at end of file diff --git a/httphandlers/config.go b/httphandlers/config.go index 13f869a..6ba1c3b 100644 --- a/httphandlers/config.go +++ b/httphandlers/config.go @@ -1,6 +1,7 @@ package httphandlers import ( + "encoding/json" "github.com/MeetPlan/MeetPlanBackend/sql" "net/http" "strconv" @@ -59,6 +60,22 @@ func (server *httpImpl) UpdateConfiguration(w http.ResponseWriter, r *http.Reque WriteBadRequest(w) return } + blockRegistrations, err := strconv.ParseBool(r.FormValue("block_registrations")) + if err != nil { + WriteBadRequest(w) + return + } + blockMeals, err := strconv.ParseBool(r.FormValue("block_meals")) + if err != nil { + WriteBadRequest(w) + return + } + // admins, pls no shady business when patching dates, otherwise, system will not work anymore + err = json.Unmarshal([]byte(r.FormValue("school_free_days")), &server.config.SchoolFreeDays) + if err != nil { + WriteBadRequest(w) + return + } server.config.SchoolPostCode = schoolPostCode server.config.SchoolCountry = r.FormValue("school_country") server.config.SchoolAddress = r.FormValue("school_address") @@ -68,6 +85,8 @@ func (server *httpImpl) UpdateConfiguration(w http.ResponseWriter, r *http.Reque server.config.ParentViewAbsences = parentViewAbsences server.config.ParentViewHomework = parentViewHomework server.config.ParentViewGradings = parentViewGradings + server.config.BlockRegistrations = blockRegistrations + server.config.BlockMeals = blockMeals err = sql.SaveConfig(server.config) if err != nil { WriteJSON(w, Response{Data: "Failed to save config", Error: err.Error(), Success: false}, http.StatusInternalServerError) diff --git a/httphandlers/helpers.go b/httphandlers/helpers.go index 7708128..44c36f8 100644 --- a/httphandlers/helpers.go +++ b/httphandlers/helpers.go @@ -28,7 +28,11 @@ func GetAuthorizationJWT(r *http.Request) string { if h == "" { return "" } - return strings.Split(h, " ")[1] + split := strings.Split(h, " ") + if len(split) != 2 { + return "" + } + return split[1] } func WriteBadRequest(w http.ResponseWriter) { diff --git a/httphandlers/interface.go b/httphandlers/interface.go index 5c504af..188fc57 100644 --- a/httphandlers/interface.go +++ b/httphandlers/interface.go @@ -97,6 +97,7 @@ type HTTP interface { DeleteMeal(w http.ResponseWriter, r *http.Request) BlockUnblockOrder(w http.ResponseWriter, r *http.Request) RemoveOrder(w http.ResponseWriter, r *http.Request) + MealsBlocked(w http.ResponseWriter, r *http.Request) // parent.go AssignUserToParent(w http.ResponseWriter, r *http.Request) diff --git a/httphandlers/meals.go b/httphandlers/meals.go index f60ded5..aa239d9 100644 --- a/httphandlers/meals.go +++ b/httphandlers/meals.go @@ -22,6 +22,10 @@ type MealDate struct { } func (server *httpImpl) GetMeals(w http.ResponseWriter, r *http.Request) { + if server.config.BlockMeals { + WriteJSON(w, Response{Data: "Admin has disabled meals", Success: false}, http.StatusForbidden) + return + } jwt, err := sql.CheckJWT(GetAuthorizationJWT(r)) if err != nil { WriteForbiddenJWT(w) @@ -97,6 +101,10 @@ func (server *httpImpl) GetMeals(w http.ResponseWriter, r *http.Request) { } func (server *httpImpl) NewMeal(w http.ResponseWriter, r *http.Request) { + if server.config.BlockMeals { + WriteJSON(w, Response{Data: "Admin has disabled meals", Success: false}, http.StatusForbidden) + return + } jwt, err := sql.CheckJWT(GetAuthorizationJWT(r)) if err != nil { WriteForbiddenJWT(w) @@ -160,6 +168,10 @@ func (server *httpImpl) NewMeal(w http.ResponseWriter, r *http.Request) { } func (server *httpImpl) NewOrder(w http.ResponseWriter, r *http.Request) { + if server.config.BlockMeals { + WriteJSON(w, Response{Data: "Admin has disabled meals", Success: false}, http.StatusForbidden) + return + } jwt, err := sql.CheckJWT(GetAuthorizationJWT(r)) if err != nil { WriteForbiddenJWT(w) @@ -210,6 +222,10 @@ func (server *httpImpl) NewOrder(w http.ResponseWriter, r *http.Request) { } func (server *httpImpl) EditMeal(w http.ResponseWriter, r *http.Request) { + if server.config.BlockMeals { + WriteJSON(w, Response{Data: "Admin has disabled meals", Success: false}, http.StatusForbidden) + return + } jwt, err := sql.CheckJWT(GetAuthorizationJWT(r)) if err != nil { WriteForbiddenJWT(w) @@ -275,6 +291,10 @@ func (server *httpImpl) EditMeal(w http.ResponseWriter, r *http.Request) { } func (server *httpImpl) DeleteMeal(w http.ResponseWriter, r *http.Request) { + if server.config.BlockMeals { + WriteJSON(w, Response{Data: "Admin has disabled meals", Success: false}, http.StatusForbidden) + return + } jwt, err := sql.CheckJWT(GetAuthorizationJWT(r)) if err != nil { WriteForbiddenJWT(w) @@ -303,6 +323,10 @@ func (server *httpImpl) DeleteMeal(w http.ResponseWriter, r *http.Request) { } func (server *httpImpl) BlockUnblockOrder(w http.ResponseWriter, r *http.Request) { + if server.config.BlockMeals { + WriteJSON(w, Response{Data: "Admin has disabled meals", Success: false}, http.StatusForbidden) + return + } jwt, err := sql.CheckJWT(GetAuthorizationJWT(r)) if err != nil { WriteForbiddenJWT(w) @@ -336,6 +360,10 @@ func (server *httpImpl) BlockUnblockOrder(w http.ResponseWriter, r *http.Request } func (server *httpImpl) RemoveOrder(w http.ResponseWriter, r *http.Request) { + if server.config.BlockMeals { + WriteJSON(w, Response{Data: "Admin has disabled meals", Success: false}, http.StatusForbidden) + return + } jwt, err := sql.CheckJWT(GetAuthorizationJWT(r)) if err != nil { WriteForbiddenJWT(w) @@ -376,3 +404,12 @@ func (server *httpImpl) RemoveOrder(w http.ResponseWriter, r *http.Request) { } WriteJSON(w, Response{Success: true, Data: "OK"}, http.StatusOK) } + +func (server *httpImpl) MealsBlocked(w http.ResponseWriter, r *http.Request) { + _, err := sql.CheckJWT(GetAuthorizationJWT(r)) + if err != nil { + WriteForbiddenJWT(w) + return + } + WriteJSON(w, Response{Success: true, Data: server.config.BlockMeals}, http.StatusOK) +} diff --git a/httphandlers/user.go b/httphandlers/user.go index f350891..90e9eaa 100644 --- a/httphandlers/user.go +++ b/httphandlers/user.go @@ -18,6 +18,12 @@ func (server *httpImpl) Login(w http.ResponseWriter, r *http.Request) { pass := r.FormValue("pass") // Check if password is valid user, err := server.db.GetUserByEmail(email) + + if user.Role == "unverified" { + WriteJSON(w, Response{Data: "You are unverified. You cannot login until the school administrator confirms you.", Success: false}, http.StatusForbidden) + return + } + hashCorrect := sql.CheckHash(pass, user.Password) if !hashCorrect { WriteJSON(w, Response{Data: "Hashes don't match...", Success: false}, http.StatusForbidden) @@ -35,6 +41,23 @@ func (server *httpImpl) Login(w http.ResponseWriter, r *http.Request) { } func (server *httpImpl) NewUser(w http.ResponseWriter, r *http.Request) { + if server.config.BlockRegistrations { + j := GetAuthorizationJWT(r) + if j == "" { + WriteForbiddenJWT(w) + return + } + jwt, err := sql.CheckJWT(j) + if err != nil { + WriteForbiddenJWT(w) + return + } + if jwt["role"] == "admin" || jwt["role"] == "principal" || jwt["role"] == "principal assistant" { + } else { + WriteForbiddenJWT(w) + return + } + } email := r.FormValue("email") pass := r.FormValue("pass") name := r.FormValue("name") @@ -64,7 +87,7 @@ func (server *httpImpl) NewUser(w http.ResponseWriter, r *http.Request) { return } - var role = "student" + var role = "unverified" isAdmin := !server.db.CheckIfAdminIsCreated() if isAdmin { @@ -280,7 +303,7 @@ func (server *httpImpl) GetAbsencesUser(w http.ResponseWriter, r *http.Request) absences, err := server.db.GetAbsencesForUser(studentId) if err != nil { if err.Error() == "sql: no rows in result set" { - WriteJSON(w, Response{Data: absenceJson, Error: err.Error(), Success: true}, http.StatusOK) + WriteJSON(w, Response{Data: absenceJson, Error: err.Error(), Success: true}, http.StatusOK) return } WriteJSON(w, Response{Data: "Could not fetch absences", Error: err.Error(), Success: false}, http.StatusInternalServerError) diff --git a/main.go b/main.go index fcc8fbb..f9f52a6 100644 --- a/main.go +++ b/main.go @@ -87,6 +87,7 @@ func main() { r.HandleFunc("/meal/get/{meal_id}", httphandler.EditMeal).Methods("PATCH") r.HandleFunc("/meal/get/{meal_id}", httphandler.DeleteMeal).Methods("DELETE") r.HandleFunc("/meals/new", httphandler.NewMeal).Methods("POST") + r.HandleFunc("/meals/blocked", httphandler.MealsBlocked).Methods("GET") r.HandleFunc("/teachers/get", httphandler.GetTeachers).Methods("GET") r.HandleFunc("/students/get", httphandler.GetStudents).Methods("GET") r.HandleFunc("/user/role/update/{id}", httphandler.ChangeRole).Methods("PATCH") diff --git a/sql/absence.go b/sql/absence.go index f285ddb..9fa3407 100644 --- a/sql/absence.go +++ b/sql/absence.go @@ -33,12 +33,12 @@ func (db *sqlImpl) GetAbsenceForUserMeeting(meeting_id int, user_id int) (absenc } func (db *sqlImpl) GetAbsencesForUser(user_id int) (absence []Absence, err error) { - err = db.db.Select(&absence, "SELECT * FROM absence WHERE user_id=$1", user_id) + err = db.db.Select(&absence, "SELECT * FROM absence WHERE user_id=$1 ORDER BY id ASC", user_id) return absence, err } func (db *sqlImpl) GetAllAbsences(id int) (absences []Absence, err error) { - err = db.db.Select(&absences, "SELECT * FROM absence WHERE user_id=$1", id) + err = db.db.Select(&absences, "SELECT * FROM absence WHERE user_id=$1 ORDER BY id ASC", id) return absences, err } diff --git a/sql/classes.go b/sql/classes.go index c8eb2a5..038843c 100644 --- a/sql/classes.go +++ b/sql/classes.go @@ -50,7 +50,7 @@ func (db *sqlImpl) GetLastClassID() (id int) { } func (db *sqlImpl) GetClasses() (classes []Class, err error) { - err = db.db.Select(&classes, "SELECT * FROM classes") + err = db.db.Select(&classes, "SELECT * FROM classes ORDER BY id ASC") return classes, err } diff --git a/sql/communication.go b/sql/communication.go index 25bd2d3..f18c955 100644 --- a/sql/communication.go +++ b/sql/communication.go @@ -41,7 +41,7 @@ func (db *sqlImpl) GetLastCommunicationID() (id int) { } func (db *sqlImpl) GetCommunications() (communication []Communication, err error) { - err = db.db.Select(&communication, "SELECT * FROM communication") + err = db.db.Select(&communication, "SELECT * FROM communication ORDER BY id ASC") return communication, err } diff --git a/sql/config.go b/sql/config.go index adcecb5..c989c81 100644 --- a/sql/config.go +++ b/sql/config.go @@ -6,19 +6,22 @@ import ( ) type Config struct { - DatabaseName string `json:"database_name"` - DatabaseConfig string `json:"database_config"` - Debug bool `json:"debug"` - Host string `json:"host"` - SchoolName string `json:"school_name"` - SchoolAddress string `json:"school_address"` - SchoolCity string `json:"school_city"` - SchoolCountry string `json:"school_country"` - SchoolPostCode int `json:"school_post_code"` - ParentViewGrades bool `json:"parent_view_grades"` - ParentViewAbsences bool `json:"parent_view_absences"` - ParentViewHomework bool `json:"parent_view_homework"` - ParentViewGradings bool `json:"parent_view_gradings"` + DatabaseName string `json:"database_name"` + DatabaseConfig string `json:"database_config"` + Debug bool `json:"debug"` + Host string `json:"host"` + SchoolName string `json:"school_name"` + SchoolAddress string `json:"school_address"` + SchoolCity string `json:"school_city"` + SchoolCountry string `json:"school_country"` + SchoolPostCode int `json:"school_post_code"` + ParentViewGrades bool `json:"parent_view_grades"` + ParentViewAbsences bool `json:"parent_view_absences"` + ParentViewHomework bool `json:"parent_view_homework"` + ParentViewGradings bool `json:"parent_view_gradings"` + BlockRegistrations bool `json:"block_registrations"` + BlockMeals bool `json:"block_meals"` + SchoolFreeDays []string `json:"school_free_days"` } func GetConfig() (Config, error) { diff --git a/sql/grades.go b/sql/grades.go index 78443ea..fd75e7b 100644 --- a/sql/grades.go +++ b/sql/grades.go @@ -33,7 +33,7 @@ func (db *sqlImpl) GetGrade(id int) (grade Grade, err error) { } func (db *sqlImpl) GetGradesForUser(userId int) (grades []Grade, err error) { - err = db.db.Select(&grades, "SELECT * FROM grades WHERE user_id=$1", userId) + err = db.db.Select(&grades, "SELECT * FROM grades WHERE user_id=$1 ORDER BY id ASC", userId) return grades, err } @@ -43,7 +43,7 @@ func (db *sqlImpl) CheckIfFinal(userId int, subjectId int) (grade Grade, err err } func (db *sqlImpl) GetGradesForUserInSubject(userId int, subjectId int) (grades []Grade, err error) { - err = db.db.Select(&grades, "SELECT * FROM grades WHERE user_id=$1 AND subject_id=$2", userId, subjectId) + err = db.db.Select(&grades, "SELECT * FROM grades WHERE user_id=$1 AND subject_id=$2 ORDER BY id ASC", userId, subjectId) return grades, err } diff --git a/sql/homework.go b/sql/homework.go index 8c6132e..e01ff9c 100644 --- a/sql/homework.go +++ b/sql/homework.go @@ -29,7 +29,7 @@ func (db *sqlImpl) GetHomework(id int) (homework Homework, err error) { } func (db *sqlImpl) GetHomeworkForSubject(id int) (homework []Homework, err error) { - err = db.db.Select(&homework, "SELECT * FROM homework WHERE subject_id=$1", id) + err = db.db.Select(&homework, "SELECT * FROM homework WHERE subject_id=$1 ORDER BY id ASC", id) if homework == nil { homework = make([]Homework, 0) } @@ -37,7 +37,7 @@ func (db *sqlImpl) GetHomeworkForSubject(id int) (homework []Homework, err error } func (db *sqlImpl) GetHomeworkForTeacher(teacherId int) (homework []Homework, err error) { - err = db.db.Select(&homework, "SELECT * FROM homework WHERE teacher_id=$1", teacherId) + err = db.db.Select(&homework, "SELECT * FROM homework WHERE teacher_id=$1 ORDER BY id ASC", teacherId) if homework == nil { homework = make([]Homework, 0) } diff --git a/sql/jwt.go b/sql/jwt.go index 543cd87..5dad698 100644 --- a/sql/jwt.go +++ b/sql/jwt.go @@ -67,10 +67,13 @@ func CheckJWT(tokenString string) (jwt.MapClaims, error) { if token != nil { if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { - if claims["iss"] == JWTIssuer { - return claims, nil + if claims["iss"] != JWTIssuer { + return nil, errors.New("JWT issuer isn't correct") } - return nil, errors.New("JWT issuer isn't correct") + if claims["role"] == "unverified" { + return nil, errors.New("you are an unverified user. You cannot do anything in this system until the server administrator confirms you") + } + return claims, nil } else { return nil, err } diff --git a/sql/meals.go b/sql/meals.go index e74b3ed..ae789f6 100644 --- a/sql/meals.go +++ b/sql/meals.go @@ -47,7 +47,7 @@ func (db *sqlImpl) GetLastMealID() (id int) { } func (db *sqlImpl) GetMeals() (meals []Meal, err error) { - err = db.db.Select(&meals, "SELECT * FROM meals") + err = db.db.Select(&meals, "SELECT * FROM meals ORDER BY id ASC") return meals, err } diff --git a/sql/meeting.go b/sql/meeting.go index 512ff95..a0573ae 100644 --- a/sql/meeting.go +++ b/sql/meeting.go @@ -24,17 +24,17 @@ func (db *sqlImpl) GetMeeting(id int) (meeting Meeting, err error) { } func (db *sqlImpl) GetMeetingsOnSpecificTime(date string, hour int) (meetings []Meeting, err error) { - err = db.db.Select(&meetings, "SELECT * FROM meetings WHERE date=$1 AND hour=$2", date, hour) + err = db.db.Select(&meetings, "SELECT * FROM meetings WHERE date=$1 AND hour=$2 ORDER BY id ASC", date, hour) return meetings, err } func (db *sqlImpl) GetMeetingsOnSpecificDate(date string) (meetings []Meeting, err error) { - err = db.db.Select(&meetings, "SELECT * FROM meetings WHERE date=$1", date) + err = db.db.Select(&meetings, "SELECT * FROM meetings WHERE date=$1 ORDER BY id ASC", date) return meetings, err } func (db *sqlImpl) GetMeetingsForSubject(subjectId int) (meetings []Meeting, err error) { - err = db.db.Select(&meetings, "SELECT * FROM meetings WHERE subject_id=$1", subjectId) + err = db.db.Select(&meetings, "SELECT * FROM meetings WHERE subject_id=$1 ORDER BY id ASC", subjectId) return meetings, err } @@ -76,7 +76,7 @@ func (db *sqlImpl) GetLastMeetingID() (id int) { } func (db *sqlImpl) GetMeetings() (meetings []Meeting, err error) { - err = db.db.Select(&meetings, "SELECT * FROM meetings") + err = db.db.Select(&meetings, "SELECT * FROM meetings ORDER BY id ASC") return meetings, err } diff --git a/sql/message.go b/sql/message.go index 73cd23b..560d446 100644 --- a/sql/message.go +++ b/sql/message.go @@ -48,12 +48,12 @@ func (db *sqlImpl) GetLastMessageID() (id int) { } func (db *sqlImpl) GetAllMessages() (messages []Message, err error) { - err = db.db.Select(&messages, "SELECT * FROM message") + err = db.db.Select(&messages, "SELECT * FROM message ORDER BY id ASC") return messages, err } func (db *sqlImpl) GetAllUnreadMessages(userId int) (messages []Message, err error) { - err = db.db.Select(&messages, "SELECT * FROM message") + err = db.db.Select(&messages, "SELECT * FROM message ORDER BY id ASC") var unread = make([]Message, 0) for i := 0; i < len(messages); i++ { message := messages[i] diff --git a/sql/selftesting.go b/sql/selftesting.go index 6dcb35a..ce5ed7a 100644 --- a/sql/selftesting.go +++ b/sql/selftesting.go @@ -90,7 +90,7 @@ func (db *sqlImpl) GetTestingResult(date string, id int) (Testing, error) { } func (db *sqlImpl) GetAllTestingsForUser(id int) (testing []Testing, err error) { - err = db.db.Select(&testing, "SELECT * FROM testing WHERE user_id=$1", id) + err = db.db.Select(&testing, "SELECT * FROM testing WHERE user_id=$1 ORDER BY id ASC", id) return testing, err } diff --git a/sql/student_homework.go b/sql/student_homework.go index 04f58e6..7e19971 100644 --- a/sql/student_homework.go +++ b/sql/student_homework.go @@ -39,7 +39,7 @@ func (db *sqlImpl) GetStudentHomeworkForUser(homeworkId int, userId int) (homewo } func (db *sqlImpl) GetStudentsHomework(id int) (homework []StudentHomework, err error) { - err = db.db.Select(&homework, "SELECT * FROM student_homework WHERE user_id=$1", id) + err = db.db.Select(&homework, "SELECT * FROM student_homework WHERE user_id=$1 ORDER BY id ASC", id) if homework == nil { homework = make([]StudentHomework, 0) } diff --git a/sql/subject.go b/sql/subject.go index 3abfb3d..4310a7e 100644 --- a/sql/subject.go +++ b/sql/subject.go @@ -40,12 +40,12 @@ func (db *sqlImpl) GetSubject(id int) (subject Subject, err error) { } func (db *sqlImpl) GetAllSubjectsForTeacher(id int) (subject []Subject, err error) { - err = db.db.Select(&subject, "SELECT * FROM subject WHERE teacher_id=$1", id) + err = db.db.Select(&subject, "SELECT * FROM subject WHERE teacher_id=$1 ORDER BY id ASC", id) return subject, err } func (db *sqlImpl) GetAllSubjects() (subject []Subject, err error) { - err = db.db.Select(&subject, "SELECT * FROM subject") + err = db.db.Select(&subject, "SELECT * FROM subject ORDER BY id ASC") return subject, err }