98 lines
3.0 KiB
C#
98 lines
3.0 KiB
C#
|
|
using Microsoft.AspNetCore.Builder;
|
||
|
|
using Microsoft.AspNetCore.Http;
|
||
|
|
using Microsoft.AspNetCore.Routing;
|
||
|
|
using Microsoft.EntityFrameworkCore;
|
||
|
|
using TeamUp.Modules.Skills.Domain;
|
||
|
|
using TeamUp.Modules.Skills.Indexing;
|
||
|
|
using TeamUp.Modules.Skills.Persistence;
|
||
|
|
using TeamUp.SharedKernel.Modularity;
|
||
|
|
|
||
|
|
namespace TeamUp.Modules.Skills.Endpoints;
|
||
|
|
|
||
|
|
internal static class SkillsEndpoints
|
||
|
|
{
|
||
|
|
public static void Map(IEndpointRouteBuilder endpoints)
|
||
|
|
{
|
||
|
|
var group = endpoints.MapGroup("/api/skills").WithTags("Skills");
|
||
|
|
|
||
|
|
group.MapGet("/ping", () => TypedResults.Ok(new ModulePing("skills")));
|
||
|
|
group.MapGet("/", ListSkills).RequireAuthorization();
|
||
|
|
group.MapGet("/{key}", GetSkill).RequireAuthorization();
|
||
|
|
group.MapPost("/index", IndexSkill).RequireAuthorization();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static async Task<IResult> ListSkills(
|
||
|
|
string? role, string? visibility, SkillsDbContext db, CancellationToken ct)
|
||
|
|
{
|
||
|
|
var query = db.Skills.AsQueryable();
|
||
|
|
|
||
|
|
if (!string.IsNullOrWhiteSpace(role))
|
||
|
|
{
|
||
|
|
query = query.Where(s => s.Roles.Contains(role));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (Enum.TryParse<SkillVisibility>(visibility, ignoreCase: true, out var vis))
|
||
|
|
{
|
||
|
|
query = query.Where(s => s.Visibility == vis);
|
||
|
|
}
|
||
|
|
|
||
|
|
var skills = await query
|
||
|
|
.OrderBy(s => s.SkillKey)
|
||
|
|
.ThenByDescending(s => s.Version)
|
||
|
|
.ToListAsync(ct);
|
||
|
|
|
||
|
|
return Results.Ok(skills.Select(ToSummary).ToList());
|
||
|
|
}
|
||
|
|
|
||
|
|
private static async Task<IResult> GetSkill(string key, SkillsDbContext db, CancellationToken ct)
|
||
|
|
{
|
||
|
|
var versions = await db.Skills
|
||
|
|
.Where(s => s.SkillKey == key)
|
||
|
|
.OrderByDescending(s => s.Version)
|
||
|
|
.ToListAsync(ct);
|
||
|
|
|
||
|
|
return versions.Count == 0
|
||
|
|
? Results.NotFound()
|
||
|
|
: Results.Ok(versions.Select(ToDetail).ToList());
|
||
|
|
}
|
||
|
|
|
||
|
|
private static async Task<IResult> IndexSkill(IndexRequest request, SkillIndexer indexer, CancellationToken ct)
|
||
|
|
{
|
||
|
|
if (string.IsNullOrWhiteSpace(request.Content))
|
||
|
|
{
|
||
|
|
return Results.BadRequest("content is required.");
|
||
|
|
}
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var skill = await indexer.IndexAsync(
|
||
|
|
request.Content, request.SourceRepo, request.SourcePath, request.SourceCommit, ct);
|
||
|
|
return Results.Ok(ToDetail(skill));
|
||
|
|
}
|
||
|
|
catch (FormatException ex)
|
||
|
|
{
|
||
|
|
return Results.BadRequest(ex.Message);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static SkillSummary ToSummary(Skill skill) => new(
|
||
|
|
skill.SkillKey,
|
||
|
|
skill.Name,
|
||
|
|
skill.Version,
|
||
|
|
skill.Summary,
|
||
|
|
skill.Roles,
|
||
|
|
skill.Visibility.ToString(),
|
||
|
|
skill.MinTier.ToString(),
|
||
|
|
skill.Status.ToString(),
|
||
|
|
skill.Actions.Select(a => new ActionDto(a.Name, a.Risk.ToString())).ToList());
|
||
|
|
|
||
|
|
private static SkillDetail ToDetail(Skill skill) => new(
|
||
|
|
ToSummary(skill),
|
||
|
|
skill.Inputs,
|
||
|
|
skill.Outputs,
|
||
|
|
skill.Tools,
|
||
|
|
skill.Context,
|
||
|
|
skill.GoldenTests.Count,
|
||
|
|
skill.Body);
|
||
|
|
}
|