Compare commits
4 Commits
5f886a46c5
...
5274a165a3
| Author | SHA1 | Date | |
|---|---|---|---|
| 5274a165a3 | |||
| 9987cc226d | |||
| 04f9eb33d4 | |||
| 4a0d3a850a |
@@ -62,8 +62,8 @@ func getBookings(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO add config for timeoffset
|
||||||
tsFrom, err := parseTimestamp(r, "time_from", "2000-01-01")
|
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)
|
log.Println("Error parsing 'from' time", err)
|
||||||
http.Error(w, "Timestamp 'from' cannot be parsed!", http.StatusBadRequest)
|
http.Error(w, "Timestamp 'from' cannot be parsed!", http.StatusBadRequest)
|
||||||
@@ -103,11 +103,12 @@ func updateBooking(w http.ResponseWriter, r *http.Request){
|
|||||||
log.Println("Error getting booking!", err)
|
log.Println("Error getting booking!", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
parsedTime, err := time.Parse("15:04", possibleBooking[0])
|
parsedTime, err := time.ParseInLocation("15:04", possibleBooking[0], time.Local)
|
||||||
if(err != nil){
|
if(err != nil){
|
||||||
log.Println("Error parsing time!", err)
|
log.Println("Error parsing time!", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
log.Println("Parsing time", parsedTime)
|
||||||
booking.UpdateTime(parsedTime)
|
booking.UpdateTime(parsedTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,13 +209,13 @@ func checkLastBooking(b Booking) bool {
|
|||||||
|
|
||||||
func (b *Booking) UpdateTime(newTime time.Time){
|
func (b *Booking) UpdateTime(newTime time.Time){
|
||||||
hour, minute, _ := newTime.Clock()
|
hour, minute, _ := newTime.Clock()
|
||||||
if(hour == b.Timestamp.Local().Hour() && minute == b.Timestamp.Local().Minute()){
|
if(hour == b.Timestamp.Hour() && minute == b.Timestamp.Minute()){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO: add check for time overlap
|
// TODO: add check for time overlap
|
||||||
|
|
||||||
var newBooking Booking
|
var newBooking Booking
|
||||||
newBooking.Timestamp = time.Date(b.Timestamp.Year(), b.Timestamp.Month(), b.Timestamp.Day(), hour, minute, 0, 0, time.Local).UTC()
|
newBooking.Timestamp = time.Date(b.Timestamp.Year(), b.Timestamp.Month(), b.Timestamp.Day(), hour, minute, 0, 0, time.Local)
|
||||||
if(b.CheckInOut < 3){
|
if(b.CheckInOut < 3){
|
||||||
newBooking.CheckInOut = b.CheckInOut + 2
|
newBooking.CheckInOut = b.CheckInOut + 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package models
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
@@ -94,6 +94,19 @@ func (u *User) GetByPersonalNummer (personalNummer int) (User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) Login(password string) bool {
|
func (u *User) Login(password string) bool {
|
||||||
userPassword := strings.ToLower(fmt.Sprintf("%s_%s", u.Vorname, u.Name)) //temp password: "max_mustermann"
|
var loginSuccess bool
|
||||||
return userPassword == password
|
qStr, err := DB.Prepare((`SELECT (pass_hash = crypt($2, pass_hash)) AS pass_hash FROM user_password WHERE personal_nummer = $1;`))
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error preparing db statement", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer qStr.Close()
|
||||||
|
err = qStr.QueryRow(u.PersonalNummer, password).Scan(&loginSuccess)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error queriing db", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return loginSuccess
|
||||||
|
// userPassword := strings.ToLower(fmt.Sprintf("%s_%s", u.Vorname, u.Name)) //temp password: "max_mustermann"
|
||||||
|
// return userPassword == password
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,8 +122,8 @@ templ lineComponent(){
|
|||||||
templ bookingComponent(booking models.Booking) {
|
templ bookingComponent(booking models.Booking) {
|
||||||
<div>
|
<div>
|
||||||
<p class="text-neutral-500">
|
<p class="text-neutral-500">
|
||||||
<span class="text-neutral-700 group-[.edit]:hidden inline">{booking.Timestamp.Local().Format("15:04")}</span>
|
<span class="text-neutral-700 group-[.edit]:hidden inline">{booking.Timestamp.Format("15:04")}</span>
|
||||||
<input name={"booking_" + strconv.Itoa(booking.CounterId)} class="text-neutral-700 group-[.edit]:inline hidden bg-neutral-100 text-sm border border-neutral-200 rounded-md px-3 py-2 transition duration-300 ease focus:outline-none focus:border-neutral-400 hover:border-neutral-300" type="time" value={booking.Timestamp.Local().Format("15:04")} />
|
<input name={"booking_" + strconv.Itoa(booking.CounterId)} type="time" value={booking.Timestamp.Format("15:04")} class="text-neutral-700 group-[.edit]:inline hidden bg-neutral-100 text-sm border border-neutral-200 rounded-md px-3 py-2 transition duration-300 ease focus:outline-none focus:border-neutral-400 hover:border-neutral-300" />
|
||||||
{booking.GetBookingType()}</p>
|
{booking.GetBookingType()}</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -430,9 +430,9 @@ func bookingComponent(booking models.Booking) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var20 string
|
var templ_7745c5c3_Var20 string
|
||||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(booking.Timestamp.Local().Format("15:04"))
|
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(booking.Timestamp.Format("15:04"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 125, Col: 103}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 125, Col: 95}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -451,20 +451,20 @@ func bookingComponent(booking models.Booking) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "\" class=\"text-neutral-700 group-[.edit]:inline hidden bg-neutral-100 text-sm border border-neutral-200 rounded-md px-3 py-2 transition duration-300 ease focus:outline-none focus:border-neutral-400 hover:border-neutral-300\" type=\"time\" value=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "\" type=\"time\" value=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var22 string
|
var templ_7745c5c3_Var22 string
|
||||||
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(booking.Timestamp.Local().Format("15:04"))
|
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(booking.Timestamp.Format("15:04"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 126, Col: 342}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timeComponents.templ`, Line: 126, Col: 113}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "\"> ")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "\" class=\"text-neutral-700 group-[.edit]:inline hidden bg-neutral-100 text-sm border border-neutral-200 rounded-md px-3 py-2 transition duration-300 ease focus:outline-none focus:border-neutral-400 hover:border-neutral-300\"> ")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,34 @@ CREATE TABLE "personal_daten" (
|
|||||||
);
|
);
|
||||||
COMMENT ON COLUMN "personal_daten"."geschlecht" IS '1==weiblich, 2==maennlich, 3==divers';
|
COMMENT ON COLUMN "personal_daten"."geschlecht" IS '1==weiblich, 2==maennlich, 3==divers';
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS "user_password";
|
||||||
|
CREATE TABLE "user_password" (
|
||||||
|
"personal_nummer" int4 NOT NULL PRIMARY KEY,
|
||||||
|
"pass_hash" TEXT,
|
||||||
|
"zuletzt_geandert" timestamp(6) DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION update_zuletzt_geandert()
|
||||||
|
RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
-- Nur wenn hash geändert wurde
|
||||||
|
IF NEW.pass_hash IS DISTINCT FROM OLD.pass_hash THEN
|
||||||
|
NEW.zuletzt_geandert = now();
|
||||||
|
END IF;
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
CREATE TRIGGER pass_hash_update
|
||||||
|
BEFORE UPDATE ON user_password
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION update_zuletzt_geandert();
|
||||||
|
|
||||||
|
-- Adds crypto extension
|
||||||
|
|
||||||
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||||
|
|
||||||
|
|
||||||
-- Insert into personal_daten
|
-- Insert into personal_daten
|
||||||
|
|
||||||
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
|
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
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-E
|
|||||||
CREATE USER $POSTGRES_API_USER WITH ENCRYPTED PASSWORD '$POSTGRES_API_PASSWORD';
|
CREATE USER $POSTGRES_API_USER WITH ENCRYPTED PASSWORD '$POSTGRES_API_PASSWORD';
|
||||||
GRANT CONNECT ON DATABASE $POSTGRES_DB TO $POSTGRES_API_USER;
|
GRANT CONNECT ON DATABASE $POSTGRES_DB TO $POSTGRES_API_USER;
|
||||||
GRANT USAGE ON SCHEMA public TO $POSTGRES_API_USER;
|
GRANT USAGE ON SCHEMA public TO $POSTGRES_API_USER;
|
||||||
GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO $POSTGRES_API_USER;
|
GRANT SELECT, INSERT, UPDATE ON anwesenheit, personal_daten, user_password TO $POSTGRES_API_USER;
|
||||||
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO $POSTGRES_API_USER;
|
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO $POSTGRES_API_USER;
|
||||||
EOSQL
|
EOSQL
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
POSTGRES_ADMIN=root
|
POSTGRES_USER=root
|
||||||
POSTGRES_ADMIN_PASS=very_secure
|
POSTGRES_PASSWORD=very_secure
|
||||||
POSTGRES_USER=api_nuter
|
POSTGRES_API_USER=api_nuter
|
||||||
POSTGRES_PASSWORD=password
|
POSTGRES_API_PASSWORD=password
|
||||||
POSTGRES_PATH=../DB
|
POSTGRES_PATH=../DB
|
||||||
POSTGRES_DB=arbeitszeitmessung
|
POSTGRES_DB=arbeitszeitmessung
|
||||||
EXPOSED_PORT=8000
|
EXPOSED_PORT=8000
|
||||||
|
TZ=Europe/Berlin
|
||||||
|
PGTZ=Europe/Berlin
|
||||||
|
|||||||
Reference in New Issue
Block a user