diff --git a/main.go b/main.go index 66acaae..83c0be9 100644 --- a/main.go +++ b/main.go @@ -8,10 +8,11 @@ import ( "net/http" "os" - "github.com/go-sql-driver/mysql" - "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" + "github.com/go-sql-driver/mysql" + + "log101-blog-services/middleware" ) var db *sql.DB @@ -101,7 +102,10 @@ func main() { } corsConfig.AllowHeaders = []string{"hx-current-url", "hx-request"} + + // Middlewares r.Use(cors.New(corsConfig)) + r.Use(middleware.AnonymizeIPMiddleware()) var hxPostUrl string if ginMode == gin.DebugMode { @@ -145,7 +149,7 @@ func main() { } // Add the new emoji entry to the database - _, err := db.Exec("INSERT INTO emoji_clicks (post_id, emoji) VALUES (?, ?)", postId, emoji) + _, err := db.Exec("INSERT INTO emoji_clicks (user_anon_data, post_id, emoji) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE emoji = ?", c.Request.RemoteAddr, postId, emoji, emoji) if err != nil { c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{"error": "error writing to database", "postId": postId, "hxPostUrl": hxPostUrl}) return diff --git a/middleware/middleware.go b/middleware/middleware.go new file mode 100644 index 0000000..6761e07 --- /dev/null +++ b/middleware/middleware.go @@ -0,0 +1,48 @@ +package middleware + +import ( + "net/netip" + + "github.com/gin-gonic/gin" +) + +// AnonymizeIPMiddleware masks the last segment of IPv4 addresses +// and the last 80 bits of IPv6 addresses. +func AnonymizeIPMiddleware() gin.HandlerFunc { + return func(c *gin.Context) { + ip := c.ClientIP() + anonymizedIP := anonymizeIP(ip) + c.Request.RemoteAddr = anonymizedIP + c.Next() + } +} + +// anonymizeIP masks the last segment of IPv4 addresses +// and the last 80 bits of IPv6 addresses. +func anonymizeIP(ip string) string { + parsedIP, err := netip.ParseAddr(ip) + if err != nil { + // If there's an error parsing the IP, return the original IP + return ip + } + + if parsedIP.Is4() { + // Mask the last octet for IPv4 + ipPrefix, err := parsedIP.Prefix(24) + if err != nil { + return ip + } + + return ipPrefix.Masked().String() + } else if parsedIP.Is6() { + // Mask the last 80 bits for IPv6 + ipPrefix, err := parsedIP.Prefix(48) + if err != nil { + return ip + } + return ipPrefix.Masked().String() + } + + // If it's neither IPv4 nor IPv6, return the original IP + return ip +} diff --git a/schema.sql b/schema.sql index cd01a56..413ae5c 100644 --- a/schema.sql +++ b/schema.sql @@ -5,6 +5,7 @@ USE emojis; CREATE TABLE IF NOT EXISTS emoji_clicks ( id INT PRIMARY KEY AUTO_INCREMENT, + user_anon_data TEXT NOT NULL, post_id TEXT NOT NULL, emoji TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP