using System; using System.Threading.Tasks; using Dapper; namespace MiniWiki.Data.Sessions; public class SessionsDatabaseRepository(IDbConnectionFactory connectionFactory) : ISessionsRepository { public async Task CreateAsync(string userId, long durationSeconds) { var sessionId = Guid.CreateVersion7().ToString(); var now = DateTimeOffset.UtcNow; var expiresAt = now.AddSeconds(durationSeconds); const string insertStatement = """ INSERT INTO sessions(id, user_id, created_at, expires_at) VALUES(@Id, @UserId, @CreatedAt, @ExpiresAt) """; var session = new Session(sessionId, userId, now.ToUnixTimeMilliseconds(), expiresAt.ToUnixTimeMilliseconds()); using var conn = connectionFactory.CreateConnection(); await conn.ExecuteAsync(insertStatement, session); return session; } public async Task GetAsync(string sessionId) { const string query = """ SELECT s.id, s.user_id, s.expires_at, u.email, u.display_name, u.is_admin FROM sessions s JOIN users u on s.user_id = u.id WHERE s.id = @sessionId AND s.expires_at > @now """; var connection = connectionFactory.CreateConnection(); return await connection.QuerySingleOrDefaultAsync(query, new { sessionId, now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }); } public async Task DeleteAsync(string sessionId) { const string statement = "DELETE FROM sessions WHERE id = @sessionId"; var connection = connectionFactory.CreateConnection(); await connection.ExecuteAsync(statement, new { sessionId }); } }