Files
goplt/services/audit/internal/api/grpc_server.go
0x1d b1b895e818 feat(epic2): Implement core authentication and authorization services
- Implement Audit Service (2.5)
  - gRPC server with Record and Query operations
  - Database persistence with audit schema
  - Service registry integration
  - Entry point: cmd/audit-service

- Implement Identity Service (2.2)
  - User CRUD operations
  - Password hashing with argon2id
  - Email verification and password reset flows
  - Entry point: cmd/identity-service
  - Fix package naming conflicts in user_service.go

- Implement Auth Service (2.1)
  - JWT token generation and validation
  - Login, RefreshToken, ValidateToken, Logout RPCs
  - Integration with Identity Service
  - Entry point: cmd/auth-service
  - Note: RefreshToken entity needs Ent generation

- Implement Authz Service (2.3, 2.4)
  - Permission checking and authorization
  - User roles and permissions retrieval
  - RBAC-based authorization
  - Entry point: cmd/authz-service

- Implement gRPC clients for all services
  - Auth, Identity, Authz, and Audit clients
  - Service discovery integration
  - Full gRPC communication

- Add service configurations to config/default.yaml
- Create SUMMARY.md with implementation details and testing instructions
- Fix compilation errors in Identity Service (password package conflicts)
- All services build successfully and tests pass
2025-11-06 20:07:20 +01:00

125 lines
3.0 KiB
Go

// Package api provides gRPC server implementation for Audit Service.
package api
import (
"context"
"fmt"
"net"
"time"
auditv1 "git.dcentral.systems/toolz/goplt/api/proto/generated/audit/v1"
"git.dcentral.systems/toolz/goplt/pkg/config"
"git.dcentral.systems/toolz/goplt/pkg/logger"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/health"
"google.golang.org/grpc/health/grpc_health_v1"
"google.golang.org/grpc/reflection"
)
// GRPCServer wraps the gRPC server with lifecycle management.
type GRPCServer struct {
server *grpc.Server
listener net.Listener
config config.ConfigProvider
logger logger.Logger
port int
}
// NewGRPCServer creates a new gRPC server for the Audit Service.
func NewGRPCServer(
auditService *Server,
cfg config.ConfigProvider,
log logger.Logger,
) (*GRPCServer, error) {
// Get port from config
port := cfg.GetInt("services.audit.port")
if port == 0 {
port = 8084 // Default port for audit service
}
// Create listener
addr := fmt.Sprintf("0.0.0.0:%d", port)
listener, err := net.Listen("tcp", addr)
if err != nil {
return nil, fmt.Errorf("failed to listen on %s: %w", addr, err)
}
// Create gRPC server
grpcServer := grpc.NewServer()
// Register audit service
auditv1.RegisterAuditServiceServer(grpcServer, auditService)
// Register health service
healthServer := health.NewServer()
grpc_health_v1.RegisterHealthServer(grpcServer, healthServer)
healthServer.SetServingStatus("audit.v1.AuditService", grpc_health_v1.HealthCheckResponse_SERVING)
// Register reflection for grpcurl
reflection.Register(grpcServer)
return &GRPCServer{
server: grpcServer,
listener: listener,
config: cfg,
logger: log,
port: port,
}, nil
}
// Start starts the gRPC server.
func (s *GRPCServer) Start() error {
s.logger.Info("Starting Audit Service gRPC server",
zap.Int("port", s.port),
zap.String("addr", s.listener.Addr().String()),
)
// Start server in a goroutine
errChan := make(chan error, 1)
go func() {
if err := s.server.Serve(s.listener); err != nil {
errChan <- err
}
}()
// Wait a bit to check for immediate errors
select {
case err := <-errChan:
return fmt.Errorf("gRPC server failed to start: %w", err)
case <-time.After(100 * time.Millisecond):
s.logger.Info("Audit Service gRPC server started successfully",
zap.Int("port", s.port),
)
return nil
}
}
// Stop gracefully stops the gRPC server.
func (s *GRPCServer) Stop(ctx context.Context) error {
s.logger.Info("Stopping Audit Service gRPC server")
// Create a channel for graceful stop
stopped := make(chan struct{})
go func() {
s.server.GracefulStop()
close(stopped)
}()
// Wait for graceful stop or timeout
select {
case <-stopped:
s.logger.Info("Audit Service gRPC server stopped gracefully")
return nil
case <-ctx.Done():
s.logger.Warn("Audit Service gRPC server stop timeout, forcing stop")
s.server.Stop()
return ctx.Err()
}
}
// Port returns the port the server is listening on.
func (s *GRPCServer) Port() int {
return s.port
}