- Restructure handlers into file_commands/file_queries/file_handlers - Add gRPC auth client, JWT middleware, rate limiting, request ID - Add common utilities: logger, sanitizer, s3_errors - Add unit tests for config, mediator, auth, request_id, sanitize - Add proto definitions and generated code - Remove old web UI pages - Add .dockerignore and .env.example
102 lines
2.2 KiB
Go
102 lines
2.2 KiB
Go
package grpc
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"rag/file-system/api/proto"
|
|
"rag/file-system/internal/common"
|
|
"time"
|
|
|
|
"github.com/patrickmn/go-cache"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials/insecure"
|
|
)
|
|
|
|
type TokenInfo struct {
|
|
Valid bool
|
|
UserId string
|
|
Username string
|
|
Email string
|
|
Roles []string
|
|
Permissions []string
|
|
ExpiresAt int64
|
|
}
|
|
|
|
type AuthClient struct {
|
|
conn *grpc.ClientConn
|
|
client proto.AuthServiceClient
|
|
cache *cache.Cache
|
|
}
|
|
|
|
func NewAuthClient(addr string) (*AuthClient, error) {
|
|
conn, err := grpc.NewClient(addr,
|
|
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("gRPC connect failed: %w", err)
|
|
}
|
|
|
|
common.Logger.Info("gRPC auth client connected", "addr", addr)
|
|
|
|
return &AuthClient{
|
|
conn: conn,
|
|
client: proto.NewAuthServiceClient(conn),
|
|
cache: cache.New(2*time.Minute, 5*time.Minute),
|
|
}, nil
|
|
}
|
|
|
|
func (a *AuthClient) ValidateToken(ctx context.Context, token string) (*TokenInfo, error) {
|
|
if cached, ok := a.cache.Get(token); ok {
|
|
return cached.(*TokenInfo), nil
|
|
}
|
|
|
|
resp, err := a.client.ValidateToken(ctx, &proto.ValidateTokenRequest{Token: token})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("gRPC ValidateToken failed: %w", err)
|
|
}
|
|
|
|
info := &TokenInfo{
|
|
Valid: resp.Valid,
|
|
UserId: resp.UserId,
|
|
Username: resp.Username,
|
|
Email: resp.Email,
|
|
Roles: resp.Roles,
|
|
Permissions: resp.Permissions,
|
|
ExpiresAt: resp.ExpiresAt,
|
|
}
|
|
|
|
if info.Valid {
|
|
ttl := a.cacheTTL(resp.ExpiresAt)
|
|
a.cache.Set(token, info, ttl)
|
|
}
|
|
|
|
return info, nil
|
|
}
|
|
|
|
func (a *AuthClient) HasPermission(token, permission string) (bool, error) {
|
|
resp, err := a.client.CheckPermission(context.Background(), &proto.CheckPermissionRequest{
|
|
Token: token,
|
|
Permission: permission,
|
|
})
|
|
if err != nil {
|
|
return false, fmt.Errorf("gRPC CheckPermission failed: %w", err)
|
|
}
|
|
return resp.Allowed, nil
|
|
}
|
|
|
|
func (a *AuthClient) Close() error {
|
|
return a.conn.Close()
|
|
}
|
|
|
|
func (a *AuthClient) cacheTTL(expiresAt int64) time.Duration {
|
|
expires := time.Unix(expiresAt, 0)
|
|
ttl := time.Until(expires) - 30*time.Second
|
|
if ttl < time.Minute {
|
|
ttl = time.Minute
|
|
}
|
|
if ttl > 2*time.Minute {
|
|
ttl = 2 * time.Minute
|
|
}
|
|
return ttl
|
|
}
|