From fcb696e3a78183bd357c5db586a62797067eccbe Mon Sep 17 00:00:00 2001 From: pommee Date: Tue, 2 Dec 2025 18:10:17 +0100 Subject: [PATCH] chore: add api for fetching specific client history --- backend/api/client.go | 20 ++++++++++++++++++++ backend/api/models/models.go | 7 +++++++ backend/request/repository.go | 18 ++++++++++++++++++ backend/request/service.go | 4 ++++ 4 files changed, 49 insertions(+) diff --git a/backend/api/client.go b/backend/api/client.go index e9a54bc..867dbc1 100644 --- a/backend/api/client.go +++ b/backend/api/client.go @@ -9,6 +9,7 @@ import ( func (api *API) registerClientRoutes() { api.routes.GET("/clients", api.getClients) api.routes.GET("/clientDetails", api.getClientDetails) + api.routes.GET("/clientHistory", api.getClientHistory) api.routes.GET("/topClients", api.getTopClients) } @@ -55,6 +56,25 @@ func (api *API) getClientDetails(c *gin.Context) { }) } +func (api *API) getClientHistory(c *gin.Context) { + clientIP := c.Query("ip") + + if clientIP == "" { + c.JSON(http.StatusInternalServerError, gin.H{"error": "No client ip was provided"}) + return + } + + history, err := api.RequestService.GetClientHistory(clientIP) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, map[string]any{ + "history": history, + }) +} + func (api *API) getTopClients(c *gin.Context) { topClients, err := api.RequestService.GetTopClients() if err != nil { diff --git a/backend/api/models/models.go b/backend/api/models/models.go index 5653087..10560b8 100644 --- a/backend/api/models/models.go +++ b/backend/api/models/models.go @@ -1,5 +1,7 @@ package models +import "time" + type QueryParams struct { Search string Column string @@ -9,3 +11,8 @@ type QueryParams struct { PageSize int Offset int } + +type DomainHistory struct { + Domain string `json:"domain"` + Timestamp time.Time `json:"timestamp"` +} diff --git a/backend/request/repository.go b/backend/request/repository.go index 8daddcd..1f8d69b 100644 --- a/backend/request/repository.go +++ b/backend/request/repository.go @@ -23,6 +23,7 @@ type Repository interface { GetUniqueClientNameAndIP() []database.RequestLog FetchAllClients() (map[string]Client, error) GetClientDetailsWithDomains(clientIP string) (ClientRequestDetails, string, map[string]int, error) + GetClientHistory(clientIP string) ([]models.DomainHistory, error) GetTopBlockedDomains(blockedRequests int) ([]map[string]interface{}, error) GetTopClients() ([]map[string]interface{}, error) CountQueries(search string) (int, error) @@ -368,6 +369,23 @@ func (r *repository) GetClientDetailsWithDomains(clientIP string) (ClientRequest return crd, mostQueriedDomain, domainQueryCounts, nil } +func (r *repository) GetClientHistory(clientIP string) ([]models.DomainHistory, error) { + var history []models.DomainHistory + + err := r.db.Table("request_logs"). + Select("domain, timestamp"). + Where("client_ip = ?", clientIP). + Order("timestamp DESC"). + Limit(1000). + Scan(&history).Error + + if err != nil { + return nil, err + } + + return history, nil +} + func (r *repository) GetTopBlockedDomains(blockedRequests int) ([]map[string]interface{}, error) { var rows []struct { Domain string `gorm:"column:domain"` diff --git a/backend/request/service.go b/backend/request/service.go index 2a17a0e..5eda588 100644 --- a/backend/request/service.go +++ b/backend/request/service.go @@ -64,6 +64,10 @@ func (s *Service) GetClientDetailsWithDomains(clientIP string) (ClientRequestDet return s.repository.GetClientDetailsWithDomains(clientIP) } +func (s *Service) GetClientHistory(clientIP string) ([]models.DomainHistory, error) { + return s.repository.GetClientHistory(clientIP) +} + func (s *Service) GetTopBlockedDomains(blockedRequests int) ([]map[string]interface{}, error) { return s.repository.GetTopBlockedDomains(blockedRequests) }