From 2d1d7019cbe051d2a42350a6f9d50e1f4ed8bd11 Mon Sep 17 00:00:00 2001 From: ivarlovlie Date: Sun, 23 Jan 2022 18:42:59 +0100 Subject: feat: Remove stale tokens on a regular basis --- src/server/GlobalUsings.cs | 24 +++++++++++++----------- src/server/IOL.BookmarkThing.Server.csproj | 5 +---- src/server/Jobs/JobRegister.cs | 18 ++++++++++++++++++ src/server/Jobs/TokenCleanupJob.cs | 19 +++++++++++++++++++ src/server/Startup.cs | 25 +++++++++++++++++++++++-- src/server/Utilities/QuartzJsonSerializer.cs | 16 ++++++++++++++++ 6 files changed, 90 insertions(+), 17 deletions(-) create mode 100644 src/server/Jobs/JobRegister.cs create mode 100644 src/server/Jobs/TokenCleanupJob.cs create mode 100644 src/server/Utilities/QuartzJsonSerializer.cs (limited to 'src/server') diff --git a/src/server/GlobalUsings.cs b/src/server/GlobalUsings.cs index 882de1c..2134083 100644 --- a/src/server/GlobalUsings.cs +++ b/src/server/GlobalUsings.cs @@ -1,17 +1,7 @@ global using System.Security.Claims; global using System.Text.Json; global using System.Text.Json.Serialization; -global using Swashbuckle.AspNetCore.SwaggerGen; -global using Serilog; -global using Microsoft.AspNetCore.Mvc.Versioning; -global using IOL.Helpers; -global using IOL.BookmarkThing.Server.Models.General; -global using IOL.BookmarkThing.Server.Models.Result; -global using IOL.BookmarkThing.Server.Models.Database; -global using IOL.BookmarkThing.Server.Api; -global using IOL.BookmarkThing.Server.StaticData; -global using IOL.BookmarkThing.Server.Utilities; -global using IOL.BookmarkThing.Server.Api.V1; +global using System.Reflection; global using Microsoft.OpenApi.Models; global using Microsoft.AspNetCore.Authentication; global using Microsoft.AspNetCore.Authorization; @@ -21,3 +11,15 @@ global using Microsoft.AspNetCore.DataProtection; global using Microsoft.EntityFrameworkCore; global using Microsoft.AspNetCore.Mvc.ApiExplorer; global using Microsoft.AspNetCore.Mvc.Controllers; +global using Microsoft.AspNetCore.Mvc.Versioning; +global using IOL.BookmarkThing.Server.Models.General; +global using IOL.BookmarkThing.Server.Models.Result; +global using IOL.BookmarkThing.Server.Models.Database; +global using IOL.BookmarkThing.Server.StaticData; +global using IOL.BookmarkThing.Server.Utilities; +global using IOL.BookmarkThing.Server.Api.V1; +global using IOL.BookmarkThing.Server.Jobs; +global using IOL.Helpers; +global using Swashbuckle.AspNetCore.SwaggerGen; +global using Serilog; +global using Quartz; diff --git a/src/server/IOL.BookmarkThing.Server.csproj b/src/server/IOL.BookmarkThing.Server.csproj index e68b37e..1b7c0b4 100644 --- a/src/server/IOL.BookmarkThing.Server.csproj +++ b/src/server/IOL.BookmarkThing.Server.csproj @@ -27,12 +27,9 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + - - - - diff --git a/src/server/Jobs/JobRegister.cs b/src/server/Jobs/JobRegister.cs new file mode 100644 index 0000000..98eac97 --- /dev/null +++ b/src/server/Jobs/JobRegister.cs @@ -0,0 +1,18 @@ +using Quartz; + +namespace IOL.BookmarkThing.Server.Jobs; + +public static class JobRegister +{ + public static readonly JobKey TokenCleanupKey = new("TokenCleanupJob"); + + public static IServiceCollectionQuartzConfigurator RegisterJobs(this IServiceCollectionQuartzConfigurator configurator) { + configurator.AddJob(TokenCleanupKey); + configurator.AddTrigger(options => { + options.ForJob(TokenCleanupKey) + .WithIdentity(TokenCleanupKey.Name + "-trigger") + .WithCronSchedule(CronScheduleBuilder.DailyAtHourAndMinute(1, 0)); + }); + return configurator; + } +} diff --git a/src/server/Jobs/TokenCleanupJob.cs b/src/server/Jobs/TokenCleanupJob.cs new file mode 100644 index 0000000..99e7d0d --- /dev/null +++ b/src/server/Jobs/TokenCleanupJob.cs @@ -0,0 +1,19 @@ +namespace IOL.BookmarkThing.Server.Jobs; + +public class TokenCleanupJob : IJob +{ + private readonly ILogger _logger; + private readonly AppDbContext _context; + + public TokenCleanupJob(ILogger logger, AppDbContext context) { + _logger = logger; + _context = context; + } + + public Task Execute(IJobExecutionContext context) { + var staleTokens = _context.AccessTokens.Where(c => c.HasExpired); + _logger.LogInformation("Removing {0} stale tokens", staleTokens.Count()); + _context.AccessTokens.RemoveRange(); + return Task.CompletedTask; + } +} diff --git a/src/server/Startup.cs b/src/server/Startup.cs index a1b6eb1..4b7c097 100644 --- a/src/server/Startup.cs +++ b/src/server/Startup.cs @@ -1,5 +1,3 @@ -using System.Reflection; - namespace IOL.BookmarkThing.Server; public class Startup @@ -21,6 +19,16 @@ public class Startup return $"Server={host};Port={port};Database={database};User Id={user};Password={password}"; } + public string QuartzDatabaseConnectionString() { + var host = Configuration.GetValue("QUARTZ_DB_HOST"); + var port = Configuration.GetValue("QUARTZ_DB_PORT"); + var database = Configuration.GetValue("QUARTZ_DB_NAME"); + var user = Configuration.GetValue("QUARTZ_DB_USER"); + var password = Configuration.GetValue("QUARTZ_DB_PASSWORD"); + return $"Server={host};Port={port};Database={database};User Id={user};Password={password}"; + } + + // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddDataProtection() @@ -46,6 +54,19 @@ public class Startup } }); + services.AddQuartz(options => { + options.UsePersistentStore(o => { + o.UsePostgres(QuartzDatabaseConnectionString()); + o.UseSerializer(); + }); + options.UseMicrosoftDependencyInjectionJobFactory(); + options.RegisterJobs(); + }); + + services.AddQuartzHostedService(options => { + options.WaitForJobsToComplete = true; + }); + services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.Cookie.Name = "bookmarkthing_session"; diff --git a/src/server/Utilities/QuartzJsonSerializer.cs b/src/server/Utilities/QuartzJsonSerializer.cs new file mode 100644 index 0000000..0caa63a --- /dev/null +++ b/src/server/Utilities/QuartzJsonSerializer.cs @@ -0,0 +1,16 @@ +using Quartz.Spi; + +namespace IOL.BookmarkThing.Server.Utilities; + +public class QuartzJsonSerializer : IObjectSerializer +{ + public void Initialize() { } + + public byte[] Serialize(T obj) where T : class { + return JsonSerializer.SerializeToUtf8Bytes(obj); + } + + public T? DeSerialize(byte[] data) where T : class { + return JsonSerializer.Deserialize(data); + } +} -- cgit v1.3