Initial commit.
This commit is contained in:
10
Data/Entities/Config.cs
Normal file
10
Data/Entities/Config.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace TriliumMind.Data.Entities;
|
||||
|
||||
public class Config
|
||||
{
|
||||
[Key]
|
||||
public string Key { get; set; } = null!;
|
||||
public string Value { get; set; } = null!;
|
||||
}
|
||||
20
Data/Entities/JiraIssue.cs
Normal file
20
Data/Entities/JiraIssue.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace TriliumMind.Data.Entities;
|
||||
|
||||
public class JiraIssue
|
||||
{
|
||||
[Key]
|
||||
public string Key { get; set; } = null!;
|
||||
public string Summary { get; set; } = null!;
|
||||
public string? Parent { get; set; }
|
||||
public string Type { get; set; } = null!;
|
||||
public string Status { get; set; } = null!;
|
||||
public string Assignee { get; set; } = null!;
|
||||
public string Manager { get; set; } = null!;
|
||||
public DateTimeOffset Due { get; set; }
|
||||
public DateTimeOffset Updated { get; set; }
|
||||
public DateTimeOffset Published { get; set; }
|
||||
public string? ObjectId { get; set; }
|
||||
public int NeedNotify { get; set; }
|
||||
}
|
||||
13
Data/IAppDbContext.cs
Normal file
13
Data/IAppDbContext.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using TriliumMind.Data.Entities;
|
||||
|
||||
namespace TriliumMind.Data;
|
||||
|
||||
public interface IAppDbContext : IDisposable
|
||||
{
|
||||
DbSet<Config> Configs { get; set; }
|
||||
DbSet<JiraIssue> JiraIssues { get; set; }
|
||||
DatabaseFacade Database { get; }
|
||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
87
Data/PostgresDbContext.cs
Normal file
87
Data/PostgresDbContext.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Serilog;
|
||||
using TriliumMind.Data.Entities;
|
||||
using TriliumMind.Models;
|
||||
|
||||
namespace TriliumMind.Data;
|
||||
|
||||
public class PostgresDbContext : DbContext, IAppDbContext
|
||||
{
|
||||
private readonly Serilog.ILogger _log;
|
||||
private readonly string _connectionString;
|
||||
|
||||
public DbSet<Config> Configs { get; set; }
|
||||
public DbSet<JiraIssue> JiraIssues { get; set; }
|
||||
|
||||
public PostgresDbContext(AppConfigs configs)
|
||||
{
|
||||
_log = Log.ForContext<PostgresDbContext>();
|
||||
var pgConfig = configs.AppSettings.Database.Postgres;
|
||||
var connectionStringBuilder = new Npgsql.NpgsqlConnectionStringBuilder
|
||||
{
|
||||
Host = pgConfig.Host,
|
||||
Port = pgConfig.Port,
|
||||
Database = pgConfig.Database,
|
||||
Username = pgConfig.Username,
|
||||
Password = pgConfig.Password
|
||||
};
|
||||
|
||||
// Set SSL/TLS
|
||||
if (!string.IsNullOrEmpty(pgConfig.SslCertificatePath))
|
||||
{
|
||||
var certPath = Path.IsPathRooted(pgConfig.SslCertificatePath)
|
||||
? pgConfig.SslCertificatePath
|
||||
: Path.Combine(AppContext.BaseDirectory, pgConfig.SslCertificatePath);
|
||||
|
||||
if (File.Exists(certPath))
|
||||
{
|
||||
_log.Information("Configuring PostgreSQL with SSL certificate: {CertPath}", certPath);
|
||||
connectionStringBuilder.SslMode = Npgsql.SslMode.VerifyFull;
|
||||
connectionStringBuilder.RootCertificate = certPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.Warning("SSL certificate not found at {CertPath}, connecting without SSL", certPath);
|
||||
connectionStringBuilder.SslMode = Npgsql.SslMode.Prefer;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.Information("No SSL certificate configured, connecting without SSL");
|
||||
connectionStringBuilder.SslMode = Npgsql.SslMode.Prefer;
|
||||
}
|
||||
|
||||
_connectionString = connectionStringBuilder.ConnectionString;
|
||||
_log.Debug("PostgreSQL connection string configured (password hidden)");
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
=> optionsBuilder.UseNpgsql(_connectionString);
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
modelBuilder.Entity<Config>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Key);
|
||||
entity.Property(e => e.Key).IsRequired();
|
||||
entity.Property(e => e.Value).IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity<JiraIssue>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Key);
|
||||
entity.Property(e => e.Key).IsRequired();
|
||||
entity.Property(e => e.Summary).IsRequired();
|
||||
entity.Property(e => e.Type).IsRequired();
|
||||
entity.Property(e => e.Status).IsRequired();
|
||||
entity.Property(e => e.Assignee).IsRequired();
|
||||
entity.Property(e => e.Manager).IsRequired();
|
||||
entity.Property(e => e.Due).IsRequired();
|
||||
entity.Property(e => e.Updated).IsRequired();
|
||||
entity.Property(e => e.Published).IsRequired();
|
||||
entity.Property(e => e.NeedNotify).IsRequired();
|
||||
});
|
||||
}
|
||||
}
|
||||
62
Data/SqliteDbContext.cs
Normal file
62
Data/SqliteDbContext.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TriliumMind.Data.Entities;
|
||||
using TriliumMind.Models;
|
||||
|
||||
namespace TriliumMind.Data;
|
||||
|
||||
public class SqliteDbContext : DbContext, IAppDbContext
|
||||
{
|
||||
private readonly string _dbFilePath;
|
||||
|
||||
public DbSet<Config> Configs { get; set; }
|
||||
public DbSet<JiraIssue> JiraIssues { get; set; }
|
||||
|
||||
public SqliteDbContext(AppConfigs configs)
|
||||
{
|
||||
var dbPath = configs.AppSettings.Database.Sqlite.DatabaseFilePath;
|
||||
|
||||
if (Path.IsPathRooted(dbPath) && File.Exists(dbPath))
|
||||
{
|
||||
_dbFilePath = dbPath;
|
||||
}
|
||||
else if (Path.IsPathRooted(dbPath))
|
||||
{
|
||||
_dbFilePath = dbPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
var basePath = AppContext.BaseDirectory;
|
||||
_dbFilePath = Path.Combine(basePath, dbPath);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
=> optionsBuilder.UseSqlite($"Data Source={_dbFilePath}");
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
modelBuilder.Entity<Config>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Key);
|
||||
entity.Property(e => e.Key).IsRequired();
|
||||
entity.Property(e => e.Value).IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity<JiraIssue>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Key);
|
||||
entity.Property(e => e.Key).IsRequired();
|
||||
entity.Property(e => e.Summary).IsRequired();
|
||||
entity.Property(e => e.Type).IsRequired();
|
||||
entity.Property(e => e.Status).IsRequired();
|
||||
entity.Property(e => e.Assignee).IsRequired();
|
||||
entity.Property(e => e.Manager).IsRequired();
|
||||
entity.Property(e => e.Due).IsRequired();
|
||||
entity.Property(e => e.Updated).IsRequired();
|
||||
entity.Property(e => e.Published).IsRequired();
|
||||
entity.Property(e => e.NeedNotify).IsRequired();
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user