Verbessere Logging und Fehlerbehandlung

This commit is contained in:
Gonne 2022-09-21 22:24:08 +02:00
parent c737818ce4
commit 6e97d867de
14 changed files with 223 additions and 88 deletions

View file

@ -51,12 +51,14 @@ type Config struct {
func ReadConfigFile(filename string, conf *Config) error { func ReadConfigFile(filename string, conf *Config) error {
configData, err := ioutil.ReadFile(filename) configData, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
log.Printf("Error reading config file: %s", err.Error()) err = fmt.Errorf("Error reading config file: %w", err)
log.Println(err.Error())
return err return err
} }
err = json.Unmarshal(configData, conf) err = json.Unmarshal(configData, conf)
if err != nil { if err != nil {
log.Printf("Error parsing config file as json: %s", err.Error()) err = fmt.Errorf("Error parsing config file as json: %w", err)
log.Println(err.Error())
return err return err
} }
return validateConfig(conf) return validateConfig(conf)

View file

@ -149,12 +149,24 @@ func (b *BaseHandler) AddOfficeHourHandler(w http.ResponseWriter, req *http.Requ
id, err := b.officeHourRepo.Add(officeHour) id, err := b.officeHourRepo.Add(officeHour)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
Templates.ExecuteTemplate(w, "addFailure.html", err) templateError := Templates.ExecuteTemplate(w, "addFailure.html", err)
if templateError != nil {
log.Printf("Error executing template addFailure.html: %s", templateError.Error())
}
return return
} }
officeHour, _ = b.officeHourRepo.FindById(id) officeHour, err = b.officeHourRepo.FindById(id)
b.requestRepo.Add(officeHour, models.RequestActivate) if err != nil {
Templates.ExecuteTemplate(w, "addSuccess.html", struct{}{}) log.Printf("Error finding new office hour by id %d: %s", id, err.Error())
}
_, err = b.requestRepo.Add(officeHour, models.RequestActivate)
if err != nil {
log.Printf("Error adding request: %s", err.Error())
}
templateError := Templates.ExecuteTemplate(w, "addSuccess.html", struct{}{})
if templateError != nil {
log.Printf("Error executing template addSuccess.html: %s", templateError.Error())
}
} }
} }
@ -165,10 +177,10 @@ func (b *BaseHandler) writeAddOfficeHourMask(w http.ResponseWriter, req *http.Re
if len(data.Errors) != 0 { if len(data.Errors) != 0 {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
} }
err := Templates.ExecuteTemplate(w, "addMask.html", data) templateError := Templates.ExecuteTemplate(w, "addMask.html", data)
if err != nil { if templateError != nil {
log.Printf("Template addMask.html could not be parsed: %s", err.Error()) log.Printf("Error executing template addMask.html: %s", templateError.Error())
w.Write([]byte(fmt.Sprintf("Template konnte nicht geparst werden : %s", err.Error()))) w.Write([]byte(fmt.Sprintf("Template konnte nicht geparst werden : %s", templateError.Error())))
return return
} }
} }

View file

@ -1,6 +1,7 @@
package controllers package controllers
import ( import (
"log"
"net/http" "net/http"
) )
@ -10,16 +11,24 @@ func (b *BaseHandler) ConfirmRequestHandler(w http.ResponseWriter, req *http.Req
if err != nil { if err != nil {
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
Templates.ExecuteTemplate(w, "requestNotFound.html", struct{}{}) templateError := Templates.ExecuteTemplate(w, "requestNotFound.html", struct{}{})
if templateError != nil {
log.Printf("Error executing template requestNotFound.html: %s", templateError.Error())
}
return return
} }
err = b.requestRepo.Execute(request) err = b.requestRepo.Execute(request)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
Templates.ExecuteTemplate(w, "executeFailure.html", err.Error()) templateError := Templates.ExecuteTemplate(w, "executeFailure.html", err.Error())
if templateError != nil {
log.Printf("Error executing template executeFailure.html: %s", templateError.Error())
}
return return
} }
Templates.ExecuteTemplate(w, "executeSuccess.html", struct{}{}) templateError := Templates.ExecuteTemplate(w, "executeSuccess.html", struct{}{})
if templateError != nil {
log.Printf("Error executing template executeSuccess.html: %s", templateError.Error())
}
} }

View file

@ -2,6 +2,7 @@
package controllers package controllers
import ( import (
"log"
"net/http" "net/http"
"officeHours/models" "officeHours/models"
"strconv" "strconv"
@ -18,7 +19,10 @@ func (b *BaseHandler) DeleteOfficeHourHandler(w http.ResponseWriter, req *http.R
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
} }
_, err = b.requestRepo.Add(officeHour, models.RequestDelete) _, err = b.requestRepo.Add(officeHour, models.RequestDelete)
Templates.ExecuteTemplate(w, "deleteSuccess.html", struct{}{}) templateError := Templates.ExecuteTemplate(w, "deleteSuccess.html", struct{}{})
if templateError != nil {
log.Printf("Error executing template deleteSuccess.html: %s", templateError.Error())
}
} else { } else {
officeHours, _ := b.officeHourRepo.GetAll(true) officeHours, _ := b.officeHourRepo.GetAll(true)
timetable, slots := b.GetTimetable(officeHours) timetable, slots := b.GetTimetable(officeHours)

View file

@ -3,6 +3,7 @@ package controllers
import ( import (
"fmt" "fmt"
"html/template" "html/template"
"log"
"net/http" "net/http"
"officeHours/models" "officeHours/models"
"strconv" "strconv"
@ -19,7 +20,10 @@ func (b *BaseHandler) GetByRoomHandler(w http.ResponseWriter, req *http.Request)
b.RootHandler(w, req) b.RootHandler(w, req)
return return
} }
officeHours, _ := b.officeHourRepo.FindByRoom(room, true) officeHours, err := b.officeHourRepo.FindByRoom(room, true)
if err != nil {
log.Printf("Error getting office hours for room %s: %s", room.Name, err.Error())
}
timetable, slots := b.GetTimetable(officeHours) timetable, slots := b.GetTimetable(officeHours)
b.writeTimetablePage(w, req, b.printTimetable(timetable, slots, false)) b.writeTimetablePage(w, req, b.printTimetable(timetable, slots, false))
} }
@ -34,7 +38,10 @@ func (b *BaseHandler) GetByCourseHandler(w http.ResponseWriter, req *http.Reques
b.RootHandler(w, req) b.RootHandler(w, req)
return return
} }
officeHours, _ := b.officeHourRepo.FindByCourse(course, true) officeHours, err := b.officeHourRepo.FindByCourse(course, true)
if err != nil {
log.Printf("Error getting office hours for course %s: %s", course.Name, err.Error())
}
timetable, slots := b.GetTimetable(officeHours) timetable, slots := b.GetTimetable(officeHours)
b.writeTimetablePage(w, req, b.printTimetable(timetable, slots, false)) b.writeTimetablePage(w, req, b.printTimetable(timetable, slots, false))
} }
@ -51,9 +58,10 @@ func (b *BaseHandler) writeTimetablePage(w http.ResponseWriter, req *http.Reques
SelectedRoom int SelectedRoom int
SelectedCourse int SelectedCourse int
}{courses, rooms, timetable, selectedRoom, selectedCourse} }{courses, rooms, timetable, selectedRoom, selectedCourse}
err := Templates.ExecuteTemplate(w, "index.html", data) templateError := Templates.ExecuteTemplate(w, "index.html", data)
if err != nil { if templateError != nil {
w.Write([]byte(fmt.Sprintf("Template konnte nicht geparst werden : %s", err.Error()))) log.Printf("Error executing template index.html: %s", templateError.Error())
w.Write([]byte(fmt.Sprintf("Template konnte nicht geparst werden : %s", templateError.Error())))
return return
} }
} }

View file

@ -5,7 +5,7 @@ import (
"officeHours/models" "officeHours/models"
) )
var Templates, _ = template.Must(template.ParseFiles( var Templates, TemplateError = template.Must(template.ParseFiles(
"templates/addFailure.html", "templates/addFailure.html",
"templates/addMask.html", "templates/addMask.html",
"templates/addSuccess.html", "templates/addSuccess.html",

View file

@ -5,6 +5,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"html/template" "html/template"
"log"
"officeHours/models" "officeHours/models"
) )
@ -84,7 +85,10 @@ func (b *BaseHandler) printTimetable(timetable map[models.Date]map[int]models.Of
MinuteGranularity int MinuteGranularity int
DeleteIcons bool DeleteIcons bool
}{OfficeHour: current, MinuteGranularity: b.config.Date.MinuteGranularity, DeleteIcons: deleteIcons} }{OfficeHour: current, MinuteGranularity: b.config.Date.MinuteGranularity, DeleteIcons: deleteIcons}
Templates.ExecuteTemplate(&celldata, "td.html", data) templateError := Templates.ExecuteTemplate(&celldata, "td.html", data)
if templateError != nil {
log.Printf("Error executing template td.html: %s", templateError.Error())
}
tableBody += celldata.String() tableBody += celldata.String()
} }
} else { } else {
@ -116,6 +120,9 @@ func (b *BaseHandler) printTimetable(timetable map[models.Date]map[int]models.Of
slots[4], slots[4],
template.HTML(tableBody), template.HTML(tableBody),
} }
Templates.ExecuteTemplate(&table, "officeHourTable.html", tableData) templateError := Templates.ExecuteTemplate(&table, "officeHourTable.html", tableData)
if templateError != nil {
log.Printf("Error executing template officeHourTable.html: %s", templateError.Error())
}
return template.HTML(table.String()) return template.HTML(table.String())
} }

12
main.go
View file

@ -7,11 +7,11 @@ import (
"log" "log"
"log/syslog" "log/syslog"
"net/http" "net/http"
"os"
"officeHours/config" "officeHours/config"
"officeHours/controllers" "officeHours/controllers"
"officeHours/repositories" "officeHours/repositories"
"officeHours/sqldb" "officeHours/sqldb"
"os"
) )
func main() { func main() {
@ -19,6 +19,11 @@ func main() {
if e == nil { if e == nil {
log.SetOutput(logwriter) log.SetOutput(logwriter)
} }
if controllers.TemplateError != nil {
log.Fatalf("Error parsing templates: %s", controllers.TemplateError.Error())
}
configFile := flag.String( configFile := flag.String(
"config", "config",
"config/config.json", "config/config.json",
@ -35,7 +40,10 @@ func main() {
log.Fatalf("%s: %s", "Reading JSON config file into config structure", err) log.Fatalf("%s: %s", "Reading JSON config file into config structure", err)
} }
db := sqldb.Connect(conf) db, err := sqldb.Connect(conf)
if err != nil {
log.Fatalf(err.Error())
}
// Create repos // Create repos
roomRepo := repositories.NewRoomRepo(db) roomRepo := repositories.NewRoomRepo(db)
courseRepo := repositories.NewCourseRepo(db) courseRepo := repositories.NewCourseRepo(db)

View file

@ -3,6 +3,9 @@ package repositories
import ( import (
"database/sql" "database/sql"
"errors"
"fmt"
"log"
"officeHours/models" "officeHours/models"
) )
@ -17,26 +20,17 @@ func NewCourseRepo(db *sql.DB) *CourseRepo {
} }
func (r *CourseRepo) FindByName(name string) (models.Course, error) { func (r *CourseRepo) FindByName(name string) (models.Course, error) {
row := r.db.QueryRow("SELECT * FROM course WHERE name=?", name) return r.getFromRow(r.db.QueryRow("SELECT * FROM course WHERE name=?", name))
var course models.Course
if err := row.Scan(&course.Id, &course.Name); err != nil {
return models.Course{}, err
}
return course, nil
} }
func (r *CourseRepo) FindById(id int) (models.Course, error) { func (r *CourseRepo) FindById(id int) (models.Course, error) {
row := r.db.QueryRow("SELECT * FROM course WHERE id=?", id) return r.getFromRow(r.db.QueryRow("SELECT * FROM course WHERE id=?", id))
var course models.Course
if err := row.Scan(&course.Id, &course.Name); err != nil {
return models.Course{}, err
}
return course, nil
} }
func (r *CourseRepo) GetAll() ([]models.Course, error) { func (r *CourseRepo) GetAll() ([]models.Course, error) {
rows, err := r.db.Query("SELECT * FROM course") rows, err := r.db.Query("SELECT * FROM course")
if err != nil { if err != nil {
log.Printf("Error getting all courses: %s", err.Error())
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
@ -49,9 +43,22 @@ func (r *CourseRepo) getFromRows(rows *sql.Rows) ([]models.Course, error) {
for rows.Next() { for rows.Next() {
var course models.Course var course models.Course
if err := rows.Scan(&course.Id, &course.Name); err != nil { if err := rows.Scan(&course.Id, &course.Name); err != nil {
log.Printf("Error scanning course row: %s", err.Error())
return courses, err return courses, err
} }
courses = append(courses, course) courses = append(courses, course)
} }
return courses, nil return courses, nil
} }
func (r *CourseRepo) getFromRow(row *sql.Row) (models.Course, error) {
var course models.Course
if err := row.Scan(&course.Id, &course.Name); err != nil {
err = fmt.Errorf("Error getting course row: %w", err)
if !errors.Is(err, sql.ErrNoRows) {
log.Printf(err.Error())
}
return models.Course{}, err
}
return course, nil
}

View file

@ -3,7 +3,9 @@ package repositories
import ( import (
"database/sql" "database/sql"
"errors"
"fmt" "fmt"
"log"
"officeHours/config" "officeHours/config"
"officeHours/models" "officeHours/models"
) )
@ -35,7 +37,11 @@ func (r *OfficeHourRepo) GetAll(activeOnly bool) ([]models.OfficeHour, error) {
rows, err = r.db.Query("SELECT * FROM officeHour") rows, err = r.db.Query("SELECT * FROM officeHour")
} }
if err != nil { if err != nil {
return nil, fmt.Errorf("Error getting all officeHours from database: %s", err.Error()) err = fmt.Errorf("Error getting all officeHours from database: %w", err)
if !errors.Is(err, sql.ErrNoRows) {
log.Println(err.Error())
}
return nil, err
} }
defer rows.Close() defer rows.Close()
return r.getFromRows(rows) return r.getFromRows(rows)
@ -49,10 +55,14 @@ func (r *OfficeHourRepo) FindByCourse(course models.Course, activeOnly bool) ([]
} else { } else {
rows, err = r.db.Query("SELECT * FROM officeHour WHERE course=?", course.Id) rows, err = r.db.Query("SELECT * FROM officeHour WHERE course=?", course.Id)
} }
if err != nil {
return nil, fmt.Errorf("Error getting officeHours by course from database: %s", err.Error())
}
defer rows.Close() defer rows.Close()
if err != nil {
err = fmt.Errorf("Error getting officeHours by course from database: %w", err)
if !errors.Is(err, sql.ErrNoRows) {
log.Println(err.Error())
}
return nil, err
}
return r.getFromRows(rows) return r.getFromRows(rows)
} }
@ -65,7 +75,11 @@ func (r *OfficeHourRepo) FindByRoom(room models.Room, activeOnly bool) ([]models
rows, err = r.db.Query("SELECT * FROM officeHour WHERE room=?", room.Id) rows, err = r.db.Query("SELECT * FROM officeHour WHERE room=?", room.Id)
} }
if err != nil { if err != nil {
return nil, fmt.Errorf("Error getting officeHours by room from database: %s", err.Error()) err = fmt.Errorf("Error getting officeHours by room from database: %w", err)
if !errors.Is(err, sql.ErrNoRows) {
log.Println(err.Error())
}
return nil, err
} }
defer rows.Close() defer rows.Close()
return r.getFromRows(rows) return r.getFromRows(rows)
@ -75,11 +89,16 @@ func (r *OfficeHourRepo) FindById(id int) (models.OfficeHour, error) {
return r.getFromRow(r.db.QueryRow("SELECT * FROM officeHour WHERE id=?", id)) return r.getFromRow(r.db.QueryRow("SELECT * FROM officeHour WHERE id=?", id))
} }
func (r *OfficeHourRepo) Add(officeHour models.OfficeHour) (id int, err error) { func (r *OfficeHourRepo) Add(officeHour models.OfficeHour) (int, error) {
// Find correct tutor or add if not existent // Find correct tutor or add if not existent
r.tutorRepo.Add(officeHour.Tutor) _, err := r.tutorRepo.Add(officeHour.Tutor)
if err != nil {
return 0, err
}
officeHour.Tutor, err = r.tutorRepo.FindByNameAndEmail(officeHour.Tutor.Name, officeHour.Tutor.Email) officeHour.Tutor, err = r.tutorRepo.FindByNameAndEmail(officeHour.Tutor.Name, officeHour.Tutor.Email)
if err != nil { if err != nil {
err = fmt.Errorf("Newly added tutor not found: %w", err)
log.Println(err.Error())
return 0, err return 0, err
} }
@ -111,14 +130,19 @@ func (r *OfficeHourRepo) Add(officeHour models.OfficeHour) (id int, err error) {
officeHour.Info, officeHour.Info,
officeHour.Active, officeHour.Active,
officeHour.Duration) officeHour.Duration)
id64, _ := sqlResult.LastInsertId() id, lastInsertIdErr := sqlResult.LastInsertId()
return int(id64), err if lastInsertIdErr != nil {
log.Printf("Error getting Id for new tutor: %s", lastInsertIdErr.Error())
}
return int(id), err
} }
func (r *OfficeHourRepo) Delete(officeHour models.OfficeHour) error { func (r *OfficeHourRepo) Delete(officeHour models.OfficeHour) error {
_, err := r.db.Exec("DELETE FROM officeHour WHERE id=?", officeHour.Id) _, err := r.db.Exec("DELETE FROM officeHour WHERE id=?", officeHour.Id)
if err != nil { if err != nil {
return fmt.Errorf("Error deleting officeHour from database: %s", err.Error()) err = fmt.Errorf("Error deleting officeHour from database: %w", err)
log.Println(err.Error())
return err
} }
return nil return nil
} }
@ -128,12 +152,29 @@ func (r *OfficeHourRepo) getFromRow(row *sql.Row) (models.OfficeHour, error) {
var week, day, hour, minute, tutorId, courseId, roomId int var week, day, hour, minute, tutorId, courseId, roomId int
err := row.Scan(&officeHour.Id, &tutorId, &day, &hour, &minute, &roomId, &courseId, &week, &officeHour.Info, &officeHour.Active, &officeHour.Duration) err := row.Scan(&officeHour.Id, &tutorId, &day, &hour, &minute, &roomId, &courseId, &week, &officeHour.Info, &officeHour.Active, &officeHour.Duration)
if err != nil { if err != nil {
return models.OfficeHour{}, fmt.Errorf("Error getting single officeHours row from database: %s", err.Error()) err = fmt.Errorf("Error getting single officeHour row from database: %w", err)
log.Println(err.Error())
return models.OfficeHour{}, err
} }
officeHour.Date = models.Date{Week: week, Day: day, Hour: hour, Minute: minute} officeHour.Date = models.Date{Week: week, Day: day, Hour: hour, Minute: minute}
officeHour.Room, _ = r.roomRepo.FindById(roomId) officeHour.Room, err = r.roomRepo.FindById(roomId)
officeHour.Tutor, _ = r.tutorRepo.FindById(tutorId) if err != nil {
officeHour.Course, _ = r.courseRepo.FindById(courseId) err = fmt.Errorf("Error finding room by id %d for office hour: %w", roomId, err)
log.Println(err.Error())
return officeHour, err
}
officeHour.Tutor, err = r.tutorRepo.FindById(tutorId)
if err != nil {
err = fmt.Errorf("Error finding tutor by id %d for office hour: %w", tutorId, err)
log.Println(err.Error())
return officeHour, err
}
officeHour.Course, err = r.courseRepo.FindById(courseId)
if err != nil {
err = fmt.Errorf("Error finding course by id %d for office hour: %w", courseId, err)
log.Println(err.Error())
return officeHour, err
}
return officeHour, nil return officeHour, nil
} }
@ -142,13 +183,29 @@ func (r *OfficeHourRepo) getFromRows(rows *sql.Rows) ([]models.OfficeHour, error
for rows.Next() { for rows.Next() {
var officeHour models.OfficeHour var officeHour models.OfficeHour
var week, day, hour, minute, tutorId, roomId, courseId int var week, day, hour, minute, tutorId, roomId, courseId int
var err error
if err := rows.Scan(&officeHour.Id, &tutorId, &day, &hour, &minute, &roomId, &courseId, &week, &officeHour.Info, &officeHour.Active, &officeHour.Duration); err != nil { if err := rows.Scan(&officeHour.Id, &tutorId, &day, &hour, &minute, &roomId, &courseId, &week, &officeHour.Info, &officeHour.Active, &officeHour.Duration); err != nil {
return officeHours, fmt.Errorf("Error getting multiple officeHour rows from database: %s", err.Error()) return officeHours, fmt.Errorf("Error getting multiple officeHour rows from database: %w", err)
} }
officeHour.Date = models.Date{Week: week, Day: day, Hour: hour, Minute: minute} officeHour.Date = models.Date{Week: week, Day: day, Hour: hour, Minute: minute}
officeHour.Room, _ = r.roomRepo.FindById(roomId) officeHour.Room, err = r.roomRepo.FindById(roomId)
officeHour.Tutor, _ = r.tutorRepo.FindById(tutorId) if err != nil {
officeHour.Course, _ = r.courseRepo.FindById(courseId) err = fmt.Errorf("Error finding room by id %d for office hour: %w", roomId, err)
log.Println(err.Error())
return officeHours, err
}
officeHour.Tutor, err = r.tutorRepo.FindById(tutorId)
if err != nil {
err = fmt.Errorf("Error finding tutor by id %d for office hour: %w", tutorId, err)
log.Println(err.Error())
return officeHours, err
}
officeHour.Course, err = r.courseRepo.FindById(courseId)
if err != nil {
err = fmt.Errorf("Error finding course by id %d for office hour: %w", courseId, err)
log.Println(err.Error())
return officeHours, err
}
officeHours = append(officeHours, officeHour) officeHours = append(officeHours, officeHour)
} }
return officeHours, nil return officeHours, nil
@ -163,7 +220,9 @@ func (r *OfficeHourRepo) NumberByTimeSpanAndRoom(date models.Date, duration int,
rows, err = r.db.Query("SELECT * FROM officeHour WHERE room=?", room.Id) rows, err = r.db.Query("SELECT * FROM officeHour WHERE room=?", room.Id)
} }
if err != nil { if err != nil {
return 0, fmt.Errorf("Error getting officeHours by timespan and room from database: %s", err.Error()) err = fmt.Errorf("Error getting officeHours by timespan and room from database: %w", err)
log.Println(err.Error())
return 0, err
} }
defer rows.Close() defer rows.Close()
officeHours, err := r.getFromRows(rows) officeHours, err := r.getFromRows(rows)

View file

@ -5,6 +5,7 @@ import (
"bytes" "bytes"
"crypto/rand" "crypto/rand"
"database/sql" "database/sql"
"errors"
"fmt" "fmt"
"log" "log"
"math/big" "math/big"
@ -53,6 +54,8 @@ func (r *RequestRepo) FindByOfficeHour(officeHour models.OfficeHour) ([]models.R
var request models.Request var request models.Request
var officeHourId int var officeHourId int
if err := rows.Scan(&request.Id, &officeHourId, &request.Action, &request.Secret); err != nil { if err := rows.Scan(&request.Id, &officeHourId, &request.Action, &request.Secret); err != nil {
err = fmt.Errorf("Error scanning request row: %w", err)
log.Println(err.Error())
return requests, err return requests, err
} }
request.OfficeHour, err = r.officeHourRepo.FindById(officeHourId) request.OfficeHour, err = r.officeHourRepo.FindById(officeHourId)
@ -66,7 +69,7 @@ func (r *RequestRepo) FindByOfficeHour(officeHour models.OfficeHour) ([]models.R
func (r *RequestRepo) Add(officeHour models.OfficeHour, action int) (int, error) { func (r *RequestRepo) Add(officeHour models.OfficeHour, action int) (int, error) {
existents, err := r.FindByOfficeHour(officeHour) existents, err := r.FindByOfficeHour(officeHour)
if err != nil && err != sql.ErrNoRows { if err != nil && !errors.Is(err, sql.ErrNoRows) {
return 0, err return 0, err
} }
/* Resend confirmation mail if identical request exists, /* Resend confirmation mail if identical request exists,
@ -100,10 +103,10 @@ func (r *RequestRepo) Execute(request models.Request) error {
_, err = r.db.Exec("UPDATE officeHour SET active=true WHERE id=?", request.OfficeHour.Id) _, err = r.db.Exec("UPDATE officeHour SET active=true WHERE id=?", request.OfficeHour.Id)
r.db.Exec("DELETE FROM request WHERE officeHour=?", request.OfficeHour.Id) r.db.Exec("DELETE FROM request WHERE officeHour=?", request.OfficeHour.Id)
case models.RequestDelete: case models.RequestDelete:
r.officeHourRepo.Delete(request.OfficeHour) err = r.officeHourRepo.Delete(request.OfficeHour)
r.db.Exec("DELETE FROM request WHERE officeHour=?", request.OfficeHour.Id) r.db.Exec("DELETE FROM request WHERE officeHour=?", request.OfficeHour.Id)
default: default:
r.db.Exec("DELETE FROM request WHERE id=?", request.Id) _, err = r.db.Exec("DELETE FROM request WHERE id=?", request.Id)
} }
return err return err
} }
@ -112,10 +115,10 @@ func (r *RequestRepo) newSecret() (string, error) {
var err error var err error
var secret string var secret string
// find unused secret // find unused secret
for err != sql.ErrNoRows { for !errors.Is(err, sql.ErrNoRows) {
secret = randomString(r.config.Request.SecretLength) secret = randomString(r.config.Request.SecretLength)
_, err = r.FindBySecret(secret) _, err = r.FindBySecret(secret)
if err != nil && err != sql.ErrNoRows { if err != nil && errors.Is(err, sql.ErrNoRows) {
return "", err return "", err
} }
} }
@ -130,7 +133,8 @@ func (r *RequestRepo) sendConfirmationMail(request models.Request) error {
}{r.config, request} }{r.config, request}
err := controllers.Templates.ExecuteTemplate(&message, "confirmationMail", data) err := controllers.Templates.ExecuteTemplate(&message, "confirmationMail", data)
if err != nil { if err != nil {
log.Printf("Error parsing confirmation Mail: %s", err.Error()) err = fmt.Errorf("Error parsing confirmation Mail: %w", err)
log.Println(err.Error())
return err return err
} }
switch r.config.Mailer.Type { switch r.config.Mailer.Type {
@ -142,7 +146,12 @@ func (r *RequestRepo) sendConfirmationMail(request models.Request) error {
if r.config.Mailer.SmtpUseAuth { if r.config.Mailer.SmtpUseAuth {
auth = smtp.PlainAuth(r.config.Mailer.SmtpIdentity, r.config.Mailer.FromAddress, r.config.Mailer.SmtpPassword, r.config.Mailer.SmtpHost) auth = smtp.PlainAuth(r.config.Mailer.SmtpIdentity, r.config.Mailer.FromAddress, r.config.Mailer.SmtpPassword, r.config.Mailer.SmtpHost)
} }
return smtp.SendMail(fmt.Sprintf("%s:%d", r.config.Mailer.SmtpHost, r.config.Mailer.SmtpPort), auth, string(r.config.Mailer.FromName), to, message.Bytes()) err = smtp.SendMail(fmt.Sprintf("%s:%d", r.config.Mailer.SmtpHost, r.config.Mailer.SmtpPort), auth, string(r.config.Mailer.FromName), to, message.Bytes())
if err != nil {
err = fmt.Errorf("Error sending mail by smtp: %w", err)
log.Println(err.Error())
}
return err
} }
return nil return nil
} }
@ -154,7 +163,10 @@ func randomString(n int) string {
s := make([]rune, n) s := make([]rune, n)
for i := range s { for i := range s {
position, _ := rand.Int(rand.Reader, big.NewInt(int64(len(letters)))) position, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))
if err != nil {
log.Printf("Error getting random position in randomString(n int): %s", err.Error())
}
s[i] = letters[position.Int64()] s[i] = letters[position.Int64()]
} }
return string(s) return string(s)

View file

@ -3,6 +3,9 @@ package repositories
import ( import (
"database/sql" "database/sql"
"errors"
"fmt"
"log"
"officeHours/models" "officeHours/models"
) )
@ -29,6 +32,10 @@ func (r *RoomRepo) FindById(id int) (models.Room, error) {
row := r.db.QueryRow("SELECT * FROM room WHERE id=?", id) row := r.db.QueryRow("SELECT * FROM room WHERE id=?", id)
var room models.Room var room models.Room
if err := row.Scan(&room.Id, &room.Name, &room.MaxOccupy); err != nil { if err := row.Scan(&room.Id, &room.Name, &room.MaxOccupy); err != nil {
err = fmt.Errorf("Error scanning row to get room: %w", err)
if !errors.Is(err, sql.ErrNoRows) {
log.Println(err.Error())
}
return models.Room{}, err return models.Room{}, err
} }
return room, nil return room, nil
@ -37,6 +44,8 @@ func (r *RoomRepo) FindById(id int) (models.Room, error) {
func (r *RoomRepo) GetAll() ([]models.Room, error) { func (r *RoomRepo) GetAll() ([]models.Room, error) {
rows, err := r.db.Query("SELECT * FROM room") rows, err := r.db.Query("SELECT * FROM room")
if err != nil { if err != nil {
err = fmt.Errorf("Error getting all rooms: %w", err)
log.Println(err.Error())
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
@ -45,15 +54,10 @@ func (r *RoomRepo) GetAll() ([]models.Room, error) {
for rows.Next() { for rows.Next() {
var room models.Room var room models.Room
if err := rows.Scan(&room.Id, &room.Name, &room.MaxOccupy); err != nil { if err := rows.Scan(&room.Id, &room.Name, &room.MaxOccupy); err != nil {
err = fmt.Errorf("Error scanning row to get room: %w", err)
return rooms, err return rooms, err
} }
rooms = append(rooms, room) rooms = append(rooms, room)
} }
return rooms, nil return rooms, nil
} }
func (r *RoomRepo) Save(room models.Room) error {
return nil
}
func (r *RoomRepo) Add(room models.Room) error {
return nil
}

View file

@ -3,6 +3,9 @@ package repositories
import ( import (
"database/sql" "database/sql"
"errors"
"fmt"
"log"
"officeHours/models" "officeHours/models"
) )
@ -27,6 +30,8 @@ func (r *TutorRepo) FindByEmail(email string) ([]models.Tutor, error) {
for rows.Next() { for rows.Next() {
var tutor models.Tutor var tutor models.Tutor
if err := rows.Scan(&tutor.Id, &tutor.Name, &tutor.Email); err != nil { if err := rows.Scan(&tutor.Id, &tutor.Name, &tutor.Email); err != nil {
err = fmt.Errorf("Error scanning tutor row: %w", err)
log.Println(err.Error())
return tutors, err return tutors, err
} }
tutors = append(tutors, tutor) tutors = append(tutors, tutor)
@ -63,23 +68,24 @@ func (r *TutorRepo) GetAll() ([]models.Tutor, error) {
for rows.Next() { for rows.Next() {
var tutor models.Tutor var tutor models.Tutor
if err := rows.Scan(&tutor.Id, &tutor.Name, &tutor.Email); err != nil { if err := rows.Scan(&tutor.Id, &tutor.Name, &tutor.Email); err != nil {
err = fmt.Errorf("Error scanning tutor row: %w", err)
log.Println(err.Error())
return tutors, err return tutors, err
} }
tutors = append(tutors, tutor) tutors = append(tutors, tutor)
} }
return tutors, nil return tutors, nil
} }
func (r *TutorRepo) Save(tutor models.Tutor) error {
return nil
}
func (r *TutorRepo) Add(tutor models.Tutor) (int, error) { func (r *TutorRepo) Add(tutor models.Tutor) (int, error) {
//Don't add identical tutors //Don't add identical tutors
existentTutor, err := r.FindByNameAndEmail(tutor.Name, tutor.Email) existentTutor, err := r.FindByNameAndEmail(tutor.Name, tutor.Email)
if err == sql.ErrNoRows { if errors.Is(err, sql.ErrNoRows) {
sqlResult, err := r.db.Exec("INSERT INTO `tutor` (name, email) VALUES (?,?)", tutor.Name, tutor.Email) sqlResult, err := r.db.Exec("INSERT INTO `tutor` (name, email) VALUES (?,?)", tutor.Name, tutor.Email)
id, _ := sqlResult.LastInsertId() id, lastInsertIdErr := sqlResult.LastInsertId()
if lastInsertIdErr != nil {
log.Printf("Error getting Id for new tutor: %s", lastInsertIdErr.Error())
}
return int(id), err return int(id), err
} }
return existentTutor.Id, err return existentTutor.Id, err
} }

View file

@ -3,14 +3,13 @@ package sqldb
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"log"
"officeHours/config" "officeHours/config"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
) )
func Connect(config config.Config) *sql.DB { func Connect(config config.Config) (*sql.DB, error) {
switch config.SQL.Type { switch config.SQL.Type {
case "SQLite": case "SQLite":
return connectSQLite(config.SQL.SQLiteFile) return connectSQLite(config.SQL.SQLiteFile)
@ -21,30 +20,28 @@ func Connect(config config.Config) *sql.DB {
config.SQL.MysqlPort, config.SQL.MysqlPort,
config.SQL.MysqlDatabase) config.SQL.MysqlDatabase)
default: default:
log.Fatal("Type of database not recognised.") return nil, fmt.Errorf("Type of database not recognised: %s", config.SQL.Type)
} }
return nil
} }
func connectSQLite(file string) *sql.DB { func connectSQLite(file string) (*sql.DB, error) {
db, err := sql.Open("sqlite3", file) db, err := sql.Open("sqlite3", file)
if err != nil { if err != nil {
log.Fatal(err) return db, fmt.Errorf("Error opening SQLite database: %w", err)
} }
return db, nil
return db
} }
func connectMysql(user string, password string, address string, port int, database string) *sql.DB { func connectMysql(user string, password string, address string, port int, database string) (*sql.DB, error) {
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", user, password, address, port, database)) db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", user, password, address, port, database))
if err != nil { if err != nil {
log.Fatalf("Error connecting to database: %s", err) return db, fmt.Errorf("Error connecting to Mysql database: %w", err)
} }
err = db.Ping() err = db.Ping()
// handle error // handle error
if err != nil { if err != nil {
log.Fatalf("Error pinging database: %s", err) return db, fmt.Errorf("Error pinging Mysql database: %w", err)
} }
return db return db, nil
} }