diff --git a/Net.Vatprc.Uniapi/Controllers/SectorController.cs b/Net.Vatprc.Uniapi/Controllers/SectorController.cs new file mode 100644 index 0000000..e9eb098 --- /dev/null +++ b/Net.Vatprc.Uniapi/Controllers/SectorController.cs @@ -0,0 +1,45 @@ +using Net.Vatprc.Uniapi.Models; +using Net.Vatprc.Uniapi.Services; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Immutable; +using System.Security.Claims; +using Net.Vatprc.Uniapi.Utils; +using System.Diagnostics.CodeAnalysis; + +namespace Net.Vatprc.Uniapi.Controllers; + +/// +/// Sector information. +/// +[ApiController, Route("api/sectors")] +public class SectorController( + VATPRCContext DbContext, + VatsimService VatsimService) : ControllerBase +{ + public record SectorPermissionResponse + { + public required bool HasPermission { get; set; } + + [SetsRequiredMembers] + public SectorPermissionResponse(bool hasPermission) + { + HasPermission = hasPermission; + } + } + + [HttpGet("current/permission")] + public async Task GetPermission() + { + var user = await DbContext.User.FindAsync(this.GetUserId()) ?? + throw new ApiError.UserNotFound(this.GetUserId()); + var controllers = await VatsimService.GetAtcList(); + var atc = controllers.FirstOrDefault(c => c.Id.ToString() == user.Cid); + if (atc == null) + { + return new SectorPermissionResponse(false); + } + var hasPermission = atc.Roles.Any(r => r.Name == "Online Permission" || r.Name == "ATC Student"); + return new SectorPermissionResponse(hasPermission); + } +} diff --git a/Net.Vatprc.Uniapi/Controllers/UserController.cs b/Net.Vatprc.Uniapi/Controllers/UserController.cs index 129f889..c19456b 100644 --- a/Net.Vatprc.Uniapi/Controllers/UserController.cs +++ b/Net.Vatprc.Uniapi/Controllers/UserController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Collections.Immutable; +using System.Security.Claims; namespace Net.Vatprc.Uniapi.Controllers; @@ -51,4 +52,13 @@ public async Task Get(Ulid id) { return new UserDto(await DbContext.User.FindAsync(id) ?? throw new ApiError.UserNotFound(id)); } + + [HttpGet("me")] + public async Task Me() + { + var subject = User.FindFirstValue(ClaimTypes.NameIdentifier); + var userId = Ulid.Parse(subject); + var user = await DbContext.User.FindAsync(userId); + return new UserDto(user ?? throw new ApiError.UserNotFound(userId)); + } } diff --git a/Net.Vatprc.Uniapi/Services/VatsimData.cs b/Net.Vatprc.Uniapi/Services/VatsimData.cs index e86c399..7d2f9be 100644 --- a/Net.Vatprc.Uniapi/Services/VatsimData.cs +++ b/Net.Vatprc.Uniapi/Services/VatsimData.cs @@ -6,7 +6,7 @@ namespace Net.Vatprc.Uniapi.Services.VatsimData; -public partial class VatsimData +public class VatsimData { [JsonPropertyName("general")] public General General { get; set; } @@ -39,7 +39,7 @@ public partial class VatsimData public Rating[] MilitaryRatings { get; set; } } -public partial class Atc +public class Atc { [JsonPropertyName("cid")] public long Cid { get; set; } @@ -78,7 +78,7 @@ public partial class Atc public DateTimeOffset LogonTime { get; set; } } -public partial class Facility +public class Facility { [JsonPropertyName("id")] public long Id { get; set; } @@ -90,7 +90,7 @@ public partial class Facility public string Long { get; set; } } -public partial class General +public class General { [JsonPropertyName("version")] public long Version { get; set; } @@ -111,7 +111,7 @@ public partial class General public long UniqueUsers { get; set; } } -public partial class Rating +public class Rating { [JsonPropertyName("id")] public long Id { get; set; } @@ -123,7 +123,7 @@ public partial class Rating public string LongName { get; set; } } -public partial class Pilot +public class Pilot { [JsonPropertyName("cid")] public long Cid { get; set; } @@ -177,7 +177,7 @@ public partial class Pilot public DateTimeOffset LastUpdated { get; set; } } -public partial class FlightPlan +public class FlightPlan { [JsonPropertyName("flight_rules")] public string FlightRules { get; set; } @@ -228,7 +228,7 @@ public partial class FlightPlan public string AssignedTransponder { get; set; } } -public partial class Prefile +public class Prefile { [JsonPropertyName("cid")] public long Cid { get; set; } @@ -246,7 +246,7 @@ public partial class Prefile public DateTimeOffset LastUpdated { get; set; } } -public partial class ServerElement +public class ServerElement { [JsonPropertyName("ident")] public string Ident { get; set; } @@ -270,7 +270,7 @@ public partial class ServerElement public bool IsSweatbox { get; set; } } -public partial class AtcSchedule +public class AtcSchedule { [JsonPropertyName("callsign")] public string Callsign { get; set; } @@ -294,7 +294,7 @@ public partial class AtcSchedule public User User { get; set; } } -public partial class User +public class User { [JsonPropertyName("id")] public long Id { get; set; } @@ -305,3 +305,30 @@ public partial class User [JsonPropertyName("last_name")] public string LastName { get; set; } } + +public class Controller +{ + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("first_name")] + public string FirstName { get; set; } + + [JsonPropertyName("last_name")] + public string LastName { get; set; } + + [JsonPropertyName("roles")] + public Role[] Roles { get; set; } +} + +public class Role +{ + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("expires")] + public DateTimeOffset? Expires { get; set; } +} diff --git a/Net.Vatprc.Uniapi/Services/VatsimService.cs b/Net.Vatprc.Uniapi/Services/VatsimService.cs index 3ee840b..936128f 100644 --- a/Net.Vatprc.Uniapi/Services/VatsimService.cs +++ b/Net.Vatprc.Uniapi/Services/VatsimService.cs @@ -38,4 +38,16 @@ public static WebApplicationBuilder ConfigureOn(WebApplicationBuilder builder) }) ?? throw new Exception("Unexpected null on fetch vatprc data"); return result; } + + public async Task> GetAtcList() + { + var result = await Cache.GetOrCreateAsync("controllers", async entry => + { + entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1); + return await "https://atcapi.vatprc.net/v1/public/controllers" + .WithHeader("User-Agent", UniapiUserAgent) + .GetJsonAsync>(); + }) ?? throw new Exception("Unexpected null on fetch vatprc data"); + return result; + } }