mengstack-api/internal/modules/org/application/service.go
MengStack Dev b13427e76c feat(org,audit): M4 组织管理 + 审计日志
org 模块:
- tenants 表 (UUID PK, name, slug, status, settings)
- 完整 CRUD API: /api/v1/org/tenants
- 多租户隔离

audit 模块:
- audit_logs 表 (actor, action, resource, IP, 时间)
- 查询 API: /api/v1/audit/logs (支持分页+筛选)
- 按 tenant_id/user_id/action/resource 过滤
2026-10-03 00:58:49 +08:00

94 lines
2.3 KiB
Go

package application
import (
"context"
"mengstack/internal/kernel/errors"
"mengstack/internal/modules/org/domain"
)
type Service struct {
repo domain.TenantRepository
}
func NewService(repo domain.TenantRepository) *Service {
return &Service{repo: repo}
}
func (s *Service) CreateTenant(ctx context.Context, req domain.CreateTenantRequest) (domain.TenantDTO, error) {
if _, err := s.repo.FindBySlug(ctx, req.Slug); err == nil {
return domain.TenantDTO{}, errors.ErrConflict
}
tenant := &domain.Tenant{
Name: req.Name,
Slug: req.Slug,
}
if err := s.repo.Create(ctx, tenant); err != nil {
return domain.TenantDTO{}, errors.Wrap(err, "CREATE_TENANT_FAILED", "failed to create tenant", 500)
}
return domain.ToTenantDTO(tenant), nil
}
func (s *Service) ListTenants(ctx context.Context) ([]domain.TenantDTO, error) {
tenants, err := s.repo.FindAll(ctx)
if err != nil {
return nil, errors.Wrap(err, "QUERY_TENANTS_FAILED", "failed to query tenants", 500)
}
dtos := make([]domain.TenantDTO, len(tenants))
for i, t := range tenants {
dtos[i] = domain.ToTenantDTO(&t)
}
return dtos, nil
}
func (s *Service) GetTenant(ctx context.Context, id string) (domain.TenantDTO, error) {
tenant, err := s.repo.FindByID(ctx, id)
if err != nil {
return domain.TenantDTO{}, errors.ErrNotFound
}
return domain.ToTenantDTO(tenant), nil
}
func (s *Service) UpdateTenant(ctx context.Context, id string, req domain.UpdateTenantRequest) (domain.TenantDTO, error) {
tenant, err := s.repo.FindByID(ctx, id)
if err != nil {
return domain.TenantDTO{}, errors.ErrNotFound
}
if req.Name != "" {
tenant.Name = req.Name
}
if req.Slug != "" {
if existing, err := s.repo.FindBySlug(ctx, req.Slug); err == nil && existing.ID != id {
return domain.TenantDTO{}, errors.ErrConflict
}
tenant.Slug = req.Slug
}
if req.Status != nil {
tenant.Status = *req.Status
}
if err := s.repo.Update(ctx, tenant); err != nil {
return domain.TenantDTO{}, errors.Wrap(err, "UPDATE_TENANT_FAILED", "failed to update tenant", 500)
}
return domain.ToTenantDTO(tenant), nil
}
func (s *Service) DeleteTenant(ctx context.Context, id string) error {
if _, err := s.repo.FindByID(ctx, id); err != nil {
return errors.ErrNotFound
}
if err := s.repo.Delete(ctx, id); err != nil {
return errors.Wrap(err, "DELETE_TENANT_FAILED", "failed to delete tenant", 500)
}
return nil
}