* refactor(auth): replace dashboard sessions with stateless tokens * feat(auth): harden session issuance and distributed enforcement * fix(proxy): preserve trusted proxy compatibility defaults * refactor: address dashboard auth review feedback * refactor: remove classic frontend and flatten web app
92 lines
3.5 KiB
Go
92 lines
3.5 KiB
Go
package model
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func TestExternalIdentityClaimEnforcesSingleOwnerAtomically(t *testing.T) {
|
|
truncateTables(t)
|
|
|
|
first := User{Username: "telegram-owner-one", Password: "password", AffCode: "telegram-owner-one"}
|
|
second := User{Username: "telegram-owner-two", Password: "password", AffCode: "telegram-owner-two"}
|
|
require.NoError(t, DB.Create(&first).Error)
|
|
require.NoError(t, DB.Create(&second).Error)
|
|
|
|
require.NoError(t, DB.Transaction(func(tx *gorm.DB) error {
|
|
return ClaimExternalIdentityWithTx(tx, ExternalIdentityProviderTelegram, "telegram-123", first.Id)
|
|
}))
|
|
err := DB.Transaction(func(tx *gorm.DB) error {
|
|
return ClaimExternalIdentityWithTx(tx, ExternalIdentityProviderTelegram, "telegram-123", second.Id)
|
|
})
|
|
assert.ErrorIs(t, err, ErrExternalIdentityAlreadyClaimed)
|
|
|
|
err = DB.Transaction(func(tx *gorm.DB) error {
|
|
return ClaimExternalIdentityWithTx(tx, ExternalIdentityProviderTelegram, "telegram-456", first.Id)
|
|
})
|
|
assert.ErrorIs(t, err, ErrExternalIdentityAlreadyClaimed)
|
|
|
|
var claims []ExternalIdentityClaim
|
|
require.NoError(t, DB.Find(&claims).Error)
|
|
require.Len(t, claims, 1)
|
|
assert.Equal(t, first.Id, claims[0].UserId)
|
|
assert.Equal(t, "telegram-123", claims[0].Subject)
|
|
|
|
require.NoError(t, DB.Transaction(func(tx *gorm.DB) error {
|
|
return ReleaseExternalIdentityWithTx(tx, ExternalIdentityProviderTelegram, first.Id)
|
|
}))
|
|
require.NoError(t, DB.Transaction(func(tx *gorm.DB) error {
|
|
return ClaimExternalIdentityWithTx(tx, ExternalIdentityProviderTelegram, "telegram-123", second.Id)
|
|
}))
|
|
}
|
|
|
|
func TestClearTelegramBindingReleasesIdentityClaim(t *testing.T) {
|
|
truncateTables(t)
|
|
|
|
user := User{Username: "telegram-unbind", Password: "password", TelegramId: "telegram-unbind-id"}
|
|
require.NoError(t, DB.Create(&user).Error)
|
|
require.NoError(t, DB.Transaction(func(tx *gorm.DB) error {
|
|
return ClaimExternalIdentityWithTx(tx, ExternalIdentityProviderTelegram, user.TelegramId, user.Id)
|
|
}))
|
|
|
|
require.NoError(t, user.ClearBinding(ExternalIdentityProviderTelegram))
|
|
assert.Empty(t, user.TelegramId)
|
|
|
|
var count int64
|
|
require.NoError(t, DB.Model(&ExternalIdentityClaim{}).Where("user_id = ?", user.Id).Count(&count).Error)
|
|
assert.Zero(t, count)
|
|
}
|
|
|
|
func TestInitializeExternalIdentityClaimsIsIdempotent(t *testing.T) {
|
|
truncateTables(t)
|
|
|
|
user := User{Username: "telegram-legacy", Password: "password", TelegramId: "telegram-legacy-id"}
|
|
require.NoError(t, DB.Create(&user).Error)
|
|
require.NoError(t, InitializeExternalIdentityClaims())
|
|
require.NoError(t, InitializeExternalIdentityClaims())
|
|
|
|
var claim ExternalIdentityClaim
|
|
require.NoError(t, DB.Where("provider = ? AND subject = ?", ExternalIdentityProviderTelegram, user.TelegramId).
|
|
First(&claim).Error)
|
|
assert.Equal(t, user.Id, claim.UserId)
|
|
}
|
|
|
|
func TestInitializeExternalIdentityClaimsRejectsAmbiguousLegacyBindings(t *testing.T) {
|
|
truncateTables(t)
|
|
|
|
first := User{Username: "telegram-legacy-one", Password: "password", TelegramId: "duplicate-telegram-id", AffCode: "telegram-legacy-one"}
|
|
second := User{Username: "telegram-legacy-two", Password: "password", TelegramId: "duplicate-telegram-id", AffCode: "telegram-legacy-two"}
|
|
require.NoError(t, DB.Create(&first).Error)
|
|
require.NoError(t, DB.Create(&second).Error)
|
|
|
|
err := InitializeExternalIdentityClaims()
|
|
assert.ErrorIs(t, err, ErrExternalIdentityAlreadyClaimed)
|
|
|
|
var count int64
|
|
require.NoError(t, DB.Model(&ExternalIdentityClaim{}).Count(&count).Error)
|
|
assert.Zero(t, count)
|
|
}
|