package repository import ( "baron-sso-backend/internal/domain" "context" "errors" "gorm.io/gorm" ) type ClientConsentRepository interface { Upsert(ctx context.Context, consent *domain.ClientConsent) error Delete(ctx context.Context, subject, clientID string) error DeleteByClient(ctx context.Context, clientID string) error List(ctx context.Context, clientID string, limit, offset int) ([]domain.ClientConsentWithTenantInfo, int64, error) ListByTenant(ctx context.Context, clientID, tenantID string, limit, offset int) ([]domain.ClientConsentWithTenantInfo, int64, error) ListBySubject(ctx context.Context, subject string) ([]domain.ClientConsent, error) ListSubjectsByClient(ctx context.Context, clientID string) ([]string, error) Find(ctx context.Context, clientID, subject string) (*domain.ClientConsent, error) } type clientConsentRepo struct { db *gorm.DB } func NewClientConsentRepository(db *gorm.DB) ClientConsentRepository { return &clientConsentRepo{db: db} } func (r *clientConsentRepo) Find(ctx context.Context, clientID, subject string) (*domain.ClientConsent, error) { var consent domain.ClientConsent err := r.db.WithContext(ctx). Where("client_id = ? AND subject = ?", clientID, subject). First(&consent).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return nil, err } return &consent, nil } func (r *clientConsentRepo) Upsert(ctx context.Context, consent *domain.ClientConsent) error { return r.db.WithContext(ctx).Unscoped(). Where("client_id = ? AND subject = ?", consent.ClientID, consent.Subject). Assign(map[string]any{ "granted_scopes": consent.GrantedScopes, "updated_at": gorm.Expr("NOW()"), "deleted_at": nil, }). FirstOrCreate(consent).Error } func (r *clientConsentRepo) Delete(ctx context.Context, subject, clientID string) error { return r.db.WithContext(ctx). Where("subject = ? AND client_id = ?", subject, clientID). Delete(&domain.ClientConsent{}).Error } func (r *clientConsentRepo) DeleteByClient(ctx context.Context, clientID string) error { return r.db.WithContext(ctx). Where("client_id = ?", clientID). Delete(&domain.ClientConsent{}).Error } func (r *clientConsentRepo) List(ctx context.Context, clientID string, limit, offset int) ([]domain.ClientConsentWithTenantInfo, int64, error) { var consents []domain.ClientConsentWithTenantInfo var total int64 // Base query for counting countQuery := r.db.WithContext(ctx).Unscoped().Model(&domain.ClientConsent{}).Where("client_id = ?", clientID) if err := countQuery.Count(&total).Error; err != nil { return nil, 0, err } // Query for fetching data query := r.db.WithContext(ctx).Unscoped(). Model(&domain.ClientConsent{}). Select("client_consents.*, users.tenant_id, tenants.name as tenant_name"). Joins("LEFT JOIN users ON users.id::text = client_consents.subject"). Joins("LEFT JOIN tenants ON tenants.id = users.tenant_id"). Where("client_consents.client_id = ?", clientID) err := query.Limit(limit).Offset(offset).Order("client_consents.updated_at DESC").Scan(&consents).Error return consents, total, err } func (r *clientConsentRepo) ListByTenant(ctx context.Context, clientID, tenantID string, limit, offset int) ([]domain.ClientConsentWithTenantInfo, int64, error) { var consents []domain.ClientConsentWithTenantInfo var total int64 // Base query for counting countQuery := r.db.WithContext(ctx).Unscoped(). Model(&domain.ClientConsent{}). Joins("JOIN users ON users.id::text = client_consents.subject"). Where("client_consents.client_id = ? AND users.tenant_id = ?", clientID, tenantID) if err := countQuery.Count(&total).Error; err != nil { return nil, 0, err } // Query for fetching data query := r.db.WithContext(ctx).Unscoped(). Model(&domain.ClientConsent{}). Select("client_consents.*, users.tenant_id, tenants.name as tenant_name"). Joins("JOIN users ON users.id::text = client_consents.subject"). Joins("JOIN tenants ON tenants.id = users.tenant_id"). Where("client_consents.client_id = ? AND users.tenant_id = ?", clientID, tenantID) err := query. Limit(limit). Offset(offset). Order("client_consents.updated_at DESC"). Scan(&consents).Error return consents, total, err } func (r *clientConsentRepo) ListBySubject(ctx context.Context, subject string) ([]domain.ClientConsent, error) { var consents []domain.ClientConsent err := r.db.WithContext(ctx).Unscoped(). Where("subject = ?", subject). Order("updated_at DESC"). Find(&consents).Error return consents, err } func (r *clientConsentRepo) ListSubjectsByClient(ctx context.Context, clientID string) ([]string, error) { var subjects []string err := r.db.WithContext(ctx).Unscoped(). Model(&domain.ClientConsent{}). Distinct("subject"). Where("client_id = ?", clientID). Order("subject ASC"). Pluck("subject", &subjects).Error return subjects, err }