forked from baron/baron-sso
Implement tenant import and RP auto login policies
This commit is contained in:
@@ -63,7 +63,7 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
// Auto-migrate
|
||||
err = db.AutoMigrate(&domain.Tenant{}, &domain.TenantDomain{}, &domain.User{}, &domain.ClientConsent{})
|
||||
err = db.AutoMigrate(&domain.Tenant{}, &domain.TenantDomain{}, &domain.User{}, &domain.ClientConsent{}, &domain.RPUserMetadata{})
|
||||
if err != nil {
|
||||
log.Fatalf("failed to migrate database: %s", err)
|
||||
}
|
||||
|
||||
40
backend/internal/repository/rp_user_metadata_repository.go
Normal file
40
backend/internal/repository/rp_user_metadata_repository.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"baron-sso-backend/internal/domain"
|
||||
"context"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
type RPUserMetadataRepository interface {
|
||||
Get(ctx context.Context, clientID, userID string) (*domain.RPUserMetadata, error)
|
||||
Upsert(ctx context.Context, metadata *domain.RPUserMetadata) error
|
||||
}
|
||||
|
||||
type rpUserMetadataRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewRPUserMetadataRepository(db *gorm.DB) RPUserMetadataRepository {
|
||||
return &rpUserMetadataRepository{db: db}
|
||||
}
|
||||
|
||||
func (r *rpUserMetadataRepository) Get(ctx context.Context, clientID, userID string) (*domain.RPUserMetadata, error) {
|
||||
var metadata domain.RPUserMetadata
|
||||
if err := r.db.WithContext(ctx).First(&metadata, "client_id = ? AND user_id = ?", clientID, userID).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &metadata, nil
|
||||
}
|
||||
|
||||
func (r *rpUserMetadataRepository) Upsert(ctx context.Context, metadata *domain.RPUserMetadata) error {
|
||||
return r.db.WithContext(ctx).Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{
|
||||
{Name: "client_id"},
|
||||
{Name: "user_id"},
|
||||
},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"metadata", "updated_at"}),
|
||||
}).Create(metadata).Error
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package repository
|
||||
import (
|
||||
"baron-sso-backend/internal/domain"
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -88,6 +89,20 @@ func (r *tenantRepository) FindByIDs(ctx context.Context, ids []string) ([]domai
|
||||
}
|
||||
|
||||
func (r *tenantRepository) AddDomain(ctx context.Context, tenantID string, domainName string, verified bool) error {
|
||||
var existing domain.TenantDomain
|
||||
err := r.db.WithContext(ctx).Unscoped().
|
||||
Where("tenant_id = ? AND domain = ?", tenantID, domainName).
|
||||
First(&existing).Error
|
||||
if err == nil {
|
||||
return r.db.WithContext(ctx).Unscoped().Model(&existing).Updates(map[string]any{
|
||||
"verified": verified,
|
||||
"deleted_at": nil,
|
||||
}).Error
|
||||
}
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
|
||||
td := domain.TenantDomain{
|
||||
TenantID: tenantID,
|
||||
Domain: domainName,
|
||||
|
||||
@@ -60,6 +60,49 @@ func TestTenantRepository(t *testing.T) {
|
||||
assert.Equal(t, "test-domain.com", found.Domains[0].Domain)
|
||||
})
|
||||
|
||||
t.Run("AddDomain allows same domain on multiple tenants", func(t *testing.T) {
|
||||
first := &domain.Tenant{
|
||||
Name: "Saman Existing",
|
||||
Slug: "saman-existing",
|
||||
Type: domain.TenantTypeCompany,
|
||||
}
|
||||
second := &domain.Tenant{
|
||||
Name: "Saman Current",
|
||||
Slug: "saman-current",
|
||||
Type: domain.TenantTypeCompany,
|
||||
}
|
||||
assert.NoError(t, repo.Create(ctx, first))
|
||||
assert.NoError(t, repo.Create(ctx, second))
|
||||
|
||||
assert.NoError(t, repo.AddDomain(ctx, first.ID, "samaneng.com", true))
|
||||
assert.NoError(t, repo.AddDomain(ctx, second.ID, "samaneng.com", true))
|
||||
|
||||
var rows []domain.TenantDomain
|
||||
err := testDB.Where("domain = ?", "samaneng.com").Find(&rows).Error
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, rows, 2)
|
||||
})
|
||||
|
||||
t.Run("AddDomain restores deleted tenant domain", func(t *testing.T) {
|
||||
tenant := &domain.Tenant{
|
||||
Name: "Domain Restore",
|
||||
Slug: "domain-restore",
|
||||
Type: domain.TenantTypeCompany,
|
||||
}
|
||||
assert.NoError(t, repo.Create(ctx, tenant))
|
||||
assert.NoError(t, repo.AddDomain(ctx, tenant.ID, "restore.samaneng.com", true))
|
||||
assert.NoError(t, testDB.Where("tenant_id = ? AND domain = ?", tenant.ID, "restore.samaneng.com").Delete(&domain.TenantDomain{}).Error)
|
||||
|
||||
assert.NoError(t, repo.AddDomain(ctx, tenant.ID, "restore.samaneng.com", true))
|
||||
|
||||
var rows []domain.TenantDomain
|
||||
err := testDB.Where("tenant_id = ? AND domain = ?", tenant.ID, "restore.samaneng.com").Find(&rows).Error
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, rows, 1) {
|
||||
assert.True(t, rows[0].Verified)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Update", func(t *testing.T) {
|
||||
tenant := &domain.Tenant{
|
||||
Name: "Before Update",
|
||||
|
||||
Reference in New Issue
Block a user