forked from baron/baron-sso
feat: automatically create default user groups upon tenant registration/approval
This commit is contained in:
@@ -265,7 +265,7 @@ func main() {
|
|||||||
kratosAdminService := service.NewKratosAdminService()
|
kratosAdminService := service.NewKratosAdminService()
|
||||||
oryAdminProvider := service.NewOryProvider()
|
oryAdminProvider := service.NewOryProvider()
|
||||||
|
|
||||||
tenantService := service.NewTenantService(tenantRepo, userRepo, ketoOutboxRepo)
|
tenantService := service.NewTenantService(tenantRepo, userRepo, userGroupRepo, ketoOutboxRepo)
|
||||||
userGroupService := service.NewUserGroupService(userGroupRepo, userRepo, tenantRepo, ketoService, ketoOutboxRepo, kratosAdminService)
|
userGroupService := service.NewUserGroupService(userGroupRepo, userRepo, tenantRepo, ketoService, ketoOutboxRepo, kratosAdminService)
|
||||||
tenantService.SetKetoService(ketoService) // Keto 주입
|
tenantService.SetKetoService(ketoService) // Keto 주입
|
||||||
|
|
||||||
|
|||||||
@@ -26,17 +26,19 @@ type TenantService interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type tenantService struct {
|
type tenantService struct {
|
||||||
repo repository.TenantRepository
|
repo repository.TenantRepository
|
||||||
userRepo repository.UserRepository
|
userRepo repository.UserRepository
|
||||||
keto KetoService
|
userGroupRepo repository.UserGroupRepository
|
||||||
outboxRepo repository.KetoOutboxRepository
|
keto KetoService
|
||||||
|
outboxRepo repository.KetoOutboxRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTenantService(repo repository.TenantRepository, userRepo repository.UserRepository, outboxRepo repository.KetoOutboxRepository) TenantService {
|
func NewTenantService(repo repository.TenantRepository, userRepo repository.UserRepository, userGroupRepo repository.UserGroupRepository, outboxRepo repository.KetoOutboxRepository) TenantService {
|
||||||
return &tenantService{
|
return &tenantService{
|
||||||
repo: repo,
|
repo: repo,
|
||||||
userRepo: userRepo,
|
userRepo: userRepo,
|
||||||
outboxRepo: outboxRepo,
|
userGroupRepo: userGroupRepo,
|
||||||
|
outboxRepo: outboxRepo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +112,51 @@ func (s *tenantService) RegisterTenant(ctx context.Context, name, slug, tenantTy
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [New] Create Default User Groups
|
||||||
|
if s.userGroupRepo != nil {
|
||||||
|
groups := []struct {
|
||||||
|
Name string
|
||||||
|
Slug string
|
||||||
|
}{
|
||||||
|
{Name: "임직원", Slug: "members"},
|
||||||
|
{Name: "관리자", Slug: "admins"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, g := range groups {
|
||||||
|
newGroup := &domain.UserGroup{
|
||||||
|
TenantID: tenant.ID,
|
||||||
|
Name: g.Name,
|
||||||
|
Slug: g.Slug,
|
||||||
|
Description: tenant.Name + " " + g.Name + " 그룹",
|
||||||
|
}
|
||||||
|
if err := s.userGroupRepo.Create(ctx, newGroup); err == nil {
|
||||||
|
// Sync group to Keto via Outbox
|
||||||
|
if s.outboxRepo != nil {
|
||||||
|
_ = s.outboxRepo.Create(ctx, &domain.KetoOutbox{
|
||||||
|
Namespace: "UserGroup",
|
||||||
|
Object: newGroup.ID,
|
||||||
|
Relation: "tenants",
|
||||||
|
Subject: "Tenant:" + tenant.ID,
|
||||||
|
Action: domain.KetoOutboxActionCreate,
|
||||||
|
})
|
||||||
|
|
||||||
|
// If this is the 'admins' group and we have a creatorID, add creator to this group
|
||||||
|
if g.Slug == "admins" && creatorID != "" {
|
||||||
|
_ = s.outboxRepo.Create(ctx, &domain.KetoOutbox{
|
||||||
|
Namespace: "UserGroup",
|
||||||
|
Object: newGroup.ID,
|
||||||
|
Relation: "members",
|
||||||
|
Subject: "User:" + creatorID,
|
||||||
|
Action: domain.KetoOutboxActionCreate,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
slog.Error("Failed to create default group", "group", g.Slug, "tenant", tenant.ID, "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// [Keto] Sync hierarchy and ownership via Outbox
|
// [Keto] Sync hierarchy and ownership via Outbox
|
||||||
if s.outboxRepo != nil {
|
if s.outboxRepo != nil {
|
||||||
// Sync hierarchy
|
// Sync hierarchy
|
||||||
@@ -209,6 +256,37 @@ func (s *tenantService) ApproveTenant(ctx context.Context, id string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [New] Create Default User Groups upon approval
|
||||||
|
if s.userGroupRepo != nil {
|
||||||
|
groups := []struct {
|
||||||
|
Name string
|
||||||
|
Slug string
|
||||||
|
}{
|
||||||
|
{Name: "임직원", Slug: "members"},
|
||||||
|
{Name: "관리자", Slug: "admins"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, g := range groups {
|
||||||
|
newGroup := &domain.UserGroup{
|
||||||
|
TenantID: tenant.ID,
|
||||||
|
Name: g.Name,
|
||||||
|
Slug: g.Slug,
|
||||||
|
Description: tenant.Name + " " + g.Name + " 그룹",
|
||||||
|
}
|
||||||
|
if err := s.userGroupRepo.Create(ctx, newGroup); err == nil {
|
||||||
|
if s.outboxRepo != nil {
|
||||||
|
_ = s.outboxRepo.Create(ctx, &domain.KetoOutbox{
|
||||||
|
Namespace: "UserGroup",
|
||||||
|
Object: newGroup.ID,
|
||||||
|
Relation: "tenants",
|
||||||
|
Subject: "Tenant:" + tenant.ID,
|
||||||
|
Action: domain.KetoOutboxActionCreate,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// [Keto] Sync relation via Outbox
|
// [Keto] Sync relation via Outbox
|
||||||
if s.outboxRepo != nil {
|
if s.outboxRepo != nil {
|
||||||
if adminEmail, ok := tenant.Config["adminEmail"].(string); ok && adminEmail != "" {
|
if adminEmail, ok := tenant.Config["adminEmail"].(string); ok && adminEmail != "" {
|
||||||
|
|||||||
Reference in New Issue
Block a user