Iceshrimp.NET/Iceshrimp.Backend/Controllers/Web/SessionController.cs

121 lines
4.3 KiB
C#

using System.Net;
using System.Net.Mime;
using Iceshrimp.Backend.Controllers.Shared.Attributes;
using Iceshrimp.Backend.Core.Database;
using Iceshrimp.Backend.Core.Middleware;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;
using Microsoft.EntityFrameworkCore;
using static Iceshrimp.Shared.Schemas.Web.SessionSchemas;
namespace Iceshrimp.Backend.Controllers.Web;
[ApiController]
[Authenticate]
[Authorize]
[Tags("Session")]
[EnableRateLimiting("sliding")]
[Produces(MediaTypeNames.Application.Json)]
[Route("/api/iceshrimp/sessions")]
public class SessionController(DatabaseContext db) : ControllerBase
{
[HttpGet]
[ProducesResults(HttpStatusCode.OK)]
public async Task<List<SessionResponse>> GetSessions(int page = 0)
{
const int pageSize = 20;
var currentId = HttpContext.GetSessionOrFail().Id;
return await db.Sessions
.Where(p => p.User == HttpContext.GetUserOrFail())
.OrderByDescending(p => p.LastActiveDate ?? p.CreatedAt)
.Skip(page * pageSize)
.Take(pageSize)
.Select(p => new SessionResponse
{
Id = p.Id,
Current = p.Id == currentId,
Active = p.Active,
CreatedAt = p.CreatedAt,
LastActive = p.LastActiveDate
})
.ToListAsync();
}
[HttpDelete("{id}")]
[ProducesResults(HttpStatusCode.OK)]
[ProducesErrors(HttpStatusCode.BadRequest, HttpStatusCode.NotFound)]
public async Task TerminateSession(string id)
{
var user = HttpContext.GetUserOrFail();
var session = await db.Sessions.FirstOrDefaultAsync(p => p.Id == id && p.User == user)
?? throw GracefulException.NotFound("Session not found");
if (session.Id == HttpContext.GetSessionOrFail().Id)
throw GracefulException.BadRequest("Refusing to terminate current session");
db.Remove(session);
await db.SaveChangesAsync();
}
[HttpGet("mastodon")]
[ProducesResults(HttpStatusCode.OK)]
public async Task<List<MastodonSessionResponse>> GetMastodonSessions(int page = 0)
{
const int pageSize = 20;
return await db.OauthTokens
.Include(p => p.App)
.Where(p => p.User == HttpContext.GetUserOrFail())
.OrderByDescending(p => p.LastActiveDate ?? p.CreatedAt)
.Skip(page * pageSize)
.Take(pageSize)
.Select(p => new MastodonSessionResponse
{
Id = p.Id,
Active = p.Active,
CreatedAt = p.CreatedAt,
LastActive = p.LastActiveDate,
App = p.App.Name,
Scopes = p.Scopes,
Flags = new MastodonSessionFlags
{
SupportsHtmlFormatting = p.SupportsHtmlFormatting,
AutoDetectQuotes = p.AutoDetectQuotes,
IsPleroma = p.IsPleroma,
SupportsInlineMedia = p.SupportsInlineMedia
}
})
.ToListAsync();
}
[HttpPatch("mastodon/{id}")]
[ProducesResults(HttpStatusCode.OK)]
[ProducesErrors(HttpStatusCode.BadRequest, HttpStatusCode.NotFound)]
public async Task UpdateMastodonSession(string id, [FromBody] MastodonSessionFlags flags)
{
var user = HttpContext.GetUserOrFail();
var token = await db.OauthTokens.FirstOrDefaultAsync(p => p.Id == id && p.User == user)
?? throw GracefulException.NotFound("Session not found");
token.SupportsHtmlFormatting = flags.SupportsHtmlFormatting;
token.AutoDetectQuotes = flags.AutoDetectQuotes;
token.IsPleroma = flags.IsPleroma;
token.SupportsInlineMedia = flags.SupportsInlineMedia;
await db.SaveChangesAsync();
}
[HttpDelete("mastodon/{id}")]
[ProducesResults(HttpStatusCode.OK)]
[ProducesErrors(HttpStatusCode.BadRequest, HttpStatusCode.NotFound)]
public async Task TerminateMastodonSession(string id)
{
var user = HttpContext.GetUserOrFail();
var token = await db.OauthTokens.FirstOrDefaultAsync(p => p.Id == id && p.User == user)
?? throw GracefulException.NotFound("Session not found");
db.Remove(token);
await db.SaveChangesAsync();
}
}