1
0

ModelPostgres.cs 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. using System;
  2. using System.Linq;
  3. using Microsoft.EntityFrameworkCore;
  4. using Microsoft.EntityFrameworkCore.Diagnostics;
  5. using Microsoft.EntityFrameworkCore.Infrastructure;
  6. using Microsoft.EntityFrameworkCore.Storage;
  7. using Npgsql;
  8. namespace Content.Server.Database
  9. {
  10. public sealed class PostgresServerDbContext : ServerDbContext
  11. {
  12. public PostgresServerDbContext(DbContextOptions<PostgresServerDbContext> options) : base(options)
  13. {
  14. }
  15. protected override void OnConfiguring(DbContextOptionsBuilder options)
  16. {
  17. ((IDbContextOptionsBuilderInfrastructure) options).AddOrUpdateExtension(new SnakeCaseExtension());
  18. options.ConfigureWarnings(x =>
  19. {
  20. x.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning);
  21. #if DEBUG
  22. // for tests
  23. x.Ignore(CoreEventId.SensitiveDataLoggingEnabledWarning);
  24. #endif
  25. });
  26. #if DEBUG
  27. options.EnableSensitiveDataLogging();
  28. #endif
  29. }
  30. protected override void OnModelCreating(ModelBuilder modelBuilder)
  31. {
  32. base.OnModelCreating(modelBuilder);
  33. // ReSharper disable StringLiteralTypo
  34. // Enforce that an address cannot be IPv6-mapped IPv4.
  35. // So that IPv4 addresses are consistent between separate-socket and dual-stack socket modes.
  36. modelBuilder.Entity<ServerBan>().ToTable(t =>
  37. t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"));
  38. modelBuilder.Entity<ServerRoleBan>().ToTable( t =>
  39. t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"));
  40. modelBuilder.Entity<Player>().ToTable(t =>
  41. t.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4",
  42. "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address"));
  43. modelBuilder.Entity<ConnectionLog>().ToTable(t =>
  44. t.HasCheckConstraint("AddressNotIPv6MappedIPv4",
  45. "NOT inet '::ffff:0.0.0.0/96' >>= address"));
  46. // ReSharper restore StringLiteralTypo
  47. modelBuilder.Entity<AdminLog>()
  48. .HasIndex(l => l.Message)
  49. .HasMethod("GIN")
  50. .IsTsVectorExpressionIndex("english");
  51. foreach(var entity in modelBuilder.Model.GetEntityTypes())
  52. {
  53. foreach(var property in entity.GetProperties())
  54. {
  55. if (property.FieldInfo?.FieldType == typeof(DateTime) || property.FieldInfo?.FieldType == typeof(DateTime?))
  56. property.SetColumnType("timestamp with time zone");
  57. }
  58. }
  59. }
  60. public override IQueryable<AdminLog> SearchLogs(IQueryable<AdminLog> query, string searchText)
  61. {
  62. return query.Where(log => EF.Functions.ToTsVector("english", log.Message).Matches(searchText));
  63. }
  64. public override int CountAdminLogs()
  65. {
  66. using var command = new NpgsqlCommand("SELECT reltuples FROM pg_class WHERE relname = 'admin_log';", (NpgsqlConnection?) Database.GetDbConnection());
  67. Database.GetDbConnection().Open();
  68. var count = Convert.ToInt32((float) (command.ExecuteScalar() ?? 0));
  69. Database.GetDbConnection().Close();
  70. return count;
  71. }
  72. }
  73. }