From a87bef8c89fe7a47c9c588b3272f5e2d3bc2d4c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20Tr=C3=B6ger?= Date: Tue, 12 Aug 2025 15:47:36 +0200 Subject: [PATCH] added user Session Handler --> closed #20 --- Backend/endpoints/team.go | 5 --- Backend/endpoints/team_presence.go | 10 ++--- Backend/endpoints/time-create.go | 4 -- Backend/endpoints/time.go | 7 --- .../{user-login.go => user-session.go} | 24 ++++------ Backend/endpoints/user-settings.go | 34 -------------- Backend/endpoints/user.go | 45 +++++++++++++++++++ Backend/main.go | 15 +++---- Backend/static/script.js | 12 ++--- Backend/templates/headerComponent.templ | 5 +-- Backend/templates/headerComponent_templ.go | 12 ++++- Backend/templates/pages.templ | 14 ++++-- Backend/templates/pages_templ.go | 41 ++++++++++++++--- 13 files changed, 127 insertions(+), 101 deletions(-) rename Backend/endpoints/{user-login.go => user-session.go} (87%) create mode 100644 Backend/endpoints/user.go diff --git a/Backend/endpoints/team.go b/Backend/endpoints/team.go index 9b214ea..3526085 100644 --- a/Backend/endpoints/team.go +++ b/Backend/endpoints/team.go @@ -17,13 +17,10 @@ func TeamHandler(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodPost: submitReport(w, r) - break case http.MethodGet: showWeeks(w, r) - break default: http.Error(w, "Method not allowed!", http.StatusMethodNotAllowed) - break } } @@ -47,10 +44,8 @@ func submitReport(w http.ResponseWriter, r *http.Request) { switch r.FormValue("method") { case "send": err = workWeek.Send() - break case "accept": err = workWeek.Accept() - break default: break } diff --git a/Backend/endpoints/team_presence.go b/Backend/endpoints/team_presence.go index 5ca18e0..b313627 100644 --- a/Backend/endpoints/team_presence.go +++ b/Backend/endpoints/team_presence.go @@ -8,24 +8,21 @@ import ( "net/http" ) -func TeamPresenceHandler(w http.ResponseWriter, r *http.Request){ +func TeamPresenceHandler(w http.ResponseWriter, r *http.Request) { helper.RequiresLogin(Session, w, r) helper.SetCors(w) switch r.Method { case http.MethodGet: teamPresence(w, r) - break case http.MethodOptions: // just support options header for non GET Requests from SWAGGER w.WriteHeader(http.StatusOK) - break default: http.Error(w, "Method not allowed!", http.StatusMethodNotAllowed) - break } } -func teamPresence(w http.ResponseWriter, r *http.Request){ +func teamPresence(w http.ResponseWriter, r *http.Request) { user, err := (*models.User).GetUserFromSession(nil, Session, r.Context()) if err != nil { log.Println("Error getting user!", err) @@ -37,8 +34,7 @@ func teamPresence(w http.ResponseWriter, r *http.Request){ teamPresence[present] = append(teamPresence[present], user) } - - if(err != nil){ + if err != nil { log.Println("Error getting team", err) } templates.TeamPresencePage(teamPresence).Render(r.Context(), w) diff --git a/Backend/endpoints/time-create.go b/Backend/endpoints/time-create.go index 7dd0e29..05edd1c 100644 --- a/Backend/endpoints/time-create.go +++ b/Backend/endpoints/time-create.go @@ -16,17 +16,13 @@ func TimeCreateHandler(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodPut: createBooking(w, r) - break case http.MethodGet: createBooking(w, r) - break case http.MethodOptions: // just support options header for non GET Requests from SWAGGER w.WriteHeader(http.StatusOK) - break default: http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) - break } } diff --git a/Backend/endpoints/time.go b/Backend/endpoints/time.go index 9dae1a3..eef7537 100644 --- a/Backend/endpoints/time.go +++ b/Backend/endpoints/time.go @@ -20,17 +20,13 @@ func TimeHandler(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: getBookings(w, r) - break case http.MethodPost: updateBooking(w, r) - break case http.MethodOptions: // just support options header for non GET Requests from SWAGGER w.WriteHeader(http.StatusOK) - break default: http.Error(w, "Method not allowed!", http.StatusMethodNotAllowed) - break } } @@ -120,7 +116,6 @@ func updateBooking(w http.ResponseWriter, r *http.Request) { if err != nil { log.Println("Error inserting booking", err) } - break case "change": absenceType, err := strconv.Atoi(r.FormValue("absence")) if err != nil { @@ -151,9 +146,7 @@ func updateBooking(w http.ResponseWriter, r *http.Request) { booking.UpdateTime(parsedTime) } } - break } - getBookings(w, r) } diff --git a/Backend/endpoints/user-login.go b/Backend/endpoints/user-session.go similarity index 87% rename from Backend/endpoints/user-login.go rename to Backend/endpoints/user-session.go index ee19238..9b9084c 100644 --- a/Backend/endpoints/user-login.go +++ b/Backend/endpoints/user-session.go @@ -21,20 +21,6 @@ func CreateSessionManager(lifetime time.Duration) *scs.SessionManager { return Session } -func LoginHandler(w http.ResponseWriter, r *http.Request) { - switch r.Method { - case http.MethodGet: - showLoginPage(w, r, false) - break - case http.MethodPost: - loginUser(w, r) - break - default: - http.Error(w, "Method not allowed!", http.StatusMethodNotAllowed) - break - } -} - func showLoginPage(w http.ResponseWriter, r *http.Request, failed bool) { r = r.WithContext(context.WithValue(r.Context(), "session", Session)) if helper.GetEnv("GO_ENV", "production") == "debug" { @@ -83,5 +69,13 @@ func loginUser(w http.ResponseWriter, r *http.Request) { return } showLoginPage(w, r, false) - return +} + +func logoutUser(w http.ResponseWriter, r *http.Request) { + log.Println("Loggin out user!") + err := Session.Destroy(r.Context()) + if err != nil { + log.Println("Error destroying session!", err) + } + http.Redirect(w, r, "/user/login", http.StatusSeeOther) } diff --git a/Backend/endpoints/user-settings.go b/Backend/endpoints/user-settings.go index 7524f81..d8509a0 100644 --- a/Backend/endpoints/user-settings.go +++ b/Backend/endpoints/user-settings.go @@ -1,36 +1,12 @@ package endpoints import ( - "arbeitszeitmessung/helper" "arbeitszeitmessung/models" "arbeitszeitmessung/templates" "log" "net/http" ) -func UserSettingsHandler(w http.ResponseWriter, r *http.Request) { - helper.RequiresLogin(Session, w, r) - switch r.Method { - case http.MethodGet: - showUserPage(w, r, 0) - break - case http.MethodPost: - switch r.FormValue("action") { - case "change-pass": - changePassword(w, r) - break - case "logout-user": - logoutUser(w, r) - break - } - - break - default: - http.Error(w, "Method not allowed!", http.StatusMethodNotAllowed) - break - } -} - // change user password and store salted hash in db func changePassword(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() @@ -61,16 +37,6 @@ func changePassword(w http.ResponseWriter, r *http.Request) { showUserPage(w, r, http.StatusUnauthorized) } -func logoutUser(w http.ResponseWriter, r *http.Request) { - - err := Session.Destroy(r.Context()) - if err != nil { - log.Println("Error destroying session!", err) - } - http.Redirect(w, r, "/user/login", http.StatusSeeOther) -} - func showUserPage(w http.ResponseWriter, r *http.Request, status int) { templates.UserPage(status).Render(r.Context(), w) - return } diff --git a/Backend/endpoints/user.go b/Backend/endpoints/user.go new file mode 100644 index 0000000..540d117 --- /dev/null +++ b/Backend/endpoints/user.go @@ -0,0 +1,45 @@ +package endpoints + +import ( + "arbeitszeitmessung/helper" + "net/http" +) + +func UserHandler(w http.ResponseWriter, r *http.Request) { + switch r.PathValue("action") { + case "login": + LoginHandler(w, r) + case "settings": + UserSettingsHandler(w, r) + case "logout": + logoutUser(w, r) + } +} + +func LoginHandler(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodGet: + showLoginPage(w, r, false) + case http.MethodPost: + loginUser(w, r) + default: + http.Error(w, "Method not allowed!", http.StatusMethodNotAllowed) + } +} + +func UserSettingsHandler(w http.ResponseWriter, r *http.Request) { + helper.RequiresLogin(Session, w, r) + switch r.Method { + case http.MethodGet: + showUserPage(w, r, 0) + case http.MethodPost: + switch r.FormValue("action") { + case "change-pass": + changePassword(w, r) + case "logout-user": + logoutUser(w, r) + } + default: + http.Error(w, "Method not allowed!", http.StatusMethodNotAllowed) + } +} diff --git a/Backend/main.go b/Backend/main.go index 969ab60..3d2aee2 100644 --- a/Backend/main.go +++ b/Backend/main.go @@ -22,17 +22,15 @@ func main() { if err != nil { log.Println("No .env file found in directory!") } - if(helper.GetEnv("GO_ENV", "production") == "debug") { + if helper.GetEnv("GO_ENV", "production") == "debug" { log.Println("Debug mode enabled") log.Println("Environment Variables") envs := os.Environ() - for _, e := range envs { - fmt.Println(e) - } + for _, e := range envs { + fmt.Println(e) + } } - - models.DB, err = OpenDatabase() if err != nil { log.Fatal(err) @@ -48,8 +46,9 @@ func main() { server.HandleFunc("/time/new", endpoints.TimeCreateHandler) server.Handle("/time", ParamsMiddleware(endpoints.TimeHandler)) server.HandleFunc("/logout", endpoints.LogoutHandler) - server.HandleFunc("/user/login", endpoints.LoginHandler) - server.HandleFunc("/user/settings", endpoints.UserSettingsHandler) + server.HandleFunc("/user/{action}", endpoints.UserHandler) + // server.HandleFunc("/user/login", endpoints.LoginHandler) + // server.HandleFunc("/user/settings", endpoints.UserSettingsHandler) server.HandleFunc("/team", endpoints.TeamHandler) server.HandleFunc("/team/presence", endpoints.TeamPresenceHandler) server.Handle("/", http.RedirectHandler("/time", http.StatusPermanentRedirect)) diff --git a/Backend/static/script.js b/Backend/static/script.js index 5bc2abb..520ec52 100644 --- a/Backend/static/script.js +++ b/Backend/static/script.js @@ -1,7 +1,5 @@ function editDay(element, event, formId) { - var form = element - .closest(".grid-sub") - .querySelector(".all-booking-component > form"); + var form = element.closest(".grid-sub").querySelector(".all-booking-component > form"); form.classList.toggle("edit"); element.classList.toggle("edit"); if (element.classList.contains("edit")) { @@ -15,9 +13,7 @@ function editDay(element, event, formId) { } function editAbwesenheit(element, event) { - var newBookingComponent = element - .closest(".grid-sub") - .querySelector(".new-booking-component"); + var newBookingComponent = element.closest(".grid-sub").querySelector(".new-booking-component"); if (element.value == 0) { newBookingComponent.style.display = ""; } else { @@ -32,3 +28,7 @@ function navigateWeek(element, event, direction) { date.setHours(10); dateInput.valueAsDate = date; } + +function logoutUser() { + fetch("/user/logout", {}).then(() => window.location.reload()); +} diff --git a/Backend/templates/headerComponent.templ b/Backend/templates/headerComponent.templ index bfb040f..ec2d673 100644 --- a/Backend/templates/headerComponent.templ +++ b/Backend/templates/headerComponent.templ @@ -1,14 +1,13 @@ package templates - - templ headerComponent() { -
+
Zeitverwaltung Abrechnung if true { Anwesenheit } Einstellungen + @LogoutButton()
} diff --git a/Backend/templates/headerComponent_templ.go b/Backend/templates/headerComponent_templ.go index fa6028b..aeef6ec 100644 --- a/Backend/templates/headerComponent_templ.go +++ b/Backend/templates/headerComponent_templ.go @@ -29,7 +29,7 @@ func headerComponent() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
Zeitverwaltung Abrechnung ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
Zeitverwaltung Abrechnung ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -39,7 +39,15 @@ func headerComponent() templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "Einstellungen
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "Einstellungen") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = LogoutButton().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/Backend/templates/pages.templ b/Backend/templates/pages.templ index 73d9785..11d8b3f 100644 --- a/Backend/templates/pages.templ +++ b/Backend/templates/pages.templ @@ -68,15 +68,15 @@ templ UserPage(status int) {
-
+

Nutzer abmelden

Nutzer von Weboberfläche abmelden.

- +
- +
} @@ -88,7 +88,9 @@ templ TeamPage(weeks []models.WorkWeek, userWeek models.WorkWeek) { @headerComponent()
-
{ fmt.Sprintf("%s %s", userWeek.User.Vorname, userWeek.User.Name) }
+
+ { fmt.Sprintf("%s %s", userWeek.User.Vorname, userWeek.User.Name) } +
for _, day := range userWeek.WorkDays { @weekDayComponent(userWeek.User, day) @@ -182,3 +184,7 @@ templ TeamPresencePage(teamPresence map[bool][]models.User) {
} + +templ LogoutButton() { + +} diff --git a/Backend/templates/pages_templ.go b/Backend/templates/pages_templ.go index 40a7152..d9d42b6 100644 --- a/Backend/templates/pages_templ.go +++ b/Backend/templates/pages_templ.go @@ -192,7 +192,7 @@ func UserPage(status int) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "

Nutzer abmelden

Nutzer von Weboberfläche abmelden.

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "

Nutzer abmelden

Nutzer von Weboberfläche abmelden.

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -238,7 +238,7 @@ func TeamPage(weeks []models.WorkWeek, userWeek models.WorkWeek) templ.Component var templ_7745c5c3_Var6 string templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%s %s", userWeek.User.Vorname, userWeek.User.Name)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pages.templ`, Line: 91, Col: 111} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pages.templ`, Line: 92, Col: 69} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { @@ -261,7 +261,7 @@ func TeamPage(weeks []models.WorkWeek, userWeek models.WorkWeek) templ.Component var templ_7745c5c3_Var7 string templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(userWeek.WeekStart.Format(time.DateOnly)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pages.templ`, Line: 99, Col: 110} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pages.templ`, Line: 101, Col: 110} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { @@ -291,7 +291,7 @@ func TeamPage(weeks []models.WorkWeek, userWeek models.WorkWeek) templ.Component var templ_7745c5c3_Var9 string templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%02d, %d", kw, year)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pages.templ`, Line: 105, Col: 72} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pages.templ`, Line: 107, Col: 72} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { @@ -331,7 +331,7 @@ func TeamPage(weeks []models.WorkWeek, userWeek models.WorkWeek) templ.Component var templ_7745c5c3_Var11 string templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(userWeek.User.PersonalNummer)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pages.templ`, Line: 114, Col: 88} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pages.templ`, Line: 116, Col: 88} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { @@ -344,7 +344,7 @@ func TeamPage(weeks []models.WorkWeek, userWeek models.WorkWeek) templ.Component var templ_7745c5c3_Var12 string templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(userWeek.WeekStart.Format(time.DateOnly)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pages.templ`, Line: 115, Col: 86} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pages.templ`, Line: 117, Col: 86} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) if templ_7745c5c3_Err != nil { @@ -495,4 +495,33 @@ func TeamPresencePage(teamPresence map[bool][]models.User) templ.Component { }) } +func LogoutButton() templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var15 := templ.GetChildren(ctx) + if templ_7745c5c3_Var15 == nil { + templ_7745c5c3_Var15 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) +} + var _ = templruntime.GeneratedTemplate