mirror of
https://github.com/moonD4rk/HackBrowserData.git
synced 2026-05-19 18:58:03 +02:00
feat: add types.Category, data models, and browserdata.Data (#512)
* feat: add new types.Category, data models, and browserdata.Data Phase 1 of architecture refactoring (RFC-001/RFC-002): - types/category.go: Category enum (9 values) replacing DataType (22 values) with String(), IsSensitive(), AllCategories, NonSensitiveCategories() - types/models.go: browser-agnostic data models (LoginEntry, CookieEntry, BookmarkEntry, HistoryEntry, DownloadEntry, CreditCardEntry, StorageEntry, ExtensionEntry) — no encrypted fields, no browser prefixes - types/category_test.go: tests for Category methods - browserdata/browser_data.go: new Data struct with typed slices, coexists with old BrowserData during migration * docs: replace Coveralls badge with Codecov in README * fix: apply review suggestions (is_http_only tag, json tags on Data)
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
package types
|
||||
|
||||
// Category represents a kind of browser data.
|
||||
// It is browser-agnostic — a password is a password regardless of which browser it came from.
|
||||
type Category int
|
||||
|
||||
const (
|
||||
Password Category = iota
|
||||
Cookie
|
||||
Bookmark
|
||||
History
|
||||
Download
|
||||
CreditCard
|
||||
Extension
|
||||
LocalStorage
|
||||
SessionStorage
|
||||
)
|
||||
|
||||
// AllCategories returns all supported data categories.
|
||||
var AllCategories = []Category{
|
||||
Password, Cookie, Bookmark, History, Download,
|
||||
CreditCard, Extension, LocalStorage, SessionStorage,
|
||||
}
|
||||
|
||||
// String returns the human-readable name of the category.
|
||||
func (c Category) String() string {
|
||||
switch c {
|
||||
case Password:
|
||||
return "password"
|
||||
case Cookie:
|
||||
return "cookie"
|
||||
case Bookmark:
|
||||
return "bookmark"
|
||||
case History:
|
||||
return "history"
|
||||
case Download:
|
||||
return "download"
|
||||
case CreditCard:
|
||||
return "creditcard"
|
||||
case Extension:
|
||||
return "extension"
|
||||
case LocalStorage:
|
||||
return "localstorage"
|
||||
case SessionStorage:
|
||||
return "sessionstorage"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
// IsSensitive returns whether the category contains sensitive data
|
||||
// that requires explicit opt-in to export.
|
||||
func (c Category) IsSensitive() bool {
|
||||
switch c {
|
||||
case Password, Cookie, CreditCard:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// NonSensitiveCategories returns categories that are safe to export by default.
|
||||
func NonSensitiveCategories() []Category {
|
||||
var cats []Category
|
||||
for _, c := range AllCategories {
|
||||
if !c.IsSensitive() {
|
||||
cats = append(cats, c)
|
||||
}
|
||||
}
|
||||
return cats
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCategory_String(t *testing.T) {
|
||||
tests := []struct {
|
||||
cat Category
|
||||
want string
|
||||
}{
|
||||
{Password, "password"},
|
||||
{Cookie, "cookie"},
|
||||
{Bookmark, "bookmark"},
|
||||
{History, "history"},
|
||||
{Download, "download"},
|
||||
{CreditCard, "creditcard"},
|
||||
{Extension, "extension"},
|
||||
{LocalStorage, "localstorage"},
|
||||
{SessionStorage, "sessionstorage"},
|
||||
{Category(999), "unknown"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
assert.Equal(t, tt.want, tt.cat.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCategory_IsSensitive(t *testing.T) {
|
||||
sensitive := []Category{Password, Cookie, CreditCard}
|
||||
for _, c := range sensitive {
|
||||
assert.True(t, c.IsSensitive(), "%s should be sensitive", c)
|
||||
}
|
||||
|
||||
notSensitive := []Category{Bookmark, History, Download, Extension, LocalStorage, SessionStorage}
|
||||
for _, c := range notSensitive {
|
||||
assert.False(t, c.IsSensitive(), "%s should not be sensitive", c)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllCategories(t *testing.T) {
|
||||
assert.Len(t, AllCategories, 9)
|
||||
}
|
||||
|
||||
func TestNonSensitiveCategories(t *testing.T) {
|
||||
cats := NonSensitiveCategories()
|
||||
assert.Len(t, cats, 6)
|
||||
for _, c := range cats {
|
||||
assert.False(t, c.IsSensitive())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package types
|
||||
|
||||
import "time"
|
||||
|
||||
// LoginEntry represents a single saved login credential.
|
||||
type LoginEntry struct {
|
||||
URL string `json:"url" csv:"url"`
|
||||
Username string `json:"username" csv:"username"`
|
||||
Password string `json:"password" csv:"password"`
|
||||
CreatedAt time.Time `json:"created_at" csv:"created_at"`
|
||||
}
|
||||
|
||||
// CookieEntry represents a single browser cookie.
|
||||
type CookieEntry struct {
|
||||
Host string `json:"host" csv:"host"`
|
||||
Path string `json:"path" csv:"path"`
|
||||
Name string `json:"name" csv:"name"`
|
||||
Value string `json:"value" csv:"value"`
|
||||
IsSecure bool `json:"is_secure" csv:"is_secure"`
|
||||
IsHTTPOnly bool `json:"is_http_only" csv:"is_http_only"`
|
||||
ExpireAt time.Time `json:"expire_at" csv:"expire_at"`
|
||||
CreatedAt time.Time `json:"created_at" csv:"created_at"`
|
||||
}
|
||||
|
||||
// BookmarkEntry represents a single browser bookmark.
|
||||
type BookmarkEntry struct {
|
||||
Name string `json:"name" csv:"name"`
|
||||
URL string `json:"url" csv:"url"`
|
||||
Folder string `json:"folder" csv:"folder"`
|
||||
CreatedAt time.Time `json:"created_at" csv:"created_at"`
|
||||
}
|
||||
|
||||
// HistoryEntry represents a single browser history record.
|
||||
type HistoryEntry struct {
|
||||
URL string `json:"url" csv:"url"`
|
||||
Title string `json:"title" csv:"title"`
|
||||
VisitCount int `json:"visit_count" csv:"visit_count"`
|
||||
LastVisit time.Time `json:"last_visit" csv:"last_visit"`
|
||||
}
|
||||
|
||||
// DownloadEntry represents a single browser download record.
|
||||
type DownloadEntry struct {
|
||||
URL string `json:"url" csv:"url"`
|
||||
TargetPath string `json:"target_path" csv:"target_path"`
|
||||
TotalBytes int64 `json:"total_bytes" csv:"total_bytes"`
|
||||
StartTime time.Time `json:"start_time" csv:"start_time"`
|
||||
EndTime time.Time `json:"end_time" csv:"end_time"`
|
||||
}
|
||||
|
||||
// CreditCardEntry represents a single saved credit card.
|
||||
type CreditCardEntry struct {
|
||||
Name string `json:"name" csv:"name"`
|
||||
Number string `json:"number" csv:"number"`
|
||||
ExpMonth string `json:"exp_month" csv:"exp_month"`
|
||||
ExpYear string `json:"exp_year" csv:"exp_year"`
|
||||
}
|
||||
|
||||
// StorageEntry represents a single key-value pair from local or session storage.
|
||||
type StorageEntry struct {
|
||||
URL string `json:"url" csv:"url"`
|
||||
Key string `json:"key" csv:"key"`
|
||||
Value string `json:"value" csv:"value"`
|
||||
}
|
||||
|
||||
// ExtensionEntry represents a single browser extension.
|
||||
type ExtensionEntry struct {
|
||||
Name string `json:"name" csv:"name"`
|
||||
ID string `json:"id" csv:"id"`
|
||||
Description string `json:"description" csv:"description"`
|
||||
Version string `json:"version" csv:"version"`
|
||||
}
|
||||
Reference in New Issue
Block a user