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
This commit is contained in:
124
services/audit/internal/api/grpc_server.go
Normal file
124
services/audit/internal/api/grpc_server.go
Normal file
@@ -0,0 +1,124 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user