diff --git a/Backend/endpoints/time.go b/Backend/endpoints/time.go index ce65cde..2db1489 100644 --- a/Backend/endpoints/time.go +++ b/Backend/endpoints/time.go @@ -28,27 +28,26 @@ func TimeHandler(w http.ResponseWriter, r *http.Request) { } } -func parseTimestamp(r *http.Request , get_key string, fallback string) (time.Time, error) { +func parseTimestamp(r *http.Request, get_key string, fallback string) (time.Time, error) { _timestamp_get := r.URL.Query().Get(get_key) - if(_timestamp_get == "") { + if _timestamp_get == "" { _timestamp_get = fallback } timestamp_get, err := time.Parse("2006-01-02", _timestamp_get) - if(err != nil){ + if err != nil { return time.Now(), err } return timestamp_get, nil } - // Returns bookings from DB with similar card uid -> checks for card uid in http query params func getBookings(w http.ResponseWriter, r *http.Request) { var user models.User var err error - if(helper.GetEnv("GO_ENV", "production") == "debug"){ + if helper.GetEnv("GO_ENV", "production") == "debug" { user, err = (*models.User).GetByPersonalNummer(nil, 123) - }else{ - if(!Session.Exists(r.Context(), "user")){ + } else { + if !Session.Exists(r.Context(), "user") { log.Println("No user in session storage!") http.Error(w, "Not logged in!", http.StatusForbidden) return @@ -56,7 +55,7 @@ func getBookings(w http.ResponseWriter, r *http.Request) { user, err = (*models.User).GetByPersonalNummer(nil, Session.GetInt(r.Context(), "user")) } - if(err != nil){ + if err != nil { log.Println("No user found with the given personal number!") http.Error(w, "No user found", http.StatusNotFound) return @@ -64,18 +63,18 @@ func getBookings(w http.ResponseWriter, r *http.Request) { // TODO add config for timeoffset tsFrom, err := parseTimestamp(r, "time_from", time.Now().AddDate(0, -1, 0).Format("2006-01-02")) - if(err != nil ){ + if err != nil { log.Println("Error parsing 'from' time", err) http.Error(w, "Timestamp 'from' cannot be parsed!", http.StatusBadRequest) return } tsTo, err := parseTimestamp(r, "time_to", time.Now().Format("2006-01-02")) - if(err != nil ){ + if err != nil { log.Println("Error parsing 'to' time", err) http.Error(w, "Timestamp 'to' cannot be parsed!", http.StatusBadRequest) return } - tsTo = tsTo.AddDate(0,0,1) // so that today is inside + tsTo = tsTo.AddDate(0, 0, 1) // so that today is inside bookings, err := (*models.Booking).GetBookingsGrouped(nil, user.CardUID, tsFrom, tsTo) if err != nil { @@ -87,22 +86,22 @@ func getBookings(w http.ResponseWriter, r *http.Request) { templates.TimeDashboard(bookings).Render(ctx, w) } -func updateBooking(w http.ResponseWriter, r *http.Request){ +func updateBooking(w http.ResponseWriter, r *http.Request) { r.ParseForm() - for index, possibleBooking := range r.PostForm{ - if(index[:7] == "booking"){ + for index, possibleBooking := range r.PostForm { + if index[:7] == "booking" { booking_id, err := strconv.Atoi(index[8:]) - if(err != nil){ + if err != nil { log.Println("Error parsing bookingId", err) continue } booking, err := (*models.Booking).GetBookingById(nil, booking_id) - if(err != nil){ + if err != nil { log.Println("Error getting booking!", err) continue } parsedTime, err := time.ParseInLocation("15:04", possibleBooking[0], time.Local) - if(err != nil){ + if err != nil { log.Println("Error parsing time!", err) continue } @@ -113,17 +112,17 @@ func updateBooking(w http.ResponseWriter, r *http.Request){ getBookings(w, r) } -func getBookingsAPI(w http.ResponseWriter, r *http.Request){ +func getBookingsAPI(w http.ResponseWriter, r *http.Request) { _user_pn := r.URL.Query().Get("personal_nummer") user_pn, err := strconv.Atoi(_user_pn) - if(err != nil){ + if err != nil { log.Println("No personal numver found!") http.Error(w, "No personal number found", http.StatusBadRequest) return } user, err := (*models.User).GetByPersonalNummer(nil, user_pn) - if(err != nil){ + if err != nil { log.Println("No user found with the given personal number!") http.Error(w, "No user found", http.StatusNotFound) return @@ -131,18 +130,18 @@ func getBookingsAPI(w http.ResponseWriter, r *http.Request){ // TODO add config for timeoffset tsFrom, err := parseTimestamp(r, "time_from", time.Now().AddDate(0, -1, 0).Format("2006-01-02")) - if(err != nil ){ + if err != nil { log.Println("Error parsing 'from' time", err) http.Error(w, "Timestamp 'from' cannot be parsed!", http.StatusBadRequest) return } tsTo, err := parseTimestamp(r, "time_to", time.Now().Format("2006-01-02")) - if(err != nil ){ + if err != nil { log.Println("Error parsing 'to' time", err) http.Error(w, "Timestamp 'to' cannot be parsed!", http.StatusBadRequest) return } - tsTo = tsTo.AddDate(0,0,1) // so that today is inside + tsTo = tsTo.AddDate(0, 0, 1) // so that today is inside bookings, err := (*models.Booking).GetBookingsGrouped(nil, user.CardUID, tsFrom, tsTo) if err != nil { diff --git a/Backend/endpoints/time_create.go b/Backend/endpoints/time_create.go index c59b7f9..3c13053 100644 --- a/Backend/endpoints/time_create.go +++ b/Backend/endpoints/time_create.go @@ -29,7 +29,7 @@ func TimeCreateHandler(w http.ResponseWriter, r *http.Request) { // Creates a booking from the http query params -> no body needed // after that entry wi'll be written to database and the booking is returned as json func createBooking(w http.ResponseWriter, r *http.Request) { - if(!checkPassword(r)){ + if !checkPassword(r) { log.Println("Wrong or no API key provided!") http.Error(w, "Wrong or no API key provided", http.StatusUnauthorized) return diff --git a/Backend/endpoints/user.go b/Backend/endpoints/user.go index 218bb14..f821178 100644 --- a/Backend/endpoints/user.go +++ b/Backend/endpoints/user.go @@ -18,24 +18,42 @@ func CreateSessionManager(lifetime time.Duration) *scs.SessionManager { Session.Lifetime = lifetime return Session } - -func LoginHandler(w http.ResponseWriter, r *http.Request){ - switch r.Method{ - case http.MethodGet: showForm(w, r, false) +func LoginHandler(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodGet: + showLoginForm(w, r, false) break - case http.MethodPost: loginUser(w, r) + case http.MethodPost: + loginUser(w, r) break - default: - showForm(w, r, false) + default: + showLoginForm(w, r, false) break } } -func showForm(w http.ResponseWriter, r *http.Request, failed bool){ +func UserHandler(w http.ResponseWriter, r *http.Request) { + if !Session.Exists(r.Context(), "user") { + http.Redirect(w, r, "/user/login", http.StatusTemporaryRedirect) + } + switch r.Method { + case http.MethodGet: + showPWForm(w, r, 0) + break + case http.MethodPost: + changePassword(w, r) + break + default: + http.Error(w, "Method not allowed!", http.StatusMethodNotAllowed) + break + } +} + +func showLoginForm(w http.ResponseWriter, r *http.Request, failed bool) { templates.LoginForm(failed).Render(r.Context(), w) } -func loginUser(w http.ResponseWriter, r *http.Request){ +func loginUser(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { log.Println("Error parsing form!", err) @@ -43,32 +61,64 @@ func loginUser(w http.ResponseWriter, r *http.Request){ return } _personal_nummer := r.FormValue("personal_nummer") - if(_personal_nummer == ""){ + if _personal_nummer == "" { log.Println("No personal_nummer provided!") http.Error(w, "No personal_nummer provided", http.StatusBadRequest) return } personal_nummer, err := strconv.Atoi(_personal_nummer) - if(err != nil){ + if err != nil { log.Println("Cannot parse personal nubmer!") http.Error(w, "Cannot parse number", http.StatusBadRequest) return } user, err := (*models.User).GetByPersonalNummer(nil, personal_nummer) - if(err != nil){ + if err != nil { log.Println("No user found under this personal number!") http.Error(w, "No user found!", http.StatusNotFound) } password := r.FormValue("password") - if(user.Login(password)){ + if user.Login(password) { log.Printf("New succesfull user login from %s %s!\n", user.Vorname, user.Name) Session.Put(r.Context(), "user", user.PersonalNummer) http.Redirect(w, r, "/time", http.StatusSeeOther) //with this browser always uses GET - }else{ - showForm(w, r, true) + } else { + showLoginForm(w, r, true) } - -showForm(w, r, false) + showLoginForm(w, r, false) +} + +// change user password and store salted hash in db +func changePassword(w http.ResponseWriter, r *http.Request) { + err := r.ParseForm() + if err != nil { + log.Println("Error parsing form!", err) + http.Error(w, "Error parsing form error", http.StatusBadRequest) + return + } + password := r.FormValue("password") + newPassword := r.FormValue("new_password") + if password == "" || newPassword == "" || newPassword != r.FormValue("new_password_repeat") { + showPWForm(w, r, http.StatusBadRequest) + } + user, err := (*models.User).GetByPersonalNummer(nil, Session.GetInt(r.Context(), "user")) + if err != nil { + log.Println("Error getting user!", err) + showPWForm(w, r, http.StatusBadRequest) + } + auth, err := user.ChangePass(password, newPassword) + if err != nil { + log.Println("Error when changing password!", err) + } + if auth { + showPWForm(w, r, http.StatusOK) + return + } + showPWForm(w, r, http.StatusUnauthorized) +} + +func showPWForm(w http.ResponseWriter, r *http.Request, status int) { + templates.UserForm(status).Render(r.Context(), w) } diff --git a/Backend/main.go b/Backend/main.go index 2db8612..8ba7a39 100644 --- a/Backend/main.go +++ b/Backend/main.go @@ -14,15 +14,13 @@ import ( _ "github.com/lib/pq" ) - - func main() { var err error err = godotenv.Load(".env") if err != nil { log.Println("No .env file found in directory!") - } + } models.DB, err = OpenDatabase() if err != nil { @@ -36,11 +34,11 @@ func main() { server := http.NewServeMux() // handles the different http routes - withMiddleware := ParamsMiddleware(endpoints.TimeHandler) server.HandleFunc("/time/new", endpoints.TimeCreateHandler) - server.Handle("/time", withMiddleware) + server.Handle("/time", ParamsMiddleware(endpoints.TimeHandler)) server.HandleFunc("/logout", endpoints.LogoutHandler) - server.HandleFunc("/", endpoints.LoginHandler) + server.HandleFunc("/user/login", endpoints.LoginHandler) + server.HandleFunc("/user", endpoints.UserHandler) server.Handle("/static/", http.StripPrefix("/static/", fs)) serverSessionMiddleware := endpoints.Session.LoadAndSave(server) @@ -50,8 +48,8 @@ func main() { log.Fatal(http.ListenAndServe(":8080", serverSessionMiddleware)) } -func ParamsMiddleware(next http.HandlerFunc) http.Handler{ - return http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) { +func ParamsMiddleware(next http.HandlerFunc) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { queryParams := r.URL.Query() ctx := context.WithValue(r.Context(), "urlParams", queryParams) next.ServeHTTP(w, r.WithContext(ctx)) diff --git a/Backend/models/user.go b/Backend/models/user.go index adbc41a..4cf9989 100644 --- a/Backend/models/user.go +++ b/Backend/models/user.go @@ -6,11 +6,11 @@ import ( ) type User struct { - CardUID string `json:"card_uid"` - Name string `json:"name"` - Vorname string `json:"vorname"` - PersonalNummer int `json:"personal_nummer"` - Arbeitszeit float32 `json:"arbeitszeit"` + CardUID string `json:"card_uid"` + Name string `json:"name"` + Vorname string `json:"vorname"` + PersonalNummer int `json:"personal_nummer"` + Arbeitszeit float32 `json:"arbeitszeit"` } func (u *User) GetAll() ([]User, error) { @@ -67,7 +67,7 @@ func (u *User) Logout() error { return nil } -func (u *User) GetByPersonalNummer (personalNummer int) (User, error) { +func (u *User) GetByPersonalNummer(personalNummer int) (User, error) { var user User qStr, err := DB.Prepare((`SELECT personal_nummer, card_uid, vorname, nachname, arbeitszeit_per_tag FROM personal_daten WHERE personal_nummer = $1;`)) @@ -76,7 +76,7 @@ func (u *User) GetByPersonalNummer (personalNummer int) (User, error) { } err = qStr.QueryRow(personalNummer).Scan(&user.PersonalNummer, &user.CardUID, &user.Vorname, &user.Name, &user.Arbeitszeit) - if err != nil{ + if err != nil { return user, err } return user, nil @@ -97,3 +97,21 @@ func (u *User) Login(password string) bool { } return loginSuccess } + +// checks if old password matches and changes to new password +// +// returns auth(bool), error +func (u *User) ChangePass(password, newPassword string) (bool, error) { + if !u.Login(password) { + return false, nil + } + qStr, err := DB.Prepare((`UPDATE user_password SET pass_hash = crypt($2, gen_salt('bf')) WHERE personal_nummer = $1;`)) + if err != nil { + return false, err + } + _, err = qStr.Exec(u.PersonalNummer, newPassword) + if err != nil { + return false, err + } + return true, nil +} diff --git a/Backend/static/css/styles.css b/Backend/static/css/styles.css index 50586e6..25acb06 100644 --- a/Backend/static/css/styles.css +++ b/Backend/static/css/styles.css @@ -565,6 +565,9 @@ .mt-1 { margin-top: calc(var(--spacing) * 1); } + .mb-2 { + margin-bottom: calc(var(--spacing) * 2); + } .block { display: block; } @@ -606,21 +609,24 @@ .h-full { height: 100%; } - .w-1 { - width: calc(var(--spacing) * 1); - } - .w-1\/2 { - width: calc(1/2 * 100%); - } .w-2 { width: calc(var(--spacing) * 2); } .w-4 { width: calc(var(--spacing) * 4); } + .w-9 { + width: calc(var(--spacing) * 9); + } + .w-9\/10 { + width: calc(9/10 * 100%); + } .w-\[2px\] { width: 2px; } + .w-\[90\%\] { + width: 90%; + } .w-full { width: 100%; } @@ -697,9 +703,6 @@ border-color: var(--color-neutral-400); } } - .self-end { - align-self: flex-end; - } .justify-self-end { justify-self: flex-end; } @@ -726,15 +729,9 @@ .border-neutral-300 { border-color: var(--color-neutral-300); } - .border-neutral-400 { - border-color: var(--color-neutral-400); - } .border-neutral-900 { border-color: var(--color-neutral-900); } - .border-red-600 { - border-color: var(--color-red-600); - } .bg-accent { background-color: var(--color-accent); } @@ -753,9 +750,6 @@ .bg-purple-600 { background-color: var(--color-purple-600); } - .bg-red-200 { - background-color: var(--color-red-200); - } .bg-red-600 { background-color: var(--color-red-600); } @@ -775,9 +769,9 @@ font-size: var(--text-sm); line-height: var(--tw-leading, var(--text-sm--line-height)); } - .text-xs { - font-size: var(--text-xs); - line-height: var(--tw-leading, var(--text-xs--line-height)); + .text-xl { + font-size: var(--text-xl); + line-height: var(--tw-leading, var(--text-xl--line-height)); } .font-bold { --tw-font-weight: var(--font-weight-bold); @@ -786,12 +780,12 @@ .text-accent { color: var(--color-accent); } + .text-accent-600 { + color: var(--color-accent-600); + } .text-neutral-500 { color: var(--color-neutral-500); } - .text-neutral-600 { - color: var(--color-neutral-600); - } .text-neutral-700 { color: var(--color-neutral-700); } @@ -953,6 +947,11 @@ display: inline; } } + .md\:w-1\/2 { + @media (width >= 48rem) { + width: calc(1/2 * 100%); + } + } .md\:grid-cols-5 { @media (width >= 48rem) { grid-template-columns: repeat(5, minmax(0, 1fr)); diff --git a/Backend/templates/timeComponents.templ b/Backend/templates/timeComponents.templ index aefe297..23bf079 100644 --- a/Backend/templates/timeComponents.templ +++ b/Backend/templates/timeComponents.templ @@ -2,141 +2,140 @@ package templates import ( "arbeitszeitmessung/models" - "net/url" - "time" "fmt" + "net/url" "strconv" + "time" ) -templ inputForm(){ +templ inputForm() { {{ urlParams := ctx.Value("urlParams").(url.Values) user := ctx.Value("user").(models.User) }}
-
-

{user.Vorname + " " + user.Name}

-
-

Überstunden

-

4h 32min

+
+

{ user.Vorname + " " + user.Name }

+
+

Überstunden

+

4h 32min

+
+
+
+ @lineComponent() +
+ + +
+
+
+
-
- // - @lineComponent() -
- - -
-
-
- -
-
} -templ dayComponent(workDay models.WorkDay){ +templ dayComponent(workDay models.WorkDay) { {{ work, pause := workDay.GetWorkTimeString() }}
-
- @timeGaugeComponent(workDay.GetWorkDayProgress(ctx.Value("user").(models.User)), workDay.Day.Equal(time.Now().Truncate(24 * time.Hour)), workDay.RequiresAction()) -
-

{workDay.Day.Format("02.01.2006")}

-

Arbeitszeit:

- if (workDay.RequiresAction()) { -

Bitte anpassen

- }else { -

{work}

- } -

{pause}

+
+ @timeGaugeComponent(workDay.GetWorkDayProgress(ctx.Value("user").(models.User)), workDay.Day.Equal(time.Now().Truncate(24*time.Hour)), workDay.RequiresAction()) +
+

{ workDay.Day.Format("02.01.2006") }

+

Arbeitszeit:

+ if (workDay.RequiresAction()) { +

Bitte anpassen

+ } else { +

{ work }

+ } +

{ pause }

+
+
+
+ @lineComponent() +
+ for _, booking := range workDay.Bookings { + @bookingComponent(booking) + } +
+
+
+ @changeButtonComponent("time-" + workDay.Day.Format("2006-01-02"))
-
-
- @lineComponent() -
- for _, booking := range workDay.Bookings { - @bookingComponent(booking) - } -
-
-
- @changeButtonComponent("time-" + workDay.Day.Format("2006-01-02")) -
} -templ changeButtonComponent(id string){ - } -templ timeGaugeComponent(progress uint8, today bool, warning bool){ +templ timeGaugeComponent(progress uint8, today bool, warning bool) { {{ var bgColor string - switch { - case (warning): + switch { + case (warning): bgColor = "bg-red-600" break - case (progress > 0 && progress < 90): + case (progress > 0 && progress < 90): bgColor = "bg-orange-500" break - case (90 <= progress && progress <=110): + case (90 <= progress && progress <= 110): bgColor = "bg-accent" break - case(progress > 110): + case (progress > 110): bgColor = "bg-purple-600" break - default: + default: bgColor = "bg-neutral-400" break } }} if today { -
-
-
- }else { -
- +
+
+
+ } else { +
} } -templ lineComponent(){ -
- - - -
- - - +templ lineComponent() { +
+ + + +
+ + +
} templ bookingComponent(booking models.Booking) {

- {booking.Timestamp.Format("15:04")} - - {booking.GetBookingType()}

+ { booking.Timestamp.Format("15:04") } + + { booking.GetBookingType() } +

} -templ LegendComponent(){ +templ LegendComponent() {
-
Fehler
-
Arbeitszeit unter regulär
-
Arbeitszeit vollständig
-
Überstunden
-
Keine Buchungen
+
Fehler
+
Arbeitszeit unter regulär
+
Arbeitszeit vollständig
+
Überstunden
+
Keine Buchungen
} diff --git a/Backend/templates/timeComponents_templ.go b/Backend/templates/timeComponents_templ.go index bbd7d1e..93f5cf9 100644 --- a/Backend/templates/timeComponents_templ.go +++ b/Backend/templates/timeComponents_templ.go @@ -47,7 +47,7 @@ func inputForm() templ.Component { var templ_7745c5c3_Var2 string templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(user.Vorname + " " + user.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 18, Col: 64} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 18, Col: 66} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) if templ_7745c5c3_Err != nil { @@ -68,7 +68,7 @@ func inputForm() templ.Component { var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(urlParams.Get("time_from")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 28, Col: 55} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 27, Col: 57} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -81,13 +81,13 @@ func inputForm() templ.Component { var templ_7745c5c3_Var4 string templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(urlParams.Get("time_to")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 29, Col: 53} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 28, Col: 55} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\" name=\"time_to\" class=\"w-full bg-neutral-100 placeholder:text-neutral-400 text-neutral-700 text-sm border border-neutral-0 rounded-md px-3 py-2 transition duration-300 ease focus:outline-none focus:border-neutral-400 hover:border-neutral-300\" placeholder=\"Zeitraum bis...\">
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\" name=\"time_to\" class=\"w-full bg-neutral-100 placeholder:text-neutral-400 text-neutral-700 text-sm border border-neutral-0 rounded-md px-3 py-2 transition duration-300 ease focus:outline-none focus:border-neutral-400 hover:border-neutral-300\" placeholder=\"Zeitraum bis...\">
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -133,7 +133,7 @@ func dayComponent(workDay models.WorkDay) templ.Component { var templ_7745c5c3_Var6 string templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(workDay.Day.Format("Mon")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 48, Col: 94} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 47, Col: 94} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { @@ -146,7 +146,7 @@ func dayComponent(workDay models.WorkDay) templ.Component { var templ_7745c5c3_Var7 string templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(workDay.Day.Format("02.01.2006")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 48, Col: 137} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 47, Col: 139} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { @@ -169,7 +169,7 @@ func dayComponent(workDay models.WorkDay) templ.Component { var templ_7745c5c3_Var8 string templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(work) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 53, Col: 33} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 52, Col: 35} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { @@ -187,7 +187,7 @@ func dayComponent(workDay models.WorkDay) templ.Component { var templ_7745c5c3_Var9 string templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(pause) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 55, Col: 38} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 54, Col: 39} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { @@ -208,7 +208,7 @@ func dayComponent(workDay models.WorkDay) templ.Component { var templ_7745c5c3_Var10 string templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs("time-" + workDay.Day.Format("2006-01-02")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 60, Col: 54} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 59, Col: 56} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) if templ_7745c5c3_Err != nil { @@ -352,7 +352,7 @@ func timeGaugeComponent(progress uint8, today bool, warning bool) templ.Componen var templ_7745c5c3_Var16 string templ_7745c5c3_Var16, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("height: %d%%", int(progress))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 105, Col: 146} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 104, Col: 149} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) if templ_7745c5c3_Err != nil { @@ -447,7 +447,7 @@ func bookingComponent(booking models.Booking) templ.Component { var templ_7745c5c3_Var21 string templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(booking.Timestamp.Format("15:04")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 128, Col: 95} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 126, Col: 97} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) if templ_7745c5c3_Err != nil { @@ -460,7 +460,7 @@ func bookingComponent(booking models.Booking) templ.Component { var templ_7745c5c3_Var22 string templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs("booking_" + strconv.Itoa(booking.CounterId)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 129, Col: 59} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 127, Col: 61} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) if templ_7745c5c3_Err != nil { @@ -473,7 +473,7 @@ func bookingComponent(booking models.Booking) templ.Component { var templ_7745c5c3_Var23 string templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(booking.Timestamp.Format("15:04")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 129, Col: 113} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 127, Col: 117} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) if templ_7745c5c3_Err != nil { @@ -486,7 +486,7 @@ func bookingComponent(booking models.Booking) templ.Component { var templ_7745c5c3_Var24 string templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(booking.GetBookingType()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 130, Col: 27} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 128, Col: 29} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) if templ_7745c5c3_Err != nil { diff --git a/Backend/templates/user.templ b/Backend/templates/user.templ index 847016f..ab1f970 100644 --- a/Backend/templates/user.templ +++ b/Backend/templates/user.templ @@ -1,16 +1,37 @@ package templates -templ LoginForm(failed bool){ +templ LoginForm(failed bool) { @Style()
- -
- - - if failed { -

Login fehlgeschlagen, bitte erneut versuchen!

- } - -
+
+

Benutzer Anmelden

+ + + if failed { +

Login fehlgeschlagen, bitte erneut versuchen!

+ } + +
+
+} + +templ UserForm(status int) { + @Style() +
+
+

Passwort ändern

+ + + + switch { + case status == 401: +

Aktuelles Passwort nicht korrekt!

+ case status >= 400: +

Passwortwechsel fehlgeschlagen, bitte erneut versuchen!

+ case status == 200: +

Passwortänderung erfolgreich

+ } + +
} diff --git a/Backend/templates/user_templ.go b/Backend/templates/user_templ.go index 7cc5269..5b7a5ae 100644 --- a/Backend/templates/user_templ.go +++ b/Backend/templates/user_templ.go @@ -33,7 +33,7 @@ func LoginForm(failed bool) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

Benutzer Anmelden

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -51,4 +51,58 @@ func LoginForm(failed bool) templ.Component { }) } +func UserForm(status int) 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_Var2 := templ.GetChildren(ctx) + if templ_7745c5c3_Var2 == nil { + templ_7745c5c3_Var2 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = Style().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "

Passwort ändern

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + switch { + case status == 401: + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "

Aktuelles Passwort nicht korrekt!

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + case status >= 400: + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "

Passwortwechsel fehlgeschlagen, bitte erneut versuchen!

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + case status == 200: + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "

Passwortänderung erfolgreich

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) +} + var _ = templruntime.GeneratedTemplate diff --git a/DB/initdb/01_create_tables.sql b/DB/initdb/01_create_tables.sql index a2a7aaf..f38b59a 100644 --- a/DB/initdb/01_create_tables.sql +++ b/DB/initdb/01_create_tables.sql @@ -66,3 +66,6 @@ CREATE EXTENSION IF NOT EXISTS pgcrypto; INSERT INTO "personal_daten" ("personal_nummer", "aktiv_beschaeftigt", "vorname", "nachname", "geburtsdatum", "plz", "adresse", "geschlecht", "card_uid", "hauptbeschaeftigungs_ort", "arbeitszeit_per_tag", "arbeitszeit_min_start", "arbeitszeit_max_ende", "vorgesetzter_pers_nr") VALUES (123, 't', 'Max', 'Mustermann', '2003-02-01', '08963', 'Altenburger Str. 44A', 1, 'acde-edca', 1, 7.5, '07:00:00', '20:00:00', 0); + +INSERT INTO "user_password" ("personal_nummer", "pass_hash") VALUES +(123, crypt('max_pass', gen_salt('bf'))); diff --git a/DB/initdb/02_create_user.sh b/DB/initdb/02_create_user.sh index fda0630..325dbd6 100644 --- a/DB/initdb/02_create_user.sh +++ b/DB/initdb/02_create_user.sh @@ -12,3 +12,5 @@ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-E EOSQL echo "User creation and permissions setup complete!" + +# psql -v ON_ERROR_STOP=1 --username root --dbname arbeitszeitmessung