Skip to content

Commit

Permalink
Added Login method to UserManager. Resolved #41.
Browse files Browse the repository at this point in the history
  • Loading branch information
hikalkan committed Mar 7, 2015
1 parent c158885 commit 8e86c9d
Show file tree
Hide file tree
Showing 10 changed files with 341 additions and 87 deletions.
1 change: 1 addition & 0 deletions src/Abp.Zero/Abp.Zero.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
<Compile Include="Authorization\PermissionGrantInfo.cs" />
<Compile Include="Authorization\Roles\RolePermissionSetting.cs" />
<Compile Include="Authorization\Roles\IRolePermissionStore.cs" />
<Compile Include="Authorization\Users\AbpLoginResultType.cs" />
<Compile Include="Authorization\Users\AbpUserManagerExtensions.cs" />
<Compile Include="Authorization\Users\UserPermissionSetting.cs" />
<Compile Include="Configuration\Setting.cs" />
Expand Down
14 changes: 14 additions & 0 deletions src/Abp.Zero/Authorization/Users/AbpLoginResultType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Abp.Authorization.Users
{
public enum AbpLoginResultType
{
Success = 1,

InvalidUserNameOrEmailAddress,
InvalidPassword,
UserIsNotActive,

InvalidTenancyName,
TenantIsNotActive
}
}
125 changes: 123 additions & 2 deletions src/Abp.Zero/Authorization/Users/AbpUserManager.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
using System.Linq;
using System;
using System.Globalization;
using System.Security.Claims;
using System.Threading.Tasks;
using Abp.Authorization.Roles;
using Abp.Dependency;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.MultiTenancy;
using Abp.Runtime.Security;
using Abp.Zero.Configuration;
using Microsoft.AspNet.Identity;

namespace Abp.Authorization.Users
Expand All @@ -16,11 +22,21 @@ public abstract class AbpUserManager<TTenant, TRole, TUser> : UserManager<TUser,
where TUser : AbpUser<TTenant, TUser>
{
private readonly AbpRoleManager<TTenant, TRole, TUser> _roleManager;
private readonly IRepository<TTenant> _tenantRepository;
private readonly MultiTenancyConfig _multiTenancyConfig;
private readonly AbpUserStore<TTenant, TRole, TUser> _abpUserStore;

protected AbpUserManager(AbpUserStore<TTenant, TRole, TUser> userStore, AbpRoleManager<TTenant, TRole, TUser> roleManager)
protected AbpUserManager(
AbpUserStore<TTenant, TRole, TUser> userStore,
AbpRoleManager<TTenant, TRole, TUser> roleManager,
IRepository<TTenant> tenantRepository,
MultiTenancyConfig multiTenancyConfig)
: base(userStore)
{
_abpUserStore = userStore;
_roleManager = roleManager;
_tenantRepository = tenantRepository;
_multiTenancyConfig = multiTenancyConfig;
}

/// <summary>
Expand All @@ -40,5 +56,110 @@ public async Task<bool> IsGrantedAsync(long userId, string permissionName)

return false;
}

public async Task<TUser> FindByNameOrEmailAsync(string userNameOrEmailAddress)
{
return await _abpUserStore.FindByNameOrEmailAsync(userNameOrEmailAddress);
}

public async Task<AbpLoginResult> LoginAsync(string userNameOrEmailAddress, string plainPassword, string tenancyName = null)
{
//TODO: Email confirmation check? (optional)

if (userNameOrEmailAddress.IsNullOrEmpty())
{
throw new ArgumentNullException("userNameOrEmailAddress");
}

if (plainPassword.IsNullOrEmpty())
{
throw new ArgumentNullException("plainPassword");
}

TUser user;

if (!_multiTenancyConfig.IsEnabled)
{
//Log in with default denant
user = await FindByNameOrEmailAsync(userNameOrEmailAddress);
if (user == null)
{
return new AbpLoginResult(AbpLoginResultType.InvalidUserNameOrEmailAddress);
}
}
else
{
if (string.IsNullOrWhiteSpace(tenancyName))
{
//Log in as tenancy owner user
user = await _abpUserStore.FindByNameOrEmailAsync(null, userNameOrEmailAddress);
}
else
{
//Log in as tenant user
var tenant = await _tenantRepository.FirstOrDefaultAsync(t => t.TenancyName == tenancyName);
if (tenant == null)
{
return new AbpLoginResult(AbpLoginResultType.InvalidTenancyName);
}

if (!tenant.IsActive)
{
return new AbpLoginResult(AbpLoginResultType.TenantIsNotActive);
}

user = await _abpUserStore.FindByNameOrEmailAsync(tenant.Id, userNameOrEmailAddress);
}

if (user == null)
{
return new AbpLoginResult(AbpLoginResultType.InvalidUserNameOrEmailAddress);
}
}

var verificationResult = new PasswordHasher().VerifyHashedPassword(user.Password, plainPassword);
if (verificationResult != PasswordVerificationResult.Success)
{
return new AbpLoginResult(AbpLoginResultType.InvalidPassword);
}

if (!user.IsActive)
{
return new AbpLoginResult(AbpLoginResultType.UserIsNotActive);
}

user.LastLoginTime = DateTime.Now;

await Store.UpdateAsync(user);

var identity = await CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
if (user.TenantId.HasValue)
{
identity.AddClaim(new Claim(AbpClaimTypes.TenantId, user.TenantId.Value.ToString(CultureInfo.InvariantCulture)));
}

return new AbpLoginResult(user, identity);
}

public class AbpLoginResult
{
public AbpLoginResultType Result { get; private set; }

public TUser User { get; private set; }

public ClaimsIdentity Identity { get; private set; }

public AbpLoginResult(AbpLoginResultType result)
{
Result = result;
}

public AbpLoginResult(TUser user, ClaimsIdentity identity)
:this(AbpLoginResultType.Success)
{
User = user;
Identity = identity;
}
}
}
}
15 changes: 13 additions & 2 deletions src/Abp.Zero/Authorization/Users/AbpUserStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,21 @@ public async Task<TUser> FindByEmailAsync(string email)
/// <param name="userNameOrEmailAddress">User name or email address</param>
/// <returns>User or null</returns>
public async Task<TUser> FindByNameOrEmailAsync(string userNameOrEmailAddress)
{
return await FindByNameOrEmailAsync(_session.TenantId, userNameOrEmailAddress);
}

/// <summary>
/// Tries to find a user with user name or email address.
/// </summary>
/// <param name="tenantId">Tenant Id</param>
/// <param name="userNameOrEmailAddress">User name or email address</param>
/// <returns>User or null</returns>
public async Task<TUser> FindByNameOrEmailAsync(int? tenantId, string userNameOrEmailAddress)
{
return await _userRepository.FirstOrDefaultAsync(
user =>
user.TenantId == _session.TenantId &&
user =>
user.TenantId == tenantId &&
(user.UserName == userNameOrEmailAddress || user.EmailAddress == userNameOrEmailAddress)
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Abp.Zero/Zero/AbpZeroCoreModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class AbpZeroCoreModule : AbpModule
/// <summary>
/// Current version of the zero module.
/// </summary>
public const string CurrentVersion = "0.5.5.1";
public const string CurrentVersion = "0.5.6.0";

public override void PreInitialize()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,10 @@
<Compile Include="Configuration\Settings_Tests.cs" />
<Compile Include="Roles\RoleManager_Tests.cs" />
<Compile Include="SampleAppTestBase.cs" />
<Compile Include="Users\UserLogin_Tests.cs" />
<Compile Include="Users\UserRepository_Tests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Users\UserRole_Tests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
Expand Down
96 changes: 96 additions & 0 deletions src/Tests/Abp.Zero.SampleApp.Tests/Users/UserLogin_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using System.Threading.Tasks;
using Abp.Authorization.Users;
using Abp.Zero.Configuration;
using Abp.Zero.SampleApp.MultiTenancy;
using Abp.Zero.SampleApp.Users;
using Shouldly;
using Xunit;

namespace Abp.Zero.SampleApp.Tests.Users
{
public class UserLogin_Tests : SampleAppTestBase
{
private readonly UserManager _userManager;

public UserLogin_Tests()
{
UsingDbContext(
context =>
{
var tenant1 = context.Tenants.Add(new Tenant("tenant1", "Tenant one"));

context.Users.Add(
new User
{
Tenant = null, //Tenancy owner
UserName = "userOwner",
Name = "Owner",
Surname = "One",
EmailAddress = "[email protected]",
IsEmailConfirmed = true,
Password = "AM4OLBpptxBYmM79lGOX9egzZk3vIQU3d/gFCJzaBjAPXzYIK3tQ2N7X4fcrHtElTw==" //123qwe
});

context.Users.Add(
new User
{
Tenant = tenant1, //A user of tenant1
UserName = "user1",
Name = "User",
Surname = "One",
EmailAddress = "[email protected]",
IsEmailConfirmed = true,
Password = "AM4OLBpptxBYmM79lGOX9egzZk3vIQU3d/gFCJzaBjAPXzYIK3tQ2N7X4fcrHtElTw==" //123qwe
});
});

_userManager = LocalIocManager.Resolve<UserManager>();
}

[Fact]
public async Task Should_Login_With_Correct_Values_Without_MultiTenancy()
{
Resolve<MultiTenancyConfig>().IsEnabled = false;
AbpSession.TenantId = 1; //TODO: We should not need to set this and implement AbpSession instead of TestSession.

var loginResult = await _userManager.LoginAsync("user1", "123qwe");
loginResult.Result.ShouldBe(AbpLoginResultType.Success);
loginResult.User.Name.ShouldBe("User");
loginResult.Identity.ShouldNotBe(null);
}

[Fact]
public async Task Should_Not_Login_With_Invalid_UserName_Without_MultiTenancy()
{
Resolve<MultiTenancyConfig>().IsEnabled = false;
AbpSession.TenantId = 1; //TODO: We should not need to set this and implement AbpSession instead of TestSession.

var loginResult = await _userManager.LoginAsync("wrongUserName", "asdfgh");
loginResult.Result.ShouldBe(AbpLoginResultType.InvalidUserNameOrEmailAddress);
loginResult.User.ShouldBe(null);
loginResult.Identity.ShouldBe(null);
}

[Fact]
public async Task Should_Login_With_Correct_Values_With_MultiTenancy()
{
Resolve<MultiTenancyConfig>().IsEnabled = true;

var loginResult = await _userManager.LoginAsync("user1", "123qwe", "tenant1");
loginResult.Result.ShouldBe(AbpLoginResultType.Success);
loginResult.User.Name.ShouldBe("User");
loginResult.Identity.ShouldNotBe(null);
}

[Fact]
public async Task Should_Login_TenancyOwner_With_Correct_Values()
{
Resolve<MultiTenancyConfig>().IsEnabled = true;

var loginResult = await _userManager.LoginAsync("userOwner", "123qwe");
loginResult.Result.ShouldBe(AbpLoginResultType.Success);
loginResult.User.Name.ShouldBe("Owner");
loginResult.Identity.ShouldNotBe(null);
}
}
}
Loading

0 comments on commit 8e86c9d

Please sign in to comment.