Files
ocdp-go/backend/internal/domain/service/registry_service.go
Ivan087 7f238a3168 refactor: full-stack restructure with multi-tenancy, workspace management, and K8s diagnostics
- Add Workspace domain (entity, repository, service, handler, DTO)
- Add multi-tenant K8s client with tenant binding and quota management
- Add K8s diagnostics client (instance diagnostics)
- Add authorization middleware (authz package)
- Restructure frontend to feature-based architecture (features/)
- Add User Management page in configuration
- Add AccessDenied page and route guards
- Refactor shared components (form inputs, layout, UI)
- Update Tailwind config for new design system
- Add comprehensive documentation (docs/, tasks/, plans)
- Improve cluster service with better kubeconfig handling
- Add tests for crypto, config, helm client, tenant binding
2026-05-12 16:15:14 +08:00

154 lines
4.4 KiB
Go

package service
import (
"context"
"github.com/google/uuid"
"github.com/ocdp/cluster-service/internal/domain/entity"
"github.com/ocdp/cluster-service/internal/domain/repository"
"github.com/ocdp/cluster-service/internal/pkg/authz"
)
// RegistryService Registry 管理领域服务
type RegistryService struct {
registryRepo repository.RegistryRepository
ociClient repository.OCIClient
}
// NewRegistryService 创建 Registry 服务
func NewRegistryService(
registryRepo repository.RegistryRepository,
ociClient repository.OCIClient,
) *RegistryService {
return &RegistryService{
registryRepo: registryRepo,
ociClient: ociClient,
}
}
// CreateRegistry 创建新 Registry
func (s *RegistryService) CreateRegistry(ctx context.Context, registry *entity.Registry) error {
principal, err := authz.RequirePrincipal(ctx)
if err != nil {
return entity.ErrUnauthorized
}
// 生成 ID
registry.ID = uuid.New().String()
registry.OwnerID = principal.UserID
registry.WorkspaceID = principal.WorkspaceID
if principal.IsAdmin() && registry.WorkspaceID == "" {
registry.WorkspaceID = entity.DefaultWorkspaceID
}
if !principal.IsAdmin() && registry.Visibility == authz.VisibilityGlobalShared {
return entity.ErrForbidden
}
registry.Visibility = authz.NormalizeVisibility(principal.Role, registry.Visibility)
// 验证
if err := registry.Validate(); err != nil {
return err
}
// 检查是否已存在
registries, _ := s.registryRepo.List(ctx)
for _, existingRegistry := range registries {
if existingRegistry.Name == registry.Name && existingRegistry.WorkspaceID == registry.WorkspaceID && existingRegistry.OwnerID == registry.OwnerID {
return entity.ErrRegistryExists
}
}
return s.registryRepo.Create(ctx, registry)
}
// GetRegistry 获取 Registry
func (s *RegistryService) GetRegistry(ctx context.Context, id string) (*entity.Registry, error) {
principal, err := authz.RequirePrincipal(ctx)
if err != nil {
return nil, entity.ErrUnauthorized
}
registry, err := s.registryRepo.GetByID(ctx, id)
if err != nil {
return nil, err
}
if !authz.CanReadResource(principal, registry.WorkspaceID, registry.OwnerID, registry.Visibility) {
return nil, entity.ErrRegistryNotFound
}
return registry, nil
}
// UpdateRegistry 更新 Registry
func (s *RegistryService) UpdateRegistry(ctx context.Context, registry *entity.Registry) error {
principal, err := authz.RequirePrincipal(ctx)
if err != nil {
return entity.ErrUnauthorized
}
// 检查是否存在
existing, err := s.registryRepo.GetByID(ctx, registry.ID)
if err != nil {
return entity.ErrRegistryNotFound
}
if !authz.CanWriteResource(principal, existing.WorkspaceID, existing.OwnerID, existing.Visibility) {
return entity.ErrForbidden
}
registry.WorkspaceID = existing.WorkspaceID
registry.OwnerID = existing.OwnerID
if principal.IsAdmin() {
registry.Visibility = authz.NormalizeVisibility(principal.Role, registry.Visibility)
} else {
registry.Visibility = existing.Visibility
}
// 验证
if err := registry.Validate(); err != nil {
return err
}
return s.registryRepo.Update(ctx, registry)
}
// DeleteRegistry 删除 Registry
func (s *RegistryService) DeleteRegistry(ctx context.Context, id string) error {
principal, err := authz.RequirePrincipal(ctx)
if err != nil {
return entity.ErrUnauthorized
}
// 检查是否存在
registry, err := s.registryRepo.GetByID(ctx, id)
if err != nil {
return entity.ErrRegistryNotFound
}
if !authz.CanWriteResource(principal, registry.WorkspaceID, registry.OwnerID, registry.Visibility) {
return entity.ErrForbidden
}
return s.registryRepo.Delete(ctx, id)
}
// ListRegistries 列出所有 Registries
func (s *RegistryService) ListRegistries(ctx context.Context) ([]*entity.Registry, error) {
principal, err := authz.RequirePrincipal(ctx)
if err != nil {
return nil, entity.ErrUnauthorized
}
registries, err := s.registryRepo.List(ctx)
if err != nil {
return nil, err
}
visible := make([]*entity.Registry, 0, len(registries))
for _, registry := range registries {
if authz.CanReadResource(principal, registry.WorkspaceID, registry.OwnerID, registry.Visibility) {
visible = append(visible, registry)
}
}
return visible, nil
}
// CheckHealth 检查 Registry 健康状态
func (s *RegistryService) CheckHealth(ctx context.Context, id string) error {
registry, err := s.GetRegistry(ctx, id)
if err != nil {
return entity.ErrRegistryNotFound
}
return s.ociClient.CheckHealth(ctx, registry)
}