From 8b6da48e8c285b15c1f78d8268caec4a4e1283f5 Mon Sep 17 00:00:00 2001 From: jbergner Date: Thu, 12 Jun 2025 16:04:05 +0200 Subject: [PATCH] Updates und Bugfixes --- main.go | 158 +++++++++++++++++++++++++---- static/css/main.css | 6 +- static/templates/base.html | 10 +- static/templates/kontaktliste.html | 6 +- 4 files changed, 147 insertions(+), 33 deletions(-) diff --git a/main.go b/main.go index af3376f..7eb7ecf 100644 --- a/main.go +++ b/main.go @@ -15,6 +15,7 @@ import ( "os/signal" "strconv" "strings" + "sync" "syscall" "time" @@ -114,6 +115,20 @@ type Contact struct { LocationId sql.NullInt64 } +type SimplifiedContact struct { + Id int + OwnerId sql.NullInt64 + AdUserId sql.NullInt64 + DisplayName string + Phone string + Mobile string + Homeoffice string + Email string + Room string + DepartmentId string + LocationId string +} + type ContactKeywordLink struct { Contact sql.NullInt64 Keyword sql.NullInt64 @@ -131,6 +146,12 @@ type DataPort struct { /*Links []ContactKeywordLink*/ } +type SimplifiedDataPort struct { + Contacts []SimplifiedContact + Keywords []Keyword + /*Links []ContactKeywordLink*/ +} + /* ################################################################## */ /* ENDE DER STRUKTUREN */ /* ################################################################## */ @@ -144,8 +165,15 @@ func (s *Server) privateHello(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hallo %s - hier deine persönlichen Daten", user) } -func GetDataReturnDataPort(QueryContact, QueryKeyword string) DataPort { - var contList []Contact +func NullInt64ToString(n sql.NullInt64) string { + if !n.Valid { + return "" + } + return strconv.FormatInt(n.Int64, 10) +} + +func GetDataReturnDataPort(QueryContact, QueryKeyword string) SimplifiedDataPort { + var contList []SimplifiedContact var keywordList []Keyword if QueryContact != "" { @@ -154,7 +182,7 @@ func GetDataReturnDataPort(QueryContact, QueryKeyword string) DataPort { fmt.Println("a", err) } for rowsContact.Next() { - var c Contact + var c SimplifiedContact err = rowsContact.Scan(&c.Id, &c.OwnerId, &c.AdUserId, &c.DisplayName, &c.Phone, &c.Mobile, &c.Homeoffice, &c.Email, &c.Room, &c.DepartmentId, &c.LocationId) if err != nil { fmt.Println("b", err) @@ -178,11 +206,15 @@ func GetDataReturnDataPort(QueryContact, QueryKeyword string) DataPort { } } - return DataPort{Contacts: contList, Keywords: keywordList} + return SimplifiedDataPort{Contacts: contList, Keywords: keywordList} +} + +func makeContactTableJoin() string { + return "SELECT c.contact_id, c.contact_owner_id, c.contact_aduser_id, c.contact_displayname, c.contact_phone, c.contact_mobile, c.contact_homeoffice, c.contact_email, c.contact_room, d.department_name, l.location_name FROM contact c JOIN department d ON (c.contact_department_id = d.department_id) JOIN location l ON (c.contact_location_id = l.location_id) " } func (s *Server) ListPublic(w http.ResponseWriter, r *http.Request) { - D := GetDataReturnDataPort("SELECT * FROM contact c WHERE c.contact_owner_id = -1;", "SELECT * FROM keyword c WHERE c.keyword_owner = -1;") + D := GetDataReturnDataPort(makeContactTableJoin()+"WHERE c.contact_owner_id = -1;", "SELECT * FROM keyword c WHERE c.keyword_owner = -1;") funcs := template.FuncMap{"now": time.Now} templatesDir := getenv("BLOG_TEMPLATES_DIR", "./static/templates") layout := template.Must(template.New("base").Funcs(funcs).ParseFiles(templatesDir + "/base.html")) @@ -194,19 +226,31 @@ func (s *Server) ListPublic(w http.ResponseWriter, r *http.Request) { } func (s *Server) ListPrivate(w http.ResponseWriter, r *http.Request) { - D := GetDataReturnDataPort("SELECT * FROM contact c WHERE c.contact_owner_id = -1 OR c.contact_owner_id = 1;", "SELECT * FROM keyword c WHERE c.keyword_owner = -1 OR c.keyword_owner = 1;") + user := r.Context().Value(userKey).(string) + /*fmt.Fprintf(w, "Hallo %s - hier deine persönlichen Daten", user)*/ + fmt.Println("Hallo "+user+" hier deine persönlichen Daten", user) + + D := GetDataReturnDataPort(makeContactTableJoin()+"WHERE c.contact_owner_id = -1 OR c.contact_owner_id = 1;", "SELECT * FROM keyword c WHERE c.keyword_owner = -1 OR c.keyword_owner = 1;") funcs := template.FuncMap{"now": time.Now} templatesDir := getenv("BLOG_TEMPLATES_DIR", "./static/templates") layout := template.Must(template.New("base").Funcs(funcs).ParseFiles(templatesDir + "/base.html")) tplFull := template.Must(layout.Clone()) template.Must(tplFull.Funcs(funcs).ParseFiles(templatesDir+"/kontaktliste.html", templatesDir+"/schlagwortliste.html")) tplFull.ExecuteTemplate(w, "layout", D) - /*user := r.Context().Value(userKey).(string) - fmt.Fprintf(w, "Hallo %s - hier deine persönlichen Daten", user)*/ + } func (s *Server) XcontactPublic(w http.ResponseWriter, r *http.Request) { - + if err := r.ParseForm(); err != nil { + http.Error(w, "bad request", http.StatusBadRequest) + return + } + sparam := strings.TrimSpace(r.Form.Get("search")) + D := GetDataReturnDataPort(makeContactTableJoin()+"WHERE c.contact_owner_id = -1 AND (c.contact_displayname LIKE '%"+sparam+"%' OR c.contact_phone LIKE '%"+sparam+"%' OR c.contact_mobile LIKE '%"+sparam+"%' OR c.contact_homeoffice LIKE '%"+sparam+"%');", "SELECT * FROM keyword c WHERE c.keyword_owner = -1;") + funcs := template.FuncMap{"now": time.Now} + templatesDir := getenv("BLOG_TEMPLATES_DIR", "./static/templates") + layout := template.Must(template.New("kontakt").Funcs(funcs).ParseFiles(templatesDir + "/kontaktliste.html")) + layout.ExecuteTemplate(w, "kontakt", D) } func (s *Server) XcontactPrivate(w http.ResponseWriter, r *http.Request) { @@ -214,7 +258,16 @@ func (s *Server) XcontactPrivate(w http.ResponseWriter, r *http.Request) { } func (s *Server) XdepartmentPublic(w http.ResponseWriter, r *http.Request) { - + if err := r.ParseForm(); err != nil { + http.Error(w, "bad request", http.StatusBadRequest) + return + } + sparam := strings.TrimSpace(r.Form.Get("search")) + D := GetDataReturnDataPort(makeContactTableJoin()+"WHERE c.contact_owner_id = -1 AND (d.department_name LIKE '%"+sparam+"%');", "SELECT * FROM keyword c WHERE c.keyword_owner = -1;") + funcs := template.FuncMap{"now": time.Now} + templatesDir := getenv("BLOG_TEMPLATES_DIR", "./static/templates") + layout := template.Must(template.New("kontakt").Funcs(funcs).ParseFiles(templatesDir + "/kontaktliste.html")) + layout.ExecuteTemplate(w, "kontakt", D) } func (s *Server) XdepartmentPrivate(w http.ResponseWriter, r *http.Request) { @@ -222,7 +275,16 @@ func (s *Server) XdepartmentPrivate(w http.ResponseWriter, r *http.Request) { } func (s *Server) XroomPublic(w http.ResponseWriter, r *http.Request) { - + if err := r.ParseForm(); err != nil { + http.Error(w, "bad request", http.StatusBadRequest) + return + } + sparam := strings.TrimSpace(r.Form.Get("search")) + D := GetDataReturnDataPort(makeContactTableJoin()+"WHERE c.contact_owner_id = -1 AND (c.contact_room LIKE '%"+sparam+"%');", "SELECT * FROM keyword c WHERE c.keyword_owner = -1;") + funcs := template.FuncMap{"now": time.Now} + templatesDir := getenv("BLOG_TEMPLATES_DIR", "./static/templates") + layout := template.Must(template.New("kontakt").Funcs(funcs).ParseFiles(templatesDir + "/kontaktliste.html")) + layout.ExecuteTemplate(w, "kontakt", D) } func (s *Server) XroomPrivate(w http.ResponseWriter, r *http.Request) { @@ -230,7 +292,16 @@ func (s *Server) XroomPrivate(w http.ResponseWriter, r *http.Request) { } func (s *Server) XlocationPublic(w http.ResponseWriter, r *http.Request) { - + if err := r.ParseForm(); err != nil { + http.Error(w, "bad request", http.StatusBadRequest) + return + } + sparam := strings.TrimSpace(r.Form.Get("search")) + D := GetDataReturnDataPort(makeContactTableJoin()+"WHERE c.contact_owner_id = -1 AND (l.location_name LIKE '%"+sparam+"%');", "SELECT * FROM keyword c WHERE c.keyword_owner = -1;") + funcs := template.FuncMap{"now": time.Now} + templatesDir := getenv("BLOG_TEMPLATES_DIR", "./static/templates") + layout := template.Must(template.New("kontakt").Funcs(funcs).ParseFiles(templatesDir + "/kontaktliste.html")) + layout.ExecuteTemplate(w, "kontakt", D) } func (s *Server) XlocationPrivate(w http.ResponseWriter, r *http.Request) { @@ -238,15 +309,42 @@ func (s *Server) XlocationPrivate(w http.ResponseWriter, r *http.Request) { } func (s *Server) XkeywordPublic(w http.ResponseWriter, r *http.Request) { - + if err := r.ParseForm(); err != nil { + http.Error(w, "bad request", http.StatusBadRequest) + return + } + sparam := strings.TrimSpace(r.Form.Get("search")) + D := GetDataReturnDataPort(makeContactTableJoin()+"WHERE c.contact_owner_id = -1 AND (l.location_name LIKE '%"+sparam+"%');", "SELECT * FROM keyword c WHERE c.keyword_owner = -1 AND c.keyword_name LIKE '%"+sparam+"%';") + funcs := template.FuncMap{"now": time.Now} + templatesDir := getenv("BLOG_TEMPLATES_DIR", "./static/templates") + layout := template.Must(template.New("schlagwort").Funcs(funcs).ParseFiles(templatesDir + "/schlagwortliste.html")) + layout.ExecuteTemplate(w, "schlagwort", D) } func (s *Server) XkeywordPrivate(w http.ResponseWriter, r *http.Request) { - + if err := r.ParseForm(); err != nil { + http.Error(w, "bad request", http.StatusBadRequest) + return + } + sparam := strings.TrimSpace(r.Form.Get("search")) + D := GetDataReturnDataPort(makeContactTableJoin()+"WHERE c.contact_owner_id = -1 AND (l.location_name LIKE '%"+sparam+"%');", "SELECT * FROM keyword c WHERE (c.keyword_owner = -1 OR c.keyword_owner = 1) AND c.keyword_name LIKE '%"+sparam+"%';") + funcs := template.FuncMap{"now": time.Now} + templatesDir := getenv("BLOG_TEMPLATES_DIR", "./static/templates") + layout := template.Must(template.New("schlagwort").Funcs(funcs).ParseFiles(templatesDir + "/schlagwortliste.html")) + layout.ExecuteTemplate(w, "schlagwort", D) } func (s *Server) XkwbctPublic(w http.ResponseWriter, r *http.Request) { - + if err := r.ParseForm(); err != nil { + http.Error(w, "bad request", http.StatusBadRequest) + return + } + sparam := strings.TrimSpace(r.Form.Get("cid")) + D := GetDataReturnDataPort(makeContactTableJoin()+"WHERE c.contact_owner_id = -1 AND (l.location_name LIKE '%"+sparam+"%');", "SELECT c.* FROM keyword c JOIN contactkeyword z ON (z.contactkeyword_keyword = c.keyword_id) WHERE z.contactkeyword_contact = "+sparam+";") + funcs := template.FuncMap{"now": time.Now} + templatesDir := getenv("BLOG_TEMPLATES_DIR", "./static/templates") + layout := template.Must(template.New("schlagwort").Funcs(funcs).ParseFiles(templatesDir + "/schlagwortliste.html")) + layout.ExecuteTemplate(w, "schlagwort", D) } func (s *Server) XkwbctPrivate(w http.ResponseWriter, r *http.Request) { @@ -264,6 +362,22 @@ func (s *Server) XctbkwPrivate(w http.ResponseWriter, r *http.Request) { var CFG Config var DB *sql.DB +type Ranger struct { + mu sync.RWMutex + xContacts map[string]struct{} +} + +/*func newRanger() *Ranger { + return &Ranger{ + blocks: make(map[string]map[netip.Prefix]struct{}), + whites: make(map[netip.Addr]struct{}), + } +}*/ + +type XServer struct { + ranger *Ranger +} + func main() { // Signal-Kanal einrichten @@ -283,7 +397,7 @@ func main() { templatesDir := getenv("BLOG_TEMPLATES_DIR", "./static/templates") CFG = Config{ - DSN: "hikos:hikos@tcp(10.10.5.31:3306)/hikos?parseTime=true", + DSN: "hikos:hikos@tcp(db-mysql-ubnt-a.stadt-hilden.de:3306)/hikos?parseTime=true", LDAPURL: "ldaps://ldaps.example.com:636", LDAPBindPattern: "uid=%s,ou=users,dc=example,dc=com", SessionTTL: 24 * time.Hour, @@ -322,8 +436,8 @@ func main() { tplFull := template.Must(layout.Clone()) template.Must(tplFull.Funcs(funcs).ParseFiles(templatesDir+"/kontaktliste.html", templatesDir+"/schlagwortliste.html")) - tplKontakt := template.Must(template.New("kontakt").Funcs(funcs).ParseFiles(templatesDir + "/kontaktliste.html")) - tplSchlagwort := template.Must(template.New("kontakt").Funcs(funcs).ParseFiles(templatesDir + "/schlagwortliste.html")) + /*tplKontakt := template.Must(template.New("kontakt").Funcs(funcs).ParseFiles(templatesDir + "/kontaktliste.html")) + tplSchlagwort := template.Must(template.New("kontakt").Funcs(funcs).ParseFiles(templatesDir + "/schlagwortliste.html"))*/ layoutSSO := template.Must(template.New("sso").Funcs(funcs).ParseFiles(templatesDir + "/login.html")) @@ -349,7 +463,7 @@ func main() { mux.Handle("/htmx/keywordbycontact", srv.authAware(false, http.HandlerFunc(srv.XkwbctPublic), http.HandlerFunc(srv.XkwbctPrivate))) mux.Handle("/htmx/contactbykeyword", srv.authAware(false, http.HandlerFunc(srv.XctbkwPublic), http.HandlerFunc(srv.XctbkwPrivate))) - mux.HandleFunc("/htmx/contact", func(w http.ResponseWriter, r *http.Request) { + /*mux.HandleFunc("/htmx/contact", func(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { http.Error(w, "bad request", http.StatusBadRequest) return @@ -391,7 +505,7 @@ func main() { mux.HandleFunc("/htmx/schlagwortbykontakt", func(w http.ResponseWriter, r *http.Request) { tplSchlagwort.ExecuteTemplate(w, "schlagwort", nil) - }) + })*/ mux.Handle("/static/", cacheControl(http.StripPrefix("/static/", http.FileServer(http.Dir(staticDir))))) @@ -555,7 +669,7 @@ func (s *Server) loginHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, "internal error", http.StatusInternalServerError) return } - http.SetCookie(w, &http.Cookie{Name: "session_token", Value: token, Expires: time.Now().Add(s.cfg.SessionTTL), Path: "/", Secure: true, HttpOnly: true, SameSite: http.SameSiteStrictMode}) + http.SetCookie(w, &http.Cookie{Name: "session_token", Value: token, Expires: time.Now().Add(s.cfg.SessionTTL), Path: "/", Secure: false, HttpOnly: true, SameSite: http.SameSiteStrictMode}) http.Redirect(w, r, "/", http.StatusMovedPermanently) } @@ -596,7 +710,7 @@ func (s *Server) authAware(required bool, unauth, auth http.Handler) http.Handle if required { if !isAuth { - http.Redirect(w, r, "/login", http.StatusFound) + http.Redirect(w, r, "/sso", http.StatusFound) return } auth.ServeHTTP(w, r) // C diff --git a/static/css/main.css b/static/css/main.css index 207f296..7f41cb1 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -35,7 +35,7 @@ } /* Dark mode (optional) */ - @media (prefers-color-scheme: dark) { + /*@media (prefers-color-scheme: dark) { :root { --bg: #161b22; --bg-alt: #161b22; @@ -48,7 +48,7 @@ --code-border: #30363d; --shadow: 0 4px 16px rgba(0,0,0,.32); } - } + }*/ * { margin: 0; @@ -175,7 +175,7 @@ th, td { border: 1px solid #ddd; /* Beispiel für einen Rahmen */ - padding: 8px; + padding: 4px; text-align: center; /* Beispiel für Textzentrierung */ } diff --git a/static/templates/base.html b/static/templates/base.html index 6fd057a..bfe3d73 100644 --- a/static/templates/base.html +++ b/static/templates/base.html @@ -14,16 +14,16 @@
- - - - + + + +
{{ template "kontakt" . }}
- +
{{ template "schlagwort" . }}
diff --git a/static/templates/kontaktliste.html b/static/templates/kontaktliste.html index d314889..9be31bc 100644 --- a/static/templates/kontaktliste.html +++ b/static/templates/kontaktliste.html @@ -23,14 +23,14 @@ {{ range .Contacts }} - + {{ if .DisplayName }}{{ .DisplayName }}{{ end }} {{ if .Phone }}{{ .Phone }}{{ end }} {{ if .Mobile }}{{ .Mobile }}{{ end }} {{ if .Homeoffice }}{{ .Homeoffice }}{{ end }} - {{ if .DepartmentId.Valid }}{{ .DepartmentId.Int64 }}{{ end }} + {{ if .DepartmentId }}{{ .DepartmentId }}{{ end }} {{ if .Room }}{{ .Room }}{{ end }} - {{ if .LocationId.Valid }}{{ .LocationId.Int64 }}{{ end }} + {{ if .LocationId }}{{ .LocationId }}{{ end }} {{ end }}