Initial commit carried over from private repo. This is V2.
All checks were successful
Build and Push Docker Image / build (push) Successful in 1m3s
Build and Push Docker Image / docker (push) Successful in 43s

This commit is contained in:
2025-07-04 21:24:12 +02:00
parent 7715816029
commit 4393977389
96 changed files with 3223 additions and 0 deletions

View File

@ -0,0 +1,8 @@
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace MessengerApi.Db.Converters
{
public sealed class DateTimeAsUtcValueConverter()
: ValueConverter<DateTime, DateTime>(
v => v, v => new DateTime(v.Ticks, DateTimeKind.Utc));
}

View File

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<BaseOutputPath>..\out\</BaseOutputPath>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MessengerApi.Db.Contracts\MessengerApi.Db.Contracts.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,26 @@
using MessengerApi.Db.Converters;
using MessengerApi.Db.Entities;
using Microsoft.EntityFrameworkCore;
namespace MessengerApi.Db
{
public abstract class MessengerDbContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Message> Messages { get; set; }
public DbSet<UserRoute> UserRoutes { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().HasKey(e => e.Id);
modelBuilder.Entity<Message>().HasKey(e => e.Id);
modelBuilder.Entity<Message>().Property(e => e.CreatedUtc).HasConversion<DateTimeAsUtcValueConverter>();
modelBuilder.Entity<Message>().Property(e => e.PayloadLifespanInSeconds).IsRequired();
modelBuilder.Entity<UserRoute>().HasKey(e => e.Id);
}
}
}

View File

@ -0,0 +1,23 @@
using MessengerApi.Db.Contracts.Repositories;
using MessengerApi.Db.Entities;
using Microsoft.EntityFrameworkCore;
namespace MessengerApi.Db.Repositories
{
public class MessageRepository : Repository<Message>, IMessageRepository
{
public MessageRepository(DbSet<Message> db) : base(db)
{
}
public IEnumerable<Message> GetPendingMessages(User user)
{
var timestamp = DateTime.UtcNow;
return this.db
.Where(x => x.ToId == user.Id && x.IsDelivered == false)
.Where(x => x.PayloadLifespanInSeconds == null || x.CreatedUtc.AddSeconds(x.PayloadLifespanInSeconds.Value) >= timestamp)
.OrderBy(x => x.CreatedUtc);
}
}
}

View File

@ -0,0 +1,26 @@
using MessengerApi.Db.Contracts.Entities;
using MessengerApi.Db.Contracts.Repositories;
using Microsoft.EntityFrameworkCore;
namespace MessengerApi.Db.Repositories
{
public abstract class Repository<T> : IRepository<T> where T : class, IEntity<T>
{
protected readonly DbSet<T> db;
public Repository(DbSet<T> db)
{
this.db = db;
}
public void Add(T entity)
{
this.db.Add(entity);
}
public T GetById(Guid id)
{
return this.db.Single(x => x.Id == id);
}
}
}

View File

@ -0,0 +1,18 @@
using MessengerApi.Db.Contracts.Repositories;
using MessengerApi.Db.Entities;
using Microsoft.EntityFrameworkCore;
namespace MessengerApi.Db.Repositories
{
public class UserRepository : Repository<User>, IUserRepository
{
public UserRepository(DbSet<User> db) : base(db)
{
}
public User SingleByApiKeyAndEnabled(Guid id, bool enabled)
{
return this.db.Single(x => x.ApiKey == id && x.IsEnabled == enabled);
}
}
}

View File

@ -0,0 +1,23 @@
using MessengerApi.Db.Contracts.Repositories;
using MessengerApi.Db.Entities;
using Microsoft.EntityFrameworkCore;
namespace MessengerApi.Db.Repositories
{
public class UserRouteRepository : Repository<UserRoute>, IUserRouteRepository
{
public UserRouteRepository(DbSet<UserRoute> db) : base(db)
{
}
public IEnumerable<UserRoute> GetAllByUser(User sender)
{
return this.db.Include(x => x.From).Include(x => x.To).Where(x => x.From.Id == sender.Id || x.To.Id == sender.Id);
}
public IEnumerable<UserRoute> GetByFrom(User user)
{
return this.db.Include(x => x.From).Include(x => x.To).Where(x => x.From.Id == user.Id);
}
}
}