PhoneToolMX/PhoneToolMX.Models/Data/PTMXContext.cs

138 lines
5.6 KiB
C#

// using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using System.Security.Claims;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using PhoneToolMX.Models;
using System.Net.NetworkInformation;
// ReSharper disable CheckNamespace
// ReSharper disable UnusedAutoPropertyAccessor.Global
namespace PhoneToolMX.Data {
public class PTMXContext : DbContext
{
public DbSet<Phone> Phones { get; set; }
public DbSet<PhoneModel> PhoneModels { get; set; }
public DbSet<Extension> Extensions { get; set; }
public DbSet<CustomData> CustomData { get; set; }
public DbSet<User> Users { get; set; }
public PTMXContext(DbContextOptions<PTMXContext> options) : base(options)
{
}
#region Public helpers
/// <summary>
/// Adds an <see cref="IOwnedModel"/> entity to the database, marking the given <see cref="User"/> as its owner.
/// </summary>
/// <param name="owner">The <see cref="User"/> that owns this entity.</param>
/// <param name="entity">The entity to be created.</param>
/// <typeparam name="TEntity">A model conforming to <see cref="IOwnedModel"/>.</typeparam>
/// <returns>The entity entry for the created entity.</returns>
public async Task<EntityEntry<TEntity>> AddOwnable<TEntity>(User owner, TEntity entity) where TEntity: OwnedBase
{
var set = Set<TEntity>();
entity.Owners ??= new List<User>();
entity.Owners.Add(owner);
var entry = await AddAsync(entity);
return entry;
}
/// <summary>
/// Gets a DbSet with all required relationships
/// </summary>
/// <typeparam name="TEntity">IOwnedModel</typeparam>
/// <returns>DbSet&lt;TEntity&gt;</returns>
private IQueryable<TEntity> GetFullSet<TEntity>() where TEntity: class, IModel
{
var set = Set<TEntity>().AsQueryable();
return typeof(TEntity).GetProperties()
.Where(p => p.GetCustomAttributes(typeof(AlwaysIncludeAttribute), true)
.Length != 0)
.Aggregate(set, (current, prop) => current.Include(prop.Name));
}
/// <summary>
/// Gets all entities of a certain model owned by the <see cref="User"/>.
/// </summary>
/// <param name="owner">The <see cref="User"/> object to be considered the owner.</param>
/// <typeparam name="TEntity">A model conforming to <see cref="IOwnedModel"/></typeparam>
/// <returns>All entities of the model owned by the given user</returns>
public ICollection<TEntity> GetOwned<TEntity>(User owner) where TEntity : class, IOwnedModel
{
if (owner == null) return null;
var entity = GetFullSet<TEntity>().Where(x => x.Owners.Any(o => o.Id == owner.Id));
// eager load all w/ AlwaysInclude
return entity.ToList();
}
/// <summary>
/// Gets a model entity by its Id
/// </summary>
/// <param name="id">Id of the model, or null if you're like that</param>
/// <typeparam name="TEntity">A model confirming to <see cref="IModel"/> that has a given DbSet</typeparam>
/// <returns>The model defined by the Id, or null if none exist.</returns>
/// <remarks>If null is provided as the id, null will be returned. <c>id</c> is nullable solely for compatibility.
/// </remarks>
public TEntity GetEntityById<TEntity>(int? id) where TEntity : class, IModel
{
return id == null ? null : GetFullSet<TEntity>().FirstOrDefault(o => o.Id == id);
}
#endregion
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Core of PTMX: Phones and extensions
var ext = modelBuilder.Entity<Extension>();
ext.HasKey(x => x.Id);
ext.Property(x => x.Id).UseIdentityColumn();
ext.Property(x => x.ExtId).HasComputedColumnSql("\"Id\" + 1000", stored: true);
// Randomly generates a 24-char password
ext
.Property(p => p.Password)
.HasDefaultValueSql("encode(gen_random_bytes(18), 'base64')");
var phone = modelBuilder.Entity<Phone>();
phone
.HasMany(p => p.Extensions)
.WithMany(x => x.Phones);
phone.HasKey(p => p.Id);
phone.Property(p => p.Id).UseIdentityColumn();
phone.HasOne(p => p.PrimaryExtension).WithMany();
// Wallpapers, ringtones, etc
var cd = modelBuilder.Entity<CustomData>();
cd.HasKey(c => c.Id);
cd.Property(c => c.Id).UseIdentityColumn();
// Phone models, for custom tests
var pm = modelBuilder.Entity<PhoneModel>();
pm.HasKey(p => p.Id);
pm.Property(p => p.Id).UseIdentityColumn();
pm.HasData(new PhoneModel
{
Id = 0,
ModelName = "Polycom VVX300/310",
MaxExtensions = 6,
PreVvxPolycom = false,
});
// Authz/RBAC
var userEnt = modelBuilder.Entity<User>();
userEnt
.HasMany(u => u.Phones)
.WithMany(p => p.Owners);
userEnt
.HasMany(u => u.Extensions)
.WithMany(x => x.Owners);
userEnt
.HasKey(u => u.Id);
modelBuilder.Entity<Role>()
.HasKey(r => r.Id);
}
}
}