Added identity & account modules.

pull/301/head
Halil ibrahim Kalkan 7 years ago
parent fd016c759c
commit fbe0ad3f49

@ -0,0 +1,2 @@
# abp-account
Account module for ABP framework.

@ -0,0 +1,37 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27428.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B5881429-EFF7-4F30-8C0B-0AC41E36B74E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Account.Web", "src\Volo.Abp.Account.Web\Volo.Abp.Account.Web.csproj", "{FCAC4354-7B13-4A91-A2F4-04D00F253C91}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Account.Web.IdentityServer", "src\Volo.Abp.Account.Web.IdentityServer\Volo.Abp.Account.Web.IdentityServer.csproj", "{A65A6E45-8FF7-4B78-AEA6-EAA0CDAA47E8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FCAC4354-7B13-4A91-A2F4-04D00F253C91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FCAC4354-7B13-4A91-A2F4-04D00F253C91}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FCAC4354-7B13-4A91-A2F4-04D00F253C91}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FCAC4354-7B13-4A91-A2F4-04D00F253C91}.Release|Any CPU.Build.0 = Release|Any CPU
{A65A6E45-8FF7-4B78-AEA6-EAA0CDAA47E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A65A6E45-8FF7-4B78-AEA6-EAA0CDAA47E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A65A6E45-8FF7-4B78-AEA6-EAA0CDAA47E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A65A6E45-8FF7-4B78-AEA6-EAA0CDAA47E8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{FCAC4354-7B13-4A91-A2F4-04D00F253C91} = {B5881429-EFF7-4F30-8C0B-0AC41E36B74E}
{A65A6E45-8FF7-4B78-AEA6-EAA0CDAA47E8} = {B5881429-EFF7-4F30-8C0B-0AC41E36B74E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2B054393-D2B2-4EA8-8A15-D60CBCF3E7A9}
EndGlobalSection
EndGlobal

@ -0,0 +1,16 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>0.3.0</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<PackageIconUrl>http://www.aspnetboilerplate.com/images/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>http://abp.io</PackageProjectUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/volosoft/abp/</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SourceLink.Create.CommandLine" Version="2.8.1" PrivateAssets="All" />
</ItemGroup>
</Project>

@ -0,0 +1,16 @@
namespace Volo.Abp.Account.Web
{
public class AbpAccountOptions
{
/// <summary>
/// Default value: "Windows".
/// </summary>
public string WindowsAuthenticationSchemeName { get; set; }
public AbpAccountOptions()
{
//TODO: This makes us depend on the Microsoft.AspNetCore.Server.IISIntegration package.
WindowsAuthenticationSchemeName = "Windows"; //Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme;
}
}
}

@ -0,0 +1,30 @@
using System.Threading.Tasks;
using Localization.Resources.AbpUi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.Account.Web
{
public class AbpAccountUserMenuContributor : IMenuContributor
{
public AbpAccountUserMenuContributor()
{
}
public Task ConfigureMenuAsync(MenuConfigurationContext context)
{
if (context.Menu.Name != StandardMenus.User)
{
return Task.CompletedTask;
}
var l = context.ServiceProvider.GetRequiredService<IStringLocalizer<AbpUiResource>>();
context.Menu.AddItem(new ApplicationMenuItem("Account.Logout", l["Logout"], url: "/Account/Logout", icon: "fa fa-power-off", order: int.MaxValue - 1000));
return Task.CompletedTask;
}
}
}

@ -0,0 +1,57 @@
using Localization.Resources.AbpUi;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Account.Web.Localization;
using Volo.Abp.Account.Web.Settings;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.Identity;
using Volo.Abp.Localization;
using Volo.Abp.Localization.Resources.AbpValidation;
using Volo.Abp.Modularity;
using Volo.Abp.Settings;
using Volo.Abp.UI.Navigation;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.Account.Web
{
[DependsOn(typeof(AbpIdentityDomainModule))]
[DependsOn(typeof(AbpAspNetCoreMvcUiBootstrapModule))]
public class AbpAccountWebModule : AbpModule
{
public override void PreConfigureServices(IServiceCollection services)
{
services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options =>
{
options.AddAssemblyResource(typeof(AccountResource), typeof(AbpAccountWebModule).Assembly);
});
}
public override void ConfigureServices(IServiceCollection services)
{
services.Configure<SettingOptions>(options =>
{
options.DefinitionProviders.Add<AccountSettingDefinitionProvider>();
});
services.Configure<VirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpAccountWebModule>("Volo.Abp.Account.Web");
});
services.Configure<NavigationOptions>(options =>
{
options.MenuContributors.Add(new AbpAccountUserMenuContributor());
});
services.Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<AccountResource>("en")
.AddVirtualJson("/Localization/Resources/AbpAccount/Web")
.AddBaseTypes(typeof(AbpUiResource), typeof(AbpValidationResource));
});
services.AddAssemblyOf<AbpAccountWebModule>();
}
}
}

@ -0,0 +1,26 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Identity;
namespace Volo.Abp.Account.Web.Areas.Account.Controllers
{
[Area("Account")]
public class LogoutController : AbpController
{
private readonly SignInManager<IdentityUser> _signInManager;
public LogoutController(SignInManager<IdentityUser> signInManager)
{
_signInManager = signInManager;
}
public async Task<IActionResult> Index()
{
await _signInManager.SignOutAsync();
return RedirectToPage("/Account/Login");
}
}
}

@ -0,0 +1,10 @@
using Volo.Abp.Localization;
namespace Volo.Abp.Account.Web.Localization
{
[LocalizationResourceName("AbpAccount")]
public class AccountResource
{
}
}

@ -0,0 +1,15 @@
{
"culture": "en",
"texts": {
"UserName": "User name",
"EmailAddress": "Email address",
"UserNameOrEmailAddress": "User name or email address",
"Password": "Password",
"RememberMe": "Remember me",
"UseAnotherServiceToLogin": "Use another service to log in",
"UserLockedOutMessage": "The user account has been locked out due to invalid login attempts. Please wait a while and try again.",
"InvalidUserNameOrPassword": "Invalid username or password!",
"LoginIsNotAllowed": "You are not allowed to login! You need to confirm your email/phone number.",
"SelfRegistrationDisabledMessage": "Self user registration is disabled for this application. Contact to the application administrator to register a new user."
}
}

@ -0,0 +1,15 @@
{
"culture": "tr",
"texts": {
"UserName": "Kullanıcı adı",
"EmailAddress": "E-posta adresi",
"UserNameOrEmailAddress": "Kullanıcı adı veya e-posta",
"Password": "Şifre",
"RememberMe": "Beni hatırla",
"UseAnotherServiceToLogin": "Başka bir servisle giriş yap",
"UserLockedOutMessage": "Kullanıcı hesabı hatalı giriş denemeleri nedeniyle kilitlenmiştir. Lütfen bir süre bekleyip tekrar deneyin.",
"InvalidUserNameOrPassword": "Kullanıcı adı ya da şifre geçersiz!",
"LoginIsNotAllowed": "You are not allowed to login! E-posta adresinizi ya da telefon numaranızı doğrulamanız gerekiyor.",
"SelfRegistrationDisabledMessage": "Bu uygulama için kullanıcıların kendi kendilerine kaydolmaları engellenmiştir. Yeni bir kullanıcı kaydetmek için lütfen uygulama yöneticisi ile iletişime geçin."
}
}

@ -0,0 +1,13 @@
using Microsoft.AspNetCore.Mvc.Localization;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Volo.Abp.Account.Web.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
namespace Volo.Abp.Account.Web.Pages.Account
{
public abstract class AccountPage : AbpPage
{
[RazorInject]
public IHtmlLocalizer<AccountResource> L { get; set; }
}
}

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
using Volo.Abp.Account.Web.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.Identity;
using Volo.Abp.UI;
namespace Volo.Abp.Account.Web.Pages.Account
{
public abstract class AccountPageModel : AbpPageModel
{
public SignInManager<IdentityUser> SignInManager { get; set; }
public IdentityUserManager UserManager { get; set; }
public IStringLocalizer<AccountResource> L { get; set; }
protected RedirectResult RedirectSafely(string returnUrl, string returnUrlHash = null)
{
return Redirect(GetRedirectUrl(returnUrl, returnUrlHash));
}
protected void CheckIdentityErrors(IdentityResult identityResult)
{
if (!identityResult.Succeeded)
{
throw new UserFriendlyException("Operation failed: " + identityResult.Errors.Select(e => $"[{e.Code}] {e.Description}").JoinAsString(", "));
}
//identityResult.CheckErrors(LocalizationManager); //TODO: Get from old Abp
}
private string GetRedirectUrl(string returnUrl, string returnUrlHash = null)
{
returnUrl = NormalizeReturnUrl(returnUrl);
if (!returnUrlHash.IsNullOrWhiteSpace())
{
returnUrl = returnUrl + returnUrlHash;
}
return returnUrl;
}
private string NormalizeReturnUrl(string returnUrl)
{
if (returnUrl.IsNullOrEmpty())
{
return GetAppHomeUrl();
}
if (Url.IsLocalUrl(returnUrl))
{
return returnUrl;
}
return GetAppHomeUrl();
}
protected virtual void CheckCurrentTenant(Guid? tenantId)
{
if (CurrentTenant.Id != tenantId)
{
throw new ApplicationException($"Current tenant is different than given tenant. CurrentTenant.Id: {CurrentTenant.Id}, given tenantId: {tenantId}");
}
}
protected virtual string GetAppHomeUrl()
{
return "/"; //TODO: ???
}
}
}

@ -0,0 +1,36 @@
@page
@model Volo.Abp.Account.Web.Pages.Account.LoginModel
@using Volo.Abp.Account.Web.Settings
@inherits Volo.Abp.Account.Web.Pages.Account.AccountPage
@inject Volo.Abp.Settings.ISettingManager SettingManager
<h2>@L["Login"]</h2>
<abp-row>
<abp-column size-md="_3">
<form method="post">
<abp-input asp-for="Input.UserNameOrEmailAddress" auto-focus="true" />
<abp-input asp-for="Input.Password" />
<abp-input asp-for="Input.RememberMe" class="mb-3" />
<abp-button button-type="Primary" type="submit">@L["Login"]</abp-button>
@if (string.Equals(await SettingManager.GetOrNullAsync(AccountSettingNames.IsSelfRegistrationEnabled), "true", StringComparison.OrdinalIgnoreCase))
{
<a abp-button="Secondary" href="@Url.Page("./Register", new {returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash})">@L["Register"]</a>
}
</form>
</abp-column>
@if (Model.ExternalLogins.Any())
{
<abp-column size-md="_3">
<h4>Use another service to log in.</h4>
<form asp-page="./Login" asp-page-handler="ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" asp-route-returnUrlHash="@Model.ReturnUrlHash" method="post">
<div>
@foreach (var provider in Model.ExternalLogins)
{
<abp-button button-type="Primary" type="submit" name="provider" value="@provider.Name">@provider.DisplayName</abp-button>
}
</div>
</form>
</abp-column>
}
</abp-row>

@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Volo.Abp.Identity;
using Volo.Abp.Security.Claims;
using Volo.Abp.UI;
using Volo.Abp.Uow;
namespace Volo.Abp.Account.Web.Pages.Account
{
public class LoginModel : AccountPageModel
{
[BindProperty(SupportsGet = true)]
public string ReturnUrl { get; set; }
[BindProperty(SupportsGet = true)]
public string ReturnUrlHash { get; set; }
[BindProperty]
public PostInput Input { get; set; }
public IList<AuthenticationScheme> ExternalLogins { get; set; }
public async Task OnGetAsync()
{
ExternalLogins = (await SignInManager.GetExternalAuthenticationSchemesAsync()).ToList();
}
[UnitOfWork] //TODO: Will be removed when we implement action filter
public virtual async Task<IActionResult> OnPostAsync()
{
ValidateModel();
var result = await SignInManager.PasswordSignInAsync(
Input.UserNameOrEmailAddress,
Input.Password,
Input.RememberMe,
true
);
if (result.IsLockedOut)
{
Alerts.Warning(L["UserLockedOutMessage"]);
return Page();
}
if (result.RequiresTwoFactor)
{
return RedirectToPage("./SendSecurityCode");
}
if (result.IsNotAllowed)
{
Alerts.Warning(L["LoginIsNotAllowed"]);
return Page();
}
if (!result.Succeeded)
{
Alerts.Danger(L["InvalidUserNameOrPassword"]);
return Page();
}
return RedirectSafely(ReturnUrl, ReturnUrlHash);
}
[UnitOfWork] //TODO: Will be removed when we implement action filter
public virtual IActionResult OnPostExternalLogin(string provider, string returnUrl = "", string returnUrlHash = "")
{
var redirectUrl = Url.Page("./Login", pageHandler: "ExternalLoginCallback", values: new { returnUrl, returnUrlHash });
var properties = SignInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return new ChallengeResult(provider, properties);
}
[UnitOfWork] //TODO: Will be removed when we implement action filter
public virtual async Task<IActionResult> OnGetExternalLoginCallbackAsync(string returnUrl = "", string returnUrlHash = "", string remoteError = null)
{
if (remoteError != null)
{
Logger.LogWarning($"External login callback error: {remoteError}");
return RedirectToPage("./Login");
}
var loginInfo = await SignInManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
Logger.LogWarning("External login info is not available");
return RedirectToPage("./Login");
}
var result = await SignInManager.ExternalLoginSignInAsync(
loginInfo.LoginProvider,
loginInfo.ProviderKey,
isPersistent: false,
bypassTwoFactor: true
);
if (result.IsLockedOut)
{
throw new UserFriendlyException("Cannot proceed because user is locked out!");
}
//TODO: Handle other cases
if (result.Succeeded)
{
return RedirectSafely(returnUrl, returnUrlHash);
}
// Get the information about the user from the external login provider
var info = await SignInManager.GetExternalLoginInfoAsync();
if (info == null)
{
throw new ApplicationException("Error loading external login information during confirmation.");
}
var user = await CreateExternalUserAsync(info);
await SignInManager.SignInAsync(user, false);
return RedirectSafely(returnUrl, returnUrlHash);
}
private async Task<IdentityUser> CreateExternalUserAsync(ExternalLoginInfo info)
{
var emailAddress = info.Principal.FindFirstValue(AbpClaimTypes.Email);
var user = new IdentityUser(GuidGenerator.Create(), emailAddress, emailAddress, CurrentTenant.Id);
CheckIdentityErrors(await UserManager.CreateAsync(user));
CheckIdentityErrors(await UserManager.SetEmailAsync(user, emailAddress));
CheckIdentityErrors(await UserManager.AddLoginAsync(user, info));
return user;
}
public class PostInput
{
[Required]
[StringLength(255)]
[DisplayName(nameof(UserNameOrEmailAddress))]
public string UserNameOrEmailAddress { get; set; }
[Required]
[StringLength(32)]
[DataType(DataType.Password)]
[DisplayName(nameof(Password))]
public string Password { get; set; }
[DisplayName(nameof(RememberMe))]
public bool RememberMe { get; set; }
}
}
}

@ -0,0 +1,14 @@
@page
@model Volo.Abp.Account.Web.Pages.Account.RegisterModel
@inherits Volo.Abp.Account.Web.Pages.Account.AccountPage
<h2>@L["Register"]</h2>
<abp-row>
<abp-column size-md="_3">
<form method="post">
<abp-input asp-for="Input.UserName" auto-focus="true" />
<abp-input asp-for="Input.EmailAddress" />
<abp-input asp-for="Input.Password" />
<abp-button button-type="Primary" type="submit">@L["Register"]</abp-button>
</form>
</abp-column>
</abp-row>

@ -0,0 +1,81 @@
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Account.Web.Settings;
using Volo.Abp.Identity;
using Volo.Abp.Settings;
using Volo.Abp.UI;
using Volo.Abp.Uow;
namespace Volo.Abp.Account.Web.Pages.Account
{
public class RegisterModel : AccountPageModel
{
[BindProperty(SupportsGet = true)]
public string ReturnUrl { get; set; }
[BindProperty(SupportsGet = true)]
public string ReturnUrlHash { get; set; }
[BindProperty]
public PostInput Input { get; set; }
public virtual async Task OnGet()
{
await CheckSelfRegistrationAsync();
}
[UnitOfWork] //TODO: Will be removed when we implement action filter
public virtual async Task<IActionResult> OnPostAsync()
{
ValidateModel();
await CheckSelfRegistrationAsync();
var user = new IdentityUser(GuidGenerator.Create(), Input.UserName, Input.EmailAddress, CurrentTenant.Id);
var result = await UserManager.CreateAsync(user, Input.Password);
if (!result.Succeeded)
{
throw new NotImplementedException();
}
await UserManager.SetEmailAsync(user, Input.EmailAddress);
await SignInManager.SignInAsync(user, isPersistent: false);
return Redirect(ReturnUrl ?? "/"); //TODO: How to ensure safety? IdentityServer requires it however it should be checked somehow!
}
protected virtual async Task CheckSelfRegistrationAsync()
{
if (!await SettingManager.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled))
{
throw new UserFriendlyException(L["SelfRegistrationDisabledMessage"]);
}
}
public class PostInput
{
[Required]
[StringLength(32)]
[DisplayName(nameof(UserName))]
public string UserName { get; set; }
[Required]
[EmailAddress]
[StringLength(255)]
[DisplayName(nameof(EmailAddress))]
public string EmailAddress { get; set; }
[Required]
[StringLength(32)]
[DataType(DataType.Password)]
[DisplayName(nameof(Password))]
public string Password { get; set; }
}
}
}

@ -0,0 +1,6 @@
@page
@using Volo.Abp.Account.Web.Pages.Account
@inherits AccountPage
@model SendSecurityCodeModel
<h2>Send security code!</h2>
<p>TODO: This page is under construction.</p>

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace Volo.Abp.Account.Web.Pages.Account
{
public class SendSecurityCodeModel : AccountPageModel
{
public List<SelectListItem> Providers { get; set; }
public async Task<IActionResult> OnGetAsync()
{
var user = await SignInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
return RedirectToPage("./Login");
}
return Page();
//CheckCurrentTenant(await SignInManager.GetVerifiedTenantIdAsync());
//Providers = (await UserManager.GetValidTwoFactorProvidersAsync(user))
// .Select(userProvider =>
// new SelectListItem
// {
// Text = userProvider,
// Value = userProvider
// }).ToList();
//return View(
// new SendSecurityCodeViewModel
// {
// ReturnUrl = returnUrl,
// RememberMe = rememberMe
// }
//);
}
}
}

@ -0,0 +1,2 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap

@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:56009/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Volo.Abp.Account.Web": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:56013/"
}
}
}

@ -0,0 +1,14 @@
using Volo.Abp.Settings;
namespace Volo.Abp.Account.Web.Settings
{
public class AccountSettingDefinitionProvider : SettingDefinitionProvider
{
public override void Define(ISettingDefinitionContext context)
{
context.Add(
new SettingDefinition(AccountSettingNames.IsSelfRegistrationEnabled, "true")
);
}
}
}

@ -0,0 +1,7 @@
namespace Volo.Abp.Account.Web.Settings
{
public class AccountSettingNames
{
public const string IsSelfRegistrationEnabled = "Abp.Account.IsSelfRegistrationEnabled";
}
}

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Account.Web</AssemblyName>
<PackageId>Volo.Abp.Account.Web</PackageId>
<IsPackable>true</IsPackable>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace>Volo.Abp.Account.Web</RootNamespace>
<OutputType>Library</OutputType>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Pages\**\*.*" Exclude="*.cs" />
<EmbeddedResource Include="Localization\Resources\*.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\abp-identity\src\Volo.Abp.Identity.Domain\Volo.Abp.Identity.Domain.csproj" />
<ProjectReference Include="..\..\..\abp\src\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,2 @@
# abp-identity
Microsoft ASP.NET Core Identity integration &amp; management module

@ -0,0 +1,123 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27428.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{AADC5A0A-F100-4511-87DE-B74E55F5B69B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.Domain.Shared", "src\Volo.Abp.Identity.Domain.Shared\Volo.Abp.Identity.Domain.Shared.csproj", "{0A023ED6-1476-4145-B1FB-A87427D1F601}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.Domain", "src\Volo.Abp.Identity.Domain\Volo.Abp.Identity.Domain.csproj", "{762003A8-46D0-48B7-8529-8B78433662C3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.Application.Contracts", "src\Volo.Abp.Identity.Application.Contracts\Volo.Abp.Identity.Application.Contracts.csproj", "{B8A5EBD5-0D41-46B0-8E09-96503A7F2FF9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.Application", "src\Volo.Abp.Identity.Application\Volo.Abp.Identity.Application.csproj", "{A4EEB11B-C94A-4039-B5B5-FE5E4D6877ED}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.EntityFrameworkCore", "src\Volo.Abp.Identity.EntityFrameworkCore\Volo.Abp.Identity.EntityFrameworkCore.csproj", "{8932D139-42B5-435F-8E54-A0283034EF0C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.HttpApi", "src\Volo.Abp.Identity.HttpApi\Volo.Abp.Identity.HttpApi.csproj", "{8AAE1E26-9804-4691-B308-68FC4940A2CF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.HttpApi.Client", "src\Volo.Abp.Identity.HttpApi.Client\Volo.Abp.Identity.HttpApi.Client.csproj", "{281365DF-9F93-4734-9F37-0EDAA58DF6B5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.Web", "src\Volo.Abp.Identity.Web\Volo.Abp.Identity.Web.csproj", "{9BA53D0D-C68D-4BEB-B1C0-51ED8B1162EB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{9FACAF96-A681-4B36-A938-A37DCA0B7EC1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.Application.Tests", "test\Volo.Abp.Identity.Application.Tests\Volo.Abp.Identity.Application.Tests.csproj", "{16D87575-35A5-4AEE-840B-C1EC74C3E22C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.MongoDB", "src\Volo.Abp.Identity.MongoDB\Volo.Abp.Identity.MongoDB.csproj", "{F33E45A6-22E6-4F6E-947F-7E82E5171D4F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.MongoDB.Tests", "test\Volo.Abp.Identity.MongoDB.Tests\Volo.Abp.Identity.MongoDB.Tests.csproj", "{B5891082-0799-474E-8A62-8685935D88C3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.EntityFrameworkCore.Tests", "test\Volo.Abp.Identity.EntityFrameworkCore.Tests\Volo.Abp.Identity.EntityFrameworkCore.Tests.csproj", "{7291DCF0-7AA2-41A6-9AA7-98C2E9D13222}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.TestBase", "test\Volo.Abp.Identity.TestBase\Volo.Abp.Identity.TestBase.csproj", "{D7F61598-E7CE-4DAB-99EA-C266F0423606}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.Domain.Tests", "test\Volo.Abp.Identity.Domain.Tests\Volo.Abp.Identity.Domain.Tests.csproj", "{588B6E38-323B-4251-AC21-5F67C815A44E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0A023ED6-1476-4145-B1FB-A87427D1F601}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0A023ED6-1476-4145-B1FB-A87427D1F601}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A023ED6-1476-4145-B1FB-A87427D1F601}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A023ED6-1476-4145-B1FB-A87427D1F601}.Release|Any CPU.Build.0 = Release|Any CPU
{762003A8-46D0-48B7-8529-8B78433662C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{762003A8-46D0-48B7-8529-8B78433662C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{762003A8-46D0-48B7-8529-8B78433662C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{762003A8-46D0-48B7-8529-8B78433662C3}.Release|Any CPU.Build.0 = Release|Any CPU
{B8A5EBD5-0D41-46B0-8E09-96503A7F2FF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B8A5EBD5-0D41-46B0-8E09-96503A7F2FF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8A5EBD5-0D41-46B0-8E09-96503A7F2FF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8A5EBD5-0D41-46B0-8E09-96503A7F2FF9}.Release|Any CPU.Build.0 = Release|Any CPU
{A4EEB11B-C94A-4039-B5B5-FE5E4D6877ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A4EEB11B-C94A-4039-B5B5-FE5E4D6877ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A4EEB11B-C94A-4039-B5B5-FE5E4D6877ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A4EEB11B-C94A-4039-B5B5-FE5E4D6877ED}.Release|Any CPU.Build.0 = Release|Any CPU
{8932D139-42B5-435F-8E54-A0283034EF0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8932D139-42B5-435F-8E54-A0283034EF0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8932D139-42B5-435F-8E54-A0283034EF0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8932D139-42B5-435F-8E54-A0283034EF0C}.Release|Any CPU.Build.0 = Release|Any CPU
{8AAE1E26-9804-4691-B308-68FC4940A2CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8AAE1E26-9804-4691-B308-68FC4940A2CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8AAE1E26-9804-4691-B308-68FC4940A2CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8AAE1E26-9804-4691-B308-68FC4940A2CF}.Release|Any CPU.Build.0 = Release|Any CPU
{281365DF-9F93-4734-9F37-0EDAA58DF6B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{281365DF-9F93-4734-9F37-0EDAA58DF6B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{281365DF-9F93-4734-9F37-0EDAA58DF6B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{281365DF-9F93-4734-9F37-0EDAA58DF6B5}.Release|Any CPU.Build.0 = Release|Any CPU
{9BA53D0D-C68D-4BEB-B1C0-51ED8B1162EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9BA53D0D-C68D-4BEB-B1C0-51ED8B1162EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9BA53D0D-C68D-4BEB-B1C0-51ED8B1162EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9BA53D0D-C68D-4BEB-B1C0-51ED8B1162EB}.Release|Any CPU.Build.0 = Release|Any CPU
{16D87575-35A5-4AEE-840B-C1EC74C3E22C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{16D87575-35A5-4AEE-840B-C1EC74C3E22C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{16D87575-35A5-4AEE-840B-C1EC74C3E22C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{16D87575-35A5-4AEE-840B-C1EC74C3E22C}.Release|Any CPU.Build.0 = Release|Any CPU
{F33E45A6-22E6-4F6E-947F-7E82E5171D4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F33E45A6-22E6-4F6E-947F-7E82E5171D4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F33E45A6-22E6-4F6E-947F-7E82E5171D4F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F33E45A6-22E6-4F6E-947F-7E82E5171D4F}.Release|Any CPU.Build.0 = Release|Any CPU
{B5891082-0799-474E-8A62-8685935D88C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B5891082-0799-474E-8A62-8685935D88C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B5891082-0799-474E-8A62-8685935D88C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B5891082-0799-474E-8A62-8685935D88C3}.Release|Any CPU.Build.0 = Release|Any CPU
{7291DCF0-7AA2-41A6-9AA7-98C2E9D13222}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7291DCF0-7AA2-41A6-9AA7-98C2E9D13222}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7291DCF0-7AA2-41A6-9AA7-98C2E9D13222}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7291DCF0-7AA2-41A6-9AA7-98C2E9D13222}.Release|Any CPU.Build.0 = Release|Any CPU
{D7F61598-E7CE-4DAB-99EA-C266F0423606}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D7F61598-E7CE-4DAB-99EA-C266F0423606}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D7F61598-E7CE-4DAB-99EA-C266F0423606}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D7F61598-E7CE-4DAB-99EA-C266F0423606}.Release|Any CPU.Build.0 = Release|Any CPU
{588B6E38-323B-4251-AC21-5F67C815A44E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{588B6E38-323B-4251-AC21-5F67C815A44E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{588B6E38-323B-4251-AC21-5F67C815A44E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{588B6E38-323B-4251-AC21-5F67C815A44E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{0A023ED6-1476-4145-B1FB-A87427D1F601} = {AADC5A0A-F100-4511-87DE-B74E55F5B69B}
{762003A8-46D0-48B7-8529-8B78433662C3} = {AADC5A0A-F100-4511-87DE-B74E55F5B69B}
{B8A5EBD5-0D41-46B0-8E09-96503A7F2FF9} = {AADC5A0A-F100-4511-87DE-B74E55F5B69B}
{A4EEB11B-C94A-4039-B5B5-FE5E4D6877ED} = {AADC5A0A-F100-4511-87DE-B74E55F5B69B}
{8932D139-42B5-435F-8E54-A0283034EF0C} = {AADC5A0A-F100-4511-87DE-B74E55F5B69B}
{8AAE1E26-9804-4691-B308-68FC4940A2CF} = {AADC5A0A-F100-4511-87DE-B74E55F5B69B}
{281365DF-9F93-4734-9F37-0EDAA58DF6B5} = {AADC5A0A-F100-4511-87DE-B74E55F5B69B}
{9BA53D0D-C68D-4BEB-B1C0-51ED8B1162EB} = {AADC5A0A-F100-4511-87DE-B74E55F5B69B}
{16D87575-35A5-4AEE-840B-C1EC74C3E22C} = {9FACAF96-A681-4B36-A938-A37DCA0B7EC1}
{F33E45A6-22E6-4F6E-947F-7E82E5171D4F} = {AADC5A0A-F100-4511-87DE-B74E55F5B69B}
{B5891082-0799-474E-8A62-8685935D88C3} = {9FACAF96-A681-4B36-A938-A37DCA0B7EC1}
{7291DCF0-7AA2-41A6-9AA7-98C2E9D13222} = {9FACAF96-A681-4B36-A938-A37DCA0B7EC1}
{D7F61598-E7CE-4DAB-99EA-C266F0423606} = {9FACAF96-A681-4B36-A938-A37DCA0B7EC1}
{588B6E38-323B-4251-AC21-5F67C815A44E} = {9FACAF96-A681-4B36-A938-A37DCA0B7EC1}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {05740D37-83CF-4041-9C2A-D89F1B3DB5A4}
EndGlobalSection
EndGlobal

@ -0,0 +1,16 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>0.3.0</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<PackageIconUrl>http://www.aspnetboilerplate.com/images/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>http://abp.io</PackageProjectUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/volosoft/abp/</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SourceLink.Create.CommandLine" Version="2.8.1" PrivateAssets="All" />
</ItemGroup>
</Project>

@ -0,0 +1,18 @@
using System.Reflection;
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: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Volo.Abp.Identity.Application.Contracts")]
[assembly: AssemblyTrademark("")]
// 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("c714a3ab-8402-4dc2-b120-accb2e29bd8f")]

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Identity.Application.Contracts</AssemblyName>
<PackageId>Volo.Abp.Identity.Application.Contracts</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Abp\Identity\Localization\ApplicationContracts\*.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Identity.Domain.Shared\Volo.Abp.Identity.Domain.Shared.csproj" />
<ProjectReference Include="..\..\..\abp-permissionmanagement\src\Volo.Abp.PermissionManagement.Application.Contracts\Volo.Abp.PermissionManagement.Application.Contracts.csproj" />
<ProjectReference Include="..\..\..\abp\src\Volo.Abp.Authorization\Volo.Abp.Authorization.csproj" />
<ProjectReference Include="..\..\..\abp\src\Volo.Abp.Ddd.Application\Volo.Abp.Ddd.Application.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,39 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Application;
using Volo.Abp.Authorization;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Identity.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.Identity
{
[DependsOn(typeof(AbpIdentityDomainSharedModule))]
[DependsOn(typeof(AbpAuthorizationModule))]
[DependsOn(typeof(AbpDddApplicationModule))]
[DependsOn(typeof(AbpPermissionManagementApplicationContractsModule))]
public class AbpIdentityApplicationContractsModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.Configure<PermissionOptions>(options =>
{
options.DefinitionProviders.Add<IdentityPermissionDefinitionProvider>();
});
services.Configure<VirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpIdentityApplicationContractsModule>();
});
services.Configure<AbpLocalizationOptions>(options =>
{
options.Resources.Get<IdentityResource>().AddVirtualJson("/Volo/Abp/Identity/Localization/ApplicationContracts");
});
services.AddAssemblyOf<AbpIdentityApplicationContractsModule>();
}
}
}

@ -0,0 +1,9 @@
using Volo.Abp.Application.Dtos;
namespace Volo.Abp.Identity
{
public class GetIdentityRolesInput : PagedAndSortedResultRequestDto
{
public string Filter { get; set; }
}
}

@ -0,0 +1,9 @@
using Volo.Abp.Application.Dtos;
namespace Volo.Abp.Identity
{
public class GetIdentityUsersInput : PagedAndSortedResultRequestDto
{
public string Filter { get; set; }
}
}

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.PermissionManagement;
namespace Volo.Abp.Identity
{
public interface IIdentityRoleAppService : IAsyncCrudAppService<IdentityRoleDto, Guid, GetIdentityRolesInput, IdentityRoleCreateDto, IdentityRoleUpdateDto>
{
//TODO: remove after a better design
Task<List<IdentityRoleDto>> GetAllListAsync();
Task<GetPermissionListResultDto> GetPermissionsAsync(Guid id);
Task UpdatePermissionsAsync(Guid id, UpdatePermissionsDto input);
}
}

@ -0,0 +1,19 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.PermissionManagement;
namespace Volo.Abp.Identity
{
public interface IIdentityUserAppService : IAsyncCrudAppService<IdentityUserDto, Guid, GetIdentityUsersInput, IdentityUserCreateDto, IdentityUserUpdateDto>
{
Task<ListResultDto<IdentityRoleDto>> GetRolesAsync(Guid id);
Task UpdateRolesAsync(Guid id, IdentityUserUpdateRolesDto input);
Task<GetPermissionListResultDto> GetPermissionsAsync(Guid id);
Task UpdatePermissionsAsync(Guid id, UpdatePermissionsDto input);
}
}

@ -0,0 +1,31 @@
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Identity.Localization;
using Volo.Abp.Localization;
namespace Volo.Abp.Identity
{
public class IdentityPermissionDefinitionProvider : PermissionDefinitionProvider
{
public override void Define(IPermissionDefinitionContext context)
{
var identityGroup = context.AddGroup(IdentityPermissions.GroupName, L("Permission:IdentityManagement"));
var rolesPermission = identityGroup.AddPermission(IdentityPermissions.Roles.Default, L("Permission:RoleManagement"));
rolesPermission.AddChild(IdentityPermissions.Roles.Create, L("Permission:Create"));
rolesPermission.AddChild(IdentityPermissions.Roles.Update, L("Permission:Edit"));
rolesPermission.AddChild(IdentityPermissions.Roles.Delete, L("Permission:Delete"));
rolesPermission.AddChild(IdentityPermissions.Roles.ManagePermissions, L("Permission:ChangePermissions"));
var usersPermission = identityGroup.AddPermission(IdentityPermissions.Users.Default, L("Permission:UserManagement"));
usersPermission.AddChild(IdentityPermissions.Users.Create, L("Permission:Create"));
usersPermission.AddChild(IdentityPermissions.Users.Update, L("Permission:Edit"));
usersPermission.AddChild(IdentityPermissions.Users.Delete, L("Permission:Delete"));
usersPermission.AddChild(IdentityPermissions.Users.ManagePermissions, L("Permission:ChangePermissions"));
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<IdentityResource>(name);
}
}
}

@ -0,0 +1,43 @@
namespace Volo.Abp.Identity
{
public static class IdentityPermissions
{
public const string GroupName = "AbpIdentity";
public static class Roles
{
public const string Default = GroupName + ".Roles";
public const string Create = Default + ".Create";
public const string Update = Default + ".Update";
public const string Delete = Default + ".Delete";
public const string ManagePermissions = Default + ".ManagePermissions";
}
public static class Users
{
public const string Default = GroupName + ".Users";
public const string Create = Default + ".Create";
public const string Update = Default + ".Update";
public const string Delete = Default + ".Delete";
public const string ManagePermissions = Default + ".ManagePermissions";
}
public static string[] GetAll()
{
return new[]
{
GroupName,
Roles.Default,
Roles.Create,
Roles.Update,
Roles.Delete,
Roles.ManagePermissions,
Users.Default,
Users.Create,
Users.Update,
Users.Delete,
Users.ManagePermissions
};
}
}
}

@ -0,0 +1,7 @@
namespace Volo.Abp.Identity
{
public class IdentityRoleCreateDto : IdentityRoleCreateOrUpdateDtoBase
{
}
}

@ -0,0 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace Volo.Abp.Identity
{
public class IdentityRoleCreateOrUpdateDtoBase
{
[Required]
[StringLength(IdentityRoleConsts.MaxNameLength)]
public string Name { get; set; }
}
}

@ -0,0 +1,10 @@
using System;
using Volo.Abp.Application.Dtos;
namespace Volo.Abp.Identity
{
public class IdentityRoleDto : EntityDto<Guid>
{
public string Name { get; set; }
}
}

@ -0,0 +1,7 @@
namespace Volo.Abp.Identity
{
public class IdentityRoleUpdateDto : IdentityRoleCreateOrUpdateDtoBase
{
}
}

@ -0,0 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace Volo.Abp.Identity
{
public class IdentityUserCreateDto : IdentityUserCreateOrUpdateDtoBase
{
[Required]
[StringLength(IdentityUserConsts.MaxPasswordLength)]
public string Password { get; set; }
}
}

@ -0,0 +1,27 @@
using System.ComponentModel.DataAnnotations;
using JetBrains.Annotations;
namespace Volo.Abp.Identity
{
public abstract class IdentityUserCreateOrUpdateDtoBase
{
[Required]
[StringLength(IdentityUserConsts.MaxUserNameLength)]
public string UserName { get; set; }
[Required]
[EmailAddress]
[StringLength(IdentityUserConsts.MaxEmailLength)]
public string Email { get; set; }
[StringLength(IdentityUserConsts.MaxPhoneNumberLength)]
public string PhoneNumber { get; set; }
public bool TwoFactorEnabled { get; set; }
public bool LockoutEnabled { get; set; }
[CanBeNull]
public string[] RoleNames { get; set; }
}
}

@ -0,0 +1,27 @@
using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Identity
{
public class IdentityUserDto : EntityDto<Guid>, IMultiTenant
{
public Guid? TenantId { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public bool TwoFactorEnabled { get; set; }
public bool LockoutEnabled { get; set; }
public DateTimeOffset? LockoutEnd { get; set; }
}
}

@ -0,0 +1,6 @@
namespace Volo.Abp.Identity
{
public class IdentityUserUpdateDto : IdentityUserCreateOrUpdateDtoBase
{
}
}

@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
namespace Volo.Abp.Identity
{
public class IdentityUserUpdateRolesDto
{
[Required]
public string[] RoleNames { get; set; }
}
}

@ -0,0 +1,12 @@
{
"culture": "en",
"texts": {
"Permission:IdentityManagement": "Idetity management",
"Permission:RoleManagement": "Role management",
"Permission:Create": "Create",
"Permission:Edit": "Edit",
"Permission:Delete": "Delete",
"Permission:ChangePermissions": "Change permissions",
"Permission:UserManagement": "User management"
}
}

@ -0,0 +1,12 @@
{
"culture": "tr",
"texts": {
"Permission:IdentityManagement": "Kimlik yönetimi",
"Permission:RoleManagement": "Rol yönetimi",
"Permission:Create": "Oluşturma",
"Permission:Edit": "Düzenleme",
"Permission:Delete": "Silme",
"Permission:ChangePermissions": "İzinleri değiştirme",
"Permission:UserManagement": "Kullanıcı yönetimi"
}
}

@ -0,0 +1,18 @@
using System.Reflection;
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: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Volo.Abp.Identity.Application")]
[assembly: AssemblyTrademark("")]
// 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("54592671-9cb6-48ae-9ae0-84cd016e87ff")]

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Identity.Application</AssemblyName>
<PackageId>Volo.Abp.Identity.Application</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Identity.Application.Contracts\Volo.Abp.Identity.Application.Contracts.csproj" />
<ProjectReference Include="..\Volo.Abp.Identity.Domain\Volo.Abp.Identity.Domain.csproj" />
<ProjectReference Include="..\..\..\abp-permissionmanagement\src\Volo.Abp.PermissionManagement.Application\Volo.Abp.PermissionManagement.Application.csproj" />
<ProjectReference Include="..\..\..\abp\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,26 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement;
namespace Volo.Abp.Identity
{
[DependsOn(
typeof(AbpIdentityDomainModule),
typeof(AbpIdentityApplicationContractsModule),
typeof(AbpAutoMapperModule),
typeof(AbpPermissionManagementApplicationModule)
)]
public class AbpIdentityApplicationModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpIdentityApplicationModuleAutoMapperProfile>();
});
services.AddAssemblyOf<AbpIdentityApplicationModule>();
}
}
}

@ -0,0 +1,13 @@
using AutoMapper;
namespace Volo.Abp.Identity
{
public class AbpIdentityApplicationModuleAutoMapperProfile : Profile
{
public AbpIdentityApplicationModuleAutoMapperProfile()
{
CreateMap<IdentityUser, IdentityUserDto>();
CreateMap<IdentityRole, IdentityRoleDto>();
}
}
}

@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Identity;
using Volo.Abp.Application.Services;
namespace Volo.Abp.Identity
{
public abstract class IdentityAppServiceBase : ApplicationService
{
protected void CheckIdentityErrors(IdentityResult identityResult)
{
if (!identityResult.Succeeded)
{
//TODO: A better exception that can be shown on UI as localized?
throw new AbpException("Operation failed: " + identityResult.Errors.Select(e => $"[{e.Code}] {e.Description}").JoinAsString(", "));
}
//identityResult.CheckErrors(LocalizationManager); //TODO: Get from old Abp
}
}
}

@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.PermissionManagement;
namespace Volo.Abp.Identity
{
[Authorize(IdentityPermissions.Roles.Default)]
public class IdentityRoleAppService : ApplicationService, IIdentityRoleAppService
{
private readonly IdentityRoleManager _roleManager;
private readonly IIdentityRoleRepository _roleRepository;
private readonly IPermissionAppServiceHelper _permissionAppServiceHelper;
public IdentityRoleAppService(
IdentityRoleManager roleManager,
IIdentityRoleRepository roleRepository,
IPermissionAppServiceHelper permissionAppServiceHelper)
{
_roleManager = roleManager;
_roleRepository = roleRepository;
_permissionAppServiceHelper = permissionAppServiceHelper;
}
public async Task<IdentityRoleDto> GetAsync(Guid id)
{
return ObjectMapper.Map<IdentityRole, IdentityRoleDto>(
await _roleManager.GetByIdAsync(id)
);
}
public async Task<PagedResultDto<IdentityRoleDto>> GetListAsync(GetIdentityRolesInput input) //TODO: Remove this method since it's not used
{
var count = (int) await _roleRepository.GetCountAsync();
var list = await _roleRepository.GetListAsync();
return new PagedResultDto<IdentityRoleDto>(
count,
ObjectMapper.Map<List<IdentityRole>, List<IdentityRoleDto>>(list)
);
}
public async Task<List<IdentityRoleDto>> GetAllListAsync() //TODO: Rename to GetList (however it's not possible because of the design of the IAsyncCrudAppService)
{
var list = await _roleRepository.GetListAsync();
return ObjectMapper.Map<List<IdentityRole>, List<IdentityRoleDto>>(list);
}
[Authorize(IdentityPermissions.Roles.ManagePermissions)]
public async Task<GetPermissionListResultDto> GetPermissionsAsync(Guid id)
{
var role = await _roleRepository.GetAsync(id);
return await _permissionAppServiceHelper.GetAsync(RolePermissionValueProvider.ProviderName, role.Name); //TODO: User normalized role name instad of name?
}
[Authorize(IdentityPermissions.Roles.ManagePermissions)]
public async Task UpdatePermissionsAsync(Guid id, UpdatePermissionsDto input)
{
var role = await _roleRepository.GetAsync(id);
await _permissionAppServiceHelper.UpdateAsync(RolePermissionValueProvider.ProviderName, role.Name, input);
}
[Authorize(IdentityPermissions.Roles.Create)]
public async Task<IdentityRoleDto> CreateAsync(IdentityRoleCreateDto input)
{
var role = new IdentityRole(GuidGenerator.Create(), input.Name, CurrentTenant.Id);
await _roleManager.CreateAsync(role);
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<IdentityRole, IdentityRoleDto>(role);
}
[Authorize(IdentityPermissions.Roles.Update)]
public async Task<IdentityRoleDto> UpdateAsync(Guid id, IdentityRoleUpdateDto input)
{
var role = await _roleManager.GetByIdAsync(id);
await _roleManager.SetRoleNameAsync(role, input.Name);
await _roleManager.UpdateAsync(role);
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<IdentityRole, IdentityRoleDto>(role);
}
[Authorize(IdentityPermissions.Roles.Delete)]
public async Task DeleteAsync(Guid id)
{
var role = await _roleManager.FindByIdAsync(id.ToString());
if (role == null)
{
return;
}
await _roleManager.DeleteAsync(role);
}
}
}

@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.PermissionManagement;
namespace Volo.Abp.Identity
{
[Authorize(IdentityPermissions.Users.Default)]
public class IdentityUserAppService : IdentityAppServiceBase, IIdentityUserAppService
{
private readonly IdentityUserManager _userManager;
private readonly IIdentityUserRepository _userRepository;
private readonly IPermissionAppServiceHelper _permissionAppServiceHelper;
public IdentityUserAppService(
IdentityUserManager userManager,
IIdentityUserRepository userRepository,
IPermissionAppServiceHelper permissionAppServiceHelper)
{
_userManager = userManager;
_userRepository = userRepository;
_permissionAppServiceHelper = permissionAppServiceHelper;
}
public async Task<IdentityUserDto> GetAsync(Guid id)
{
return ObjectMapper.Map<IdentityUser, IdentityUserDto>(
await _userManager.GetByIdAsync(id)
);
}
public async Task<PagedResultDto<IdentityUserDto>> GetListAsync(GetIdentityUsersInput input)
{
var count = await _userRepository.GetCountAsync(); //TODO:
var list = await _userRepository.GetListAsync(input.Sorting, input.MaxResultCount, input.SkipCount, input.Filter);
return new PagedResultDto<IdentityUserDto>(
count,
ObjectMapper.Map<List<IdentityUser>, List<IdentityUserDto>>(list)
);
}
public async Task<ListResultDto<IdentityRoleDto>> GetRolesAsync(Guid id)
{
var roles = await _userRepository.GetRolesAsync(id);
return new ListResultDto<IdentityRoleDto>(
ObjectMapper.Map<List<IdentityRole>, List<IdentityRoleDto>>(roles)
);
}
[Authorize(IdentityPermissions.Users.Create)]
public async Task<IdentityUserDto> CreateAsync(IdentityUserCreateDto input)
{
var user = new IdentityUser(GuidGenerator.Create(), input.UserName, input.Email, CurrentTenant.Id);
CheckIdentityErrors(await _userManager.CreateAsync(user, input.Password));
await UpdateUserByInput(user, input);
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<IdentityUser, IdentityUserDto>(user);
}
[Authorize(IdentityPermissions.Users.Update)]
public async Task<IdentityUserDto> UpdateAsync(Guid id, IdentityUserUpdateDto input)
{
var user = await _userManager.GetByIdAsync(id);
CheckIdentityErrors(await _userManager.SetUserNameAsync(user, input.UserName));
await UpdateUserByInput(user, input);
CheckIdentityErrors(await _userManager.UpdateAsync(user));
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<IdentityUser, IdentityUserDto>(user);
}
[Authorize(IdentityPermissions.Users.Delete)]
public async Task DeleteAsync(Guid id)
{
var user = await _userManager.FindByIdAsync(id.ToString());
if (user == null)
{
return;
}
CheckIdentityErrors(await _userManager.DeleteAsync(user));
}
[Authorize(IdentityPermissions.Users.Update)]
public async Task UpdateRolesAsync(Guid id, IdentityUserUpdateRolesDto input)
{
var user = await _userManager.GetByIdAsync(id);
CheckIdentityErrors(await _userManager.SetRolesAsync(user, input.RoleNames));
await _userRepository.UpdateAsync(user);
}
[Authorize(IdentityPermissions.Users.ManagePermissions)]
public async Task<GetPermissionListResultDto> GetPermissionsAsync(Guid id)
{
var user = await _userManager.GetByIdAsync(id);
var result = await _permissionAppServiceHelper.GetAsync(UserPermissionValueProvider.ProviderName, id.ToString());
result.EntityDisplayName = user.UserName;
return result;
}
[Authorize(IdentityPermissions.Users.ManagePermissions)]
public async Task UpdatePermissionsAsync(Guid id, UpdatePermissionsDto input)
{
await _permissionAppServiceHelper.UpdateAsync(UserPermissionValueProvider.ProviderName, id.ToString(), input);
}
private async Task UpdateUserByInput(IdentityUser user, IdentityUserCreateOrUpdateDtoBase input)
{
CheckIdentityErrors(await _userManager.SetEmailAsync(user, input.Email));
CheckIdentityErrors(await _userManager.SetPhoneNumberAsync(user, input.PhoneNumber));
CheckIdentityErrors(await _userManager.SetTwoFactorEnabledAsync(user, input.TwoFactorEnabled));
CheckIdentityErrors(await _userManager.SetLockoutEnabledAsync(user, input.LockoutEnabled));
if (input.RoleNames != null)
{
CheckIdentityErrors(await _userManager.SetRolesAsync(user, input.RoleNames));
}
}
}
}

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Identity.Domain.Shared</AssemblyName>
<PackageId>Volo.Abp.Identity.Domain.Shared</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\abp-users\src\Volo.Abp.Users.Domain.Shared\Volo.Abp.Users.Domain.Shared.csproj" />
<ProjectReference Include="..\..\..\abp\src\Volo.Abp.Localization\Volo.Abp.Localization.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,23 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Identity.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Users;
namespace Volo.Abp.Identity
{
[DependsOn(typeof(AbpUsersDomainSharedModule))]
[DependsOn(typeof(AbpLocalizationModule))]
public class AbpIdentityDomainSharedModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.Configure<AbpLocalizationOptions>(options =>
{
options.Resources.Add<IdentityResource>("en");
});
services.AddAssemblyOf<AbpIdentityDomainSharedModule>();
}
}
}

@ -0,0 +1,9 @@
namespace Volo.Abp.Identity
{
public static class IdentityRoleClaimConsts
{
public const int MaxClaimTypeLength = IdentityUserClaimConsts.MaxClaimTypeLength;
public const int MaxClaimValueLength = IdentityUserClaimConsts.MaxClaimValueLength;
}
}

@ -0,0 +1,8 @@
namespace Volo.Abp.Identity
{
public static class IdentityRoleConsts
{
public const int MaxNameLength = 256;
public const int MaxNormalizedNameLength = MaxNameLength;
}
}

@ -0,0 +1,9 @@
namespace Volo.Abp.Identity
{
public static class IdentityUserClaimConsts
{
public const int MaxClaimTypeLength = 256;
public const int MaxClaimValueLength = 1024;
}
}

@ -0,0 +1,25 @@
using Volo.Abp.Users;
namespace Volo.Abp.Identity
{
public static class IdentityUserConsts
{
public const int MaxUserNameLength = AbpUserConsts.MaxUserNameLength;
public const int MaxNormalizedUserNameLength = MaxUserNameLength;
public const int MaxEmailLength = AbpUserConsts.MaxEmailLength;
public const int MaxNormalizedEmailLength = MaxEmailLength;
public const int MaxPhoneNumberLength = AbpUserConsts.MaxPhoneNumberLength;
public const int MaxPasswordLength = 32;
public const int MaxPasswordHashLength = 256;
public const int MaxSecurityStampLength = 256;
public const int MaxConcurrencyStampLength = 256;
}
}

@ -0,0 +1,9 @@
namespace Volo.Abp.Identity
{
public static class IdentityUserLoginConsts
{
public const int MaxLoginProviderLength = 64;
public const int MaxProviderKeyLength = 196;
public const int MaxProviderDisplayNameLength = 128;
}
}

@ -0,0 +1,9 @@
namespace Volo.Abp.Identity
{
public static class IdentityUserTokenConsts
{
public const int MaxLoginProviderLength = 64;
public const int MaxNameLength = 128;
}
}

@ -0,0 +1,10 @@
using Volo.Abp.Localization;
namespace Volo.Abp.Identity.Localization
{
[LocalizationResourceName("AbpIdentity")]
public class IdentityResource //TODO: Rename to AbpIdentityResource
{
}
}

@ -0,0 +1,44 @@
using System;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.Identity;
namespace Microsoft.Extensions.DependencyInjection
{
public static class AbpIdentityServiceCollectionExtensions
{
public static IdentityBuilder AddAbpIdentity(this IServiceCollection services)
{
return services.AddAbpIdentity(setupAction: null);
}
public static IdentityBuilder AddAbpIdentity(this IServiceCollection services, Action<IdentityOptions> setupAction)
{
//AbpRoleManager
services.TryAddScoped<IdentityRoleManager>();
services.TryAddScoped(typeof(RoleManager<IdentityRole>), provider => provider.GetService(typeof(IdentityRoleManager)));
//AbpUserManager
services.TryAddScoped<IdentityUserManager>();
services.TryAddScoped(typeof(UserManager<IdentityUser>), provider => provider.GetService(typeof(IdentityUserManager)));
//AbpSecurityStampValidator
services.TryAddScoped<AbpSecurityStampValidator>();
services.TryAddScoped(typeof(SecurityStampValidator<IdentityUser>), provider => provider.GetService(typeof(AbpSecurityStampValidator)));
services.TryAddScoped(typeof(ISecurityStampValidator), provider => provider.GetService(typeof(AbpSecurityStampValidator)));
//AbpUserStore
services.TryAddScoped<IdentityUserStore>();
services.TryAddScoped(typeof(IUserStore<IdentityUser>), provider => provider.GetService(typeof(IdentityUserStore)));
//AbpRoleStore
services.TryAddScoped<IdentityRoleStore>();
services.TryAddScoped(typeof(IRoleStore<IdentityRole>), provider => provider.GetService(typeof(IdentityRoleStore)));
return services.AddIdentity<IdentityUser, IdentityRole>(setupAction)
.AddDefaultTokenProviders()
.AddClaimsPrincipalFactory<AbpUserClaimsPrincipalFactory>();
//return services.AddIdentityCore<IdentityUser>(setupAction);
}
}
}

@ -0,0 +1,22 @@
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: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Volo.Abp.Identity")]
[assembly: AssemblyTrademark("")]
[assembly: InternalsVisibleTo("Volo.Abp.Identity.Application.Tests")]
[assembly: InternalsVisibleTo("Volo.Abp.Identity.TestBase.Orm")]
[assembly: InternalsVisibleTo("Volo.Abp.Identity.TestBase")]
// 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("17dbb40a-243e-41f7-a672-fa316ecb1e33")]

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Identity.Domain</AssemblyName>
<PackageId>Volo.Abp.Identity.Domain</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Identity.Domain.Shared\Volo.Abp.Identity.Domain.Shared.csproj" />
<ProjectReference Include="..\..\..\abp-users\src\Volo.Abp.Users.Domain\Volo.Abp.Users.Domain.csproj" />
<ProjectReference Include="..\..\..\abp-permissionmanagement\src\Volo.Abp.PermissionManagement.Domain\Volo.Abp.PermissionManagement.Domain.csproj" />
<ProjectReference Include="..\..\..\abp\src\Volo.Abp.Ddd.Domain\Volo.Abp.Ddd.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.1.0" />
</ItemGroup>
</Project>

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp71</s:String></wpf:ResourceDictionary>

@ -0,0 +1,9 @@
namespace Volo.Abp.Identity
{
public static class AbpIdentityConsts
{
public const string DefaultDbTablePrefix = "Abp";
public const string DefaultDbSchema = null;
}
}

@ -0,0 +1,50 @@
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Volo.Abp.Domain;
using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement;
using Volo.Abp.Settings;
using Volo.Abp.Users;
namespace Volo.Abp.Identity
{
[DependsOn(typeof(AbpPermissionManagementDomainModule))]
[DependsOn(typeof(AbpDddDomainModule))]
[DependsOn(typeof(AbpIdentityDomainSharedModule))]
[DependsOn(typeof(AbpUsersDomainModule))]
public class AbpIdentityDomainModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.Configure<PermissionManagementOptions>(options =>
{
options.ManagementProviders.Add<UserPermissionManagementProvider>();
options.ManagementProviders.Add<RolePermissionManagementProvider>();
});
services.Configure<SettingOptions>(options =>
{
options.DefinitionProviders.Add<AbpIdentitySettingDefinitionProvider>();
});
var identityBuilder = services.AddAbpIdentity(options =>
{
options.User.RequireUniqueEmail = true;
});
services.ExecutePreConfiguredActions(identityBuilder);
AddAbpIdentityOptionsFactory(services);
services.AddAssemblyOf<AbpIdentityDomainModule>();
}
private static void AddAbpIdentityOptionsFactory(IServiceCollection services)
{
services.Replace(ServiceDescriptor.Transient<IOptionsFactory<IdentityOptions>, AbpIdentityOptionsFactory>());
services.Replace(ServiceDescriptor.Scoped<IOptions<IdentityOptions>, OptionsManager<IdentityOptions>>());
}
}
}

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Volo.Abp.Json;
using Volo.Abp.Options;
using Volo.Abp.Settings;
namespace Volo.Abp.Identity
{
public class AbpIdentityOptionsFactory : AbpOptionsFactory<IdentityOptions>
{
private readonly ISettingManager _settingManager;
private readonly IJsonSerializer _jsonSerializer;
public AbpIdentityOptionsFactory(
IEnumerable<IConfigureOptions<IdentityOptions>> setups,
IEnumerable<IPostConfigureOptions<IdentityOptions>> postConfigures,
ISettingManager settingManager,
IJsonSerializer jsonSerializer)
: base(setups, postConfigures)
{
_settingManager = settingManager;
_jsonSerializer = jsonSerializer;
}
public override IdentityOptions Create(string name)
{
var options = base.Create(name);
SetPasswordOptions(options);
return options;
}
protected virtual void SetPasswordOptions(IdentityOptions options)
{
options.Password.RequiredLength = _settingManager.Get(IdentitySettingNames.Password.RequiredLength, options.Password.RequiredLength);
options.Password.RequiredUniqueChars = _settingManager.Get(IdentitySettingNames.Password.RequiredUniqueChars, options.Password.RequiredUniqueChars);
options.Password.RequireNonAlphanumeric = _settingManager.Get(IdentitySettingNames.Password.RequireNonAlphanumeric, options.Password.RequireNonAlphanumeric);
options.Password.RequireLowercase = _settingManager.Get(IdentitySettingNames.Password.RequireLowercase, options.Password.RequireLowercase);
options.Password.RequireUppercase = _settingManager.Get(IdentitySettingNames.Password.RequireUppercase, options.Password.RequireUppercase);
options.Password.RequireDigit = _settingManager.Get(IdentitySettingNames.Password.RequireDigit, options.Password.RequireDigit);
options.Lockout.AllowedForNewUsers = _settingManager.Get(IdentitySettingNames.Lockout.AllowedForNewUsers, options.Lockout.AllowedForNewUsers);
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromSeconds(_settingManager.Get(IdentitySettingNames.Lockout.LockoutDuration, options.Lockout.DefaultLockoutTimeSpan.TotalSeconds.To<int>()));
options.Lockout.MaxFailedAccessAttempts = _settingManager.Get(IdentitySettingNames.Lockout.MaxFailedAccessAttempts, options.Lockout.MaxFailedAccessAttempts);
options.SignIn.RequireConfirmedEmail = _settingManager.Get(IdentitySettingNames.SignIn.RequireConfirmedEmail, options.SignIn.RequireConfirmedEmail);
options.SignIn.RequireConfirmedPhoneNumber = _settingManager.Get(IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber, options.SignIn.RequireConfirmedPhoneNumber);
}
}
}

@ -0,0 +1,28 @@
using Volo.Abp.Settings;
namespace Volo.Abp.Identity
{
public class AbpIdentitySettingDefinitionProvider : SettingDefinitionProvider
{
public override void Define(ISettingDefinitionContext context)
{
context.Add(
new SettingDefinition(IdentitySettingNames.Password.RequiredLength),
new SettingDefinition(IdentitySettingNames.Password.RequiredUniqueChars),
new SettingDefinition(IdentitySettingNames.Password.RequireNonAlphanumeric),
new SettingDefinition(IdentitySettingNames.Password.RequireLowercase),
new SettingDefinition(IdentitySettingNames.Password.RequireUppercase),
new SettingDefinition(IdentitySettingNames.Password.RequireDigit),
new SettingDefinition(IdentitySettingNames.Lockout.AllowedForNewUsers),
new SettingDefinition(IdentitySettingNames.Lockout.LockoutDuration),
new SettingDefinition(IdentitySettingNames.Lockout.MaxFailedAccessAttempts),
new SettingDefinition(IdentitySettingNames.SignIn.RequireConfirmedEmail),
new SettingDefinition(IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber)
);
}
}
}

@ -0,0 +1,29 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Volo.Abp.Uow;
namespace Volo.Abp.Identity
{
public class AbpSecurityStampValidator : SecurityStampValidator<IdentityUser>
{
public AbpSecurityStampValidator(
IOptions<SecurityStampValidatorOptions> options,
SignInManager<IdentityUser> signInManager,
ISystemClock systemClock)
: base(
options,
signInManager,
systemClock)
{
}
[UnitOfWork]
public override Task ValidateAsync(CookieValidatePrincipalContext context)
{
return base.ValidateAsync(context);
}
}
}

@ -0,0 +1,40 @@
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims;
using Volo.Abp.Uow;
namespace Volo.Abp.Identity
{
public class AbpUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<IdentityUser, IdentityRole>, ITransientDependency
{
public AbpUserClaimsPrincipalFactory(
UserManager<IdentityUser> userManager,
RoleManager<IdentityRole> roleManager,
IOptions<IdentityOptions> options)
: base(
userManager,
roleManager,
options)
{
}
[UnitOfWork]
public override async Task<ClaimsPrincipal> CreateAsync(IdentityUser user)
{
var principal = await base.CreateAsync(user);
if (user.TenantId.HasValue)
{
principal.Identities
.First()
.AddClaim(new Claim(AbpClaimTypes.TenantId, user.TenantId.ToString()));
}
return principal;
}
}
}

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Volo.Abp.Identity
{
public interface IIdentityDataSeeder
{
Task SeedAsync(
string adminUserPassword,
IEnumerable<string> adminRolePermissions = null,
Guid? tenantId = null);
}
}

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.Identity
{
public interface IIdentityRoleRepository : IBasicRepository<IdentityRole, Guid>
{
Task<IdentityRole> FindByNormalizedNameAsync(
string normalizedRoleName,
bool includeDetails = true,
CancellationToken cancellationToken = default
);
Task<List<IdentityRole>> GetListAsync(
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
bool includeDetails = false,
CancellationToken cancellationToken = default
);
Task<long> GetCountAsync(
CancellationToken cancellationToken = default
);
}
}

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.Identity
{
public interface IIdentityUserRepository : IBasicRepository<IdentityUser, Guid>
{
Task<IdentityUser> FindByNormalizedUserNameAsync(
[NotNull] string normalizedUserName,
bool includeDetails = true,
CancellationToken cancellationToken = default
);
Task<List<string>> GetRoleNamesAsync(
Guid id,
CancellationToken cancellationToken = default
);
Task<IdentityUser> FindByLoginAsync(
[NotNull] string loginProvider,
[NotNull] string providerKey,
bool includeDetails = true,
CancellationToken cancellationToken = default
);
Task<IdentityUser> FindByNormalizedEmailAsync(
[NotNull] string normalizedEmail,
bool includeDetails = true,
CancellationToken cancellationToken = default
);
Task<List<IdentityUser>> GetListByClaimAsync(
Claim claim,
bool includeDetails = false,
CancellationToken cancellationToken = default
);
Task<List<IdentityUser>> GetListByNormalizedRoleNameAsync(
string normalizedRoleName,
bool includeDetails = false,
CancellationToken cancellationToken = default
);
Task<List<IdentityUser>> GetListAsync(
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
string filter = null,
bool includeDetails = false,
CancellationToken cancellationToken = default
);
Task<List<IdentityRole>> GetRolesAsync(
Guid id,
bool includeDetails = false,
CancellationToken cancellationToken = default
);
Task<long> GetCountAsync(
string filter = null,
CancellationToken cancellationToken = default
);
}
}

@ -0,0 +1,61 @@
using System;
using System.Security.Claims;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Identity
{
public abstract class IdentityClaim : Entity<Guid>, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
/// <summary>
/// Gets or sets the claim type for this claim.
/// </summary>
public virtual string ClaimType { get; protected set; }
/// <summary>
/// Gets or sets the claim value for this claim.
/// </summary>
public virtual string ClaimValue { get; protected set; }
protected IdentityClaim()
{
}
protected internal IdentityClaim(Guid id, [NotNull] Claim claim, Guid? tenantId)
: this(id, claim.Type, claim.Value, tenantId)
{
}
protected internal IdentityClaim(Guid id, [NotNull] string claimType, string claimValue, Guid? tenantId)
{
Check.NotNull(claimType, nameof(claimType));
Id = id;
ClaimType = claimType;
ClaimValue = claimValue;
TenantId = tenantId;
}
/// <summary>
/// Creates a Claim instance from this entity.
/// </summary>
/// <returns></returns>
public virtual Claim ToClaim()
{
return new Claim(ClaimType, ClaimValue);
}
public virtual void SetClaim([NotNull] Claim claim)
{
Check.NotNull(claim, nameof(claim));
ClaimType = claim.Type;
ClaimValue = claim.Value;
}
}
}

@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.PermissionManagement;
using Volo.Abp.Uow;
namespace Volo.Abp.Identity
{
public class IdentityDataSeeder : ITransientDependency, IIdentityDataSeeder
{
private readonly IGuidGenerator _guidGenerator;
private readonly IPermissionGrantRepository _permissionGrantRepository;
private readonly IIdentityRoleRepository _roleRepository;
private readonly IIdentityUserRepository _userRepository;
private readonly ILookupNormalizer _lookupNormalizer;
private readonly IdentityUserManager _userManager;
private readonly IdentityRoleManager _roleManager;
public IdentityDataSeeder(
IGuidGenerator guidGenerator,
IPermissionGrantRepository permissionGrantRepository,
IIdentityRoleRepository roleRepository,
IIdentityUserRepository userRepository,
ILookupNormalizer lookupNormalizer,
IdentityUserManager userManager,
IdentityRoleManager roleManager)
{
_guidGenerator = guidGenerator;
_permissionGrantRepository = permissionGrantRepository;
_roleRepository = roleRepository;
_userRepository = userRepository;
_lookupNormalizer = lookupNormalizer;
_userManager = userManager;
_roleManager = roleManager;
}
[UnitOfWork]
public virtual async Task SeedAsync(
string adminUserPassword,
IEnumerable<string> adminRolePermissions = null,
Guid? tenantId = null)
{
const string adminUserName = "admin";
const string adminRoleName = "admin";
//"admin" user
var adminUser = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize(adminUserName));
if (adminUser != null)
{
return;
}
adminUser = new IdentityUser(_guidGenerator.Create(), adminUserName, "admin@abp.io", tenantId);
CheckIdentityErrors(await _userManager.CreateAsync(adminUser, adminUserPassword));
//"admin" role
var adminRole = await _roleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize(adminRoleName));
if (adminRole == null)
{
adminRole = new IdentityRole(_guidGenerator.Create(), adminRoleName, tenantId);
CheckIdentityErrors(await _roleManager.CreateAsync(adminRole));
if (adminRolePermissions != null)
{
await AddRolePermissionsAsync(adminRole, adminRolePermissions);
}
}
CheckIdentityErrors(await _userManager.AddToRoleAsync(adminUser, adminRoleName));
}
protected virtual async Task AddRolePermissionsAsync(IdentityRole role, IEnumerable<string> permissionNames)
{
foreach (var permissionName in permissionNames)
{
await AddPermissionAsync(permissionName, RolePermissionValueProvider.ProviderName, role.Name, role.TenantId);
}
}
protected virtual Task AddPermissionAsync(string permissionName, string providerName, string providerKey, Guid? tenantId)
{
return _permissionGrantRepository.InsertAsync(
new PermissionGrant(
_guidGenerator.Create(),
permissionName,
providerName,
providerKey,
tenantId
)
);
}
protected void CheckIdentityErrors(IdentityResult identityResult) //TODO: This is temporary and duplicate code!
{
if (!identityResult.Succeeded)
{
//TODO: A better exception that can be shown on UI as localized?
throw new AbpException("Operation failed: " + identityResult.Errors.Select(e => $"[{e.Code}] {e.Description}").JoinAsString(", "));
}
//identityResult.CheckErrors(LocalizationManager); //TODO: Get from old Abp
}
}
}

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Security.Claims;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Identity
{
/// <summary>
/// Represents a role in the identity system
/// </summary>
public class IdentityRole : AggregateRoot<Guid>, IHasConcurrencyStamp, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
/// <summary>
/// Gets or sets the name for this role.
/// </summary>
public virtual string Name { get; protected internal set; }
/// <summary>
/// Gets or sets the normalized name for this role.
/// </summary>
public virtual string NormalizedName { get; protected internal set; }
/// <summary>
/// Navigation property for claims in this role.
/// </summary>
public virtual ICollection<IdentityRoleClaim> Claims { get; protected set; }
/// <summary>
/// A random value that should change whenever a role is persisted to the store
/// </summary>
public virtual string ConcurrencyStamp { get; set; }
/// <summary>
/// Initializes a new instance of <see cref="IdentityRole"/>.
/// </summary>
protected IdentityRole() { }
public IdentityRole(Guid id, [NotNull] string name, Guid? tenantId = null)
{
Check.NotNull(name, nameof(name));
Id = id;
Name = name;
TenantId = tenantId;
NormalizedName = name.ToUpperInvariant();
ConcurrencyStamp = Guid.NewGuid().ToString();
Claims = new Collection<IdentityRoleClaim>();
}
public virtual void AddClaim([NotNull] IGuidGenerator guidGenerator, [NotNull] Claim claim)
{
Check.NotNull(guidGenerator, nameof(guidGenerator));
Check.NotNull(claim, nameof(claim));
Claims.Add(new IdentityRoleClaim(guidGenerator.Create(), Id, claim, TenantId));
}
public virtual void AddClaims([NotNull] IGuidGenerator guidGenerator, [NotNull] IEnumerable<Claim> claims)
{
Check.NotNull(guidGenerator, nameof(guidGenerator));
Check.NotNull(claims, nameof(claims));
foreach (var claim in claims)
{
AddClaim(guidGenerator, claim);
}
}
public virtual void RemoveClaim([NotNull] Claim claim)
{
Check.NotNull(claim, nameof(claim));
Claims.RemoveAll(c => c.ClaimType == claim.Type && c.ClaimValue == claim.Value);
}
public override string ToString()
{
return $"{base.ToString()}, Name = {Name}";
}
}
}

@ -0,0 +1,50 @@
using System;
using System.Security.Claims;
using JetBrains.Annotations;
namespace Volo.Abp.Identity
{
/// <summary>
/// Represents a claim that is granted to all users within a role.
/// </summary>
public class IdentityRoleClaim : IdentityClaim
{
/// <summary>
/// Gets or sets the of the primary key of the role associated with this claim.
/// </summary>
public virtual Guid RoleId { get; protected set; }
protected IdentityRoleClaim()
{
}
protected internal IdentityRoleClaim(
Guid id,
Guid roleId,
[NotNull] Claim claim,
Guid? tenantId)
: base(
id,
claim,
tenantId)
{
RoleId = roleId;
}
protected internal IdentityRoleClaim(
Guid id,
Guid roleId,
[NotNull] string claimType,
string claimValue,
Guid? tenantId)
: base(
id,
claimType,
claimValue,
tenantId)
{
RoleId = roleId;
}
}
}

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Services;
using Volo.Abp.Threading;
namespace Volo.Abp.Identity
{
public class IdentityRoleManager : RoleManager<IdentityRole>, IDomainService
{
protected override CancellationToken CancellationToken => _cancellationTokenProvider.Token;
private readonly ICancellationTokenProvider _cancellationTokenProvider;
public IdentityRoleManager(
IdentityRoleStore store,
IEnumerable<IRoleValidator<IdentityRole>> roleValidators,
ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors,
ILogger<IdentityRoleManager> logger,
ICancellationTokenProvider cancellationTokenProvider)
: base(
store,
roleValidators,
keyNormalizer,
errors,
logger)
{
_cancellationTokenProvider = cancellationTokenProvider;
}
public async Task<IdentityRole> GetByIdAsync(Guid id)
{
var role = await Store.FindByIdAsync(id.ToString(), CancellationToken);
if (role == null)
{
throw new EntityNotFoundException(typeof(IdentityRole), id);
}
return role;
}
}
}

@ -0,0 +1,14 @@
using Volo.Abp.Threading;
namespace Volo.Abp.Identity
{
public static class IdentityRoleRepositoryExtensions
{
public static IdentityRole FindByNormalizedName(this IIdentityRoleRepository roleRepository, string normalizedRoleName)
{
return AsyncHelper.RunSync(() => roleRepository.FindByNormalizedNameAsync(normalizedRoleName));
}
//TODO: Other sync extension methods
}
}

@ -0,0 +1,293 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids;
namespace Volo.Abp.Identity
{
/// <summary>
/// Creates a new instance of a persistence store for roles.
/// </summary>
public class IdentityRoleStore :
IRoleStore<IdentityRole>,
IRoleClaimStore<IdentityRole>,
ITransientDependency
{
private readonly IIdentityRoleRepository _roleRepository;
private readonly ILogger<IdentityRoleStore> _logger;
private readonly IGuidGenerator _guidGenerator;
/// <summary>
/// Constructs a new instance of <see cref="IdentityRoleStore"/>.
/// </summary>
public IdentityRoleStore(
IIdentityRoleRepository roleRepository,
ILogger<IdentityRoleStore> logger,
IGuidGenerator guidGenerator,
IdentityErrorDescriber describer = null)
{
_roleRepository = roleRepository;
_logger = logger;
_guidGenerator = guidGenerator;
ErrorDescriber = describer ?? new IdentityErrorDescriber();
}
/// <summary>
/// Gets or sets the <see cref="IdentityErrorDescriber"/> for any error that occurred with the current operation.
/// </summary>
public IdentityErrorDescriber ErrorDescriber { get; set; }
/// <summary>
/// Gets or sets a flag indicating if changes should be persisted after CreateAsync, UpdateAsync and DeleteAsync are called.
/// </summary>
/// <value>
/// True if changes should be automatically persisted, otherwise false.
/// </value>
public bool AutoSaveChanges { get; set; } = true;
/// <summary>
/// Creates a new role in a store as an asynchronous operation.
/// </summary>
/// <param name="role">The role to create in the store.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="IdentityResult"/> of the asynchronous query.</returns>
public virtual async Task<IdentityResult> CreateAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Check.NotNull(role, nameof(role));
await _roleRepository.InsertAsync(role, AutoSaveChanges, cancellationToken);
return IdentityResult.Success;
}
/// <summary>
/// Updates a role in a store as an asynchronous operation.
/// </summary>
/// <param name="role">The role to update in the store.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="IdentityResult"/> of the asynchronous query.</returns>
public virtual async Task<IdentityResult> UpdateAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Check.NotNull(role, nameof(role));
try
{
await _roleRepository.UpdateAsync(role, AutoSaveChanges, cancellationToken);
}
catch (AbpDbConcurrencyException ex)
{
_logger.LogWarning(ex.ToString()); //Trigger some AbpHandledException event
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
}
return IdentityResult.Success;
}
/// <summary>
/// Deletes a role from the store as an asynchronous operation.
/// </summary>
/// <param name="role">The role to delete from the store.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="IdentityResult"/> of the asynchronous query.</returns>
public virtual async Task<IdentityResult> DeleteAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Check.NotNull(role, nameof(role));
try
{
await _roleRepository.DeleteAsync(role, AutoSaveChanges, cancellationToken);
}
catch (AbpDbConcurrencyException ex)
{
_logger.LogWarning(ex.ToString()); //Trigger some AbpHandledException event
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
}
return IdentityResult.Success;
}
/// <summary>
/// Gets the ID for a role from the store as an asynchronous operation.
/// </summary>
/// <param name="role">The role whose ID should be returned.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that contains the ID of the role.</returns>
public Task<string> GetRoleIdAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Check.NotNull(role, nameof(role));
return Task.FromResult(role.Id.ToString());
}
/// <summary>
/// Gets the name of a role from the store as an asynchronous operation.
/// </summary>
/// <param name="role">The role whose name should be returned.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that contains the name of the role.</returns>
public Task<string> GetRoleNameAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Check.NotNull(role, nameof(role));
return Task.FromResult(role.Name);
}
/// <summary>
/// Sets the name of a role in the store as an asynchronous operation.
/// </summary>
/// <param name="role">The role whose name should be set.</param>
/// <param name="roleName">The name of the role.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
public Task SetRoleNameAsync([NotNull] IdentityRole role, string roleName, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Check.NotNull(role, nameof(role));
role.Name = roleName;
return Task.CompletedTask;
}
/// <summary>
/// Finds the role who has the specified ID as an asynchronous operation.
/// </summary>
/// <param name="id">The role ID to look for.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that result of the look up.</returns>
public virtual Task<IdentityRole> FindByIdAsync(string id, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return _roleRepository.FindAsync(Guid.Parse(id), cancellationToken: cancellationToken);
}
/// <summary>
/// Finds the role who has the specified normalized name as an asynchronous operation.
/// </summary>
/// <param name="normalizedName">The normalized role name to look for.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that result of the look up.</returns>
public virtual Task<IdentityRole> FindByNameAsync([NotNull] string normalizedName, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Check.NotNull(normalizedName, nameof(normalizedName));
return _roleRepository.FindByNormalizedNameAsync(normalizedName, cancellationToken: cancellationToken);
}
/// <summary>
/// Get a role's normalized name as an asynchronous operation.
/// </summary>
/// <param name="role">The role whose normalized name should be retrieved.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that contains the name of the role.</returns>
public virtual Task<string> GetNormalizedRoleNameAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Check.NotNull(role, nameof(role));
return Task.FromResult(role.NormalizedName);
}
/// <summary>
/// Set a role's normalized name as an asynchronous operation.
/// </summary>
/// <param name="role">The role whose normalized name should be set.</param>
/// <param name="normalizedName">The normalized name to set</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
public virtual Task SetNormalizedRoleNameAsync([NotNull] IdentityRole role, string normalizedName, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Check.NotNull(role, nameof(role));
role.NormalizedName = normalizedName;
return Task.CompletedTask;
}
/// <summary>
/// Dispose the stores
/// </summary>
public void Dispose()
{
}
/// <summary>
/// Get the claims associated with the specified <paramref name="role"/> as an asynchronous operation.
/// </summary>
/// <param name="role">The role whose claims should be retrieved.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that contains the claims granted to a role.</returns>
public async Task<IList<Claim>> GetClaimsAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Check.NotNull(role, nameof(role));
await _roleRepository.EnsureCollectionLoadedAsync(role, r => r.Claims, cancellationToken);
return role.Claims.Select(c => c.ToClaim()).ToList();
}
/// <summary>
/// Adds the <paramref name="claim"/> given to the specified <paramref name="role"/>.
/// </summary>
/// <param name="role">The role to add the claim to.</param>
/// <param name="claim">The claim to add to the role.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
public async Task AddClaimAsync([NotNull] IdentityRole role, [NotNull] Claim claim, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Check.NotNull(role, nameof(role));
Check.NotNull(claim, nameof(claim));
await _roleRepository.EnsureCollectionLoadedAsync(role, r => r.Claims, cancellationToken);
role.AddClaim(_guidGenerator, claim);
}
/// <summary>
/// Removes the <paramref name="claim"/> given from the specified <paramref name="role"/>.
/// </summary>
/// <param name="role">The role to remove the claim from.</param>
/// <param name="claim">The claim to remove from the role.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
public async Task RemoveClaimAsync([NotNull] IdentityRole role, [NotNull] Claim claim, CancellationToken cancellationToken = default)
{
Check.NotNull(role, nameof(role));
Check.NotNull(claim, nameof(claim));
await _roleRepository.EnsureCollectionLoadedAsync(role, r => r.Claims, cancellationToken);
role.RemoveClaim(claim);
}
}
}

@ -0,0 +1,36 @@
namespace Volo.Abp.Identity
{
public static class IdentitySettingNames
{
private const string Prefix = "Abp.Identity";
public static class Password
{
private const string PasswordPrefix = Prefix + ".Password";
public const string RequiredLength = PasswordPrefix + ".RequiredLength";
public const string RequiredUniqueChars = PasswordPrefix + ".RequiredUniqueChars";
public const string RequireNonAlphanumeric = PasswordPrefix + ".RequireNonAlphanumeric";
public const string RequireLowercase = PasswordPrefix + ".RequireLowercase";
public const string RequireUppercase = PasswordPrefix + ".RequireUppercase";
public const string RequireDigit = PasswordPrefix + ".RequireDigit";
}
public static class Lockout
{
private const string LockoutPrefix = Prefix + ".Lockout";
public const string AllowedForNewUsers = LockoutPrefix + ".AllowedForNewUsers";
public const string LockoutDuration = LockoutPrefix + ".LockoutDuration";
public const string MaxFailedAccessAttempts = LockoutPrefix + ".MaxFailedAccessAttempts";
}
public static class SignIn
{
private const string SignInPrefix = Prefix + ".SignIn";
public const string RequireConfirmedEmail = SignInPrefix + ".RequireConfirmedEmail";
public const string RequireConfirmedPhoneNumber = SignInPrefix + ".RequireConfirmedPhoneNumber";
}
}
}

@ -0,0 +1,269 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Security.Claims;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Identity;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Guids;
using Volo.Abp.Users;
namespace Volo.Abp.Identity
{
public class IdentityUser : AggregateRoot<Guid>, IHasConcurrencyStamp, IUser, IHasExtraProperties
{
public virtual Guid? TenantId { get; protected set; }
/// <summary>
/// Gets or sets the user name for this user.
/// </summary>
public virtual string UserName { get; protected internal set; }
/// <summary>
/// Gets or sets the normalized user name for this user.
/// </summary>
public virtual string NormalizedUserName { get; protected internal set; }
/// <summary>
/// Gets or sets the email address for this user.
/// </summary>
public virtual string Email { get; protected internal set; }
/// <summary>
/// Gets or sets the normalized email address for this user.
/// </summary>
public virtual string NormalizedEmail { get; protected internal set; }
/// <summary>
/// Gets or sets a flag indicating if a user has confirmed their email address.
/// </summary>
/// <value>True if the email address has been confirmed, otherwise false.</value>
public virtual bool EmailConfirmed { get; protected internal set; }
/// <summary>
/// Gets or sets a salted and hashed representation of the password for this user.
/// </summary>
public virtual string PasswordHash { get; protected internal set; }
/// <summary>
/// A random value that must change whenever a users credentials change (password changed, login removed)
/// </summary>
public virtual string SecurityStamp { get; protected internal set; }
/// <summary>
/// A random value that must change whenever a user is persisted to the store
/// </summary>
public virtual string ConcurrencyStamp { get; set; }
/// <summary>
/// Gets or sets a telephone number for the user.
/// </summary>
public virtual string PhoneNumber { get; protected internal set; }
/// <summary>
/// Gets or sets a flag indicating if a user has confirmed their telephone address.
/// </summary>
/// <value>True if the telephone number has been confirmed, otherwise false.</value>
public virtual bool PhoneNumberConfirmed { get; protected internal set; }
/// <summary>
/// Gets or sets a flag indicating if two factor authentication is enabled for this user.
/// </summary>
/// <value>True if 2fa is enabled, otherwise false.</value>
public virtual bool TwoFactorEnabled { get; protected internal set; }
/// <summary>
/// Gets or sets the date and time, in UTC, when any user lockout ends.
/// </summary>
/// <remarks>
/// A value in the past means the user is not locked out.
/// </remarks>
public virtual DateTimeOffset? LockoutEnd { get; protected internal set; }
/// <summary>
/// Gets or sets a flag indicating if the user could be locked out.
/// </summary>
/// <value>True if the user could be locked out, otherwise false.</value>
public virtual bool LockoutEnabled { get; protected internal set; }
/// <summary>
/// Gets or sets the number of failed login attempts for the current user.
/// </summary>
public virtual int AccessFailedCount { get; protected internal set; }
//TODO: Can we make collections readonly collection, which will provide encapsulation. But... can work for all ORMs?
/// <summary>
/// Navigation property for the roles this user belongs to.
/// </summary>
public virtual ICollection<IdentityUserRole> Roles { get; protected set; }
/// <summary>
/// Navigation property for the claims this user possesses.
/// </summary>
public virtual ICollection<IdentityUserClaim> Claims { get; protected set; }
/// <summary>
/// Navigation property for this users login accounts.
/// </summary>
public virtual ICollection<IdentityUserLogin> Logins { get; protected set; }
/// <summary>
/// Navigation property for this users tokens.
/// </summary>
public virtual ICollection<IdentityUserToken> Tokens { get; protected set; }
public Dictionary<string, object> ExtraProperties { get; protected set; }
protected IdentityUser()
{
ExtraProperties = new Dictionary<string, object>();
}
public IdentityUser(Guid id, [NotNull] string userName, [NotNull] string email, Guid? tenantId = null)
{
Check.NotNull(userName, nameof(userName));
Id = id;
TenantId = tenantId;
UserName = userName;
NormalizedUserName = userName.ToUpperInvariant();
Email = email;
NormalizedEmail = email.ToUpperInvariant();
ConcurrencyStamp = Guid.NewGuid().ToString();
SecurityStamp = Guid.NewGuid().ToString();
Roles = new Collection<IdentityUserRole>();
Claims = new Collection<IdentityUserClaim>();
Logins = new Collection<IdentityUserLogin>();
Tokens = new Collection<IdentityUserToken>();
ExtraProperties = new Dictionary<string, object>();
}
public virtual void AddRole(Guid roleId)
{
Check.NotNull(roleId, nameof(roleId));
if (IsInRole(roleId))
{
return;
}
Roles.Add(new IdentityUserRole(Id, roleId, TenantId));
}
public virtual void RemoveRole(Guid roleId)
{
Check.NotNull(roleId, nameof(roleId));
if (!IsInRole(roleId))
{
return;
}
Roles.RemoveAll(r => r.RoleId == roleId);
}
public virtual bool IsInRole(Guid roleId)
{
Check.NotNull(roleId, nameof(roleId));
return Roles.Any(r => r.RoleId == roleId);
}
public virtual void AddClaim([NotNull] IGuidGenerator guidGenerator, [NotNull] Claim claim)
{
Check.NotNull(guidGenerator, nameof(guidGenerator));
Check.NotNull(claim, nameof(claim));
Claims.Add(new IdentityUserClaim(guidGenerator.Create(), Id, claim, TenantId));
}
public virtual void AddClaims([NotNull] IGuidGenerator guidGenerator, [NotNull] IEnumerable<Claim> claims)
{
Check.NotNull(guidGenerator, nameof(guidGenerator));
Check.NotNull(claims, nameof(claims));
foreach (var claim in claims)
{
AddClaim(guidGenerator, claim);
}
}
public virtual void ReplaceClaim([NotNull] Claim claim, [NotNull] Claim newClaim)
{
Check.NotNull(claim, nameof(claim));
Check.NotNull(newClaim, nameof(newClaim));
var userClaims = Claims.Where(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type);
foreach (var userClaim in userClaims)
{
userClaim.SetClaim(newClaim);
}
}
public virtual void RemoveClaims([NotNull] IEnumerable<Claim> claims)
{
Check.NotNull(claims, nameof(claims));
foreach (var claim in claims)
{
RemoveClaim(claim);
}
}
public virtual void RemoveClaim([NotNull] Claim claim)
{
Check.NotNull(claim, nameof(claim));
Claims.RemoveAll(c => c.ClaimValue == claim.Value && c.ClaimType == claim.Type);
}
public virtual void AddLogin([NotNull] UserLoginInfo login)
{
Check.NotNull(login, nameof(login));
Logins.Add(new IdentityUserLogin(Id, login, TenantId));
}
public virtual void RemoveLogin([NotNull] string loginProvider, [NotNull] string providerKey)
{
Check.NotNull(loginProvider, nameof(loginProvider));
Check.NotNull(providerKey, nameof(providerKey));
Logins.RemoveAll(userLogin => userLogin.LoginProvider == loginProvider && userLogin.ProviderKey == providerKey);
}
[CanBeNull]
public virtual IdentityUserToken FindToken(string loginProvider, string name)
{
return Tokens.FirstOrDefault(t => t.LoginProvider == loginProvider && t.Name == name);
}
public virtual void SetToken(string loginProvider, string name, string value)
{
var token = FindToken(loginProvider, name);
if (token == null)
{
Tokens.Add(new IdentityUserToken(Id, loginProvider, name, value, TenantId));
}
else
{
token.Value = value;
}
}
public virtual void RemoveToken(string loginProvider, string name)
{
Tokens.RemoveAll(t => t.LoginProvider == loginProvider && t.Name == name);
}
public override string ToString()
{
return $"{base.ToString()}, UserName = {UserName}";
}
}
}

@ -0,0 +1,34 @@
using System;
using System.Security.Claims;
using JetBrains.Annotations;
namespace Volo.Abp.Identity
{
/// <summary>
/// Represents a claim that a user possesses.
/// </summary>
public class IdentityUserClaim : IdentityClaim
{
/// <summary>
/// Gets or sets the primary key of the user associated with this claim.
/// </summary>
public virtual Guid UserId { get; protected set; }
protected IdentityUserClaim()
{
}
protected internal IdentityUserClaim(Guid id, Guid userId, [NotNull] Claim claim, Guid? tenantId)
: base(id, claim, tenantId)
{
UserId = userId;
}
protected internal IdentityUserClaim(Guid id, Guid userId, [NotNull] string claimType, string claimValue, Guid? tenantId)
: base(id, claimType, claimValue, tenantId)
{
UserId = userId;
}
}
}

@ -0,0 +1,76 @@
using System;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Identity;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Identity
{
/// <summary>
/// Represents a login and its associated provider for a user.
/// </summary>
public class IdentityUserLogin : Entity, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
/// <summary>
/// Gets or sets the of the primary key of the user associated with this login.
/// </summary>
public virtual Guid UserId { get; protected set; }
/// <summary>
/// Gets or sets the login provider for the login (e.g. facebook, google)
/// </summary>
public virtual string LoginProvider { get; protected set; }
/// <summary>
/// Gets or sets the unique provider identifier for this login.
/// </summary>
public virtual string ProviderKey { get; protected set; }
/// <summary>
/// Gets or sets the friendly name used in a UI for this login.
/// </summary>
public virtual string ProviderDisplayName { get; protected set; }
protected IdentityUserLogin()
{
}
protected internal IdentityUserLogin(
Guid userId,
[NotNull] string loginProvider,
[NotNull] string providerKey,
string providerDisplayName,
Guid? tenantId)
{
Check.NotNull(loginProvider, nameof(loginProvider));
Check.NotNull(providerKey, nameof(providerKey));
UserId = userId;
LoginProvider = loginProvider;
ProviderKey = providerKey;
ProviderDisplayName = providerDisplayName;
TenantId = tenantId;
}
protected internal IdentityUserLogin(
Guid userId,
[NotNull] UserLoginInfo login,
Guid? tenantId)
: this(
userId,
login.LoginProvider,
login.ProviderKey,
login.ProviderDisplayName,
tenantId)
{
}
public UserLoginInfo ToUserLoginInfo()
{
return new UserLoginInfo(LoginProvider, ProviderKey, ProviderDisplayName);
}
}
}

@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Services;
using Volo.Abp.Threading;
namespace Volo.Abp.Identity
{
public class IdentityUserManager : UserManager<IdentityUser>, IDomainService
{
protected override CancellationToken CancellationToken => _cancellationTokenProvider.Token;
private readonly ICancellationTokenProvider _cancellationTokenProvider;
public IdentityUserManager(
IdentityUserStore store,
IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<IdentityUser> passwordHasher,
IEnumerable<IUserValidator<IdentityUser>> userValidators,
IEnumerable<IPasswordValidator<IdentityUser>> passwordValidators,
ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors,
IServiceProvider services,
ILogger<IdentityUserManager> logger,
ICancellationTokenProvider cancellationTokenProvider)
: base(
store,
optionsAccessor,
passwordHasher,
userValidators,
passwordValidators,
keyNormalizer,
errors,
services,
logger)
{
_cancellationTokenProvider = cancellationTokenProvider;
}
public async Task<IdentityUser> GetByIdAsync(Guid id)
{
var user = await Store.FindByIdAsync(id.ToString(), CancellationToken);
if (user == null)
{
throw new EntityNotFoundException(typeof(IdentityUser), id);
}
return user;
}
public async Task<IdentityResult> SetRolesAsync([NotNull] IdentityUser user, [NotNull] IEnumerable<string> roleNames)
{
Check.NotNull(user, nameof(user));
Check.NotNull(roleNames, nameof(roleNames));
var currentRoleNames = await GetRolesAsync(user);
var result = await RemoveFromRolesAsync(user, currentRoleNames.Except(roleNames).Distinct());
if (!result.Succeeded)
{
return result;
}
result = await AddToRolesAsync(user, roleNames.Except(currentRoleNames).Distinct());
if (!result.Succeeded)
{
return result;
}
return IdentityResult.Success;
}
}
}

@ -0,0 +1,15 @@
using JetBrains.Annotations;
using Volo.Abp.Threading;
namespace Volo.Abp.Identity
{
public static class IdentityUserRepositoryExtensions
{
public static IdentityUser FindByNormalizedUserName(this IIdentityUserRepository repository, [NotNull] string normalizedUserName)
{
return AsyncHelper.RunSync(() => repository.FindByNormalizedUserNameAsync(normalizedUserName));
}
//TODO: Other sync extension methods
}
}

@ -0,0 +1,49 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Users;
namespace Volo.Abp.Identity
{
public class IdentityUserRepositoryExternalUserLookupServiceProvider : IExternalUserLookupServiceProvider, ITransientDependency
{
private readonly IIdentityUserRepository _userRepository;
private readonly ILookupNormalizer _lookupNormalizer;
public IdentityUserRepositoryExternalUserLookupServiceProvider(
IIdentityUserRepository userRepository,
ILookupNormalizer lookupNormalizer)
{
_userRepository = userRepository;
_lookupNormalizer = lookupNormalizer;
}
public async Task<IUserData> FindByIdAsync(
Guid id,
CancellationToken cancellationToken = default)
{
return (
await _userRepository.FindAsync(
id,
includeDetails: false,
cancellationToken: cancellationToken
)
).ToAbpUserData();
}
public async Task<IUserData> FindByUserNameAsync(
string userName,
CancellationToken cancellationToken = default)
{
return (
await _userRepository.FindByNormalizedUserNameAsync(
_lookupNormalizer.Normalize(userName),
includeDetails: false,
cancellationToken: cancellationToken
)
).ToAbpUserData();
}
}
}

@ -0,0 +1,36 @@
using System;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Identity
{
/// <summary>
/// Represents the link between a user and a role.
/// </summary>
public class IdentityUserRole : Entity, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
/// <summary>
/// Gets or sets the primary key of the user that is linked to a role.
/// </summary>
public virtual Guid UserId { get; protected set; }
/// <summary>
/// Gets or sets the primary key of the role that is linked to the user.
/// </summary>
public virtual Guid RoleId { get; protected set; }
protected IdentityUserRole()
{
}
protected internal IdentityUserRole(Guid userId, Guid roleId, Guid? tenantId)
{
UserId = userId;
RoleId = roleId;
TenantId = tenantId;
}
}
}

@ -0,0 +1,57 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Identity
{
/// <summary>
/// Represents an authentication token for a user.
/// </summary>
public class IdentityUserToken : Entity, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
/// <summary>
/// Gets or sets the primary key of the user that the token belongs to.
/// </summary>
public virtual Guid UserId { get; protected set; }
/// <summary>
/// Gets or sets the LoginProvider this token is from.
/// </summary>
public virtual string LoginProvider { get; protected set; }
/// <summary>
/// Gets or sets the name of the token.
/// </summary>
public virtual string Name { get; protected set; }
/// <summary>
/// Gets or sets the token value.
/// </summary>
public virtual string Value { get; set; }
protected IdentityUserToken()
{
}
protected internal IdentityUserToken(
Guid userId,
[NotNull] string loginProvider,
[NotNull] string name,
string value,
Guid? tenantId)
{
Check.NotNull(loginProvider, nameof(loginProvider));
Check.NotNull(name, nameof(name));
UserId = userId;
LoginProvider = loginProvider;
Name = name;
Value = value;
TenantId = tenantId;
}
}
}

@ -0,0 +1,57 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.PermissionManagement;
namespace Volo.Abp.Identity
{
public class RolePermissionManagementProvider : PermissionManagementProvider
{
public override string Name => RolePermissionValueProvider.ProviderName;
private readonly IIdentityUserRepository _identityUserRepository;
public RolePermissionManagementProvider(
IPermissionGrantRepository permissionGrantRepository,
IGuidGenerator guidGenerator,
IIdentityUserRepository identityUserRepository,
ICurrentTenant currentTenant)
: base(
permissionGrantRepository,
guidGenerator,
currentTenant)
{
_identityUserRepository = identityUserRepository;
}
public override async Task<PermissionValueProviderGrantInfo> CheckAsync(string name, string providerName, string providerKey)
{
if (providerName == Name)
{
return new PermissionValueProviderGrantInfo(
await PermissionGrantRepository.FindAsync(name, providerName, providerKey) != null,
providerKey
);
}
if (providerName == "User")
{
var userId = Guid.Parse(providerKey);
var roleNames = await _identityUserRepository.GetRoleNamesAsync(userId);
foreach (var roleName in roleNames)
{
var permissionGrant = await PermissionGrantRepository.FindAsync(name, Name, roleName);
if (permissionGrant != null)
{
return new PermissionValueProviderGrantInfo(true, roleName);
}
}
}
return PermissionValueProviderGrantInfo.NonGranted;
}
}
}

@ -0,0 +1,24 @@
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.PermissionManagement;
namespace Volo.Abp.Identity
{
public class UserPermissionManagementProvider : PermissionManagementProvider
{
public override string Name => UserPermissionValueProvider.ProviderName;
public UserPermissionManagementProvider(IPermissionGrantRepository
permissionGrantRepository,
IGuidGenerator guidGenerator,
ICurrentTenant currentTenant)
: base(
permissionGrantRepository,
guidGenerator,
currentTenant)
{
}
}
}

@ -0,0 +1,32 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.PermissionManagement;
namespace Volo.Abp.Permissions
{
public static class RolePermissionManagerExtensions
{
public static Task<PermissionWithGrantedProviders> GetForRoleAsync([NotNull] this IPermissionManager permissionManager, string roleName, string permissionName)
{
Check.NotNull(permissionManager, nameof(permissionManager));
return permissionManager.GetAsync(permissionName, RolePermissionValueProvider.ProviderName, roleName);
}
public static Task<List<PermissionWithGrantedProviders>> GetAllForRoleAsync([NotNull] this IPermissionManager permissionManager, string roleName)
{
Check.NotNull(permissionManager, nameof(permissionManager));
return permissionManager.GetAllAsync(RolePermissionValueProvider.ProviderName, roleName);
}
public static Task SetForRoleAsync([NotNull] this IPermissionManager permissionManager, string roleName, [NotNull] string permissionName, bool isGranted)
{
Check.NotNull(permissionManager, nameof(permissionManager));
return permissionManager.SetAsync(permissionName, RolePermissionValueProvider.ProviderName, roleName, isGranted);
}
}
}

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.PermissionManagement;
namespace Volo.Abp.Permissions
{
public static class UserPermissionManagerExtensions
{
public static Task<List<PermissionWithGrantedProviders>> GetAllForUserAsync([NotNull] this IPermissionManager permissionManager, Guid userId)
{
Check.NotNull(permissionManager, nameof(permissionManager));
return permissionManager.GetAllAsync(UserPermissionValueProvider.ProviderName, userId.ToString());
}
public static Task SetForUserAsync([NotNull] this IPermissionManager permissionManager, Guid userId, [NotNull] string name, bool isGranted)
{
Check.NotNull(permissionManager, nameof(permissionManager));
return permissionManager.SetAsync(name, UserPermissionValueProvider.ProviderName, userId.ToString(), isGranted);
}
}
}

@ -0,0 +1,18 @@
using System.Reflection;
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: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Volo.Abp.Identity.EntityFrameworkCore")]
[assembly: AssemblyTrademark("")]
// 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("439dfc0f-1ba2-464f-900e-ea7e18c08975")]

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Identity.EntityFrameworkCore</AssemblyName>
<PackageId>Volo.Abp.Identity.EntityFrameworkCore</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Identity.Domain\Volo.Abp.Identity.Domain.csproj" />
<ProjectReference Include="..\..\..\abp-users\src\Volo.Abp.Users.EntityFrameworkCore\Volo.Abp.Users.EntityFrameworkCore.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp71</s:String></wpf:ResourceDictionary>

@ -0,0 +1,23 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
using Volo.Abp.Users.EntityFrameworkCore;
namespace Volo.Abp.Identity.EntityFrameworkCore
{
[DependsOn(
typeof(AbpIdentityDomainModule),
typeof(AbpUsersEntityFrameworkCoreModule))]
public class AbpIdentityEntityFrameworkCoreModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddAbpDbContext<IdentityDbContext>(options =>
{
options.AddRepository<IdentityUser, EfCoreIdentityUserRepository>();
options.AddRepository<IdentityRole, EfCoreIdentityRoleRepository>();
});
services.AddAssemblyOf<AbpIdentityEntityFrameworkCoreModule>();
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save