126 lines
5.2 KiB
C#
126 lines
5.2 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 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 = Set<TEntity>().Where(x => x.Owners.Any(o => o.Id == owner.Id));
|
||
|
// eager load all w/ AlwaysInclude
|
||
|
entity = typeof(TEntity).GetProperties()
|
||
|
.Where(p => p.GetCustomAttributes(typeof(AlwaysIncludeAttribute), true)
|
||
|
.Length != 0)
|
||
|
.Aggregate(entity, (current, prop) => current.Include(prop.Name));
|
||
|
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 : Set<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);
|
||
|
|
||
|
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();
|
||
|
// Randomly generates a 24-char password
|
||
|
phone
|
||
|
.Property(p => p.Password)
|
||
|
.HasDefaultValueSql("encode(gen_random_bytes(18), 'base64')");
|
||
|
|
||
|
// 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);
|
||
|
}
|
||
|
}
|
||
|
}
|