package grpcserver import ( "context" "errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" pb "git.wntrmute.dev/mc/metacrypt/gen/metacrypt/v2" "git.wntrmute.dev/mc/metacrypt/internal/auth" "git.wntrmute.dev/mc/metacrypt/internal/engine" ) type engineServer struct { pb.UnimplementedEngineServiceServer s *GRPCServer } func (es *engineServer) Mount(ctx context.Context, req *pb.MountRequest) (*pb.MountResponse, error) { if req.Name == "" || req.Type == "" { return nil, status.Error(codes.InvalidArgument, "name and type are required") } var config map[string]interface{} if len(req.Config) > 0 { config = make(map[string]interface{}, len(req.Config)) for k, v := range req.Config { config[k] = v } } // Inject external_url into engine config if available and not already set. if config == nil { config = make(map[string]interface{}) } if _, ok := config["external_url"]; !ok && es.s.cfg.Server.ExternalURL != "" { config["external_url"] = es.s.cfg.Server.ExternalURL } if err := es.s.engines.Mount(ctx, req.Name, engine.EngineType(req.Type), config); err != nil { es.s.logger.Error("grpc: mount engine", "name", req.Name, "type", req.Type, "error", err) switch { case errors.Is(err, engine.ErrMountExists): return nil, status.Error(codes.AlreadyExists, err.Error()) case errors.Is(err, engine.ErrUnknownType): return nil, status.Error(codes.InvalidArgument, err.Error()) default: return nil, status.Error(codes.Internal, err.Error()) } } ti := auth.TokenInfoFromContext(ctx) username := "" if ti != nil { username = ti.Username } es.s.logger.Info("audit: engine mounted", "name", req.Name, "type", req.Type, "username", username) return &pb.MountResponse{}, nil } func (es *engineServer) Unmount(ctx context.Context, req *pb.UnmountRequest) (*pb.UnmountResponse, error) { if req.Name == "" { return nil, status.Error(codes.InvalidArgument, "name is required") } if err := es.s.engines.Unmount(ctx, req.Name); err != nil { if errors.Is(err, engine.ErrMountNotFound) { return nil, status.Error(codes.NotFound, err.Error()) } return nil, status.Error(codes.Internal, err.Error()) } ti := auth.TokenInfoFromContext(ctx) username := "" if ti != nil { username = ti.Username } es.s.logger.Info("audit: engine unmounted", "name", req.Name, "username", username) return &pb.UnmountResponse{}, nil } func (es *engineServer) ListMounts(_ context.Context, _ *pb.ListMountsRequest) (*pb.ListMountsResponse, error) { mounts := es.s.engines.ListMounts() pbMounts := make([]*pb.MountInfo, 0, len(mounts)) for _, m := range mounts { pbMounts = append(pbMounts, &pb.MountInfo{ Name: m.Name, Type: string(m.Type), MountPath: m.MountPath, }) } return &pb.ListMountsResponse{Mounts: pbMounts}, nil }