@@ -0,0 +1,129 @@
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using Domain;
using Domain.Orders;
using Domain.People;
using Domain.Store;
using Domain.Users;

namespace DAL
{
public class DbInitializer : DropCreateDatabaseIfModelChanges<StoreItDbContext>
{
protected override void Seed(StoreItDbContext context)
{
// This method will be called after migrating to the latest version.

// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//


#region Person seed
context.ContactTypes.AddOrUpdate(
new ContactType { ContactTypeId = 1, ContactTypeActive = true, ContactTypeValue = new MultiLangString("Cellphone") },
new ContactType { ContactTypeId = 2, ContactTypeActive = true, ContactTypeValue = new MultiLangString("E-mail") },
new ContactType { ContactTypeId = 3, ContactTypeActive = true, ContactTypeValue = new MultiLangString("Skype") }
);

context.PersonTypes.AddOrUpdate(
new PersonType { PersonTypeId = 1, PersonTypeActive = true, PersonTypeValue = new MultiLangString("Employee") },
new PersonType { PersonTypeId = 2, PersonTypeActive = true, PersonTypeValue = new MultiLangString("Client") },
new PersonType { PersonTypeId = 3, PersonTypeActive = true, PersonTypeValue = new MultiLangString("Partner") },
new PersonType { PersonTypeId = 4, PersonTypeActive = true, PersonTypeValue = new MultiLangString("Manager") }
);

context.People.AddOrUpdate(
new Person { PersonId = 1, PersonActive = true, Firstname = "Peeter", Lastname = "Pakiraam", PersonTypeId = 1 }, //ID1
new Person { PersonId = 2, PersonActive = true, Firstname = "Ants", Lastname = "Pakiraam", PersonTypeId = 1 }, //ID2
new Person { PersonId = 3, PersonActive = true, Firstname = "Paula", Lastname = "Pakiraam", PersonTypeId = 2 }, //ID3
new Person { PersonId = 4, PersonActive = true, Firstname = "Peeter", Lastname = "Lorenzo", PersonTypeId = 2 }, //ID4
new Person { PersonId = 5, PersonActive = true, Firstname = "Al", Lastname = "Pacino", PersonTypeId = 3 }, //ID5
new Person { PersonId = 6, PersonActive = true, Firstname = "Obama", Lastname = "Ohama", PersonTypeId = 4 }, //ID6
new Person { PersonId = 7, PersonActive = true, Firstname = "Scarabeus", Lastname = "Obama", PersonTypeId = 1 } //ID7
);

context.Contacts.AddOrUpdate(
new Contact { ContactId = 1, ContactActive = true, ContactValue = "5553325", ContactTypeId = 1, PersonId = 1 },
new Contact { ContactId = 2, ContactActive = true, ContactValue = "minapeeter", ContactTypeId = 3, PersonId = 1 },
new Contact { ContactId = 3, ContactActive = true, ContactValue = "5552323", ContactTypeId = 1, PersonId = 2 },
new Contact { ContactId = 4, ContactActive = true, ContactValue = "5552351", ContactTypeId = 1, PersonId = 3 },
new Contact { ContactId = 5, ContactActive = true, ContactValue = "5544444", ContactTypeId = 1, PersonId = 4 },
new Contact { ContactId = 6, ContactActive = true, ContactValue = "ppakiraam@itcollege.ee", ContactTypeId = 2, PersonId = 1 },
new Contact { ContactId = 7, ContactActive = true, ContactValue = "5998989", ContactTypeId = 1, PersonId = 6 }
);
#endregion

#region Users seed
/*context.UserRoles.AddOrUpdate(
new UserRole { UserRoleId = 1, UserRoleActive = true, UserRoleName = new MultiLangString("Admin"), UserRoleDescription = new MultiLangString("System administrator") },
new UserRole { UserRoleId = 2, UserRoleActive = true, UserRoleName = new MultiLangString("Employee"), UserRoleDescription = new MultiLangString("Employees of the company") },
new UserRole { UserRoleId = 3, UserRoleActive = true, UserRoleName = new MultiLangString("Client"), UserRoleDescription = new MultiLangString("Client's user") },
new UserRole { UserRoleId = 4, UserRoleActive = true, UserRoleName = new MultiLangString("root"), UserRoleDescription = new MultiLangString("God") }
);*/

/*context.Users.AddOrUpdate(
new User { UserId = 1, UserActive = true, Username = "admin", Password = "", UserRoleId = 1, PersonId = 1 },
new User { UserId = 2, UserActive = true, Username = "user1", Password = "", UserRoleId = 2, PersonId = 2 },
new User { UserId = 3, UserActive = true, Username = "user2", Password = "", UserRoleId = 2, PersonId = 5 },
new User { UserId = 4, UserActive = true, Username = "employee3", Password = "", UserRoleId = 2, PersonId = 7 }
);*/
#endregion

#region Store seed
context.ProductCategories.AddOrUpdate(
new ProductCategory { ProductCategoryId = 1, ProductCategoryActive = true, ProductCategoryValue = new MultiLangString("Engine"), ProductCategoryDescription = new MultiLangString("Engine related parts") },
new ProductCategory { ProductCategoryId = 2, ProductCategoryActive = true, ProductCategoryValue = new MultiLangString("Transmission"), ProductCategoryDescription = new MultiLangString("Transmission related parts") }
);

context.Products.AddOrUpdate(
new Product { ProductId = 1, ProductActive = true, ProductName = new MultiLangString("Water pump"), ProductValue = 120.5, ProductCategoryId = 1 },
new Product { ProductId = 2, ProductActive = true, ProductName = new MultiLangString("Timing belt"), ProductValue = 50.75, ProductCategoryId = 1 },
new Product { ProductId = 3, ProductActive = true, ProductName = new MultiLangString("5-speed gearbox"), ProductValue = 320.50, ProductCategoryId = 2 },
new Product { ProductId = 4, ProductActive = true, ProductName = new MultiLangString("A dog's tail"), ProductValue = 1500.05, ProductCategoryId = 2 }
);

context.Storages.AddOrUpdate(
new Storage { StorageId = 1, StorageName = new MultiLangString("Tartu storage") },
new Storage { StorageId = 2, StorageName = new MultiLangString("Tallinn storage") }
);

context.StoredProducts.AddOrUpdate(
new StoredProduct { StoredProductId = 1, StorageId = 1, ProductId = 1, Quantity = 100 },
new StoredProduct { StoredProductId = 2, StorageId = 1, ProductId = 2, Quantity = 55 },
new StoredProduct { StoredProductId = 3, StorageId = 1, ProductId = 3, Quantity = 100 },
new StoredProduct { StoredProductId = 4, StorageId = 1, ProductId = 4, Quantity = 200 }
);
#endregion

#region Orders seed
context.OrderTypes.AddOrUpdate(
new OrderType { OrderTypeId = 1, OrderTypeActive = true, OrderTypeValue = new MultiLangString("Order"), OrderTypeDescription = new MultiLangString("Orders") }
);

context.Orders.AddOrUpdate(
new Order { OrderId = 1, OrderTypeId = 1, ClientId = 3, EmployeeId = 1, OrderPaymentDate = new DateTime(2016, 6, 20) },
new Order { OrderId = 2, OrderTypeId = 1, ClientId = 4, EmployeeId = 2, OrderPaymentDate = new DateTime(2016, 7, 25) }
);

context.OrderedProducts.AddOrUpdate(
new OrderedProduct { OrderedProductId = 1, OrderId = 1, ProductId = 1, OrderedPrice = 130.1, OrderedQuantity = 2 },
new OrderedProduct { OrderedProductId = 2, OrderId = 1, ProductId = 2, OrderedPrice = 75, OrderedQuantity = 2 },
new OrderedProduct { OrderedProductId = 3, OrderId = 1, ProductId = 3, OrderedPrice = 400, OrderedQuantity = 1 },
new OrderedProduct { OrderedProductId = 4, OrderId = 2, ProductId = 2, OrderedPrice = 65, OrderedQuantity = 3 },
new OrderedProduct { OrderedProductId = 5, OrderId = 2, ProductId = 4, OrderedPrice = 2000, OrderedQuantity = 1 }
);
#endregion

context.SaveChanges();
}
}
}
@@ -0,0 +1,30 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Infrastructure.Annotations;
using System.Data.Entity.ModelConfiguration;
using Domain.Users;

namespace DAL.EFConfiguration
{
public class RoleMap : EntityTypeConfiguration<Role>
{
public RoleMap()
{
Property(r => r.Name)
.IsRequired()
.HasMaxLength(256)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("RoleNameIndex") { IsUnique = true }));
HasMany(r => r.Users).WithRequired().HasForeignKey(ur => ur.RoleId);

// Primary Key
HasKey(t => t.Id);

// Properties
Property(t => t.Id)
.IsRequired();

Property(t => t.Name)
.IsRequired()
.HasMaxLength(256);
}
}
}
@@ -0,0 +1,7 @@
namespace DAL.EFConfiguration
{
public class ServiceMap
{

}
}
@@ -0,0 +1,18 @@
using System.Data.Entity.ModelConfiguration;
using Domain.Users;

namespace DAL.EFConfiguration
{
public class UserClaimMap : EntityTypeConfiguration<UserClaim>
{
public UserClaimMap()
{
// Primary Key
HasKey(t => t.Id);

// Properties
Property(t => t.UserId)
.IsRequired();
}
}
}
@@ -0,0 +1,26 @@
using System.Data.Entity.ModelConfiguration;
using Domain.Users;

namespace DAL.EFConfiguration
{
public class UserLoginMap : EntityTypeConfiguration<UserLogin>
{
public UserLoginMap()
{
// Primary Key
HasKey(t => new { t.LoginProvider, t.ProviderKey, t.UserId });

// Properties
Property(t => t.LoginProvider)
.IsRequired()
.HasMaxLength(128);

Property(t => t.ProviderKey)
.IsRequired()
.HasMaxLength(128);

Property(t => t.UserId)
.IsRequired();
}
}
}
@@ -0,0 +1,40 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Infrastructure.Annotations;
using System.Data.Entity.ModelConfiguration;
using Domain.Users;

namespace DAL.EFConfiguration
{
public class UserMap : EntityTypeConfiguration<User>
{
public UserMap()
{
HasMany(u => u.Roles).WithRequired().HasForeignKey(ur => ur.UserId);
HasMany(u => u.Claims).WithRequired().HasForeignKey(uc => uc.UserId);
HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId);
Property(u => u.UserName)
.IsRequired()
.HasMaxLength(256)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("UserNameIndex") { IsUnique = true }));
// Primary Key
HasKey(t => t.Id);

// Properties
Property(t => t.Id)
.IsRequired();

Property(t => t.Email)
.HasMaxLength(256);

Property(t => t.UserName)
.IsRequired()
.HasMaxLength(256);

Property(t => t.FirstName).HasMaxLength(128);
Property(t => t.LastName).HasMaxLength(128);

Ignore(t => t.FirstLastName);
Ignore(t => t.LastFirstName);
}
}
}
@@ -0,0 +1,14 @@
using System.Data.Entity.ModelConfiguration;
using Domain.Users;

namespace DAL.EFConfiguration
{
public class UserRoleMap : EntityTypeConfiguration<UserRole>
{
public UserRoleMap()
{
// Primary Key
HasKey(t => new { t.UserId, t.RoleId });
}
}
}
@@ -3,6 +3,7 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DAL.Interfaces.Users;
using Domain;
using Domain.People;

@@ -12,15 +13,22 @@ public interface IUOW
{
//save pending changes to the data store
void Commit();
void RefreshAllEntities();

//get repository for type
T GetRepository<T>() where T : class;

//Standard repos, autogenerated
IEFRepository<Contact> Contacts { get; }
IEFRepository<ContactType> ContactTypes { get; }

//Customs repos, manually implemented
IPersonRepository People { get; }
IContactRepository Contacts { get; }

IUserRepository Users { get; }
IUserRoleRepository UserRoles { get; }
IRoleRepository Roles { get; }
IUserClaimRepository UserClaims { get; }
IUserLoginRepository UserLogins { get; }
}
}
@@ -0,0 +1,23 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Domain.Users;
using Microsoft.AspNet.Identity;

namespace DAL.Interfaces.Users
{

public interface IRoleRepository : IRoleRepository<int, Role>
{
}

public interface IRoleRepository<in TKey, TRole> : IEFRepository<TRole>
where TRole : class, IRole<TKey>
{
TRole GetByRoleName(string roleName);
List<TRole> GetRolesForUser(TKey userId);
}
}
@@ -0,0 +1,15 @@
using System.Collections.Generic;
using Domain.Users;

namespace DAL.Interfaces.Users
{
public interface IUserClaimRepository : IUserClaimRepository<UserClaim>
{
}

public interface IUserClaimRepository<TUserClaim> : IEFRepository<TUserClaim>
where TUserClaim : class
{
List<TUserClaim> AllIncludeUser();
}
}
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Domain.Users;

namespace DAL.Interfaces
{
public interface IUserLoginRepository : IUserLoginRepository<UserLogin>
{
}

public interface IUserLoginRepository<TUserLogin> : IEFRepository<TUserLogin>
where TUserLogin : class
{
List<TUserLogin> GetAllIncludeUser();
TUserLogin GetUserLoginByProviderAndProviderKey(string loginProvider, string providerKey);
}
}
@@ -1,7 +1,24 @@
namespace DAL.Interfaces.Users
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Domain.Users;
using Microsoft.AspNet.Identity;

namespace DAL.Interfaces.Users
{
public interface IUserRepository

public interface IUserRepository : IUserRepository<int, User>
{

}

public interface IUserRepository<in TKey, TUser> : IEFRepository<TUser>
where TUser : class, IUser<TKey>
{
TUser GetUserByUserName(string userName);
TUser GetUserByEmail(string email);
bool IsInRole(TKey userId, string roleName);
void AddUserToRole(TKey userId, string roleName);
}
}
@@ -1,7 +1,20 @@
namespace DAL.Interfaces.Users
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Domain.Users;

namespace DAL.Interfaces
{
public interface IUserRoleRepository

public interface IUserRoleRepository : IUserRoleRepository<int, UserRole>
{

}

public interface IUserRoleRepository<in TKey, TUserRole> : IEFRepository<TUserRole>
where TUserRole : class
{
TUserRole GetByUserIdAndRoleId(TKey roleId, TKey userId);
}
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -0,0 +1,40 @@
namespace DAL.Migrations
{
using System;
using System.Data.Entity.Migrations;

public partial class UserModelFixed : DbMigration
{
public override void Up()
{
DropForeignKey("dbo.UserRoles", "UserRoleDescription_MultiLangStringId", "dbo.MultiLangStrings");
DropForeignKey("dbo.UserRoles", "UserRoleName_MultiLangStringId", "dbo.MultiLangStrings");
DropForeignKey("dbo.Users", new[] { "UserRole_UserId", "UserRole_RoleId" }, "dbo.UserRoles");
DropIndex("dbo.Users", new[] { "UserRole_UserId", "UserRole_RoleId" });
DropIndex("dbo.UserRoles", new[] { "UserRoleDescription_MultiLangStringId" });
DropIndex("dbo.UserRoles", new[] { "UserRoleName_MultiLangStringId" });
DropColumn("dbo.Users", "UserRole_UserId");
DropColumn("dbo.Users", "UserRole_RoleId");
DropColumn("dbo.UserRoles", "UserRoleId");
DropColumn("dbo.UserRoles", "UserRoleActive");
DropColumn("dbo.UserRoles", "UserRoleDescription_MultiLangStringId");
DropColumn("dbo.UserRoles", "UserRoleName_MultiLangStringId");
}

public override void Down()
{
AddColumn("dbo.UserRoles", "UserRoleName_MultiLangStringId", c => c.Int());
AddColumn("dbo.UserRoles", "UserRoleDescription_MultiLangStringId", c => c.Int());
AddColumn("dbo.UserRoles", "UserRoleActive", c => c.Boolean(nullable: false));
AddColumn("dbo.UserRoles", "UserRoleId", c => c.Int(nullable: false));
AddColumn("dbo.Users", "UserRole_RoleId", c => c.Int());
AddColumn("dbo.Users", "UserRole_UserId", c => c.Int());
CreateIndex("dbo.UserRoles", "UserRoleName_MultiLangStringId");
CreateIndex("dbo.UserRoles", "UserRoleDescription_MultiLangStringId");
CreateIndex("dbo.Users", new[] { "UserRole_UserId", "UserRole_RoleId" });
AddForeignKey("dbo.Users", new[] { "UserRole_UserId", "UserRole_RoleId" }, "dbo.UserRoles", new[] { "UserId", "RoleId" });
AddForeignKey("dbo.UserRoles", "UserRoleName_MultiLangStringId", "dbo.MultiLangStrings", "MultiLangStringId");
AddForeignKey("dbo.UserRoles", "UserRoleDescription_MultiLangStringId", "dbo.MultiLangStrings", "MultiLangStringId");
}
}
}

Large diffs are not rendered by default.

@@ -32,7 +32,7 @@ protected override void Seed(DAL.StoreItDbContext context)
// );
//


/*
#region Person seed
context.ContactTypes.AddOrUpdate(
new ContactType { ContactTypeId = 1, ContactTypeActive = true, ContactTypeValue = "Mobiiltelefon" },
@@ -127,7 +127,7 @@ protected override void Seed(DAL.StoreItDbContext context)
new OrderedProduct { OrderedProductId = 4, OrderId = 2, ProductId = 2, OrderedPrice = 65, OrderedQuantity = 3 },
new OrderedProduct { OrderedProductId = 5, OrderId = 2, ProductId = 4, OrderedPrice = 2000, OrderedQuantity = 1 }
);
#endregion
#endregion */
}
}
}
@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Entity.Infrastructure.Interception;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NLog;

namespace DAL
{
public class NLogCommandInterceptor : IDbCommandInterceptor
{
private readonly ILogger _logger; // = LogManager.GetCurrentClassLogger();

public NLogCommandInterceptor(ILogger logger)
{
_logger = logger;
}

public void NonQueryExecuting(
DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
LogIfNonAsync(command, interceptionContext, nameof(NonQueryExecuting));
}

public void NonQueryExecuted(
DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
LogIfError(command, interceptionContext);
}

public void ReaderExecuting(
DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
LogIfNonAsync(command, interceptionContext, nameof(ReaderExecuting));
}

public void ReaderExecuted(
DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
LogIfError(command, interceptionContext);
}

public void ScalarExecuting(
DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
LogIfNonAsync(command, interceptionContext, nameof(ScalarExecuting));
}

public void ScalarExecuted(
DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
LogIfError(command, interceptionContext);
}

private void LogIfNonAsync<TResult>(
DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext, string caller)
{
if (!interceptionContext.IsAsync)
{
var line = caller + ": Non-async command used:\n" + command.CommandText;
foreach (var parameter in command.Parameters.Cast<DbParameter>().ToList())
{
//line = line + "\n" + "Parameter: " + parameter.ParameterName + " = " + parameter.Value;
line = line.Replace(oldValue: "@" + parameter.ParameterName, newValue: parameter.Value.ToString());
}

_logger.Info(line);
}
else
{
_logger.Info("Async command used:\n {0}", command.CommandText);
}
}

private void LogIfError<TResult>(
DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext)
{
if (interceptionContext.Exception != null)
{
_logger.Error("Command {0} failed with exception {1}",
command.CommandText, interceptionContext.Exception);
}
}
}
}
@@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DAL.Interfaces;
using DAL.Interfaces.Users;
using Domain.Users;
using Microsoft.AspNet.Identity;

namespace DAL.Repositories
{
public class RoleRepository : RoleRepository<int, Role, User, UserClaim, UserLogin, UserRole>, IRoleRepository
{
public RoleRepository(IDbContext dbContext) : base(dbContext)
{
}
}

public class RoleRepository<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole> : EFRepository<TRole>,
IRoleRepository<TKey, TRole>
where TKey : IEquatable<TKey>
where TRole : Role<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUser : User<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserClaim : UserClaim<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserLogin : UserLogin<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserRole : UserRole<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
{
public RoleRepository(IDbContext dbContext) : base(dbContext)
{
}

public TRole GetByRoleName(string roleName)
{
return DbSet.FirstOrDefault(a => a.Name.ToUpper() == roleName.ToUpper());
}

public List<TRole> GetRolesForUser(TKey userId)
{
//var query = from userRole in _userRoles
// where userRole.UserId.Equals(userId)
// join role in _roleStore.DbEntitySet on userRole.RoleId equals role.Id
// select role.Name;


//foreach (var role in ctx.Roles)
//{
// foreach (var user in role.Users.Where(a => a.Id == id))
// {
// Console.WriteLine(role.Name);
// }
//}
//return (DbSet.SelectMany(role => role.Users.Where(a => a.UserId == userId), (role, user) => role)).ToList();
//return DbSet.All(a => a.Users.Where(b => b.UserId.Equals(userId))).ToList();
return (from role in DbSet from user in role.Users.Where(a => a.UserId.Equals(userId)) select role).ToList();
}
}
}
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DAL.Interfaces;
using DAL.Interfaces.Users;
using Domain.Users;

namespace DAL.Repositories
{

public class UserClaimRepository : UserClaimRepository<int, Role, User, UserClaim, UserLogin, UserRole>,
IUserClaimRepository
{
public UserClaimRepository(IDbContext dbContext) : base(dbContext)
{
}
}

public class UserClaimRepository<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole> : EFRepository<TUserClaim>
where TKey : IEquatable<TKey>
where TRole : Role<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUser : User<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserClaim : UserClaim<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserLogin : UserLogin<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserRole : UserRole<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
{
public UserClaimRepository(IDbContext dbContext) : base(dbContext)
{
}

public List<TUserClaim> AllIncludeUser()
{
return DbSet.Include(a => a.User).ToList();
}
}
}
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using DAL.Interfaces;
using Domain.Users;

namespace DAL.Repositories
{
public class UserLoginRepository : UserLoginRepository<int, Role, User, UserClaim, UserLogin, UserRole>,
IUserLoginRepository
{
public UserLoginRepository(IDbContext dbContext)
: base(dbContext)
{
}
}

public class UserLoginRepository<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole> : EFRepository<TUserLogin>
where TKey : IEquatable<TKey>
where TRole : Role<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUser : User<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserClaim : UserClaim<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserLogin : UserLogin<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserRole : UserRole<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
{
public UserLoginRepository(IDbContext dbContext)
: base(dbContext)
{
}

public List<TUserLogin> GetAllIncludeUser()
{
return DbSet.Include(a => a.User).ToList();
}

public TUserLogin GetUserLoginByProviderAndProviderKey(string loginProvider, string providerKey)
{
return DbSet.FirstOrDefault(l => l.LoginProvider == loginProvider && l.ProviderKey == providerKey);
}
}
}
@@ -1,13 +1,52 @@
using DAL.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DAL.Interfaces;
using DAL.Interfaces.Users;
using Domain.Users;

namespace DAL.Repositories.Users
namespace DAL.Repositories
{
public class UserRepository : EFRepository<User>, IUserRepository

public class UserRepository : UserRepository<int, Role, User, UserClaim, UserLogin, UserRole>, IUserRepository
{
public UserRepository(IDbContext dbContext) : base(dbContext)
{
}
}

public class UserRepository<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole> : EFRepository<TUser>
where TKey : IEquatable<TKey>
where TRole : Role<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUser : User<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserClaim : UserClaim<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserLogin : UserLogin<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserRole : UserRole<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
{
public UserRepository(IDbContext dbContext)
: base(dbContext)
{
}

public TUser GetUserByUserName(string userName)
{
return DbSet.FirstOrDefault(a => a.UserName.ToUpper() == userName.ToUpper());
}

public TUser GetUserByEmail(string email)
{
return DbSet.FirstOrDefault(a => a.Email.ToUpper() == email.ToUpper());
}

public bool IsInRole(TKey userId, string roleName)
{
return DbSet.Find(userId).Roles.Any(a => a.Role.Name == roleName);
}

public void AddUserToRole(TKey userId, string roleName)
{
}
}
}
@@ -1,13 +1,38 @@
using DAL.Interfaces;
using DAL.Interfaces.Users;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DAL.Interfaces;
using Domain.Users;

namespace DAL.Repositories.Users
namespace DAL.Repositories
{
public class UserRoleRepository : EFRepository<UserRole>, IUserRoleRepository

public class UserRoleRepository : UserRoleRepository<int, Role, User, UserClaim, UserLogin, UserRole>,
IUserRoleRepository
{
public UserRoleRepository(IDbContext dbContext) : base(dbContext)
{
}
}

public class UserRoleRepository<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole> : EFRepository<TUserRole>
where TKey : IEquatable<TKey>
where TRole : Role<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUser : User<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserClaim : UserClaim<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserLogin : UserLogin<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserRole : UserRole<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
{
public UserRoleRepository(IDbContext dbContext)
: base(dbContext)
{
}

public TUserRole GetByUserIdAndRoleId(TKey roleId, TKey userId)
{
return DbSet.FirstOrDefault(a => a.RoleId.Equals(roleId) && a.UserId.Equals(userId));
}
}
}
@@ -1,55 +1,149 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Data.Entity.Validation;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DataAnnotations;
using DAL.EFConfiguration;
using DAL.Helpers;
using DAL.Interfaces;
using DAL.Migrations;
using Domain;
using Domain.Orders;
using Domain.People;
using Domain.Store;
using Domain.Users;
using Microsoft.AspNet.Identity.EntityFramework;
using Ninject;
using NLog;

namespace DAL
{
public class StoreItDbContext : DbContext, IDbContext
{
public StoreItDbContext() : base("StoreItDbConnectionString")
private readonly NLog.ILogger _logger;
private readonly string _instanceId = Guid.NewGuid().ToString();

[Inject]
public StoreItDbContext(ILogger logger) : base("StoreItDbConnectionString")
{
Database.SetInitializer(
new MigrateDatabaseToLatestVersion<StoreItDbContext, MigrationConfiguration>());
_logger = logger;
_logger.Debug("Instance id: " + _instanceId);
Database.SetInitializer(new DbInitializer());

#if DEBUG
Database.Log = s => Trace.Write(s);
#endif
Database.Log =
s =>
_logger.Info((s.Contains("SELECT") || s.Contains("UPDATE") || s.Contains("DELETE") ||
s.Contains("INSERT"))
? "\n" + s.Trim()
: s.Trim());
}

public StoreItDbContext() : this(NLog.LogManager.GetCurrentClassLogger())
{
}

public IDbSet<MultiLangString> MultiLangStrings { get; set; }
public IDbSet<Translation> Translations { get; set; }

//Orders
public DbSet<Order> Orders { get; set; }
public DbSet<OrderEdit> OrderEdits { get; set; }
public DbSet<OrderEditType> OrderEditTypes { get; set; }
public DbSet<OrderedProduct> OrderedProducts { get; set; }
public DbSet<OrderType> OrderTypes { get; set; }
public IDbSet<Order> Orders { get; set; }
public IDbSet<OrderEdit> OrderEdits { get; set; }
public IDbSet<OrderEditType> OrderEditTypes { get; set; }
public IDbSet<OrderedProduct> OrderedProducts { get; set; }
public IDbSet<OrderType> OrderTypes { get; set; }

//People
public DbSet<Contact> Contacts { get; set; }
public DbSet<ContactType> ContactTypes { get; set; }
public DbSet<Person> People { get; set; }
public DbSet<PersonType> PersonTypes { get; set; }
public IDbSet<Contact> Contacts { get; set; }
public IDbSet<ContactType> ContactTypes { get; set; }
public IDbSet<Person> People { get; set; }
public IDbSet<PersonType> PersonTypes { get; set; }

//Store
public DbSet<Product> Products { get; set; }
public DbSet<ProductCategory> ProductCategories { get; set; }
public DbSet<ProductEdit> ProductEdits { get; set; }
public DbSet<ProductEditType> ProductEditTypes { get; set; }
public DbSet<Storage> Storages { get; set; }
public DbSet<StoredProduct> StoredProducts { get; set; }
public IDbSet<Product> Products { get; set; }
public IDbSet<ProductCategory> ProductCategories { get; set; }
public IDbSet<ProductEdit> ProductEdits { get; set; }
public IDbSet<ProductEditType> ProductEditTypes { get; set; }
public IDbSet<Storage> Storages { get; set; }
public IDbSet<StoredProduct> StoredProducts { get; set; }

//Users
/*
public DbSet<User> Users { get; set; }
public DbSet<UserEdit> UserEdits { get; set; }
public DbSet<UserEditType> UserEditTypes { get; set; }
public DbSet<UserRole> UserRoles { get; set; }
public DbSet<UserRole> UserRoles { get; set; } */

public IDbSet<Role> Roles { get; set; }
public IDbSet<User> Users { get; set; }
public IDbSet<UserClaim> UserClaims { get; set; }
public IDbSet<UserLogin> UserLogins { get; set; }
public IDbSet<UserRole> UserRoles { get; set; }

public IDbSet<UserEdit> UserEdits { get; set; }
public IDbSet<UserEditType> UserEditTypes { get; set; }


protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//base.OnModelCreating(modelBuilder);

// remove tablename pluralizing
//modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
// remove cascade delete
//modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

// Identity, PK - int
modelBuilder.Configurations.Add(new RoleMap());
modelBuilder.Configurations.Add(new UserClaimMap());
modelBuilder.Configurations.Add(new UserLoginMap());
modelBuilder.Configurations.Add(new UserMap());
modelBuilder.Configurations.Add(new UserRoleMap());

Precision.ConfigureModelBuilder(modelBuilder);

// convert all datetime and datetime? properties to datetime2 in ms sql
// ms sql datetime has min value of 1753-01-01 00:00:00.000
modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));

// use Date type in ms sql, where [DataType(DataType.Date)] attribute is used
modelBuilder.Properties<DateTime>()
.Where(x => x.GetCustomAttributes(false).OfType<DataTypeAttribute>()
.Any(a => a.DataType == DataType.Date))
.Configure(c => c.HasColumnType("date"));

}

public override int SaveChanges()
{
// or watch this inside exception ((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors

try
{
return base.SaveChanges();
}
catch (DbEntityValidationException e)
{
var newException = new FormattedDbEntityValidationException(e);
throw newException;
}
}

protected override void Dispose(bool disposing)
{
_logger.Info("Disposing: " + disposing + " _instanceId: " + _instanceId);
base.Dispose(disposing);
}
}
}


@@ -0,0 +1,104 @@
using System;
using System.Data.Entity;
using DAL.Interfaces;
using DAL.Interfaces.Users;
using Domain;
using Domain.People;
using NLog;

namespace DAL
{
public class UOW : IUOW, IDisposable
{
private readonly NLog.ILogger _logger;
private readonly string _instanceId = Guid.NewGuid().ToString();

private IDbContext DbContext { get; set; }
protected IEFRepositoryProvider RepositoryProvider { get; set; }

public UOW(IEFRepositoryProvider repositoryProvider, IDbContext dbContext, ILogger logger)
{
_logger = logger;
_logger.Debug("InstanceId: " + _instanceId);

DbContext = dbContext;

repositoryProvider.DbContext = dbContext;
RepositoryProvider = repositoryProvider;
}

// UoW main feature - atomic commit at the end of work
public void Commit()
{
((DbContext)DbContext).SaveChanges();
}

public void RefreshAllEntities()
{
foreach (var entity in ((DbContext)DbContext).ChangeTracker.Entries())
{
entity.Reload();
}
}

//standard repos
public IEFRepository<ContactType> ContactTypes => GetStandardRepo<ContactType>();
public IEFRepository<MultiLangString> MultiLangStrings => GetStandardRepo<MultiLangString>();
public IEFRepository<Translation> Translations => GetStandardRepo<Translation>();

// repo with custom methods
// add it also in EFRepositoryFactories.cs, in method GetCustomFactories

//public IUserRepository Users => GetRepo<IUserRepository>();
//public IUserRoleRepository UserRoles => GetRepo<IUserRoleRepository>();
//public IRoleRepository Roles => GetRepo<IRoleRepository>();
//public IUserClaimRepository UserClaims => GetRepo<IUserClaimRepository>();
//public IUserLoginRepository UserLogins => GetRepo<IUserLoginRepository>();
public IPersonRepository People => GetRepo<IPersonRepository>();
public IContactRepository Contacts => GetRepo<IContactRepository>();

public IUserRepository Users => GetRepo<IUserRepository>();
public IUserRoleRepository UserRoles => GetRepo<IUserRoleRepository>();
public IRoleRepository Roles => GetRepo<IRoleRepository>();
public IUserClaimRepository UserClaims => GetRepo<IUserClaimRepository>();
public IUserLoginRepository UserLogins => GetRepo<IUserLoginRepository>();

// calling standard EF repo provider
private IEFRepository<T> GetStandardRepo<T>() where T : class
{
return RepositoryProvider.GetRepositoryForEntityType<T>();
}

// calling custom repo provier
private T GetRepo<T>() where T : class
{
return RepositoryProvider.GetRepository<T>();
}

// try to find repository
public T GetRepository<T>() where T : class
{
var res = GetRepo<T>() ?? GetStandardRepo<T>() as T;
if (res == null)
{
throw new NotImplementedException("No repository for type, " + typeof(T).FullName);
}
return res;
}

#region IDisposable

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
_logger.Debug("InstanceId: " + _instanceId + " Disposing:" + disposing);
}

#endregion
}
}
@@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework" version="6.1.3" targetFramework="net452" />
<package id="Microsoft.AspNet.Identity.Core" version="2.2.1" targetFramework="net452" />
<package id="Microsoft.AspNet.Identity.EntityFramework" version="2.2.1" targetFramework="net452" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net452" />
<package id="Ninject" version="3.2.2.0" targetFramework="net452" />
<package id="NLog" version="4.2.3" targetFramework="net452" />
</packages>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{DD6EAF54-CC53-4CFB-BF05-56CCC26F7FDF}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DataAnnotations</RootNamespace>
<AssemblyName>DataAnnotations</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Precision.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
@@ -0,0 +1,42 @@
using System;
using System.Data.Entity;
using System.Linq;

namespace DataAnnotations
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class Precision : Attribute
{
/// <summary>
/// The total number of digits to store, including decimals
/// </summary>
public byte precision { get; set; }

/// <summary>
/// The number of digits from the precision to be used for decimals
/// </summary>
public byte scale { get; set; }

/// <summary>
/// Define the precision and scale of a decimal data type
/// </summary>
/// <param name="precision">The total number of digits to store, including decimals</param>
/// <param name="scale">The number of digits from the precision to be used for decimals</param>
public Precision(byte precision, byte scale)
{
this.precision = precision;
this.scale = scale;
}

/// <summary>
/// Apply the precision to our data model for any property using this annotation
/// </summary>
/// <param name="modelBuilder"></param>
public static void ConfigureModelBuilder(DbModelBuilder modelBuilder)
{
modelBuilder.Properties().Where(x => x.GetCustomAttributes(false).OfType<Precision>().Any())
.Configure(c => c.HasPrecision(c.ClrPropertyInfo.GetCustomAttributes(false).OfType<Precision>().First()
.precision, c.ClrPropertyInfo.GetCustomAttributes(false).OfType<Precision>().First().scale));
}
}
}
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("DataAnnotations")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DataAnnotations")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("dd6eaf54-cc53-4cfb-bf05-56ccc26f7fdf")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework" version="6.1.3" targetFramework="net452" />
</packages>
@@ -38,6 +38,26 @@
<HintPath>..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.EntityFramework, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Identity.EntityFramework.2.2.1\lib\net45\Microsoft.AspNet.Identity.EntityFramework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Ninject, Version=3.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
<HintPath>..\packages\Ninject.3.2.2.0\lib\net45-full\Ninject.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.2.3\lib\net45\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" />
@@ -50,6 +70,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Aggregate\PersonWithContactCount.cs" />
<Compile Include="MultiLangString.cs" />
<Compile Include="Orders\Order.cs" />
<Compile Include="Orders\OrderEdit.cs" />
<Compile Include="Orders\OrderEditType.cs" />
@@ -65,16 +86,26 @@
<Compile Include="Store\ProductEditType.cs" />
<Compile Include="Store\Storage.cs" />
<Compile Include="Store\StoredProduct.cs" />
<Compile Include="Translation.cs" />
<Compile Include="Users\Role.cs" />
<Compile Include="Users\User.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Users\UserClaim.cs" />
<Compile Include="Users\UserEdit.cs" />
<Compile Include="Users\UserEditType.cs" />
<Compile Include="Users\UserLogin.cs" />
<Compile Include="Users\UserRole.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Resources\Resources.csproj">
<Project>{1fe9693a-55a1-4555-b263-bf7c6c12935d}</Project>
<Name>Resources</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

//Source: https://github.com/akaver/ASP.NET-BaseApps/blob/master/ContactApp/Domain/MultiLangString.cs
namespace Domain
{
public class MultiLangString
{
[Display(ResourceType = typeof(Resources.Domain), Name = "EntityPrimaryKey")]
public int MultiLangStringId { get; set; }

/// <summary>
/// Default value, when translation is not found
/// </summary>
[MaxLength(40960)]
public string Value { get; set; }

[MaxLength(255)]
public string Owner { get; set; }

// list of translations
public virtual ICollection<Translation> Translations { get; set; } = new List<Translation>();

#region Constructors

public MultiLangString()
{
}

public MultiLangString(string defaultStringValue)
{
Value = defaultStringValue;
}

public MultiLangString(string stringValue, string culture)
{
SetTranslation(stringValue, culture);
}

public MultiLangString(string stringValue, string culture, string defaultStringValue)
{
Value = defaultStringValue;
SetTranslation(stringValue, culture);
}

public MultiLangString(string stringValue, string culture, string defaultStringValue, string owner)
{
Value = defaultStringValue;
SetTranslation(stringValue, culture);
Owner = owner;
}

#endregion

public void SetTranslation(string stringValue, string culture)
{
if (Translations == null) Translations = new List<Translation>();
// this could be better? how to mix and match?
// en, en-us, en-gb
var found = Translations.FirstOrDefault(a => culture.ToUpper().StartsWith(a.Culture.ToUpper()));
if (found == null)
{
Translations.Add(new Translation
{
Culture = culture,
Value = stringValue
});
}
else
{
found.Value = stringValue;
}
}

public void SetTranslation(string stringValue, string culture, string owner)
{
Owner = owner;
SetTranslation(stringValue, culture);
}

public string Translate(string cultureName = "")
{
return TranslateToCulture(String.IsNullOrWhiteSpace(cultureName) ? null : new CultureInfo(cultureName));
}

public string TranslateToCulture(CultureInfo culture = null)
{
if (culture == null) culture = Thread.CurrentThread.CurrentCulture;
var translation = Translations.FirstOrDefault(a => culture.Name.ToUpper().StartsWith(a.Culture.ToUpper()));
return translation == null ? Value : translation.Value;
}

public override string ToString()
{
return TranslateToCulture();
}
}
}
@@ -12,10 +12,10 @@ public class OrderType
public int OrderTypeId { get; set; }

[MaxLength(32)]
public string OrderTypeValue { get; set; } //TODO max 32 digits
public MultiLangString OrderTypeValue { get; set; } //TODO max 32 digits

[MaxLength(256)]
public string OrderTypeDescription { get; set; }
public MultiLangString OrderTypeDescription { get; set; }
public bool OrderTypeActive { get; set; }

public virtual List<Order> Orders { get; set; }
@@ -12,7 +12,7 @@ public class ContactType
public int ContactTypeId { get; set; }

[MaxLength(64)]
public String ContactTypeValue { get; set; }
public MultiLangString ContactTypeValue { get; set; }
public bool ContactTypeActive { get; set; }

public virtual List<Contact> Contacts { get; set; }
@@ -33,6 +33,9 @@ public class Person
public virtual List<Order> OrdersCreatedAsEmployee { get; set; }

[NotMapped]
public string FirstLastname => (Firstname + " " + Lastname).Trim();
public string FirstLastname => (Firstname + " " + Lastname).Trim();

[NotMapped]
public string LastFirstname => (Lastname + " " + Firstname).Trim();
}
}
@@ -12,8 +12,8 @@ public class PersonType
public int PersonTypeId { get; set; }

[MaxLength(64)]
public String PersonTypeValue { get; set; }
public String PersonTypeDescription { get; set; }
public MultiLangString PersonTypeValue { get; set; }
public MultiLangString PersonTypeDescription { get; set; }
public bool PersonTypeActive { get; set; }

public virtual List<Person> Persons { get; set; }
@@ -13,7 +13,7 @@ public class Product
public int ProductId { get; set; }

[MaxLength(32)]
public String ProductName { get; set; }
public MultiLangString ProductName { get; set; }
public double ProductValue { get; set; } //TODO 2 digits after comma, 8 digits max
public bool ProductActive { get; set; }

@@ -12,8 +12,8 @@ public class ProductCategory
public int ProductCategoryId { get; set; }

[MaxLength(64)]
public String ProductCategoryValue { get; set; }
public String ProductCategoryDescription { get; set; }
public MultiLangString ProductCategoryValue { get; set; }
public MultiLangString ProductCategoryDescription { get; set; }
public bool ProductCategoryActive { get; set; }

public virtual List<Product> Products { get; set; }
@@ -12,7 +12,7 @@ public class Storage
public int StorageId { get; set; }

[MaxLength(32)]
public String StorageName { get; set; }
public MultiLangString StorageName { get; set; }

public virtual List<StoredProduct> StoredProducts { get; set; }
}
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//Source: https://github.com/akaver/ASP.NET-BaseApps/blob/master/ContactApp/Domain/Translation.cs
namespace Domain
{
public class Translation
{
public int TranslationId { get; set; }

[MaxLength(40960)]
public string Value { get; set; }

public int MultiLangStringId { get; set; }
public virtual MultiLangString MultiLangString { get; set; }

[MaxLength(12)]
public string Culture { get; set; }
}
}
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Microsoft.AspNet.Identity;

namespace Domain.Users
{
/// <summary>
/// Represents a Role entity, PK - int
/// </summary>
public class Role : Role<int, Role, User, UserClaim, UserLogin, UserRole>
{
public Role()
{
}

public Role(string roleName) : this()
{
Name = roleName;
}
}

public class Role<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole> : IRole<TKey>
where TRole : Role<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUser : User<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserClaim : UserClaim<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserLogin : UserLogin<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserRole : UserRole<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
{
public Role()
{
Users = new List<TUserRole>();
}

public TKey Id { get; set; }

[DisplayName("Role name")]
public string Name { get; set; }

public virtual ICollection<TUserRole> Users { get; set; }
}
}
@@ -1,31 +1,105 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Domain.Orders;
using Domain.People;
using Domain.Store;
using Domain.Users;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;

namespace Domain.Users
{
public class User
public class User : User<int, Role, User, UserClaim, UserLogin, UserRole>
{
public int UserId { get; set; }
public String Username { get; set; } //TODO! 16 digits max
public String Password { get; set; } //TODO! 40 digits (hash length)
public bool UserActive { get; set; }
//delete? public int UserId { get; set; }
//delete? public String Username { get; set; } //TODO! 16 digits max
//delete? public String Password { get; set; } //TODO! 40 digits (hash length)
//delete? public bool UserActive { get; set; }

public int UserRoleId { get; set; }
public virtual UserRole UserRole { get; set; }
//delete? public int UserRoleId { get; set; }
//delete? public virtual UserRole UserRole { get; set; }

public int PersonId { get; set; }
public virtual Person Person { get; set; } //TODO nullable

public virtual List<ProductEdit> ProductEdits { get; set; }
public virtual List<OrderEdit> OrderEdits { get; set; }
public virtual List<UserEdit> EditsDoneByUser { get; set; } //Edits done by this user
public virtual List<UserEdit> EditsMadeToUser { get; set; } //Edits made to this user
//public virtual List<UserEdit> EditsDoneByUser { get; set; } //Edits done by this user
//public virtual List<UserEdit> EditsMadeToUser { get; set; } //Edits made to this user


public User()
{
}

/// <summary>
/// Constructor that takes a userName
/// </summary>
/// <param name="userName"></param>
public User(string userName)
: this()
{
UserName = userName;
}

public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User, int> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}

public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User, int> manager, string authType)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authType);
// Add custom user claims here
return userIdentity;
}


}

/// <summary>
/// IUser implementation, generic
/// </summary>
public class User<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole> : IUser<TKey>
where TRole : Role<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUser : User<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserClaim : UserClaim<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserLogin : UserLogin<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserRole : UserRole<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
{
public TKey Id { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public bool TwoFactorEnabled { get; set; }
public DateTime? LockoutEndDateUtc { get; set; }
public bool LockoutEnabled { get; set; }
public int AccessFailedCount { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }

[Display(Name = "FirstLastname", ResourceType = typeof(Resources.Domain))]
public string FirstLastName => FirstName + " " + LastName;

[Display(Name = "LastFirstname", ResourceType = typeof(Resources.Domain))]
public string LastFirstName => LastName + " " + FirstName;

public virtual ICollection<TUserClaim> Claims { get; set; } = new List<TUserClaim>();
public virtual ICollection<TUserLogin> Logins { get; set; } = new List<TUserLogin>();
public virtual ICollection<TUserRole> Roles { get; set; } = new List<TUserRole>();
}
}

@@ -0,0 +1,30 @@
namespace Domain.Users
{
/// <summary>
/// EntityType that represents one specific user claim, PK - int
/// </summary>
public class UserClaim : UserClaim<int, Role, User, UserClaim, UserLogin, UserRole>
{
}

/// <summary>
/// EntityType that represents one specific user claim, generic
/// TKey - type for Id in other classes (string, int)
/// UserClaim is using int as PK
/// </summary>
public class UserClaim<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TRole : Role<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUser : User<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserClaim : UserClaim<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserLogin : UserLogin<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserRole : UserRole<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
{
public int Id { get; set; }

public TKey UserId { get; set; }
public virtual TUser User { get; set; }

public string ClaimType { get; set; }
public string ClaimValue { get; set; }
}
}
@@ -0,0 +1,27 @@
namespace Domain.Users
{
/// <summary>
/// Entity type for a user's login (i.e. facebook, google), PK - int
/// </summary>
public class UserLogin : UserLogin<int, Role, User, UserClaim, UserLogin, UserRole>
{
}

/// <summary>
/// Entity type for a user's login (i.e. facebook, google), PK - string
/// TKey - type for PK (string, int)
/// </summary>
public class UserLogin<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TRole : Role<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUser : User<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserClaim : UserClaim<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserLogin : UserLogin<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserRole : UserRole<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
{
public string LoginProvider { get; set; }
public string ProviderKey { get; set; }

public TKey UserId { get; set; }
public virtual TUser User { get; set; }
}
}
@@ -4,20 +4,32 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity.EntityFramework;

namespace Domain.Users
{
public class UserRole
/// <summary>
/// EntityType that represents a user belonging to a role, PK - int
/// </summary>
public class UserRole : UserRole<int, Role, User, UserClaim, UserLogin, UserRole>
{
public int UserRoleId { get; set; }

[MaxLength(32)]
public String UserRoleName { get; set; }
[MaxLength(256)]
public String UserRoleDescription { get; set; }
}

public bool UserRoleActive { get; set; }
/// <summary>
/// EntityType that represents a user belonging to a role, generic
/// TKey - type for Id (string, int)
/// </summary>
public class UserRole<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TRole : Role<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUser : User<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserClaim : UserClaim<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserLogin : UserLogin<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserRole : UserRole<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
{
public TKey UserId { get; set; }
public virtual TUser User { get; set; }

public virtual List<User> Users { get; set; }
public TKey RoleId { get; set; }
public virtual TRole Role { get; set; }
}
}
@@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework" version="6.1.3" targetFramework="net452" />
<package id="Microsoft.AspNet.Identity.Core" version="2.2.1" targetFramework="net452" />
<package id="Microsoft.AspNet.Identity.EntityFramework" version="2.2.1" targetFramework="net452" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net452" />
<package id="Ninject" version="3.2.2.0" targetFramework="net452" />
<package id="NLog" version="4.2.3" targetFramework="net452" />
</packages>
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;

namespace Identity
{
public class EmailService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
// Plug in your email service here to send an email.
return Task.FromResult(0);
}
}
}
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C233C330-882C-4E24-892C-00D6654C54C2}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Identity</RootNamespace>
<AssemblyName>Identity</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.2.3\lib\net45\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="EmailService.cs" />
<Compile Include="RoleStore.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UserStore.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DAL\DAL.csproj">
<Project>{00f25cd1-98a3-4c36-a6ed-41647ffd855c}</Project>
<Name>DAL</Name>
</ProjectReference>
<ProjectReference Include="..\Domain\Domain.csproj">
<Project>{5a69e765-34b4-46da-8bd8-ff2c698c09fe}</Project>
<Name>Domain</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Identity")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Identity")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c233c330-882c-4e24-892c-00d6654c54c2")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using DAL.Interfaces;
using DAL.Interfaces.Users;
using DAL.Repositories;
using Domain.Users;
using Microsoft.AspNet.Identity;

namespace Identity
{
/// <summary>
/// RoleStore implementation, PK - string
/// </summary>
public class RoleStore : RoleStore<int, Role, User, UserClaim, UserLogin, UserRole, IRoleRepository>
{
public RoleStore(IUOW uow, NLog.Logger logger)
: base(uow, logger)
{
}
}

/// <summary>
/// Generic RoleStore implementation
/// </summary>
public class RoleStore<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole, TRepo> : IRoleStore<TRole, TKey>
where TKey : IEquatable<TKey>
where TRole : Role<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUser : User<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserClaim : UserClaim<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserLogin : UserLogin<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TUserRole : UserRole<TKey, TRole, TUser, TUserClaim, TUserLogin, TUserRole>
where TRepo : class, IRoleRepository<TKey, TRole>
{
private readonly IUOW _uow;
private readonly NLog.Logger _logger;

private bool _disposed;
private readonly string _instanceId = Guid.NewGuid().ToString();

public RoleStore(IUOW uow, NLog.Logger logger)
{
_logger = logger;
_logger.Debug("InstanceId: " + _instanceId);
_uow = uow;
}

public void Dispose()
{
_logger.Debug("InstanceId: " + _instanceId);
Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// If disposing, calls dispose on dependent classes (if any).
/// DI should take care of most of disposing!
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
_logger.Debug("InstanceId: " + _instanceId + " Disposing:" + disposing);
_disposed = true;
}

private void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
}

#region IRoleStore

public Task CreateAsync(TRole role)
{
_logger.Debug("InstanceId: " + _instanceId);

ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException("role");
}
_uow.GetRepository<TRepo>().Add(role);
_uow.Commit();

return Task.FromResult<Object>(null);
}

public Task UpdateAsync(TRole role)
{
_logger.Debug("InstanceId: " + _instanceId);

ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException("role");
}

_uow.GetRepository<TRepo>().Update(role);

_uow.Commit();

return Task.FromResult<Object>(null);
}

public Task DeleteAsync(TRole role)
{
_logger.Debug("InstanceId: " + _instanceId);

ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException("role");
}
_uow.GetRepository<TRepo>().Delete(role);
_uow.Commit();
return Task.FromResult<Object>(null);
}

public Task<TRole> FindByIdAsync(TKey roleId)
{
_logger.Debug("InstanceId: " + _instanceId);

ThrowIfDisposed();
return Task.FromResult(_uow.GetRepository<TRepo>().GetById(roleId));
}

public Task<TRole> FindByNameAsync(string roleName)
{
_logger.Debug("InstanceId: " + _instanceId);

ThrowIfDisposed();
return Task.FromResult(_uow.GetRepository<TRepo>().GetByRoleName(roleName));
}

#endregion
}
}