121 lines
4.3 KiB
C#
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();
|
|
}
|
|
}
|