forked from baron/baron-sso
feat: 테넌트 그룹(Tenant Group) 기능 구현 #239
This commit is contained in:
94
backend/internal/service/tenant_group_service.go
Normal file
94
backend/internal/service/tenant_group_service.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"baron-sso-backend/internal/domain"
|
||||
"baron-sso-backend/internal/repository"
|
||||
"context"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
type TenantGroupService interface {
|
||||
CreateGroup(ctx context.Context, name, slug, description string) (*domain.TenantGroup, error)
|
||||
GetGroup(ctx context.Context, id string) (*domain.TenantGroup, error)
|
||||
ListGroups(ctx context.Context, limit, offset int) ([]domain.TenantGroup, int64, error)
|
||||
UpdateGroup(ctx context.Context, id string, name, description string) (*domain.TenantGroup, error)
|
||||
DeleteGroup(ctx context.Context, id string) error
|
||||
AddTenantToGroup(ctx context.Context, groupID, tenantID string) error
|
||||
RemoveTenantFromGroup(ctx context.Context, groupID, tenantID string) error
|
||||
}
|
||||
|
||||
type tenantGroupService struct {
|
||||
repo repository.TenantGroupRepository
|
||||
keto KetoService
|
||||
}
|
||||
|
||||
func NewTenantGroupService(repo repository.TenantGroupRepository, keto KetoService) TenantGroupService {
|
||||
return &tenantGroupService{repo: repo, keto: keto}
|
||||
}
|
||||
|
||||
func (s *tenantGroupService) CreateGroup(ctx context.Context, name, slug, description string) (*domain.TenantGroup, error) {
|
||||
group := &domain.TenantGroup{
|
||||
Name: name,
|
||||
Slug: slug,
|
||||
Description: description,
|
||||
}
|
||||
if err := s.repo.Create(ctx, group); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return group, nil
|
||||
}
|
||||
|
||||
func (s *tenantGroupService) GetGroup(ctx context.Context, id string) (*domain.TenantGroup, error) {
|
||||
return s.repo.FindByID(ctx, id)
|
||||
}
|
||||
|
||||
func (s *tenantGroupService) ListGroups(ctx context.Context, limit, offset int) ([]domain.TenantGroup, int64, error) {
|
||||
return s.repo.List(ctx, limit, offset)
|
||||
}
|
||||
|
||||
func (s *tenantGroupService) UpdateGroup(ctx context.Context, id string, name, description string) (*domain.TenantGroup, error) {
|
||||
group, err := s.repo.FindByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
group.Name = name
|
||||
group.Description = description
|
||||
if err := s.repo.Update(ctx, group); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return group, nil
|
||||
}
|
||||
|
||||
func (s *tenantGroupService) DeleteGroup(ctx context.Context, id string) error {
|
||||
return s.repo.Delete(ctx, id)
|
||||
}
|
||||
|
||||
func (s *tenantGroupService) AddTenantToGroup(ctx context.Context, groupID, tenantID string) error {
|
||||
if err := s.repo.AddTenant(ctx, groupID, tenantID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// [Keto] ReBAC: Tenant -> Group membership
|
||||
if s.keto != nil {
|
||||
err := s.keto.CreateRelation(ctx, "Tenant", tenantID, "parent_group", groupID)
|
||||
if err != nil {
|
||||
slog.Error("Failed to sync Keto relation for tenant group", "tenantID", tenantID, "groupID", groupID, "error", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *tenantGroupService) RemoveTenantFromGroup(ctx context.Context, groupID, tenantID string) error {
|
||||
if err := s.repo.RemoveTenant(ctx, groupID, tenantID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// [Keto] ReBAC: Remove Tenant -> Group membership
|
||||
if s.keto != nil {
|
||||
err := s.keto.DeleteRelation(ctx, "Tenant", tenantID, "parent_group", groupID)
|
||||
if err != nil {
|
||||
slog.Error("Failed to remove Keto relation for tenant group", "tenantID", tenantID, "groupID", groupID, "error", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user