feat: implement gRPC AgentService, Program.cs with Kestrel HTTP/2 config

This commit is contained in:
Claude Agent
2026-03-19 11:35:04 +01:00
parent fe32c9cd88
commit 5c03c18ac7
7 changed files with 317 additions and 6 deletions

View File

@@ -0,0 +1,43 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NexusRMM.Infrastructure.Data;
namespace NexusRMM.Api.Controllers;
[ApiController]
[Route("api/v1/[controller]")]
public class AgentsController : ControllerBase
{
private readonly RmmDbContext _db;
public AgentsController(RmmDbContext db) => _db = db;
[HttpGet]
public async Task<IActionResult> GetAll()
{
var agents = await _db.Agents
.OrderBy(a => a.Hostname)
.Select(a => new { a.Id, a.Hostname, a.OsType, a.OsVersion, a.IpAddress, a.Status, a.AgentVersion, a.LastSeen, a.Tags })
.ToListAsync();
return Ok(agents);
}
[HttpGet("{id:guid}")]
public async Task<IActionResult> GetById(Guid id)
{
var agent = await _db.Agents.FindAsync(id);
return agent is null ? NotFound() : Ok(agent);
}
[HttpGet("{id:guid}/metrics")]
public async Task<IActionResult> GetMetrics(Guid id, [FromQuery] int hours = 24)
{
var since = DateTime.UtcNow.AddHours(-hours);
var metrics = await _db.AgentMetrics
.Where(m => m.AgentId == id && m.Timestamp >= since)
.OrderByDescending(m => m.Timestamp)
.Take(1000)
.Select(m => new { m.Timestamp, m.Metrics })
.ToListAsync();
return Ok(metrics);
}
}

View File

@@ -0,0 +1,51 @@
using System.Text.Json;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NexusRMM.Core.Models;
using NexusRMM.Infrastructure.Data;
namespace NexusRMM.Api.Controllers;
[ApiController]
[Route("api/v1/[controller]")]
public class TasksController : ControllerBase
{
private readonly RmmDbContext _db;
public TasksController(RmmDbContext db) => _db = db;
[HttpPost]
public async Task<IActionResult> Create([FromBody] CreateTaskRequest request)
{
var task = new TaskItem
{
Id = Guid.NewGuid(),
AgentId = request.AgentId,
Type = request.Type,
Payload = request.Payload is not null ? JsonSerializer.SerializeToElement(request.Payload) : null,
CreatedAt = DateTime.UtcNow
};
_db.Tasks.Add(task);
await _db.SaveChangesAsync();
return CreatedAtAction(nameof(GetById), new { id = task.Id }, task);
}
[HttpGet("{id:guid}")]
public async Task<IActionResult> GetById(Guid id)
{
var task = await _db.Tasks.FindAsync(id);
return task is null ? NotFound() : Ok(task);
}
[HttpGet("agent/{agentId:guid}")]
public async Task<IActionResult> GetByAgent(Guid agentId)
{
var tasks = await _db.Tasks
.Where(t => t.AgentId == agentId)
.OrderByDescending(t => t.CreatedAt)
.Take(50)
.ToListAsync();
return Ok(tasks);
}
}
public record CreateTaskRequest(Guid AgentId, TaskType Type, object? Payload);

View File

@@ -0,0 +1,64 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NexusRMM.Core.Models;
using NexusRMM.Infrastructure.Data;
namespace NexusRMM.Api.Controllers;
[ApiController]
[Route("api/v1/[controller]")]
public class TicketsController : ControllerBase
{
private readonly RmmDbContext _db;
public TicketsController(RmmDbContext db) => _db = db;
[HttpGet]
public async Task<IActionResult> GetAll([FromQuery] TicketStatus? status = null)
{
var query = _db.Tickets.AsQueryable();
if (status.HasValue) query = query.Where(t => t.Status == status.Value);
var tickets = await query.OrderByDescending(t => t.CreatedAt).Take(100).ToListAsync();
return Ok(tickets);
}
[HttpGet("{id:int}")]
public async Task<IActionResult> GetById(int id)
{
var ticket = await _db.Tickets.Include(t => t.Agent).FirstOrDefaultAsync(t => t.Id == id);
return ticket is null ? NotFound() : Ok(ticket);
}
[HttpPost]
public async Task<IActionResult> Create([FromBody] CreateTicketRequest request)
{
var ticket = new Ticket
{
Title = request.Title,
Description = request.Description,
Priority = request.Priority,
AgentId = request.AgentId,
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow
};
_db.Tickets.Add(ticket);
await _db.SaveChangesAsync();
return CreatedAtAction(nameof(GetById), new { id = ticket.Id }, ticket);
}
[HttpPut("{id:int}")]
public async Task<IActionResult> Update(int id, [FromBody] UpdateTicketRequest request)
{
var ticket = await _db.Tickets.FindAsync(id);
if (ticket is null) return NotFound();
if (request.Status.HasValue) ticket.Status = request.Status.Value;
if (request.Priority.HasValue) ticket.Priority = request.Priority.Value;
if (request.Title is not null) ticket.Title = request.Title;
if (request.Description is not null) ticket.Description = request.Description;
ticket.UpdatedAt = DateTime.UtcNow;
await _db.SaveChangesAsync();
return Ok(ticket);
}
}
public record CreateTicketRequest(string Title, string Description, TicketPriority Priority, Guid? AgentId);
public record UpdateTicketRequest(string? Title, string? Description, TicketStatus? Status, TicketPriority? Priority);