diff --git a/Program.cs b/Program.cs index 3599fa9..8d5ff89 100644 --- a/Program.cs +++ b/Program.cs @@ -13,8 +13,9 @@ builder.Services.AddHttpClient(); var dataDir = Path.Combine(AppContext.BaseDirectory, "data"); -var authService = new AuthService(); -var dbService = new DatabaseService(Path.Combine(dataDir, "gott.db")); +var dbPath = Path.Combine(dataDir, "gott.db"); +var authService = new AuthService(dbPath); +var dbService = new DatabaseService(dbPath); dbService.EnsureDefaultUser(authService); builder.Services.AddSingleton(authService); diff --git a/Services/AuthService.cs b/Services/AuthService.cs index 280cbdd..fb46ee8 100644 --- a/Services/AuthService.cs +++ b/Services/AuthService.cs @@ -1,13 +1,40 @@ using System; -using System.Collections.Concurrent; using System.Security.Cryptography; using System.Text; +using Dapper; +using Microsoft.Data.Sqlite; namespace Gott.Services; public class AuthService { - private readonly ConcurrentDictionary _tokens = new(); // token -> userId + private readonly string _connectionString; + + public AuthService(string dbPath) + { + _connectionString = $"Data Source={dbPath}"; + InitializeTable(); + } + + private SqliteConnection CreateConnection() + { + var conn = new SqliteConnection(_connectionString); + conn.Open(); + return conn; + } + + private void InitializeTable() + { + using var conn = CreateConnection(); + conn.Execute(@" + CREATE TABLE IF NOT EXISTS tokens ( + token TEXT NOT NULL PRIMARY KEY, + user_id TEXT NOT NULL, + created_at TEXT NOT NULL + ); + CREATE INDEX IF NOT EXISTS idx_tokens_user ON tokens(user_id); + "); + } public string HashPassword(string password) { @@ -23,19 +50,25 @@ public class AuthService public string CreateToken(string userId) { var token = Convert.ToHexStringLower(RandomNumberGenerator.GetBytes(32)); - _tokens[token] = userId; + using var conn = CreateConnection(); + conn.Execute( + "INSERT INTO tokens (token, user_id, created_at) VALUES (@token, @userId, @now)", + new { token, userId, now = DateTime.UtcNow.ToString("o") }); return token; } public string ValidateToken(string token) { if (string.IsNullOrEmpty(token)) return null; - return _tokens.TryGetValue(token, out var userId) ? userId : null; + using var conn = CreateConnection(); + return conn.QuerySingleOrDefault( + "SELECT user_id FROM tokens WHERE token = @token", new { token }); } public void RevokeToken(string token) { - if (!string.IsNullOrEmpty(token)) - _tokens.TryRemove(token, out _); + if (string.IsNullOrEmpty(token)) return; + using var conn = CreateConnection(); + conn.Execute("DELETE FROM tokens WHERE token = @token", new { token }); } }