package services import ( "context" "fmt" "go.uber.org/zap" "github.com/kms/api-key-service/internal/domain" "github.com/kms/api-key-service/internal/repository" ) // applicationService implements the ApplicationService interface type applicationService struct { appRepo repository.ApplicationRepository logger *zap.Logger } // NewApplicationService creates a new application service func NewApplicationService(appRepo repository.ApplicationRepository, logger *zap.Logger) ApplicationService { return &applicationService{ appRepo: appRepo, logger: logger, } } // Create creates a new application func (s *applicationService) Create(ctx context.Context, req *domain.CreateApplicationRequest, userID string) (*domain.Application, error) { s.logger.Info("Creating application", zap.String("app_id", req.AppID), zap.String("user_id", userID)) // TODO: Add permission validation // TODO: Add input validation using validator app := &domain.Application{ AppID: req.AppID, AppLink: req.AppLink, Type: req.Type, CallbackURL: req.CallbackURL, HMACKey: generateHMACKey(), // TODO: Use proper key generation TokenRenewalDuration: req.TokenRenewalDuration, MaxTokenDuration: req.MaxTokenDuration, Owner: req.Owner, } if err := s.appRepo.Create(ctx, app); err != nil { s.logger.Error("Failed to create application", zap.Error(err), zap.String("app_id", req.AppID)) return nil, fmt.Errorf("failed to create application: %w", err) } s.logger.Info("Application created successfully", zap.String("app_id", app.AppID)) return app, nil } // GetByID retrieves an application by its ID func (s *applicationService) GetByID(ctx context.Context, appID string) (*domain.Application, error) { s.logger.Debug("Getting application by ID", zap.String("app_id", appID)) app, err := s.appRepo.GetByID(ctx, appID) if err != nil { s.logger.Error("Failed to get application", zap.Error(err), zap.String("app_id", appID)) return nil, fmt.Errorf("failed to get application: %w", err) } return app, nil } // List retrieves applications with pagination func (s *applicationService) List(ctx context.Context, limit, offset int) ([]*domain.Application, error) { s.logger.Debug("Listing applications", zap.Int("limit", limit), zap.Int("offset", offset)) if limit <= 0 { limit = 50 // Default limit } if limit > 100 { limit = 100 // Max limit } apps, err := s.appRepo.List(ctx, limit, offset) if err != nil { s.logger.Error("Failed to list applications", zap.Error(err)) return nil, fmt.Errorf("failed to list applications: %w", err) } s.logger.Debug("Listed applications", zap.Int("count", len(apps))) return apps, nil } // Update updates an existing application func (s *applicationService) Update(ctx context.Context, appID string, updates *domain.UpdateApplicationRequest, userID string) (*domain.Application, error) { s.logger.Info("Updating application", zap.String("app_id", appID), zap.String("user_id", userID)) // TODO: Add permission validation // TODO: Add input validation app, err := s.appRepo.Update(ctx, appID, updates) if err != nil { s.logger.Error("Failed to update application", zap.Error(err), zap.String("app_id", appID)) return nil, fmt.Errorf("failed to update application: %w", err) } s.logger.Info("Application updated successfully", zap.String("app_id", appID)) return app, nil } // Delete deletes an application func (s *applicationService) Delete(ctx context.Context, appID string, userID string) error { s.logger.Info("Deleting application", zap.String("app_id", appID), zap.String("user_id", userID)) // TODO: Add permission validation // TODO: Check for existing tokens and handle appropriately if err := s.appRepo.Delete(ctx, appID); err != nil { s.logger.Error("Failed to delete application", zap.Error(err), zap.String("app_id", appID)) return fmt.Errorf("failed to delete application: %w", err) } s.logger.Info("Application deleted successfully", zap.String("app_id", appID)) return nil } // generateHMACKey generates a secure HMAC key // TODO: Replace with proper cryptographic key generation func generateHMACKey() string { // This is a placeholder - should use proper crypto/rand return "generated-hmac-key-placeholder" }