Collect distinct visitor IP addresses
This commit is contained in:
parent
382c6df96c
commit
ff2eb285eb
|
@ -46,13 +46,20 @@ func LoginRequired(handler http.Handler) http.Handler {
|
|||
}
|
||||
|
||||
// Ping LastLoginAt for long lived sessions, but not if impersonated.
|
||||
var pingLastLoginAt bool
|
||||
if time.Since(user.LastLoginAt) > config.LastLoginAtCooldown && !session.Impersonated(r) {
|
||||
user.LastLoginAt = time.Now()
|
||||
pingLastLoginAt = true
|
||||
if err := user.Save(); err != nil {
|
||||
log.Error("LoginRequired: couldn't refresh LastLoginAt for user %s: %s", user.Username, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Log the last visit of their current IP address.
|
||||
if err := models.PingIPAddress(r, user, pingLastLoginAt); err != nil {
|
||||
log.Error("LoginRequired: couldn't ping user %s IP address: %s", user.Username, err)
|
||||
}
|
||||
|
||||
// Ask the user for their birthdate?
|
||||
if AgeGate(user, w, r) {
|
||||
return
|
||||
|
@ -115,6 +122,11 @@ func CertRequired(handler http.Handler) http.Handler {
|
|||
return
|
||||
}
|
||||
|
||||
// Log the last visit of their current IP address.
|
||||
if err := models.PingIPAddress(r, currentUser, false); err != nil {
|
||||
log.Error("CertRequired: couldn't ping user %s IP address: %s", currentUser.Username, err)
|
||||
}
|
||||
|
||||
// Are they banned?
|
||||
if currentUser.Status == models.UserStatusBanned {
|
||||
session.LogoutUser(w, r)
|
||||
|
|
|
@ -54,6 +54,7 @@ func DeleteUser(user *models.User) error {
|
|||
{"Profile Fields", DeleteProfile},
|
||||
{"User Notes", DeleteUserNotes},
|
||||
{"Change Logs", DeleteChangeLogs},
|
||||
{"IP Addresses", DeleteIPAddresses},
|
||||
}
|
||||
for _, item := range todo {
|
||||
if err := item.Fn(user.ID); err != nil {
|
||||
|
@ -350,3 +351,13 @@ func DeleteChangeLogs(userID uint64) error {
|
|||
).Delete(&models.ChangeLog{})
|
||||
return result.Error
|
||||
}
|
||||
|
||||
// DeleteIPAddresses scrubs data for deleting a user.
|
||||
func DeleteIPAddresses(userID uint64) error {
|
||||
log.Error("DeleteUser: DeleteIPAddresses(%d)", userID)
|
||||
result := models.DB.Where(
|
||||
"user_id = ?",
|
||||
userID,
|
||||
).Delete(&models.IPAddress{})
|
||||
return result.Error
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ func ExportModels(zw *zip.Writer, user *models.User) error {
|
|||
{"UserNote", ExportUserNoteTable},
|
||||
{"ChangeLog", ExportChangeLogTable},
|
||||
{"TwoFactor", ExportTwoFactorTable},
|
||||
{"IPAddress", ExportIPAddressTable},
|
||||
}
|
||||
for _, item := range todo {
|
||||
log.Info("Exporting data model: %s", item.Step)
|
||||
|
@ -428,3 +429,18 @@ func ExportTwoFactorTable(zw *zip.Writer, user *models.User) error {
|
|||
|
||||
return ZipJson(zw, "two_factor.json", items)
|
||||
}
|
||||
|
||||
func ExportIPAddressTable(zw *zip.Writer, user *models.User) error {
|
||||
var (
|
||||
items = []*models.IPAddress{}
|
||||
query = models.DB.Model(&models.IPAddress{}).Where(
|
||||
"user_id = ?",
|
||||
user.ID,
|
||||
).Find(&items)
|
||||
)
|
||||
if query.Error != nil {
|
||||
return query.Error
|
||||
}
|
||||
|
||||
return ZipJson(zw, "ip_addresses.json", items)
|
||||
}
|
||||
|
|
74
pkg/models/ip_addresses.go
Normal file
74
pkg/models/ip_addresses.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"code.nonshy.com/nonshy/website/pkg/log"
|
||||
"code.nonshy.com/nonshy/website/pkg/utility"
|
||||
)
|
||||
|
||||
// IPAddress table to log which networks users have logged in from.
|
||||
type IPAddress struct {
|
||||
ID uint64 `gorm:"primaryKey"`
|
||||
UserID uint64 `gorm:"index"`
|
||||
IPAddress string `gorm:"index"`
|
||||
NumberVisits uint64 // count of times their LastLoginAt pinged from this address
|
||||
CreatedAt time.Time // first time seen
|
||||
UpdatedAt time.Time // last time seen
|
||||
}
|
||||
|
||||
// PingIPAddress logs or upserts the user's current IP address into the IPAddress table.
|
||||
func PingIPAddress(r *http.Request, user *User, incrementVisit bool) error {
|
||||
var (
|
||||
addr = utility.IPAddress(r)
|
||||
ip *IPAddress
|
||||
)
|
||||
|
||||
// Have we seen it before?
|
||||
ip, err := LoadUserIPAddress(user, addr)
|
||||
if err != nil {
|
||||
// Insert it.
|
||||
log.Debug("User %s IP %s seen for the first time", user.Username, addr)
|
||||
ip = &IPAddress{
|
||||
UserID: user.ID,
|
||||
IPAddress: addr,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
result := DB.Create(ip)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
}
|
||||
|
||||
// Are we refreshing the NumberVisits count? Note: this happens each
|
||||
// time the main website will refresh the user LastLoginAt.
|
||||
if incrementVisit || ip.NumberVisits == 0 {
|
||||
ip.NumberVisits++
|
||||
}
|
||||
|
||||
// Ping the update.
|
||||
ip.UpdatedAt = time.Now()
|
||||
return ip.Save()
|
||||
}
|
||||
|
||||
func LoadUserIPAddress(user *User, ipAddr string) (*IPAddress, error) {
|
||||
var ip = &IPAddress{}
|
||||
var result = DB.Model(&IPAddress{}).Where(
|
||||
"user_id = ? AND ip_address = ?",
|
||||
user.ID, ipAddr,
|
||||
).First(&ip)
|
||||
return ip, result.Error
|
||||
}
|
||||
|
||||
// Save photo.
|
||||
func (ip *IPAddress) Save() error {
|
||||
result := DB.Save(ip)
|
||||
return result.Error
|
||||
}
|
||||
|
||||
// Delete the DB entry.
|
||||
func (ip *IPAddress) Delete() error {
|
||||
return DB.Delete(ip).Error
|
||||
}
|
|
@ -32,4 +32,5 @@ func AutoMigrate() {
|
|||
DB.AutoMigrate(&UserNote{})
|
||||
DB.AutoMigrate(&TwoFactor{})
|
||||
DB.AutoMigrate(&ChangeLog{})
|
||||
DB.AutoMigrate(&IPAddress{})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user