cookie ready

This commit is contained in:
2026-05-13 22:34:11 +02:00
parent 8c4e664ca8
commit 1b53c1c199
16 changed files with 798 additions and 146 deletions
+98 -11
View File
@@ -19,9 +19,11 @@ import (
)
type Service struct {
db *gorm.DB
prefix string
version string
db *gorm.DB
prefix string
version string
explicitCookieName string
domainCookie string
}
type defaults struct {
@@ -33,8 +35,14 @@ type defaults struct {
CookieHours int64
}
func NewService(db *gorm.DB, prefix, version string) *Service {
return &Service{db: db, prefix: prefix, version: version}
func NewService(db *gorm.DB, prefix, version, explicitCookieName, domainCookie string) *Service {
return &Service{
db: db,
prefix: prefix,
version: version,
explicitCookieName: explicitCookieName,
domainCookie: domainCookie,
}
}
func (s *Service) NewAnonymous(ctx context.Context, req *http.Request, cookieName string) (*pscookie.SessionContext, error) {
@@ -115,15 +123,19 @@ func (s *Service) RefreshExpiry(ctx context.Context, session *pscookie.SessionCo
}
func (s *Service) ResolveCookieName(ctx context.Context, req *http.Request) (string, error) {
if s != nil && strings.TrimSpace(s.explicitCookieName) != "" {
return s.explicitCookieName, nil
}
if s == nil || s.db == nil {
return "", fmt.Errorf("prestashop session service is not initialized")
}
host := requestHost(req)
requestedHost := requestHost(req)
shop, err := s.loadCookieShopContext(ctx, req)
if err != nil {
return "", err
}
host := cookieDomainSource(shop, requestedHost)
baseName := "ps-s" + strconv.FormatInt(shop.ShopID, 10)
sharedDomains := []string(nil)
@@ -135,10 +147,32 @@ func (s *Service) ResolveCookieName(ctx context.Context, req *http.Request) (str
}
}
sum := md5.Sum([]byte(s.version + baseName + prestashopCookieDomain(host, sharedDomains)))
domain := overrideCookieHashDomain(s.domainCookie)
if domain == "" {
domain = prestashopCookieDomain(host, sharedDomains)
}
sum := md5.Sum([]byte(s.version + baseName + domain))
return fmt.Sprintf("PrestaShop-%x", sum), nil
}
func (s *Service) ResolveCookiePath(ctx context.Context, req *http.Request) (string, error) {
if s == nil || s.db == nil {
return "", fmt.Errorf("prestashop session service is not initialized")
}
shop, err := s.loadCookieShopContext(ctx, req)
if err != nil {
return "", err
}
path := normalizeCookiePath(shop.PhysicalURI)
if path == "" {
return "/", nil
}
return path, nil
}
func (s *Service) loadDefaults(ctx context.Context) (*defaults, error) {
def := &defaults{
LanguageID: 1,
@@ -334,6 +368,9 @@ type cookieShopContext struct {
ShopID int64 `gorm:"column:id_shop"`
ShopGroupID int64 `gorm:"column:id_shop_group"`
ShareOrder bool `gorm:"column:share_order"`
Domain string `gorm:"column:domain"`
DomainSSL string `gorm:"column:domain_ssl"`
PhysicalURI string `gorm:"column:physical_uri"`
URI string `gorm:"column:uri"`
Main bool `gorm:"column:main"`
}
@@ -348,7 +385,9 @@ func (s *Service) loadCookieShopContext(ctx context.Context, req *http.Request)
if normalizedHost != "" {
query := fmt.Sprintf(`
SELECT s.id_shop, s.id_shop_group, sg.share_order, CONCAT(su.physical_uri, su.virtual_uri) AS uri, su.main
SELECT s.id_shop, s.id_shop_group, sg.share_order, su.domain, su.domain_ssl,
su.physical_uri,
CONCAT(su.physical_uri, su.virtual_uri) AS uri, su.main
FROM %s s
JOIN %s sg ON sg.id_shop_group = s.id_shop_group
JOIN %s su ON su.id_shop = s.id_shop
@@ -370,14 +409,18 @@ ORDER BY LENGTH(CONCAT(su.physical_uri, su.virtual_uri)) DESC, su.main DESC, s.i
}
fallbackQuery := fmt.Sprintf(`
SELECT s.id_shop, s.id_shop_group, sg.share_order, '' AS uri, 1 AS main
SELECT s.id_shop, s.id_shop_group, sg.share_order, su.domain, su.domain_ssl,
su.physical_uri,
'' AS uri, su.main
FROM %s s
JOIN %s sg ON sg.id_shop_group = s.id_shop_group
JOIN %s su ON su.id_shop = s.id_shop
WHERE s.active = 1
AND s.deleted = 0
ORDER BY s.id_shop ASC
AND su.active = 1
ORDER BY su.main DESC, s.id_shop ASC
LIMIT 1
`, shopTable, shopGroupTable)
`, shopTable, shopGroupTable, shopURLTable)
var shop cookieShopContext
if err := s.db.WithContext(ctx).Raw(fallbackQuery).Scan(&shop).Error; err != nil {
return nil, err
@@ -511,6 +554,50 @@ func prestashopCookieDomain(host string, sharedURLs []string) string {
return normalizedHost
}
func overrideCookieHashDomain(input string) string {
value := strings.TrimSpace(strings.ToLower(input))
value = strings.TrimPrefix(value, ".")
value = strings.TrimPrefix(value, "www.")
if value == "" || net.ParseIP(value) != nil || !strings.Contains(value, ".") {
return ""
}
return value
}
func normalizeCookiePath(input string) string {
value := strings.TrimSpace(input)
if value == "" || value == "/" {
return "/"
}
value = "/" + strings.Trim(value, "/") + "/"
return value
}
func cookieDomainSource(shop *cookieShopContext, requestedHost string) string {
if shop == nil {
return requestedHost
}
requestedHost = normalizeRequestHost(requestedHost)
domain := normalizeRequestHost(shop.Domain)
domainSSL := normalizeRequestHost(shop.DomainSSL)
switch requestedHost {
case domainSSL:
return domainSSL
case domain:
return domain
}
if domainSSL != "" {
return domainSSL
}
if domain != "" {
return domain
}
return requestedHost
}
func (s *Service) tableColumns(ctx context.Context, tableName string) (map[string]bool, error) {
type columnRow struct {
ColumnName string `gorm:"column:COLUMN_NAME"`
+65 -1
View File
@@ -1,6 +1,12 @@
package session
import "testing"
import (
"context"
"crypto/md5"
"fmt"
"net/http/httptest"
"testing"
)
func TestPrestashopCookieDomain(t *testing.T) {
if got := prestashopCookieDomain("localhost", nil); got != "" {
@@ -25,3 +31,61 @@ func TestURIMatchesRequest(t *testing.T) {
t.Fatalf("unexpected match for different shop URI")
}
}
func TestCookieDomainSourcePrefersDatabaseDomain(t *testing.T) {
shop := &cookieShopContext{
Domain: "shop.example.com",
DomainSSL: "secure.example.com",
}
if got := cookieDomainSource(shop, "proxy.internal"); got != "secure.example.com" {
t.Fatalf("cookieDomainSource() = %q, want %q", got, "secure.example.com")
}
}
func TestCookieDomainSourceKeepsMatchingDatabaseHost(t *testing.T) {
shop := &cookieShopContext{
Domain: "shop.example.com",
DomainSSL: "secure.example.com",
}
if got := cookieDomainSource(shop, "shop.example.com"); got != "shop.example.com" {
t.Fatalf("cookieDomainSource() = %q, want %q", got, "shop.example.com")
}
}
func TestOverrideCookieHashDomain(t *testing.T) {
if got := overrideCookieHashDomain(".Example.com"); got != "example.com" {
t.Fatalf("overrideCookieHashDomain() = %q, want %q", got, "example.com")
}
}
func TestResolveCookieNameReturnsExplicitOverride(t *testing.T) {
service := NewService(nil, "ps_", "1.7.3", "PrestaShop-fixed", "")
got, err := service.ResolveCookieName(context.Background(), httptest.NewRequest("GET", "https://shop.example.com/", nil))
if err != nil {
t.Fatalf("ResolveCookieName() error = %v", err)
}
if got != "PrestaShop-fixed" {
t.Fatalf("ResolveCookieName() = %q, want %q", got, "PrestaShop-fixed")
}
}
func TestDomainCookieOverrideParticipatesInHash(t *testing.T) {
sum := md5.Sum([]byte("1.7.3" + "ps-s1" + overrideCookieHashDomain(".example.com")))
got := fmt.Sprintf("PrestaShop-%x", sum)
want := "PrestaShop-1e5aa4f42a55532134a4e84017cdf643"
if got != want {
t.Fatalf("derived cookie name = %q, want %q", got, want)
}
}
func TestNormalizeCookiePath(t *testing.T) {
if got := normalizeCookiePath(""); got != "/" {
t.Fatalf("normalizeCookiePath(\"\") = %q, want %q", got, "/")
}
if got := normalizeCookiePath("shop"); got != "/shop/" {
t.Fatalf("normalizeCookiePath(\"shop\") = %q, want %q", got, "/shop/")
}
}