Merge remote-tracking branch 'abpframework/dev' into docs

pull/3191/head
liangshiwei 6 years ago
commit f5bf6e7acb

@ -171,4 +171,7 @@ Background job system is extensible and you can change the default background jo
See pre-built job manager alternatives:
* [Hangfire Background Job Manager](Background-Jobs-Hangfire.md)
* [RabbitMQ Background Job Manager](Background-Jobs-RabbitMq.md)
* [RabbitMQ Background Job Manager](Background-Jobs-RabbitMq.md)
## See Also
* [Background Workers](Background-Workers.md)

@ -1,3 +1,140 @@
# Background Workers
TODO
## Introduction
Background workers are simple independent threads in the application running in the background. Generally, they run periodically to perform some tasks. Examples;
* A background worker can run periodically to **delete old logs**.
* A background worker can run periodically to **determine inactive users** and **send emails** to get users to return to your application.
## Create a Background Worker
A background worker should directly or indirectly implement the `IBackgroundWorker` interface.
> A background worker is inherently [singleton](Dependency-Injection.md). So, only a single instance of your worker class is instantiated and run.
### BackgroundWorkerBase
`BackgroundWorkerBase` is an easy way to create a background worker.
````csharp
public class MyWorker : BackgroundWorkerBase
{
public override Task StartAsync(CancellationToken cancellationToken = default)
{
//...
}
public override Task StopAsync(CancellationToken cancellationToken = default)
{
//...
}
}
````
Start your worker in the `StartAsync` (which is called when the application begins) and stop in the `StopAsync` (which is called when the application shuts down).
> You can directly implement the `IBackgroundWorker`, but `BackgroundWorkerBase` provides some useful properties like `Logger`.
### AsyncPeriodicBackgroundWorkerBase
Assume that we want to make a user passive, if the user has not logged in to the application in last 30 days. `AsyncPeriodicBackgroundWorkerBase` class simplifies to create periodic workers, so we will use it for the example below:
````csharp
public class PassiveUserCheckerWorker : AsyncPeriodicBackgroundWorkerBase
{
public PassiveUserCheckerWorker(
AbpTimer timer,
IServiceScopeFactory serviceScopeFactory
) : base(
timer,
serviceScopeFactory)
{
Timer.Period = 600000; //10 minutes
}
protected override async Task DoWorkAsync(
PeriodicBackgroundWorkerContext workerContext)
{
Logger.LogInformation("Starting: Setting status of inactive users...");
//Resolve dependencies
var userRepository = workerContext
.ServiceProvider
.GetRequiredService<IUserRepository>();
//Do the work
await userRepository.UpdateInactiveUserStatusesAsync();
Logger.LogInformation("Completed: Setting status of inactive users...");
}
}
````
* `AsyncPeriodicBackgroundWorkerBase` uses the `AbpTimer` (a thread-safe timer) object to determine **the period**. We can set its `Period` property in the constructor.
* It required to implement the `DoWorkAsync` method to **execute** the periodic work.
* It is a good practice to **resolve dependencies** from the `PeriodicBackgroundWorkerContext` instead of constructor injection. Because `AsyncPeriodicBackgroundWorkerBase` uses a `IServiceScope` that is **disposed** when your work finishes.
* `AsyncPeriodicBackgroundWorkerBase` **catches and logs exceptions** thrown by the `DoWorkAsync` method.
## Register Background Worker
After creating a background worker class, you should to add it to the `IBackgroundWorkerManager`. The most common place is the `OnApplicationInitialization` method of your module class:
````csharp
[DependsOn(typeof(AbpBackgroundWorkersModule))]
public class MyModule : AbpModule
{
public override void OnApplicationInitialization(
ApplicationInitializationContext context)
{
context.AddBackgroundWorker<PassiveUserCheckerWorker>();
}
}
````
`context.AddBackgroundWorker(...)` is a shortcut extension method for the expression below:
````
context.ServiceProvider
.GetRequiredService<IBackgroundWorkerManager>()
.Add(
context
.ServiceProvider
.GetRequiredService<PassiveUserCheckerWorker>()
);
````
So, it resolves the given background worker and adds to the `IBackgroundWorkerManager`.
While we generally add workers in `OnApplicationInitialization`, there are no restrictions on that. You can inject `IBackgroundWorkerManager` anywhere and add workers at runtime. Background worker manager will stop and release all the registered workers when your application is being shut down.
## Options
`AbpBackgroundWorkerOptions` class is used to [set options](Options.md) for the background workers. Currently, there is only one option:
* `IsEnabled` (default: true): Used to **enable/disable** the background worker system for your application.
> See the [Options](Options.md) document to learn how to set options.
## Making Your Application Always Run
Background workers only work if your application is running. If you host the background job execution in your web application (this is the default behavior), you should ensure that your web application is configured to always be running. Otherwise, background jobs only work while your application is in use.
## Running On a Cluster
Be careful if you run multiple instances of your application simultaneously in a clustered environment. In that case, every application runs the same worker which may create conflicts if your workers are running on the same resources (processing the same data, for example).
If that's a problem for your workers, you have two options;
* Disable the background worker system using the `AbpBackgroundWorkerOptions` described above, for all the application instances, except one of them.
* Disable the background worker system for all the application instances and create another special application that runs on a single server and execute the workers.
## Quartz Integration
ABP Framework's background worker system is good to implement periodic tasks. However, you may want to use an advanced task scheduler like [Quartz](https://www.quartz-scheduler.net/). See the community contributed [quartz integration](Background-Workers-Quartz.md) for the background workers.
## See Also
* [Quartz Integration for the background workers](Background-Workers-Quartz.md)
* [Background Jobs](Background-Jobs.md)

@ -91,4 +91,18 @@ Run the `.DbMigrator` project to create the database and seed the initial data.
## Run the Application
It is ready. Just run the application and enjoy coding.
It is ready. Just run the application and enjoy coding.
## DBMS restrictions
Different DBMS may have some restrictions, such as the maximum length of field names, index length, etc.
The module may provide some built-in solutions. You can configure it via `ModelBuilder`. eg: `Identity Server` module.
```csharp
builder.ConfigureIdentityServer(options =>
{
options.DatabaseProvider = EfCoreDatabaseProvider.MySql;
});
```
Related discussions: https://github.com/abpframework/abp/issues/1920

@ -91,4 +91,18 @@ builder.ConfigureIdentityServer(options =>
## 运行应用程序
它已准备就绪, 只需要运行该应用程序与享受编码.
它已准备就绪, 只需要运行该应用程序与享受编码.
## DBMS限制
不同的DBMS可能存在一些限制, 如字段名称的最大长度, 索引长度等等.
模块可能提供了一些内置的解决方案. 你可以通过`ModelBuilder`来配置它 如: Identity Server模块
```csharp
builder.ConfigureIdentityServer(options =>
{
options.DatabaseProvider = EfCoreDatabaseProvider.MySql;
});
```
相关讨论: https://github.com/abpframework/abp/issues/1920

@ -39,6 +39,43 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
AddWithDependencies(contributorType);
}
public void Replace<TSourceContributor, TDestContributorType>(bool includeDependencies = false)
where TSourceContributor : IBundleContributor, new()
where TDestContributorType : IBundleContributor, new()
{
Replace(typeof(TSourceContributor), typeof(TDestContributorType), includeDependencies);
}
public void Replace([NotNull] Type sourceContributorType, [NotNull] Type destContributorType, bool includeDependencies = false)
{
Check.NotNull(sourceContributorType, nameof(sourceContributorType));
Check.NotNull(destContributorType, nameof(destContributorType));
if (!includeDependencies)
{
_contributors.ReplaceOne(x => x.GetType() == sourceContributorType,
contributor => (IBundleContributor) Activator.CreateInstance(destContributorType));
}
else
{
RemoveWithDependencies(sourceContributorType);
Add(destContributorType);
}
}
public void Remove<TContributor>(bool includeDependencies = false)
where TContributor : IBundleContributor, new()
{
if (!includeDependencies)
{
_contributors.RemoveAll(x => x.GetType() == typeof(TContributor));
}
else
{
RemoveWithDependencies(typeof(TContributor));
}
}
public IReadOnlyList<IBundleContributor> GetAll()
{
return _contributors.ToImmutableList();
@ -58,6 +95,16 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
AddInstanceToContributors(contributorType);
}
private void RemoveWithDependencies(Type contributorType)
{
foreach (var dependedType in GetDirectDependencies(contributorType))
{
RemoveWithDependencies(dependedType); //Recursive call
}
_contributors.RemoveAll(x => x.GetType() == contributorType);
}
private IEnumerable<Type> GetDirectDependencies(Type contributorType)
{

@ -21,7 +21,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Timeago
? "en"
: CultureInfo.CurrentUICulture.Name;
if (TryAddCultureFile(context, cultureName))
if (TryAddCultureFile(context, MapCultureName(cultureName)))
{
return;
}
@ -39,5 +39,10 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Timeago
context.Files.AddIfNotContains(filePath);
return true;
}
protected virtual string MapCultureName(string cultureName)
{
return cultureName;
}
}
}

@ -25,7 +25,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidation
var cultureName = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Replace('-', '_');
if (TryAddCultureFile(context, cultureName))
if (TryAddCultureFile(context, MapCultureName(cultureName)))
{
return;
}
@ -35,7 +35,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidation
return;
}
TryAddCultureFile(context, cultureName.Substring(0, cultureName.IndexOf('_')));
TryAddCultureFile(context, MapCultureName(cultureName.Substring(0, cultureName.IndexOf('_'))));
}
protected virtual bool TryAddCultureFile(BundleConfigurationContext context, string cultureName)
@ -51,5 +51,10 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidation
context.Files.AddIfNotContains(filePath);
return true;
}
protected virtual string MapCultureName(string cultureName)
{
return cultureName;
}
}
}

@ -0,0 +1,38 @@
using System;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
namespace Volo.Abp.BackgroundWorkers
{
public static class BackgroundWorkersApplicationInitializationContextExtensions
{
public static ApplicationInitializationContext AddBackgroundWorker<TWorker>([NotNull] this ApplicationInitializationContext context)
where TWorker : IBackgroundWorker
{
Check.NotNull(context, nameof(context));
context.AddBackgroundWorker(typeof(TWorker));
return context;
}
public static ApplicationInitializationContext AddBackgroundWorker([NotNull] this ApplicationInitializationContext context, [NotNull] Type workerType)
{
Check.NotNull(context, nameof(context));
Check.NotNull(workerType, nameof(workerType));
if (!workerType.IsAssignableTo<IBackgroundWorker>())
{
throw new AbpException($"Given type ({workerType.AssemblyQualifiedName}) must implement the {typeof(IBackgroundWorker).AssemblyQualifiedName} interface, but it doesn't!");
}
context.ServiceProvider
.GetRequiredService<IBackgroundWorkerManager>()
.Add(
(IBackgroundWorker)context.ServiceProvider.GetRequiredService(workerType)
);
return context;
}
}
}

@ -11,6 +11,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Polly;
using Polly.Extensions.Http;
using Volo.Abp.Cli.Auth;
using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.Licensing;
using Volo.Abp.Cli.ProjectBuilding;
@ -32,7 +33,8 @@ namespace Volo.Abp.Cli.NuGet
public NuGetService(
IJsonSerializer jsonSerializer,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler,
ICancellationTokenProvider cancellationTokenProvider, IApiKeyService apiKeyService)
ICancellationTokenProvider cancellationTokenProvider,
IApiKeyService apiKeyService)
{
JsonSerializer = jsonSerializer;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
@ -43,21 +45,33 @@ namespace Volo.Abp.Cli.NuGet
public async Task<SemanticVersion> GetLatestVersionOrNullAsync(string packageId, bool includePreviews = false, bool includeNightly = false)
{
var url = includeNightly ?
$"https://www.myget.org/F/abp-nightly/api/v3/flatcontainer/{packageId.ToLowerInvariant()}/index.json" :
$"https://api.nuget.org/v3-flatcontainer/{packageId.ToLowerInvariant()}/index.json";
List<string> proPackageList = null;
if (AuthService.IsLoggedIn())
{
proPackageList = await GetProPackageListAsync();
}
string url;
if (includeNightly)
{
url =
$"https://www.myget.org/F/abp-nightly/api/v3/flatcontainer/{packageId.ToLowerInvariant()}/index.json";
}
else if (proPackageList?.Contains(packageId) ?? false)
{
url = await GetNuGetUrlForCommercialPackage(packageId);
}
else
{
url = $"https://api.nuget.org/v3-flatcontainer/{packageId.ToLowerInvariant()}/index.json";
}
using (var client = new CliHttpClient(setBearerToken: false))
{
var responseMessage = await GetHttpResponseMessageWithRetryAsync(client, url);
if (responseMessage.StatusCode == HttpStatusCode.NotFound)
{
var commercialNuGetUrl = await GetNuGetUrlForCommercialPackage(packageId);
responseMessage = await GetHttpResponseMessageWithRetryAsync(client, commercialNuGetUrl);
}
if (!responseMessage.IsSuccessStatusCode)
{
throw new Exception($"ERROR: Remote server returns '{responseMessage.StatusCode}'");
@ -95,19 +109,21 @@ namespace Volo.Abp.Cli.NuGet
.OrResult(msg => !msg.IsSuccessStatusCode)
.WaitAndRetryAsync(new[]
{
TimeSpan.FromSeconds(1)
TimeSpan.FromSeconds(2),
TimeSpan.FromSeconds(4),
TimeSpan.FromSeconds(7)
},
(responseMessage, timeSpan, retryCount, context) =>
{
if (responseMessage.Exception != null)
{
Logger.LogDebug(
Logger.LogWarning(
$"{retryCount}. HTTP request attempt failed to {url} with an error: HTTP {(int)responseMessage.Result.StatusCode}-{responseMessage.Exception.Message}. " +
$"Waiting {timeSpan.TotalSeconds} secs for the next try...");
}
else if (responseMessage.Result != null)
{
Logger.LogDebug(
Logger.LogWarning(
$"{retryCount}. HTTP request attempt failed to {url} with an error: {(int)responseMessage.Result.StatusCode}-{responseMessage.Result.ReasonPhrase}. " +
$"Waiting {timeSpan.TotalSeconds} secs for the next try...");
}
@ -115,6 +131,30 @@ namespace Volo.Abp.Cli.NuGet
.ExecuteAsync(async () => await client.GetAsync(url, CancellationTokenProvider.Token));
}
private async Task<List<string>> GetProPackageListAsync()
{
using var client = new CliHttpClient();
var responseMessage = await client.GetAsync(
$"{CliUrls.WwwAbpIo}api/app/nugetPackage/proPackageNames",
CancellationTokenProvider.Token
);
if (!responseMessage.IsSuccessStatusCode)
{
var exceptionMessage = "Remote server returns '" + (int)responseMessage.StatusCode + "-" + responseMessage.ReasonPhrase + "'. ";
var remoteServiceErrorMessage = await RemoteServiceExceptionHandler.GetAbpRemoteServiceErrorAsync(responseMessage);
if (remoteServiceErrorMessage != null)
{
exceptionMessage += remoteServiceErrorMessage;
}
Logger.LogInformation(exceptionMessage);
return null;
}
return JsonSerializer.Deserialize<List<string>>(await responseMessage.Content.ReadAsStringAsync());
}
public class NuGetVersionResultDto
{

@ -28,7 +28,7 @@ using Volo.Abp.Uow;
namespace Volo.Abp.EntityFrameworkCore
{
public abstract class AbpDbContext<TDbContext> : DbContext, IEfCoreDbContext, ITransientDependency
public abstract class AbpDbContext<TDbContext> : DbContext, IAbpEfCoreDbContext, ITransientDependency
where TDbContext : DbContext
{
protected virtual Guid? CurrentTenantId => CurrentTenant?.Id;
@ -144,6 +144,19 @@ namespace Volo.Abp.EntityFrameworkCore
}
}
public virtual void Initialize(AbpEfCoreDbContextInitializationContext initializationContext)
{
if (initializationContext.UnitOfWork.Options.Timeout.HasValue &&
Database.IsRelational() &&
!Database.GetCommandTimeout().HasValue)
{
Database.SetCommandTimeout(initializationContext.UnitOfWork.Options.Timeout.Value.TotalSeconds.To<int>());
}
ChangeTracker.CascadeDeleteTiming = CascadeTiming.OnSaveChanges;
ChangeTracker.DeleteOrphansTiming = CascadeTiming.OnSaveChanges;
}
protected virtual EntityChangeReport ApplyAbpConcepts()
{
var changeReport = new EntityChangeReport();

@ -0,0 +1,14 @@
using Volo.Abp.Uow;
namespace Volo.Abp.EntityFrameworkCore
{
public class AbpEfCoreDbContextInitializationContext
{
public IUnitOfWork UnitOfWork { get; }
public AbpEfCoreDbContextInitializationContext(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
}
}

@ -0,0 +1,7 @@
namespace Volo.Abp.EntityFrameworkCore
{
public interface IAbpEfCoreDbContext : IEfCoreDbContext
{
void Initialize(AbpEfCoreDbContextInitializationContext initializationContext);
}
}

@ -1,5 +1,6 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Data;
@ -53,11 +54,13 @@ namespace Volo.Abp.Uow.EntityFrameworkCore
{
var dbContext = CreateDbContext(unitOfWork);
if (unitOfWork.Options.Timeout.HasValue &&
dbContext.Database.IsRelational() &&
!dbContext.Database.GetCommandTimeout().HasValue)
if (dbContext is IAbpEfCoreDbContext abpEfCoreDbContext)
{
dbContext.Database.SetCommandTimeout(unitOfWork.Options.Timeout.Value.TotalSeconds.To<int>());
abpEfCoreDbContext.Initialize(
new AbpEfCoreDbContextInitializationContext(
unitOfWork
)
);
}
return dbContext;

@ -60,5 +60,27 @@ namespace Volo.Abp.TestApp.Testing
douglas.Age.ShouldBe(42);
}
}
[Fact]
public async Task Cascading_Entities_Should_Not_Be_Deleted_When_Soft_Deleting_Entities()
{
var douglas = await PersonRepository.GetAsync(TestDataBuilder.UserDouglasId);
douglas.Phones.ShouldNotBeEmpty();
await PersonRepository.DeleteAsync(douglas);
douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldBeNull();
using (DataFilter.Disable<ISoftDelete>())
{
douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldNotBeNull();
douglas.IsDeleted.ShouldBeTrue();
douglas.DeletionTime.ShouldNotBeNull();
douglas.Phones.ShouldNotBeEmpty();
}
}
}
}

@ -10,14 +10,14 @@ namespace Volo.Abp.Account
{
public class AccountAppService : ApplicationService, IAccountAppService
{
private readonly IIdentityRoleRepository _roleRepository;
protected IIdentityRoleRepository RoleRepository { get; }
protected IdentityUserManager UserManager { get; }
public AccountAppService(
IdentityUserManager userManager,
IIdentityRoleRepository roleRepository)
{
_roleRepository = roleRepository;
RoleRepository = roleRepository;
UserManager = userManager;
}
@ -30,19 +30,11 @@ namespace Volo.Abp.Account
(await UserManager.CreateAsync(user, input.Password)).CheckErrors();
await UserManager.SetEmailAsync(user,input.EmailAddress);
await SetDefaultRolesAsync(user);
await UserManager.AddDefaultRolesAsync(user);
return ObjectMapper.Map<IdentityUser, IdentityUserDto>(user);
}
protected virtual async Task SetDefaultRolesAsync(IdentityUser user)
{
var defaultRoles = await _roleRepository.GetDefaultOnesAsync();
await UserManager.SetRolesAsync(user, defaultRoles.Select(r => r.Name));
}
protected virtual async Task CheckSelfRegistrationAsync()
{
if (!await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled))
@ -51,4 +43,4 @@ namespace Volo.Abp.Account
}
}
}
}
}

@ -10,18 +10,18 @@ namespace Volo.Abp.Account
[Route("api/account")]
public class AccountController : AbpController, IAccountAppService
{
private readonly IAccountAppService _accountAppService;
protected IAccountAppService AccountAppService { get; }
public AccountController(IAccountAppService accountAppService)
{
_accountAppService = accountAppService;
AccountAppService = accountAppService;
}
[HttpPost]
[Route("register")]
public Task<IdentityUserDto> RegisterAsync(RegisterDto input)
public virtual Task<IdentityUserDto> RegisterAsync(RegisterDto input)
{
return _accountAppService.RegisterAsync(input);
return AccountAppService.RegisterAsync(input);
}
}
}

@ -68,10 +68,10 @@ namespace Volo.Abp.Account.Web.Pages.Account
return Page();
}
var schemes = await _schemeProvider.GetAllSchemesAsync();
var schemes = await SchemeProvider.GetAllSchemesAsync();
var providers = schemes
.Where(x => x.DisplayName != null || x.Name.Equals(_accountOptions.WindowsAuthenticationSchemeName, StringComparison.OrdinalIgnoreCase))
.Where(x => x.DisplayName != null || x.Name.Equals(AccountOptions.WindowsAuthenticationSchemeName, StringComparison.OrdinalIgnoreCase))
.Select(x => new ExternalProviderModel
{
DisplayName = x.DisplayName,
@ -174,7 +174,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
[UnitOfWork]
public override async Task<IActionResult> OnPostExternalLogin(string provider)
{
if (_accountOptions.WindowsAuthenticationSchemeName == provider)
if (AccountOptions.WindowsAuthenticationSchemeName == provider)
{
return await ProcessWindowsLoginAsync();
}
@ -184,10 +184,10 @@ namespace Volo.Abp.Account.Web.Pages.Account
private async Task<IActionResult> ProcessWindowsLoginAsync()
{
var result = await HttpContext.AuthenticateAsync(_accountOptions.WindowsAuthenticationSchemeName);
var result = await HttpContext.AuthenticateAsync(AccountOptions.WindowsAuthenticationSchemeName);
if (!(result?.Principal is WindowsPrincipal windowsPrincipal))
{
return Challenge(_accountOptions.WindowsAuthenticationSchemeName);
return Challenge(AccountOptions.WindowsAuthenticationSchemeName);
}
var props = new AuthenticationProperties
@ -195,11 +195,11 @@ namespace Volo.Abp.Account.Web.Pages.Account
RedirectUri = Url.Page("./Login", pageHandler: "ExternalLoginCallback", values: new { ReturnUrl, ReturnUrlHash }),
Items =
{
{"scheme", _accountOptions.WindowsAuthenticationSchemeName},
{"scheme", AccountOptions.WindowsAuthenticationSchemeName},
}
};
var identity = new ClaimsIdentity(_accountOptions.WindowsAuthenticationSchemeName);
var identity = new ClaimsIdentity(AccountOptions.WindowsAuthenticationSchemeName);
identity.AddClaim(new Claim(JwtClaimTypes.Subject, windowsPrincipal.Identity.Name));
identity.AddClaim(new Claim(JwtClaimTypes.Name, windowsPrincipal.Identity.Name));

@ -9,7 +9,7 @@ namespace Volo.Abp.Account.Web
{
public class AbpAccountUserMenuContributor : IMenuContributor
{
public Task ConfigureMenuAsync(MenuConfigurationContext context)
public virtual Task ConfigureMenuAsync(MenuConfigurationContext context)
{
if (context.Menu.Name != StandardMenus.User)
{

@ -8,7 +8,7 @@ namespace Volo.Abp.Account.Web
{
public class AccountModuleToolbarContributor : IToolbarContributor
{
public Task ConfigureToolbarAsync(IToolbarConfigurationContext context)
public virtual Task ConfigureToolbarAsync(IToolbarConfigurationContext context)
{
if (context.Toolbar.Name != StandardToolbars.Main)
{

@ -22,17 +22,17 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers
[Route("api/account")]
public class AccountController : AbpController
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly IdentityUserManager _userManager;
private readonly ISettingProvider _settingProvider;
protected SignInManager<IdentityUser> SignInManager { get; }
protected IdentityUserManager UserManager { get; }
protected ISettingProvider SettingProvider { get; }
public AccountController(SignInManager<IdentityUser> signInManager, IdentityUserManager userManager, ISettingProvider settingProvider)
{
LocalizationResource = typeof(AccountResource);
_signInManager = signInManager;
_userManager = userManager;
_settingProvider = settingProvider;
SignInManager = signInManager;
UserManager = userManager;
SettingProvider = settingProvider;
}
[HttpPost]
@ -45,7 +45,7 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers
await ReplaceEmailToUsernameOfInputIfNeeds(login);
return GetAbpLoginResult(await _signInManager.PasswordSignInAsync(
return GetAbpLoginResult(await SignInManager.PasswordSignInAsync(
login.UserNameOrEmailAddress,
login.Password,
login.RememberMe,
@ -57,7 +57,7 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers
[Route("logout")]
public virtual async Task Logout()
{
await _signInManager.SignOutAsync();
await SignInManager.SignOutAsync();
}
[HttpPost]
@ -68,14 +68,14 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers
await ReplaceEmailToUsernameOfInputIfNeeds(login);
var identityUser = await _userManager.FindByNameAsync(login.UserNameOrEmailAddress);
var identityUser = await UserManager.FindByNameAsync(login.UserNameOrEmailAddress);
if (identityUser == null)
{
return new AbpLoginResult(LoginResultType.InvalidUserNameOrPassword);
}
return GetAbpLoginResult(await _signInManager.CheckPasswordSignInAsync(identityUser, login.Password, true));
return GetAbpLoginResult(await SignInManager.CheckPasswordSignInAsync(identityUser, login.Password, true));
}
protected virtual async Task ReplaceEmailToUsernameOfInputIfNeeds(UserLoginInfo login)
@ -85,13 +85,13 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers
return;
}
var userByUsername = await _userManager.FindByNameAsync(login.UserNameOrEmailAddress);
var userByUsername = await UserManager.FindByNameAsync(login.UserNameOrEmailAddress);
if (userByUsername != null)
{
return;
}
var userByEmail = await _userManager.FindByEmailAsync(login.UserNameOrEmailAddress);
var userByEmail = await UserManager.FindByEmailAsync(login.UserNameOrEmailAddress);
if (userByEmail == null)
{
return;
@ -125,7 +125,7 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers
return new AbpLoginResult(LoginResultType.Success);
}
private void ValidateLoginInfo(UserLoginInfo login)
protected virtual void ValidateLoginInfo(UserLoginInfo login)
{
if (login == null)
{
@ -143,9 +143,9 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers
}
}
private async Task CheckLocalLoginAsync()
protected virtual async Task CheckLocalLoginAsync()
{
if (!await _settingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin))
if (!await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin))
{
throw new UserFriendlyException(L["LocalLoginDisabledMessage"]);
}

@ -5,7 +5,7 @@ namespace Volo.Abp.Account.Web.Modules.Account.Components.Toolbar.UserLoginLink
{
public class UserLoginLinkViewComponent : AbpViewComponent
{
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View("~/Modules/Account/Components/Toolbar/UserLoginLink/Default.cshtml");
}

@ -21,12 +21,12 @@ namespace Volo.Abp.Account.Web.Pages.Account
ObjectMapperContext = typeof(AbpAccountWebModule);
}
protected RedirectResult RedirectSafely(string returnUrl, string returnUrlHash = null)
protected virtual RedirectResult RedirectSafely(string returnUrl, string returnUrlHash = null)
{
return Redirect(GetRedirectUrl(returnUrl, returnUrlHash));
}
protected void CheckIdentityErrors(IdentityResult identityResult)
protected virtual void CheckIdentityErrors(IdentityResult identityResult)
{
if (!identityResult.Succeeded)
{
@ -36,7 +36,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
//identityResult.CheckErrors(LocalizationManager); //TODO: Get from old Abp
}
private string GetRedirectUrl(string returnUrl, string returnUrlHash = null)
protected virtual string GetRedirectUrl(string returnUrl, string returnUrlHash = null)
{
returnUrl = NormalizeReturnUrl(returnUrl);
@ -48,7 +48,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
return returnUrl;
}
private string NormalizeReturnUrl(string returnUrl)
protected virtual string NormalizeReturnUrl(string returnUrl)
{
if (returnUrl.IsNullOrEmpty())
{

@ -48,25 +48,25 @@ namespace Volo.Abp.Account.Web.Pages.Account
//public IClientStore ClientStore { get; set; }
//public IEventService IdentityServerEvents { get; set; }
protected IAuthenticationSchemeProvider _schemeProvider;
protected AbpAccountOptions _accountOptions;
protected IAuthenticationSchemeProvider SchemeProvider { get; }
protected AbpAccountOptions AccountOptions { get; }
public LoginModel(
IAuthenticationSchemeProvider schemeProvider,
IOptions<AbpAccountOptions> accountOptions)
{
_schemeProvider = schemeProvider;
_accountOptions = accountOptions.Value;
SchemeProvider = schemeProvider;
AccountOptions = accountOptions.Value;
}
public virtual async Task<IActionResult> OnGetAsync()
{
LoginInput = new LoginInputModel();
var schemes = await _schemeProvider.GetAllSchemesAsync();
var schemes = await SchemeProvider.GetAllSchemesAsync();
var providers = schemes
.Where(x => x.DisplayName != null || x.Name.Equals(_accountOptions.WindowsAuthenticationSchemeName, StringComparison.OrdinalIgnoreCase))
.Where(x => x.DisplayName != null || x.Name.Equals(AccountOptions.WindowsAuthenticationSchemeName, StringComparison.OrdinalIgnoreCase))
.Select(x => new ExternalProviderModel
{
DisplayName = x.DisplayName,
@ -212,6 +212,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
CheckIdentityErrors(await UserManager.CreateAsync(user));
CheckIdentityErrors(await UserManager.SetEmailAsync(user, emailAddress));
CheckIdentityErrors(await UserManager.AddLoginAsync(user, info));
CheckIdentityErrors(await UserManager.AddDefaultRolesAsync(user));
return user;
}

@ -23,5 +23,10 @@ namespace Volo.Abp.Account.Web.Pages.Account
return RedirectToPage("/Account/Login");
}
public virtual Task OnPostAsync()
{
return Task.CompletedTask;
}
}
}

@ -10,19 +10,24 @@ namespace Volo.Abp.Account.Web.Pages.Account
public PersonalSettingsInfoModel PersonalSettingsInfoModel { get; set; }
private readonly IProfileAppService _profileAppService;
protected IProfileAppService ProfileAppService { get; }
public ManageModel(IProfileAppService profileAppService)
{
_profileAppService = profileAppService;
ProfileAppService = profileAppService;
}
public async Task OnGetAsync()
public virtual async Task OnGetAsync()
{
var user = await _profileAppService.GetAsync();
var user = await ProfileAppService.GetAsync();
PersonalSettingsInfoModel = ObjectMapper.Map<ProfileDto, PersonalSettingsInfoModel>(user);
}
public virtual Task OnPostAsync()
{
return Task.CompletedTask;
}
}
public class ChangePasswordInfoModel

@ -15,7 +15,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
{
public class RegisterModel : AccountPageModel
{
private readonly IAccountAppService _accountAppService;
protected IAccountAppService AccountAppService { get; }
[BindProperty(SupportsGet = true)]
public string ReturnUrl { get; set; }
@ -28,7 +28,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
public RegisterModel(IAccountAppService accountAppService)
{
_accountAppService = accountAppService;
AccountAppService = accountAppService;
}
public virtual async Task OnGetAsync()
@ -51,7 +51,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
UserName = Input.UserName
};
var userDto = await _accountAppService.RegisterAsync(registerDto);
var userDto = await AccountAppService.RegisterAsync(registerDto);
var user = await UserManager.GetByIdAsync(userDto.Id);
await UserManager.SetEmailAsync(user, Input.EmailAddress);

@ -12,7 +12,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
{
public List<SelectListItem> Providers { get; set; }
public async Task<IActionResult> OnGetAsync()
public virtual async Task<IActionResult> OnGetAsync()
{
var user = await SignInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
@ -41,5 +41,9 @@ namespace Volo.Abp.Account.Web.Pages.Account
//);
}
public virtual Task OnPostAsync()
{
return Task.CompletedTask;
}
}
}

@ -14,10 +14,10 @@ namespace Volo.Abp.AuditLogging
{
public ILogger<AuditingStore> Logger { get; set; }
private readonly IAuditLogRepository _auditLogRepository;
private readonly IGuidGenerator _guidGenerator;
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly AbpAuditingOptions Options;
protected IAuditLogRepository AuditLogRepository { get; }
protected IGuidGenerator GuidGenerator { get; }
protected IUnitOfWorkManager UnitOfWorkManager { get; }
protected AbpAuditingOptions Options { get; }
public AuditingStore(
IAuditLogRepository auditLogRepository,
@ -25,15 +25,15 @@ namespace Volo.Abp.AuditLogging
IUnitOfWorkManager unitOfWorkManager,
IOptions<AbpAuditingOptions> options)
{
_auditLogRepository = auditLogRepository;
_guidGenerator = guidGenerator;
_unitOfWorkManager = unitOfWorkManager;
AuditLogRepository = auditLogRepository;
GuidGenerator = guidGenerator;
UnitOfWorkManager = unitOfWorkManager;
Options = options.Value;
Logger = NullLogger<AuditingStore>.Instance;
}
public async Task SaveAsync(AuditLogInfo auditInfo)
public virtual async Task SaveAsync(AuditLogInfo auditInfo)
{
if (!Options.HideErrors)
{
@ -54,9 +54,9 @@ namespace Volo.Abp.AuditLogging
protected virtual async Task SaveLogAsync(AuditLogInfo auditInfo)
{
using (var uow = _unitOfWorkManager.Begin(true))
using (var uow = UnitOfWorkManager.Begin(true))
{
await _auditLogRepository.InsertAsync(new AuditLog(_guidGenerator, auditInfo));
await AuditLogRepository.InsertAsync(new AuditLog(GuidGenerator, auditInfo));
await uow.SaveChangesAsync();
}
}

@ -19,7 +19,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
}
public async Task<List<AuditLog>> GetListAsync(
public virtual async Task<List<AuditLog>> GetListAsync(
string sorting = null,
int maxResultCount = 50,
int skipCount = 0,
@ -59,7 +59,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
return auditLogs;
}
public async Task<long> GetCountAsync(
public virtual async Task<long> GetCountAsync(
DateTime? startTime = null,
DateTime? endTime = null,
string httpMethod = null,
@ -92,7 +92,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
return totalCount;
}
private IQueryable<AuditLog> GetListQuery(
protected virtual IQueryable<AuditLog> GetListQuery(
DateTime? startTime = null,
DateTime? endTime = null,
string httpMethod = null,
@ -123,7 +123,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
.WhereIf(minExecutionDuration != null && minExecutionDuration.Value > 0, auditLog => auditLog.ExecutionDuration >= minExecutionDuration);
}
public async Task<Dictionary<DateTime, double>> GetAverageExecutionDurationPerDayAsync(DateTime startDate, DateTime endDate)
public virtual async Task<Dictionary<DateTime, double>> GetAverageExecutionDurationPerDayAsync(DateTime startDate, DateTime endDate)
{
var result = await DbSet.AsNoTracking()
.Where(a => a.ExecutionTime < endDate.AddDays(1) && a.ExecutionTime > startDate)

@ -20,7 +20,7 @@ namespace Volo.Abp.AuditLogging.MongoDB
}
public async Task<List<AuditLog>> GetListAsync(
public virtual async Task<List<AuditLog>> GetListAsync(
string sorting = null,
int maxResultCount = 50,
int skipCount = 0,
@ -58,7 +58,7 @@ namespace Volo.Abp.AuditLogging.MongoDB
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<long> GetCountAsync(
public virtual async Task<long> GetCountAsync(
DateTime? startTime = null,
DateTime? endTime = null,
string httpMethod = null,
@ -92,7 +92,7 @@ namespace Volo.Abp.AuditLogging.MongoDB
return count;
}
private IQueryable<AuditLog> GetListQuery(
protected virtual IQueryable<AuditLog> GetListQuery(
DateTime? startTime = null,
DateTime? endTime = null,
string httpMethod = null,
@ -122,7 +122,7 @@ namespace Volo.Abp.AuditLogging.MongoDB
}
public async Task<Dictionary<DateTime, double>> GetAverageExecutionDurationPerDayAsync(DateTime startDate, DateTime endDate)
public virtual async Task<Dictionary<DateTime, double>> GetAverageExecutionDurationPerDayAsync(DateTime startDate, DateTime endDate)
{
var result = await GetMongoQueryable()
.Where(a => a.ExecutionTime < endDate.AddDays(1) && a.ExecutionTime > startDate)

@ -48,7 +48,7 @@ namespace Volo.Abp.BackgroundJobs
/// </summary>
public virtual BackgroundJobPriority Priority { get; set; }
private BackgroundJobRecord()
protected BackgroundJobRecord()
{
}

@ -21,13 +21,13 @@ namespace Volo.Abp.BackgroundJobs.EntityFrameworkCore
Clock = clock;
}
public async Task<List<BackgroundJobRecord>> GetWaitingListAsync(int maxResultCount)
public virtual async Task<List<BackgroundJobRecord>> GetWaitingListAsync(int maxResultCount)
{
return await GetWaitingListQuery(maxResultCount)
.ToListAsync();
}
private IQueryable<BackgroundJobRecord> GetWaitingListQuery(int maxResultCount)
protected virtual IQueryable<BackgroundJobRecord> GetWaitingListQuery(int maxResultCount)
{
var now = Clock.Now;
return DbSet

@ -21,13 +21,13 @@ namespace Volo.Abp.BackgroundJobs.MongoDB
Clock = clock;
}
public async Task<List<BackgroundJobRecord>> GetWaitingListAsync(int maxResultCount)
public virtual async Task<List<BackgroundJobRecord>> GetWaitingListAsync(int maxResultCount)
{
return await GetWaitingListQuery(maxResultCount)
.ToListAsync();
}
private IMongoQueryable<BackgroundJobRecord> GetWaitingListQuery(int maxResultCount)
protected virtual IMongoQueryable<BackgroundJobRecord> GetWaitingListQuery(int maxResultCount)
{
var now = Clock.Now;
return GetMongoQueryable()

@ -27,7 +27,7 @@
<abp-input asp-for="FocusCommentId" class="m-0" />
<div class="container">
<div class="row">
<div class="col-md-8 col-lg-8 mx-auto">
<div class="col-10 col-md-8 col-lg-7 mx-auto">
<section class="hero-section">
<div class="hero-articles">
<div class="hero-content">
@ -86,7 +86,7 @@
</div>
<div class="row">
<div class="col-md-8 col-lg-8 mx-auto">
<div class="col-10 col-md-8 col-lg-7 mx-auto">
<section class="post-content">
<p>
@Html.Raw(RenderMarkdownToHtml(Model.Post.Content))
@ -96,8 +96,8 @@
</div>
<div class="row">
<div class="col-md-8 col-lg-8 mx-auto">
<hr />
<div class="col-10 col-md-8 col-lg-7 mx-auto">
<hr />
<div class="mb-2 mt-1">
@(L["ShareOn"].Value + " :")
<a href="#" target="_blank" class="mr-2" id="TwitterShareLink" title="Twitter">
@ -121,7 +121,6 @@
</div>
}
@if (Model.CommentsWithReplies.Count > 0)
{
<abp-row v-align="Start">
@ -191,7 +190,7 @@
<input name="repliedCommentId" value="@commentWithRepliesDto.Comment.Id" hidden />
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4"></textarea>
<textarea class="form-control" name="text" id="textBoxId" rows="4"></textarea>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Comment"].Value" />
<abp-button button-type="Danger" class="btn-rounded float-right replyCancelButton" text="@L["Cancel"].Value" />
@ -208,7 +207,7 @@
<form class="editFormClass">
<input name="commentId" value="@commentWithRepliesDto.Comment.Id" hidden />
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4">@commentWithRepliesDto.Comment.Text</textarea>
<textarea class="form-control" name="text" id="textBoxId" rows="4">@commentWithRepliesDto.Comment.Text</textarea>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value" />
<abp-button button-type="Danger" class="btn-rounded float-right editCancelButton" text="@L["Cancel"].Value" />
@ -258,7 +257,7 @@
@if (hasCommentingPermission)
{
<div class="comment-form mt-4 replyForm">
<div class="clearfix bg-light p-4">
<div class="clearfix bg-light py-4">
<h3 class="mt-0">
@L["ReplyTo", commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName]
</h3>
@ -267,7 +266,7 @@
<input name="postId" value="@Model.Post.Id" hidden />
<input name="repliedCommentId" value="@commentWithRepliesDto.Comment.Id" hidden />
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4"></textarea>
<textarea class="form-control" name="text" id="textBoxId" rows="4"></textarea>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value" />
<abp-button button-type="Danger" class="btn-rounded float-right replyCancelButton" text="@L["Cancel"].Value" />
@ -279,12 +278,12 @@
@if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId))
{
<div class="comment-form mt-4 editForm">
<div class="clearfix bg-light p-4">
<div class="clearfix bg-light py-4">
<div>
<form class="editFormClass">
<input name="commentId" value="@reply.Id" hidden />
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4">@reply.Text</textarea>
<textarea class="form-control" name="text" id="textBoxId" rows="4">@reply.Text</textarea>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value" />
<abp-button button-type="Danger" class="btn-rounded float-right editCancelButton" text="@L["Cancel"].Value" />
@ -308,13 +307,13 @@
<div class="vs-blog-title mb-0">
<h3>@L["LeaveComment"]</h3>
</div>
<div class="clearfix bg-light p-4">
<div class="clearfix bg-light py-4">
<div>
<form method="post">
<input name="postId" value="@Model.Post.Id" hidden />
<input name="repliedCommentId" id="repliedCommentId" hidden />
<div class="form-group">
<textarea class="form-control no-border" name="text" id="textBoxId" rows="4"></textarea>
<textarea class="form-control" name="text" id="textBoxId" rows="4"></textarea>
</div>
<abp-button button-type="Primary" class="btn-rounded float-right" type="submit" text="@L["Submit"].Value" />
</form>

@ -17,55 +17,63 @@
<abp-script type="@typeof(TuiEditorScriptContributor)" />
<abp-script src="/Pages/Blogs/Posts/edit.js" />
</abp-script-bundle>
}
}
<div id="edit-post-container">
<form method="post" id="edit-post-form">
<abp-input asp-for="Post.Title" auto-focus="true" />
<abp-input asp-for="Post.Url" />
<abp-input asp-for="Post.CoverImage" />
<div class="container py-5">
<div class="row">
<div class="col-10 col-md-8 col-lg-7 mx-auto">
<div class="card">
<div class="card-body">
<form method="post" id="edit-post-form">
<abp-input asp-for="Post.Title" auto-focus="true" />
<abp-input asp-for="Post.Url" />
<abp-input asp-for="Post.CoverImage" />
<abp-row>
<abp-column size-sm="_9">
<div class="form-group">
<label for="CoverImageFile">@L["CoverImage"]</label>
<input class="form-control" type="file" id="CoverImageFile" />
</div>
</abp-column>
<abp-column size-sm="_3">
<img id="CoverImage" src="@Model.Post.CoverImage" height="80" width="160" />
</abp-column>
</abp-row>
<abp-row>
<abp-column size-sm="_9">
<div class="form-group">
<label for="CoverImageFile">@L["CoverImage"]</label>
<input class="form-control" type="file" id="CoverImageFile" />
</div>
</abp-column>
<abp-column size-sm="_3">
<img id="CoverImage" src="@Model.Post.CoverImage" height="80" width="160" />
</abp-column>
</abp-row>
<abp-input asp-for="Post.Tags" />
<abp-input asp-for="Post.BlogId" />
<abp-input asp-for="Post.Id" />
<abp-input asp-for="Post.Content" />
<abp-input asp-for="Post.Tags" />
<abp-input asp-for="Post.BlogId" />
<abp-input asp-for="Post.Id" />
<abp-input asp-for="Post.Content" />
<div class="form-group">
<div class="edit-post-editor">
<div class="gradient-background-animation loading-cover"></div>
</div>
</div>
<div class="form-group">
<div class="edit-post-editor">
<div class="gradient-background-animation loading-cover"></div>
</div>
</div>
<div class="actions d-flex">
<div class="text-muted editor-info d-none d-lg-block mr-auto">
<div class="actions d-flex">
<div class="text-muted editor-info d-none d-lg-block mr-auto">
<div>
<svg class="markdown-icon" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true">
<path fill-rule="evenodd" d="M14.85 3H1.15C.52 3 0 3.52 0 4.15v7.69C0 12.48.52 13 1.15 13h13.69c.64 0 1.15-.52 1.15-1.15v-7.7C16 3.52 15.48 3 14.85 3zM9 11H7V8L5.5 9.92 4 8v3H2V5h2l1.5 2L7 5h2v6zm2.99.5L9.5 8H11V5h2v3h1.5l-2.51 3.5z"></path>
</svg> <small>@L["MarkdownSupported"] </small>
</div>
<div>
<svg class="markdown-icon" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true">
<path fill-rule="evenodd" d="M14.85 3H1.15C.52 3 0 3.52 0 4.15v7.69C0 12.48.52 13 1.15 13h13.69c.64 0 1.15-.52 1.15-1.15v-7.7C16 3.52 15.48 3 14.85 3zM9 11H7V8L5.5 9.92 4 8v3H2V5h2l1.5 2L7 5h2v6zm2.99.5L9.5 8H11V5h2v3h1.5l-2.51 3.5z"></path>
</svg> <small>@L["MarkdownSupported"] </small>
</div>
<div><small><i class="fa fa-copy"></i> @L["FileUploadInfo"].Value</small></div>
<div><small><i class="fa fa-copy"></i> @L["FileUploadInfo"].Value</small></div>
</div>
<div class="mt-3 d-flex flex-row-reverse">
<abp-button button-type="Primary" type="submit" form="edit-post-form" text="@L["Submit"].Value" icon="check" />
</div>
<div class="mt-3 d-flex flex-row-reverse">
<abp-button button-type="Primary" type="submit" form="edit-post-form" text="@L["Submit"].Value" icon="check" />
<a asp-page="/Blog/Posts/Detail" asp-route-postUrl="@Model.Post.Url" asp-route-blogShortName="@Model.BlogShortName" class="btn btn-default mr-2"><span>@L["Cancel"]</span></a>
<a asp-page="/Blog/Posts/Detail" asp-route-postUrl="@Model.Post.Url" asp-route-blogShortName="@Model.BlogShortName" class="btn btn-default mr-2"><span>@L["Cancel"]</span></a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</form>
</div>
</div>

@ -43,6 +43,7 @@
</h2>
<p class="article-sum">
@Html.Raw(GetShortContent(post.Content))
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">Continue Reading</a>
</p>
</div>
@if (post.Writer != null)
@ -156,6 +157,7 @@
</h3>
<p>
@Html.Raw(GetShortContent(post.Content))
<a asp-page="./Detail" asp-route-postUrl="@post.Url" asp-route-blogShortName="@Model.BlogShortName">Continue Reading</a>
</p>
<div class="article-owner">
<div class="article-infos">

@ -4,7 +4,6 @@
min-height: 480px;
background: center center no-repeat;
background-size: cover;
}
}
}
}

@ -18,59 +18,63 @@
<abp-script src="/Pages/Blogs/Posts/new.js" />
</abp-script-bundle>
}
<main>
<section>
<div class="container">
<div id="qa-new-post-container">
<form method="post" id="new-post-form">
<abp-input asp-for="Post.BlogId" />
<abp-input asp-for="Post.Title" auto-focus="true" />
<abp-input asp-for="Post.Url" />
<abp-input asp-for="Post.CoverImage" />
<div id="qa-new-post-container">
<div class="container py-5">
<div class="row">
<div class="col-10 col-md-8 col-lg-7 mx-auto">
<div class="card">
<div class="card-body">
<form method="post" id="new-post-form">
<abp-input asp-for="Post.BlogId" />
<abp-input asp-for="Post.Title" auto-focus="true" />
<abp-input asp-for="Post.Url" />
<abp-input asp-for="Post.CoverImage" />
<abp-row>
<abp-column size-sm="_9">
<div class="form-group">
<label for="CoverImageFile">@L["CoverImage"]</label>
<input class="form-control" type="file" id="CoverImageFile" />
</div>
</abp-column>
<abp-column size-sm="_3">
<img id="CoverImage" src="@Model.Post.CoverImage" height="80" width="160" style="display:none" />
</abp-column>
</abp-row>
<abp-row>
<abp-column size-sm="_9">
<div class="form-group">
<label for="CoverImageFile">@L["CoverImage"]</label>
<input class="form-control" type="file" id="CoverImageFile" />
</div>
</abp-column>
<abp-column size-sm="_3">
<img id="CoverImage" src="@Model.Post.CoverImage" height="80" width="160" style="display:none" />
</abp-column>
</abp-row>
<abp-input asp-for="Post.Content" />
<abp-input asp-for="Post.Tags" />
<abp-input asp-for="Post.Content" />
<abp-input asp-for="Post.Tags" />
<div class="form-group">
<div class="new-post-editor">
<div class="gradient-background-animation loading-cover"></div>
</div>
</div>
<div class="form-group">
<div class="new-post-editor">
<div class="gradient-background-animation loading-cover"></div>
</div>
</div>
<div class="actions d-flex">
<div class="text-muted editor-info d-none d-lg-block mr-auto">
<div class="actions d-flex">
<div class="text-muted editor-info d-none d-lg-block mr-auto">
<div>
<svg class="markdown-icon" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true">
<path fill-rule="evenodd" d="M14.85 3H1.15C.52 3 0 3.52 0 4.15v7.69C0 12.48.52 13 1.15 13h13.69c.64 0 1.15-.52 1.15-1.15v-7.7C16 3.52 15.48 3 14.85 3zM9 11H7V8L5.5 9.92 4 8v3H2V5h2l1.5 2L7 5h2v6zm2.99.5L9.5 8H11V5h2v3h1.5l-2.51 3.5z"></path>
</svg> <small>@L["MarkdownSupported"] </small>
</div>
<div>
<svg class="markdown-icon" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true">
<path fill-rule="evenodd" d="M14.85 3H1.15C.52 3 0 3.52 0 4.15v7.69C0 12.48.52 13 1.15 13h13.69c.64 0 1.15-.52 1.15-1.15v-7.7C16 3.52 15.48 3 14.85 3zM9 11H7V8L5.5 9.92 4 8v3H2V5h2l1.5 2L7 5h2v6zm2.99.5L9.5 8H11V5h2v3h1.5l-2.51 3.5z"></path>
</svg> <small>@L["MarkdownSupported"] </small>
</div>
<div><small><i class="fa fa-copy"></i> @L["FileUploadInfo"].Value</small></div>
<div><small><i class="fa fa-copy"></i> @L["FileUploadInfo"].Value</small></div>
</div>
<div class="mt-3 d-flex flex-row-reverse">
<abp-button button-type="Primary" type="submit" form="new-post-form" text="@L["Submit"].Value" icon="check" />
</div>
<div class="mt-3 d-flex flex-row-reverse">
<abp-button button-type="Primary" type="submit" form="new-post-form" text="@L["Submit"].Value" icon="check" />
<a asp-page="./Index" class="btn btn-default mr-2"><span>@L["Cancel"]</span></a>
</div>
<a asp-page="./Index" class="btn btn-default mr-2"><span>@L["Cancel"]</span></a>
</div>
</div>
</form>
</div>
</form>
</div>
</div>
</div>
</section>
</main>
</div>
</div>

@ -13,19 +13,20 @@ h1, h2, h3, h4, h5, h6, .tab-title {
font-weight: 700;
}
h1 {
font-size: 2.25em;
font-size: 2em;
margin: 1rem 0 1.5rem;
line-height: 1.25;
}
h2, .tab-title {
font-size: 1.5em;
margin: 1.5rem 0 .75rem;
}
h3 {
font-size: 1.5em;
font-size: 1.25em;
margin: 1.5rem 0 .75rem;
}
h4 {
font-size: 1.25em;
font-size: 1.125em;
margin: 1.5rem 0 .75rem;
}
h5 {
@ -40,9 +41,10 @@ h6 {
}
img {
max-width: 100%;
}
input, select, textarea, .form-control , .btn {
}
input, select, textarea, .form-control, .btn {
border-radius: 0;
border-width: 1px 1px 2px 1px;
}
.navbar-toggler {
background: aqua;
@ -58,7 +60,7 @@ input, select, textarea, .form-control , .btn {
.list-group-item {
position: relative;
display: block;
padding: 0 0 20px 0;
padding: 30px 0 30px;
background: none;
border-radius: 0;
border: 0;
@ -69,7 +71,7 @@ input, select, textarea, .form-control , .btn {
& + .list-group-item {
border-top: 1px solid #f5f5f5;
padding: 20px 0;
padding: 45px 0 30px;
}
h3 {
@ -79,8 +81,9 @@ input, select, textarea, .form-control , .btn {
&.small-list {
.list-group-item {
padding: 10px 0;
& + .list-group-item {
padding: 10px 0;
& + .list-group-item {
padding: 10px 0;
}
}
@ -100,6 +103,6 @@ input, select, textarea, .form-control , .btn {
font-size: 1em;
}
.font-125 {
font-size: 1.25em;
font-size: 1.125em;
}

@ -5,11 +5,12 @@
position: relative;
overflow: hidden;
.hero-content {
.hero-content {
h2 {
margin-top: .5rem;
font-size: 2em;
font-size: 1.75em;
font-weight: bold;
line-height: 1.25;
}
}
@ -25,9 +26,9 @@
}
}
.article-owner {
.article-owner {
.article-infos {
color: black;
color: black;
.seperator {
@ -35,17 +36,17 @@
color: rgba(255, 255, 255, 0.2);
}
img.article-avatar {
img.article-avatar {
display: inline-block;
border-radius: 50%;
}
}
}
.img-container {
.img-container {
img {
width: 100%;
}
}
}
&:hover {
@ -128,7 +129,7 @@
}
.article-owner {
font-size: .85em;
font-size: .72em;
}
.user-link-icons {

@ -3,7 +3,7 @@
background: white;
padding: 30px;
font-family: 'Open Sans', Helvetica, Arial, sans-serif;
font-size: 14px; }
font-size: 16px; }
div.vs-blog a, div.vs-blog a:hover {
text-decoration: none;
color: #000000; }
@ -15,16 +15,17 @@
font-family: Helvetica, Arial, sans-serif;
font-weight: 700; }
div.vs-blog h1 {
font-size: 2.25em;
margin: 1rem 0 1.5rem; }
font-size: 2em;
margin: 1rem 0 1.5rem;
line-height: 1.25; }
div.vs-blog h2, div.vs-blog .tab-title {
font-size: 1.5em;
margin: 1.5rem 0 .75rem; }
div.vs-blog h3 {
font-size: 1.5em;
font-size: 1.25em;
margin: 1.5rem 0 .75rem; }
div.vs-blog h4 {
font-size: 1.25em;
font-size: 1.125em;
margin: 1.5rem 0 .75rem; }
div.vs-blog h5 {
font-size: 1em; }
@ -36,7 +37,8 @@
div.vs-blog img {
max-width: 100%; }
div.vs-blog input, div.vs-blog select, div.vs-blog textarea, div.vs-blog .form-control, div.vs-blog .btn {
border-radius: 0; }
border-radius: 0;
border-width: 1px 1px 2px 1px; }
div.vs-blog .navbar-toggler {
background: aqua; }
div.vs-blog .no-border {
@ -46,7 +48,7 @@
div.vs-blog .list-group .list-group-item {
position: relative;
display: block;
padding: 0 0 20px 0;
padding: 30px 0 30px;
background: none;
border-radius: 0;
border: 0; }
@ -54,7 +56,7 @@
background: none; }
div.vs-blog .list-group .list-group-item + .list-group-item {
border-top: 1px solid #f5f5f5;
padding: 20px 0; }
padding: 45px 0 30px; }
div.vs-blog .list-group .list-group-item h3 {
margin-top: 0; }
div.vs-blog .list-group.small-list .list-group-item {
@ -70,7 +72,7 @@
div.vs-blog .font-100 {
font-size: 1em; }
div.vs-blog .font-125 {
font-size: 1.25em; }
font-size: 1.125em; }
div.vs-blog .vs-blog-title {
padding-bottom: 15px;
margin-bottom: 25px;
@ -92,8 +94,9 @@
overflow: hidden; }
div.vs-blog .hero-section .hero-articles .hero-content h2 {
margin-top: .5rem;
font-size: 2em;
font-weight: bold; }
font-size: 1.75em;
font-weight: bold;
line-height: 1.25; }
div.vs-blog .hero-section .hero-articles .tags .tag {
background: rgba(208, 208, 208, 0.3);
color: #fff !important; }
@ -149,7 +152,7 @@
display: inline-block;
border-radius: 50%; }
div.vs-blog .article-owner {
font-size: .85em; }
font-size: .72em; }
div.vs-blog .user-link-icons {
position: absolute;
right: 18px;

File diff suppressed because one or more lines are too long

@ -3,7 +3,7 @@ div.vs-blog {
background: white;
padding: 30px;
font-family: 'Open Sans', Helvetica, Arial, sans-serif;
font-size: 14px;
font-size: 16px;
@import "bootstrap-overwrite.scss";
@import "header.scss";
@import "home.scss";

@ -10,5 +10,9 @@
{
"outputFile": "Pages/Blog/Posts/Index.css",
"inputFile": "Pages/Blog/Posts/Index.scss"
},
{
"outputFile": "Pages/Blogs/Shared/Styles/blog.css",
"inputFile": "Pages/Blogs/Shared/Styles/blog.scss"
}
]

@ -10,7 +10,7 @@ using VoloDocs.EntityFrameworkCore;
namespace VoloDocs.EntityFrameworkCore.Migrations
{
[DbContext(typeof(VoloDocsDbContext))]
[Migration("20200218014727_init")]
[Migration("20200312050853_init")]
partial class init
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -492,6 +492,9 @@ namespace VoloDocs.EntityFrameworkCore.Migrations
b.Property<DateTime>("LastCachedTime")
.HasColumnType("datetime2");
b.Property<DateTime?>("LastSignificantUpdateTime")
.HasColumnType("datetime2");
b.Property<DateTime>("LastUpdatedTime")
.HasColumnType("datetime2");

@ -132,6 +132,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations
LocalDirectory = table.Column<string>(maxLength: 512, nullable: true),
CreationTime = table.Column<DateTime>(nullable: false),
LastUpdatedTime = table.Column<DateTime>(nullable: false),
LastSignificantUpdateTime = table.Column<DateTime>(nullable: true),
LastCachedTime = table.Column<DateTime>(nullable: false)
},
constraints: table =>

@ -490,6 +490,9 @@ namespace VoloDocs.EntityFrameworkCore.Migrations
b.Property<DateTime>("LastCachedTime")
.HasColumnType("datetime2");
b.Property<DateTime?>("LastSignificantUpdateTime")
.HasColumnType("datetime2");
b.Property<DateTime>("LastUpdatedTime")
.HasColumnType("datetime2");

@ -96,6 +96,7 @@ namespace Volo.Docs.Documents
{
leaf.CreationTime = documentUpdateInfo.CreationTime;
leaf.LastUpdatedTime = documentUpdateInfo.LastUpdatedTime;
leaf.LastSignificantUpdateTime = documentUpdateInfo.LastSignificantUpdateTime;
}
}
@ -189,12 +190,12 @@ namespace Volo.Docs.Documents
{
version = string.IsNullOrWhiteSpace(version) ? project.LatestVersionBranchName : version;
async Task<DocumentWithDetailsDto> GetDocumentAsync()
async Task<DocumentWithDetailsDto> GetDocumentAsync(Document oldDocument = null)
{
Logger.LogInformation($"Not found in the cache. Requesting {documentName} from the source...");
var source = _documentStoreFactory.Create(project.DocumentStoreType);
var sourceDocument = await source.GetDocumentAsync(project, documentName, languageCode, version);
var sourceDocument = await source.GetDocumentAsync(project, documentName, languageCode, version, oldDocument?.LastSignificantUpdateTime);
await _documentRepository.DeleteAsync(project.Id, sourceDocument.Name, sourceDocument.LanguageCode, sourceDocument.Version);
await _documentRepository.InsertAsync(sourceDocument, true);
@ -206,7 +207,8 @@ namespace Volo.Docs.Documents
{
Name = sourceDocument.Name,
CreationTime = sourceDocument.CreationTime,
LastUpdatedTime = sourceDocument.LastUpdatedTime
LastUpdatedTime = sourceDocument.LastUpdatedTime,
LastSignificantUpdateTime = sourceDocument.LastSignificantUpdateTime
});
return CreateDocumentWithDetailsDto(project, sourceDocument);
@ -229,7 +231,7 @@ namespace Volo.Docs.Documents
//TODO: Configurable cache time?
document.LastCachedTime + TimeSpan.FromHours(2) < DateTime.Now)
{
return await GetDocumentAsync();
return await GetDocumentAsync(document);
}
var cacheKey = $"DocumentUpdateInfo{document.ProjectId}#{document.Name}#{document.LanguageCode}#{document.Version}";
@ -238,6 +240,7 @@ namespace Volo.Docs.Documents
Name = document.Name,
CreationTime = document.CreationTime,
LastUpdatedTime = document.LastUpdatedTime,
LastSignificantUpdateTime = document.LastSignificantUpdateTime
});
return CreateDocumentWithDetailsDto(project, document);

@ -10,5 +10,7 @@ namespace Volo.Docs.Documents
public virtual DateTime CreationTime { get; set; }
public virtual DateTime LastUpdatedTime { get; set; }
public DateTime? LastSignificantUpdateTime { get; set; }
}
}

@ -26,6 +26,8 @@ namespace Volo.Docs.Documents
public virtual DateTime? LastUpdatedTime { get; set; }
public DateTime? LastSignificantUpdateTime { get; set; }
public bool IsSelected(string documentName)
{
if (documentName == null)

@ -34,6 +34,8 @@ namespace Volo.Docs.Documents
public virtual DateTime CreationTime { get; set; }
public virtual DateTime LastUpdatedTime { get; set; }
public virtual DateTime? LastSignificantUpdateTime { get; set; }
public virtual DateTime LastCachedTime { get; set; }
@ -60,7 +62,8 @@ namespace Volo.Docs.Documents
[NotNull] string localDirectory,
DateTime creationTime,
DateTime lastUpdatedTime,
DateTime lastCachedTime
DateTime lastCachedTime,
DateTime? lastSignificantUpdateTime = null
)
{
Id = id;
@ -80,6 +83,7 @@ namespace Volo.Docs.Documents
CreationTime = creationTime;
LastUpdatedTime = lastUpdatedTime;
LastCachedTime = lastCachedTime;
LastSignificantUpdateTime = lastSignificantUpdateTime;
Contributors = new List<DocumentContributor>();
ExtraProperties = new Dictionary<string, object>();

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
@ -8,7 +9,7 @@ namespace Volo.Docs.Documents
{
public interface IDocumentSource : IDomainService
{
Task<Document> GetDocumentAsync(Project project, string documentName, string languageCode, string version);
Task<Document> GetDocumentAsync(Project project, string documentName, string languageCode, string version, DateTime? lastKnownSignificantUpdateTime = null);
Task<List<VersionInfo>> GetVersionsAsync(Project project);

@ -16,7 +16,7 @@ namespace Volo.Docs.FileSystem.Documents
{
public const string Type = "FileSystem";
public async Task<Document> GetDocumentAsync(Project project, string documentName, string languageCode, string version)
public async Task<Document> GetDocumentAsync(Project project, string documentName, string languageCode, string version, DateTime? lastKnownSignificantUpdateTime = null)
{
var projectFolder = project.GetFileSystemPath();
var path = Path.Combine(projectFolder, languageCode, documentName);

@ -21,13 +21,15 @@ namespace Volo.Docs.GitHub.Documents
public const string Type = "GitHub";
private readonly IGithubRepositoryManager _githubRepositoryManager;
private readonly IGithubPatchAnalyzer _githubPatchAnalyzer;
public GithubDocumentSource(IGithubRepositoryManager githubRepositoryManager)
public GithubDocumentSource(IGithubRepositoryManager githubRepositoryManager, IGithubPatchAnalyzer githubPatchAnalyzer)
{
_githubRepositoryManager = githubRepositoryManager;
_githubPatchAnalyzer = githubPatchAnalyzer;
}
public virtual async Task<Document> GetDocumentAsync(Project project, string documentName, string languageCode, string version)
public virtual async Task<Document> GetDocumentAsync(Project project, string documentName, string languageCode, string version, DateTime? lastKnownSignificantUpdateTime = null)
{
var token = project.GetGitHubAccessTokenOrNull();
var rootUrl = project.GetGitHubUrl(version);
@ -46,25 +48,38 @@ namespace Volo.Docs.GitHub.Documents
fileName = documentName.Substring(documentName.LastIndexOf('/') + 1);
}
var fileCommits = await GetFileCommitsAsync(project, version, $"docs/{languageCode}/{documentName}");
var fileCommits = await GetFileCommitsAsync(project, version, project.GetGitHubInnerUrl(languageCode, documentName));
var documentCreationTime = fileCommits.LastOrDefault()?.Commit.Author.Date.DateTime ?? DateTime.MinValue;
var lastSignificantUpdateTime = !isNavigationDocument && !isParameterDocument && version == project.LatestVersionBranchName ?
await GetLastSignificantUpdateTime(
fileCommits,
project,
project.GetGitHubInnerUrl(languageCode, documentName),
lastKnownSignificantUpdateTime,
documentCreationTime
) ?? lastKnownSignificantUpdateTime
: null;
var document= new Document(GuidGenerator.Create(),
project.Id,
documentName,
version,
var document = new Document(GuidGenerator.Create(),
project.Id,
documentName,
version,
languageCode,
fileName,
fileName,
await DownloadWebContentAsStringAsync(rawDocumentUrl, token, userAgent),
project.Format,
editLink,
project.Format,
editLink,
rootUrl,
rawRootUrl,
rawRootUrl,
localDirectory,
fileCommits.LastOrDefault()?.Commit.Author.Date.DateTime ?? DateTime.MinValue,
documentCreationTime,
fileCommits.FirstOrDefault()?.Commit.Author.Date.DateTime ?? DateTime.MinValue,
DateTime.Now);
DateTime.Now,
lastSignificantUpdateTime);
var authors = fileCommits
var authors = fileCommits
.Where(x => x.Author != null)
.Select(x => x.Author)
.GroupBy(x => x.Id)
@ -82,6 +97,42 @@ namespace Volo.Docs.GitHub.Documents
return document;
}
private async Task<DateTime?> GetLastSignificantUpdateTime(
IReadOnlyList<GitHubCommit> fileCommits,
Project project,
string fileName,
DateTime? lastKnownSignificantUpdateTime,
DateTime documentCreationTime)
{
if (!fileCommits.Any())
{
return null;
}
var fileCommitsAfterCreation = fileCommits.Take(fileCommits.Count - 1);
var commitsToEvaluate = (lastKnownSignificantUpdateTime != null
? fileCommitsAfterCreation.Where(c => c.Commit.Author.Date.DateTime > lastKnownSignificantUpdateTime)
: fileCommitsAfterCreation).Where(c => c.Commit.Author.Date.DateTime > DateTime.Now.AddDays(-14));
foreach (var gitHubCommit in commitsToEvaluate)
{
var fullCommit = await _githubRepositoryManager.GetSingleCommitsAsync(
GetOwnerNameFromUrl(project.GetGitHubUrl()),
GetRepositoryNameFromUrl(project.GetGitHubUrl()),
gitHubCommit.Sha,
project.GetGitHubAccessTokenOrNull());
if (_githubPatchAnalyzer.HasPatchSignificantChanges(fullCommit.Files.First(f => f.Filename == fileName).Patch))
{
return gitHubCommit.Commit.Author.Date.DateTime;
}
}
return null;
}
public async Task<List<VersionInfo>> GetVersionsAsync(Project project)
{
List<VersionInfo> versions;

@ -0,0 +1,121 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Volo.Abp.Domain.Services;
namespace Volo.Docs.GitHub.Documents
{
public class GithubPatchAnalyzer : DomainService, IGithubPatchAnalyzer
{
public bool HasPatchSignificantChanges(string patch)
{
var changes = GetChanges(patch);
return IsChangesSignificant(changes);
}
private bool IsChangesSignificant(CommitChanges change)
{
if (CompareLineCount(change))
{
return true;
}
if (CompareWordCount(change))
{
return true;
}
if (CompareWords(change))
{
return true;
}
return false;
}
private static bool CompareLineCount(CommitChanges change)
{
return Math.Abs(change.NewLines.Count - change.OldLines.Count) >= 3;
}
private static bool CompareWordCount(CommitChanges change)
{
var wordCountInNewLines =
string.Join(" ", change.NewLines).Split(" ").Count(s => !string.IsNullOrWhiteSpace(s));
var wordCountInOldLines =
string.Join(" ", change.OldLines).Split(" ").Count(s => !string.IsNullOrWhiteSpace(s));
return Math.Abs(wordCountInNewLines - wordCountInOldLines) >= 15;
}
private bool CompareWords(CommitChanges change)
{
var wordsInNewLines = GetDistinctWordsFromLineList(change.NewLines);
var wordsInOldLines = GetDistinctWordsFromLineList(change.OldLines);
var differentWordsInNewLines = wordsInNewLines.Except(wordsInOldLines).Count();
var differentWordsInOldLines = wordsInOldLines.Except(wordsInNewLines).Count();
return differentWordsInNewLines + differentWordsInOldLines >= 10;
}
private CommitChanges GetChanges(string patch)
{
var changes = new List<CommitChanges>();
var pathSplited = patch.Split("@@");
var changeList = pathSplited.Where(s => !string.IsNullOrWhiteSpace(s)).Where((c, i) => i % 2 == 1).ToList();
foreach (var change in changeList)
{
var commitChange = new CommitChanges();
var lines = change.Split("\n");
commitChange.OldLines.AddRange(lines.Where(l => l.StartsWith("-")).Select(l => l.Substring(1)).Where(l => !string.IsNullOrWhiteSpace(l)));
commitChange.NewLines.AddRange(lines.Where(l => l.StartsWith("+")).Select(l => l.Substring(1)).Where(l => !string.IsNullOrWhiteSpace(l)));
changes.Add(commitChange);
}
return MergeChanges(changes);
}
private CommitChanges MergeChanges(List<CommitChanges> changes)
{
var mergedChanges = new CommitChanges();
foreach (var commitChanges in changes)
{
mergedChanges.NewLines.AddRange(commitChanges.NewLines);
mergedChanges.OldLines.AddRange(commitChanges.OldLines);
}
return mergedChanges;
}
private List<string> GetDistinctWordsFromLineList(List<string> lines)
{
return string.Join(" ", lines).Split(" ").Where(s => !string.IsNullOrWhiteSpace(s))
.Select(TrimAndRemovePunctuation).Distinct().ToList();
}
private string TrimAndRemovePunctuation(string str)
{
return new string(str.Trim().ToCharArray().Where(c => !char.IsPunctuation(c)).ToArray());
}
private class CommitChanges
{
public List<string> OldLines { get; set; }
public List<string> NewLines { get; set; }
public CommitChanges()
{
OldLines = new List<string>();
NewLines = new List<string>();
}
}
}
}

@ -75,5 +75,15 @@ namespace Volo.Docs.GitHub.Documents
var request = new CommitRequest { Path = filename, Sha = version };
return await client.Repository.Commit.GetAll(repo.Id, request);
}
public async Task<GitHubCommit> GetSingleCommitsAsync(string name, string repositoryName, string sha, string token)
{
var client = token.IsNullOrWhiteSpace()
? new GitHubClient(new ProductHeaderValue(name))
: new GitHubClient(new ProductHeaderValue(name), new InMemoryCredentialStore(new Credentials(token)));
var repo = await client.Repository.Get(name, repositoryName);
return await client.Repository.Commit.Get(repo.Id, sha);
}
}
}

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Domain.Services;
namespace Volo.Docs.GitHub.Documents
{
public interface IGithubPatchAnalyzer : IDomainService
{
bool HasPatchSignificantChanges(string patch);
}
}

@ -16,5 +16,7 @@ namespace Volo.Docs.GitHub.Documents
Task<IReadOnlyList<Release>> GetReleasesAsync(string name, string repositoryName, string token);
Task<IReadOnlyList<GitHubCommit>> GetFileCommitsAsync(string name, string repositoryName, string version, string filename, string token);
Task<GitHubCommit> GetSingleCommitsAsync(string name, string repositoryName, string sha, string token);
}
}

@ -14,6 +14,12 @@ namespace Volo.Docs.GitHub.Projects
return project.ExtraProperties["GitHubRootUrl"] as string;
}
public static string GetGitHubInnerUrl([NotNull] this Project project, string languageCode, string documentName)
{
return project
.GetGitHubUrl().Split("{version}")[1].EnsureEndsWith('/').TrimStart('/') + languageCode + '/' + documentName;
}
public static string GetGitHubUrl([NotNull] this Project project, string version)
{
return project

@ -127,16 +127,16 @@ namespace Volo.Docs.Areas.Documents.TagHelpers
if (!node.Path.IsNullOrWhiteSpace() && node.CreationTime.HasValue && node.LastUpdatedTime.HasValue)
{
var newBadge = "<span class='badge badge-primary ml-2' title=\"" + _localizer["NewExplanation"] + "\">" + _localizer["New"] + "</span>";
var updBadge = "<span class='badge badge-light ml-2' title=\"" + _localizer["UpdatedExplanation"] + "\">" + _localizer["Upd"] + "</span>";
if(node.CreationTime + TimeSpan.FromDays(14) > DateTime.Now)
{
badge = newBadge;
var newBadge = "<span class='badge badge-primary ml-2' title=\"" + _localizer["NewExplanation"] + "\">" + _localizer["New"] + "</span>";
badge += newBadge;
}
else if (node.LastUpdatedTime + TimeSpan.FromDays(14) > DateTime.Now)
if (node.LastSignificantUpdateTime != null && node.LastSignificantUpdateTime + TimeSpan.FromDays(14) > DateTime.Now)
{
badge = updBadge;
var updBadge = "<span class='badge badge-light ml-2' title=\"" + _localizer["UpdatedExplanation"] + "\">" + _localizer["Upd"] + "</span>";
badge += updBadge;
}
}

@ -47,7 +47,7 @@
return;
}
var $targetElement = $(hash);
var $targetElement = $(decodeURIComponent(hash));
$targetElement = $targetElement.length ? $targetElement : $('[name=' + this.hash.slice(1) + ']');
@ -77,7 +77,7 @@
event.preventDefault();
var hash = this.hash;
$('html, body').animate({
scrollTop: $(hash).offset().top
scrollTop: $(decodeURIComponent(hash)).offset().top
}, 500, function () {
window.location.hash = hash;
});

@ -17,18 +17,15 @@ namespace Volo.Abp.FeatureManagement
{
protected FeatureManagementOptions Options { get; }
private readonly IFeatureManager _featureManager;
private readonly IFeatureDefinitionManager _featureDefinitionManager;
private readonly IStringLocalizerFactory _stringLocalizerFactory;
protected IFeatureManager FeatureManager { get; }
protected IFeatureDefinitionManager FeatureDefinitionManager { get; }
public FeatureAppService(IFeatureManager featureManager,
IFeatureDefinitionManager featureDefinitionManager,
IStringLocalizerFactory stringLocalizerFactory,
IOptions<FeatureManagementOptions> options)
{
_featureManager = featureManager;
_featureDefinitionManager = featureDefinitionManager;
_stringLocalizerFactory = stringLocalizerFactory;
FeatureManager = featureManager;
FeatureDefinitionManager = featureDefinitionManager;
Options = options.Value;
}
@ -36,7 +33,7 @@ namespace Volo.Abp.FeatureManagement
{
await CheckProviderPolicy(providerName);
var featureDefinitions = _featureDefinitionManager.GetAll();
var featureDefinitions = FeatureDefinitionManager.GetAll();
var features = new List<FeatureDto>();
foreach (var featureDefinition in featureDefinitions)
@ -44,11 +41,11 @@ namespace Volo.Abp.FeatureManagement
features.Add(new FeatureDto
{
Name = featureDefinition.Name,
DisplayName = featureDefinition.DisplayName?.Localize(_stringLocalizerFactory),
DisplayName = featureDefinition.DisplayName?.Localize(StringLocalizerFactory),
ValueType = featureDefinition.ValueType,
Description = featureDefinition.Description?.Localize(_stringLocalizerFactory),
Description = featureDefinition.Description?.Localize(StringLocalizerFactory),
ParentName = featureDefinition.Parent?.Name,
Value = await _featureManager.GetOrNullAsync(featureDefinition.Name, providerName, providerKey)
Value = await FeatureManager.GetOrNullAsync(featureDefinition.Name, providerName, providerKey)
});
}
@ -63,11 +60,11 @@ namespace Volo.Abp.FeatureManagement
foreach (var feature in input.Features)
{
await _featureManager.SetAsync(feature.Name, feature.Value, providerName, providerKey);
await FeatureManager.SetAsync(feature.Name, feature.Value, providerName, providerKey);
}
}
private void SetFeatureDepth(List<FeatureDto> features, string providerName, string providerKey,
protected virtual void SetFeatureDepth(List<FeatureDto> features, string providerName, string providerKey,
FeatureDto parentFeature = null, int depth = 0)
{
foreach (var feature in features)

@ -8,17 +8,17 @@ namespace Volo.Abp.FeatureManagement
{
public string Name => DefaultValueFeatureValueProvider.ProviderName;
public Task<string> GetOrNullAsync(FeatureDefinition feature, string providerKey)
public virtual Task<string> GetOrNullAsync(FeatureDefinition feature, string providerKey)
{
return Task.FromResult(feature.DefaultValue);
}
public Task SetAsync(FeatureDefinition feature, string value, string providerKey)
public virtual Task SetAsync(FeatureDefinition feature, string value, string providerKey)
{
throw new AbpException($"Can not set default value of a feature. It is only possible while defining the feature in a {typeof(IFeatureDefinitionProvider)} implementation.");
}
public Task ClearAsync(FeatureDefinition feature, string providerKey)
public virtual Task ClearAsync(FeatureDefinition feature, string providerKey)
{
throw new AbpException($"Can not clear default value of a feature. It is only possible while defining the feature in a {typeof(IFeatureDefinitionProvider)} implementation.");
}

@ -14,7 +14,7 @@ namespace Volo.Abp.FeatureManagement
Store = store;
}
public async Task<string> GetOrNullAsync(FeatureDefinition feature, string providerKey)
public virtual async Task<string> GetOrNullAsync(FeatureDefinition feature, string providerKey)
{
return await Store.GetOrNullAsync(feature.Name, Name, NormalizeProviderKey(providerKey));
}

@ -21,13 +21,13 @@ namespace Volo.Abp.FeatureManagement
Cache = cache;
}
public async Task<string> GetOrNullAsync(string name, string providerName, string providerKey)
public virtual async Task<string> GetOrNullAsync(string name, string providerName, string providerKey)
{
var cacheItem = await GetCacheItemAsync(name, providerName, providerKey);
return cacheItem.Value;
}
public async Task SetAsync(string name, string value, string providerName, string providerKey)
public virtual async Task SetAsync(string name, string value, string providerName, string providerKey)
{
var featureValue = await FeatureValueRepository.FindAsync(name, providerName, providerKey);
if (featureValue == null)
@ -42,7 +42,7 @@ namespace Volo.Abp.FeatureManagement
}
}
public async Task DeleteAsync(string name, string providerName, string providerKey)
public virtual async Task DeleteAsync(string name, string providerName, string providerKey)
{
var featureValue = await FeatureValueRepository.FindAsync(name, providerName, providerKey);
if (featureValue != null)

@ -13,7 +13,7 @@ namespace Volo.Abp.FeatureManagement
FeatureManagementStore = featureManagementStore;
}
public Task<string> GetOrNullAsync(
public virtual Task<string> GetOrNullAsync(
string name,
string providerName,
string providerKey)

@ -15,7 +15,7 @@ namespace Volo.Abp.FeatureManagement.EntityFrameworkCore
{
}
public async Task<FeatureValue> FindAsync(string name, string providerName, string providerKey)
public virtual async Task<FeatureValue> FindAsync(string name, string providerName, string providerKey)
{
return await DbSet
.FirstOrDefaultAsync(
@ -23,7 +23,7 @@ namespace Volo.Abp.FeatureManagement.EntityFrameworkCore
);
}
public async Task<List<FeatureValue>> GetListAsync(string providerName, string providerKey)
public virtual async Task<List<FeatureValue>> GetListAsync(string providerName, string providerKey)
{
return await DbSet
.Where(

@ -8,21 +8,21 @@ namespace Volo.Abp.FeatureManagement
[Area("abp")]
public class FeaturesController : AbpController, IFeatureAppService
{
private readonly IFeatureAppService _featureAppService;
protected IFeatureAppService FeatureAppService { get; }
public FeaturesController(IFeatureAppService featureAppService)
{
_featureAppService = featureAppService;
FeatureAppService = featureAppService;
}
public Task<FeatureListDto> GetAsync(string providerName, string providerKey)
public virtual Task<FeatureListDto> GetAsync(string providerName, string providerKey)
{
return _featureAppService.GetAsync(providerName, providerKey);
return FeatureAppService.GetAsync(providerName, providerKey);
}
public Task UpdateAsync(string providerName, string providerKey, UpdateFeaturesDto input)
public virtual Task UpdateAsync(string providerName, string providerKey, UpdateFeaturesDto input)
{
return _featureAppService.UpdateAsync(providerName, providerKey, input);
return FeatureAppService.UpdateAsync(providerName, providerKey, input);
}
}
}

@ -16,13 +16,13 @@ namespace Volo.Abp.FeatureManagement.MongoDB
}
public async Task<FeatureValue> FindAsync(string name, string providerName, string providerKey)
public virtual async Task<FeatureValue> FindAsync(string name, string providerName, string providerKey)
{
return await GetMongoQueryable()
.FirstOrDefaultAsync(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey);
}
public async Task<List<FeatureValue>> GetListAsync(string providerName, string providerKey)
public virtual async Task<List<FeatureValue>> GetListAsync(string providerName, string providerKey)
{
return await GetMongoQueryable()
.Where(s => s.ProviderName == providerName && s.ProviderKey == providerKey)

@ -25,21 +25,21 @@ namespace Volo.Abp.FeatureManagement.Web.Pages.FeatureManagement
public FeatureListDto FeatureListDto { get; set; }
private readonly IFeatureAppService _featureAppService;
protected IFeatureAppService FeatureAppService { get; }
public FeatureManagementModal(IFeatureAppService featureAppService)
{
ObjectMapperContext = typeof(AbpFeatureManagementWebModule);
_featureAppService = featureAppService;
FeatureAppService = featureAppService;
}
public async Task OnGetAsync()
public virtual async Task OnGetAsync()
{
FeatureListDto = await _featureAppService.GetAsync(ProviderName, ProviderKey);
FeatureListDto = await FeatureAppService.GetAsync(ProviderName, ProviderKey);
}
public async Task<IActionResult> OnPostAsync()
public virtual async Task<IActionResult> OnPostAsync()
{
var features = new UpdateFeaturesDto
{
@ -50,7 +50,7 @@ namespace Volo.Abp.FeatureManagement.Web.Pages.FeatureManagement
}).ToList()
};
await _featureAppService.UpdateAsync(ProviderName, ProviderKey, features);
await FeatureAppService.UpdateAsync(ProviderName, ProviderKey, features);
return NoContent();
}

@ -10,34 +10,34 @@ namespace Volo.Abp.Identity
[Authorize(IdentityPermissions.Roles.Default)]
public class IdentityRoleAppService : IdentityAppServiceBase, IIdentityRoleAppService
{
private readonly IdentityRoleManager _roleManager;
private readonly IIdentityRoleRepository _roleRepository;
protected IdentityRoleManager RoleManager { get; }
protected IIdentityRoleRepository RoleRepository { get; }
public IdentityRoleAppService(
IdentityRoleManager roleManager,
IIdentityRoleRepository roleRepository)
{
_roleManager = roleManager;
_roleRepository = roleRepository;
RoleManager = roleManager;
RoleRepository = roleRepository;
}
public virtual async Task<IdentityRoleDto> GetAsync(Guid id)
{
return ObjectMapper.Map<IdentityRole, IdentityRoleDto>(
await _roleManager.GetByIdAsync(id));
await RoleManager.GetByIdAsync(id));
}
public virtual async Task<ListResultDto<IdentityRoleDto>> GetAllListAsync()
{
var list = await _roleRepository.GetListAsync();
var list = await RoleRepository.GetListAsync();
return new ListResultDto<IdentityRoleDto>(
ObjectMapper.Map<List<IdentityRole>, List<IdentityRoleDto>>(list));
}
public virtual async Task<PagedResultDto<IdentityRoleDto>> GetListAsync(PagedAndSortedResultRequestDto input)
{
var list = await _roleRepository.GetListAsync(input.Sorting, input.MaxResultCount, input.SkipCount);
var totalCount = await _roleRepository.GetCountAsync();
var list = await RoleRepository.GetListAsync(input.Sorting, input.MaxResultCount, input.SkipCount);
var totalCount = await RoleRepository.GetCountAsync();
return new PagedResultDto<IdentityRoleDto>(
totalCount,
@ -53,7 +53,7 @@ namespace Volo.Abp.Identity
role.IsDefault = input.IsDefault;
role.IsPublic = input.IsPublic;
(await _roleManager.CreateAsync(role)).CheckErrors();
(await RoleManager.CreateAsync(role)).CheckErrors();
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<IdentityRole, IdentityRoleDto>(role);
@ -62,15 +62,15 @@ namespace Volo.Abp.Identity
[Authorize(IdentityPermissions.Roles.Update)]
public virtual async Task<IdentityRoleDto> UpdateAsync(Guid id, IdentityRoleUpdateDto input)
{
var role = await _roleManager.GetByIdAsync(id);
var role = await RoleManager.GetByIdAsync(id);
role.ConcurrencyStamp = input.ConcurrencyStamp;
(await _roleManager.SetRoleNameAsync(role, input.Name)).CheckErrors();
(await RoleManager.SetRoleNameAsync(role, input.Name)).CheckErrors();
role.IsDefault = input.IsDefault;
role.IsPublic = input.IsPublic;
(await _roleManager.UpdateAsync(role)).CheckErrors();
(await RoleManager.UpdateAsync(role)).CheckErrors();
await CurrentUnitOfWork.SaveChangesAsync();
return ObjectMapper.Map<IdentityRole, IdentityRoleDto>(role);
@ -79,13 +79,13 @@ namespace Volo.Abp.Identity
[Authorize(IdentityPermissions.Roles.Delete)]
public virtual async Task DeleteAsync(Guid id)
{
var role = await _roleManager.FindByIdAsync(id.ToString());
var role = await RoleManager.FindByIdAsync(id.ToString());
if (role == null)
{
return;
}
(await _roleManager.DeleteAsync(role)).CheckErrors();
(await RoleManager.DeleteAsync(role)).CheckErrors();
}
}
}

@ -9,15 +9,15 @@ namespace Volo.Abp.Identity
{
public class IdentityUserAppService : IdentityAppServiceBase, IIdentityUserAppService
{
private readonly IdentityUserManager _userManager;
private readonly IIdentityUserRepository _userRepository;
protected IdentityUserManager UserManager { get; }
protected IIdentityUserRepository UserRepository { get; }
public IdentityUserAppService(
IdentityUserManager userManager,
IIdentityUserRepository userRepository)
{
_userManager = userManager;
_userRepository = userRepository;
UserManager = userManager;
UserRepository = userRepository;
}
//TODO: [Authorize(IdentityPermissions.Users.Default)] should go the IdentityUserAppService class.
@ -25,15 +25,15 @@ namespace Volo.Abp.Identity
public virtual async Task<IdentityUserDto> GetAsync(Guid id)
{
return ObjectMapper.Map<IdentityUser, IdentityUserDto>(
await _userManager.GetByIdAsync(id)
await UserManager.GetByIdAsync(id)
);
}
[Authorize(IdentityPermissions.Users.Default)]
public virtual async Task<PagedResultDto<IdentityUserDto>> GetListAsync(GetIdentityUsersInput input)
{
var count = await _userRepository.GetCountAsync(input.Filter);
var list = await _userRepository.GetListAsync(input.Sorting, input.MaxResultCount, input.SkipCount, input.Filter);
var count = await UserRepository.GetCountAsync(input.Filter);
var list = await UserRepository.GetListAsync(input.Sorting, input.MaxResultCount, input.SkipCount, input.Filter);
return new PagedResultDto<IdentityUserDto>(
count,
@ -44,7 +44,7 @@ namespace Volo.Abp.Identity
[Authorize(IdentityPermissions.Users.Default)]
public virtual async Task<ListResultDto<IdentityRoleDto>> GetRolesAsync(Guid id)
{
var roles = await _userRepository.GetRolesAsync(id);
var roles = await UserRepository.GetRolesAsync(id);
return new ListResultDto<IdentityRoleDto>(
ObjectMapper.Map<List<IdentityRole>, List<IdentityRoleDto>>(roles)
);
@ -55,7 +55,7 @@ namespace Volo.Abp.Identity
{
var user = new IdentityUser(GuidGenerator.Create(), input.UserName, input.Email, CurrentTenant.Id);
(await _userManager.CreateAsync(user, input.Password)).CheckErrors();
(await UserManager.CreateAsync(user, input.Password)).CheckErrors();
await UpdateUserByInput(user, input);
await CurrentUnitOfWork.SaveChangesAsync();
@ -66,17 +66,17 @@ namespace Volo.Abp.Identity
[Authorize(IdentityPermissions.Users.Update)]
public virtual async Task<IdentityUserDto> UpdateAsync(Guid id, IdentityUserUpdateDto input)
{
var user = await _userManager.GetByIdAsync(id);
var user = await UserManager.GetByIdAsync(id);
user.ConcurrencyStamp = input.ConcurrencyStamp;
(await _userManager.SetUserNameAsync(user, input.UserName)).CheckErrors();
(await UserManager.SetUserNameAsync(user, input.UserName)).CheckErrors();
await UpdateUserByInput(user, input);
(await _userManager.UpdateAsync(user)).CheckErrors();
(await UserManager.UpdateAsync(user)).CheckErrors();
if (!input.Password.IsNullOrEmpty())
{
(await _userManager.RemovePasswordAsync(user)).CheckErrors();
(await _userManager.AddPasswordAsync(user, input.Password)).CheckErrors();
(await UserManager.RemovePasswordAsync(user)).CheckErrors();
(await UserManager.AddPasswordAsync(user, input.Password)).CheckErrors();
}
await CurrentUnitOfWork.SaveChangesAsync();
@ -92,28 +92,28 @@ namespace Volo.Abp.Identity
throw new BusinessException(code: IdentityErrorCodes.UserSelfDeletion);
}
var user = await _userManager.FindByIdAsync(id.ToString());
var user = await UserManager.FindByIdAsync(id.ToString());
if (user == null)
{
return;
}
(await _userManager.DeleteAsync(user)).CheckErrors();
(await UserManager.DeleteAsync(user)).CheckErrors();
}
[Authorize(IdentityPermissions.Users.Update)]
public virtual async Task UpdateRolesAsync(Guid id, IdentityUserUpdateRolesDto input)
{
var user = await _userManager.GetByIdAsync(id);
(await _userManager.SetRolesAsync(user, input.RoleNames)).CheckErrors();
await _userRepository.UpdateAsync(user);
var user = await UserManager.GetByIdAsync(id);
(await UserManager.SetRolesAsync(user, input.RoleNames)).CheckErrors();
await UserRepository.UpdateAsync(user);
}
[Authorize(IdentityPermissions.Users.Default)]
public virtual async Task<IdentityUserDto> FindByUsernameAsync(string username)
{
return ObjectMapper.Map<IdentityUser, IdentityUserDto>(
await _userManager.FindByNameAsync(username)
await UserManager.FindByNameAsync(username)
);
}
@ -121,31 +121,31 @@ namespace Volo.Abp.Identity
public virtual async Task<IdentityUserDto> FindByEmailAsync(string email)
{
return ObjectMapper.Map<IdentityUser, IdentityUserDto>(
await _userManager.FindByEmailAsync(email)
await UserManager.FindByEmailAsync(email)
);
}
private async Task UpdateUserByInput(IdentityUser user, IdentityUserCreateOrUpdateDtoBase input)
protected virtual async Task UpdateUserByInput(IdentityUser user, IdentityUserCreateOrUpdateDtoBase input)
{
if (!string.Equals(user.Email, input.Email, StringComparison.InvariantCultureIgnoreCase))
{
(await _userManager.SetEmailAsync(user, input.Email)).CheckErrors();
(await UserManager.SetEmailAsync(user, input.Email)).CheckErrors();
}
if (!string.Equals(user.PhoneNumber, input.PhoneNumber, StringComparison.InvariantCultureIgnoreCase))
{
(await _userManager.SetPhoneNumberAsync(user, input.PhoneNumber)).CheckErrors();
(await UserManager.SetPhoneNumberAsync(user, input.PhoneNumber)).CheckErrors();
}
(await _userManager.SetTwoFactorEnabledAsync(user, input.TwoFactorEnabled)).CheckErrors();
(await _userManager.SetLockoutEnabledAsync(user, input.LockoutEnabled)).CheckErrors();
(await UserManager.SetTwoFactorEnabledAsync(user, input.TwoFactorEnabled)).CheckErrors();
(await UserManager.SetLockoutEnabledAsync(user, input.LockoutEnabled)).CheckErrors();
user.Name = input.Name;
user.Surname = input.Surname;
if (input.RoleNames != null)
{
(await _userManager.SetRolesAsync(user, input.RoleNames)).CheckErrors();
(await UserManager.SetRolesAsync(user, input.RoleNames)).CheckErrors();
}
}
}

@ -10,40 +10,40 @@ namespace Volo.Abp.Identity
[Authorize]
public class ProfileAppService : IdentityAppServiceBase, IProfileAppService
{
private readonly IdentityUserManager _userManager;
protected IdentityUserManager UserManager { get; }
public ProfileAppService(IdentityUserManager userManager)
{
_userManager = userManager;
UserManager = userManager;
}
public virtual async Task<ProfileDto> GetAsync()
{
return ObjectMapper.Map<IdentityUser, ProfileDto>(
await _userManager.GetByIdAsync(CurrentUser.GetId())
await UserManager.GetByIdAsync(CurrentUser.GetId())
);
}
public virtual async Task<ProfileDto> UpdateAsync(UpdateProfileDto input)
{
var user = await _userManager.GetByIdAsync(CurrentUser.GetId());
var user = await UserManager.GetByIdAsync(CurrentUser.GetId());
if (await SettingProvider.IsTrueAsync(IdentitySettingNames.User.IsUserNameUpdateEnabled))
{
(await _userManager.SetUserNameAsync(user, input.UserName)).CheckErrors();
(await UserManager.SetUserNameAsync(user, input.UserName)).CheckErrors();
}
if (await SettingProvider.IsTrueAsync(IdentitySettingNames.User.IsEmailUpdateEnabled))
{
(await _userManager.SetEmailAsync(user, input.Email)).CheckErrors();
(await UserManager.SetEmailAsync(user, input.Email)).CheckErrors();
}
(await _userManager.SetPhoneNumberAsync(user, input.PhoneNumber)).CheckErrors();
(await UserManager.SetPhoneNumberAsync(user, input.PhoneNumber)).CheckErrors();
user.Name = input.Name;
user.Surname = input.Surname;
(await _userManager.UpdateAsync(user)).CheckErrors();
(await UserManager.UpdateAsync(user)).CheckErrors();
await CurrentUnitOfWork.SaveChangesAsync();
@ -52,8 +52,8 @@ namespace Volo.Abp.Identity
public virtual async Task ChangePasswordAsync(ChangePasswordInput input)
{
var currentUser = await _userManager.GetByIdAsync(CurrentUser.GetId());
(await _userManager.ChangePasswordAsync(currentUser, input.CurrentPassword, input.NewPassword)).CheckErrors();
var currentUser = await UserManager.GetByIdAsync(CurrentUser.GetId());
(await UserManager.ChangePasswordAsync(currentUser, input.CurrentPassword, input.NewPassword)).CheckErrors();
}
}
}

@ -12,7 +12,7 @@ namespace Volo.Abp.Identity
{
public class AbpIdentityOptionsFactory : AbpOptionsFactory<IdentityOptions>
{
private readonly ISettingProvider _settingProvider;
protected ISettingProvider SettingProvider { get; }
public AbpIdentityOptionsFactory(
IEnumerable<IConfigureOptions<IdentityOptions>> setups,
@ -20,7 +20,7 @@ namespace Volo.Abp.Identity
ISettingProvider settingProvider)
: base(setups, postConfigures)
{
_settingProvider = settingProvider;
SettingProvider = settingProvider;
}
public override IdentityOptions Create(string name)
@ -39,19 +39,19 @@ namespace Volo.Abp.Identity
protected virtual async Task OverrideOptionsAsync(IdentityOptions options)
{
options.Password.RequiredLength = await _settingProvider.GetAsync(IdentitySettingNames.Password.RequiredLength, options.Password.RequiredLength);
options.Password.RequiredUniqueChars = await _settingProvider.GetAsync(IdentitySettingNames.Password.RequiredUniqueChars, options.Password.RequiredUniqueChars);
options.Password.RequireNonAlphanumeric = await _settingProvider.GetAsync(IdentitySettingNames.Password.RequireNonAlphanumeric, options.Password.RequireNonAlphanumeric);
options.Password.RequireLowercase = await _settingProvider.GetAsync(IdentitySettingNames.Password.RequireLowercase, options.Password.RequireLowercase);
options.Password.RequireUppercase = await _settingProvider.GetAsync(IdentitySettingNames.Password.RequireUppercase, options.Password.RequireUppercase);
options.Password.RequireDigit = await _settingProvider.GetAsync(IdentitySettingNames.Password.RequireDigit, options.Password.RequireDigit);
options.Lockout.AllowedForNewUsers = await _settingProvider.GetAsync(IdentitySettingNames.Lockout.AllowedForNewUsers, options.Lockout.AllowedForNewUsers);
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromSeconds(await _settingProvider.GetAsync(IdentitySettingNames.Lockout.LockoutDuration, options.Lockout.DefaultLockoutTimeSpan.TotalSeconds.To<int>()));
options.Lockout.MaxFailedAccessAttempts = await _settingProvider.GetAsync(IdentitySettingNames.Lockout.MaxFailedAccessAttempts, options.Lockout.MaxFailedAccessAttempts);
options.SignIn.RequireConfirmedEmail = await _settingProvider.GetAsync(IdentitySettingNames.SignIn.RequireConfirmedEmail, options.SignIn.RequireConfirmedEmail);
options.SignIn.RequireConfirmedPhoneNumber = await _settingProvider.GetAsync(IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber, options.SignIn.RequireConfirmedPhoneNumber);
options.Password.RequiredLength = await SettingProvider.GetAsync(IdentitySettingNames.Password.RequiredLength, options.Password.RequiredLength);
options.Password.RequiredUniqueChars = await SettingProvider.GetAsync(IdentitySettingNames.Password.RequiredUniqueChars, options.Password.RequiredUniqueChars);
options.Password.RequireNonAlphanumeric = await SettingProvider.GetAsync(IdentitySettingNames.Password.RequireNonAlphanumeric, options.Password.RequireNonAlphanumeric);
options.Password.RequireLowercase = await SettingProvider.GetAsync(IdentitySettingNames.Password.RequireLowercase, options.Password.RequireLowercase);
options.Password.RequireUppercase = await SettingProvider.GetAsync(IdentitySettingNames.Password.RequireUppercase, options.Password.RequireUppercase);
options.Password.RequireDigit = await SettingProvider.GetAsync(IdentitySettingNames.Password.RequireDigit, options.Password.RequireDigit);
options.Lockout.AllowedForNewUsers = await SettingProvider.GetAsync(IdentitySettingNames.Lockout.AllowedForNewUsers, options.Lockout.AllowedForNewUsers);
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromSeconds(await SettingProvider.GetAsync(IdentitySettingNames.Lockout.LockoutDuration, options.Lockout.DefaultLockoutTimeSpan.TotalSeconds.To<int>()));
options.Lockout.MaxFailedAccessAttempts = await SettingProvider.GetAsync(IdentitySettingNames.Lockout.MaxFailedAccessAttempts, options.Lockout.MaxFailedAccessAttempts);
options.SignIn.RequireConfirmedEmail = await SettingProvider.GetAsync(IdentitySettingNames.SignIn.RequireConfirmedEmail, options.SignIn.RequireConfirmedEmail);
options.SignIn.RequireConfirmedPhoneNumber = await SettingProvider.GetAsync(IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber, options.SignIn.RequireConfirmedPhoneNumber);
}
}

@ -30,7 +30,7 @@ namespace Volo.Abp.Identity
}
public string LocalizeMessage(LocalizationContext context)
public virtual string LocalizeMessage(LocalizationContext context)
{
return IdentityResult.LocalizeErrors(context.LocalizerFactory.Create<IdentityResource>());
}

@ -6,26 +6,26 @@ namespace Volo.Abp.Identity
//TODO: Rename to IdentityClaimTypeManager in v2.0!
public class IdenityClaimTypeManager : DomainService
{
private readonly IIdentityClaimTypeRepository _identityClaimTypeRepository;
protected IIdentityClaimTypeRepository IdentityClaimTypeRepository { get; }
public IdenityClaimTypeManager(IIdentityClaimTypeRepository identityClaimTypeRepository)
{
_identityClaimTypeRepository = identityClaimTypeRepository;
IdentityClaimTypeRepository = identityClaimTypeRepository;
}
public virtual async Task<IdentityClaimType> CreateAsync(IdentityClaimType claimType)
{
if (await _identityClaimTypeRepository.AnyAsync(claimType.Name))
if (await IdentityClaimTypeRepository.AnyAsync(claimType.Name))
{
throw new AbpException($"Name Exist: {claimType.Name}");
}
return await _identityClaimTypeRepository.InsertAsync(claimType);
return await IdentityClaimTypeRepository.InsertAsync(claimType);
}
public virtual async Task<IdentityClaimType> UpdateAsync(IdentityClaimType claimType)
{
if (await _identityClaimTypeRepository.AnyAsync(claimType.Name, claimType.Id))
if (await IdentityClaimTypeRepository.AnyAsync(claimType.Name, claimType.Id))
{
throw new AbpException($"Name Exist: {claimType.Name}");
}
@ -36,7 +36,7 @@ namespace Volo.Abp.Identity
}
return await _identityClaimTypeRepository.UpdateAsync(claimType);
return await IdentityClaimTypeRepository.UpdateAsync(claimType);
}
}
}

@ -6,16 +6,16 @@ namespace Volo.Abp.Identity
{
public class IdentityDataSeedContributor : IDataSeedContributor, ITransientDependency
{
private readonly IIdentityDataSeeder _identityDataSeeder;
protected IIdentityDataSeeder IdentityDataSeeder { get; }
public IdentityDataSeedContributor(IIdentityDataSeeder identityDataSeeder)
{
_identityDataSeeder = identityDataSeeder;
IdentityDataSeeder = identityDataSeeder;
}
public Task SeedAsync(DataSeedContext context)
public virtual Task SeedAsync(DataSeedContext context)
{
return _identityDataSeeder.SeedAsync(
return IdentityDataSeeder.SeedAsync(
context["AdminEmail"] as string ?? "admin@abp.io",
context["AdminPassword"] as string ?? "1q2w3E*",
context.TenantId

@ -9,12 +9,12 @@ namespace Volo.Abp.Identity
{
public class IdentityDataSeeder : ITransientDependency, IIdentityDataSeeder
{
private readonly IGuidGenerator _guidGenerator;
private readonly IIdentityRoleRepository _roleRepository;
private readonly IIdentityUserRepository _userRepository;
private readonly ILookupNormalizer _lookupNormalizer;
private readonly IdentityUserManager _userManager;
private readonly IdentityRoleManager _roleManager;
protected IGuidGenerator GuidGenerator { get; }
protected IIdentityRoleRepository RoleRepository { get; }
protected IIdentityUserRepository UserRepository { get; }
protected ILookupNormalizer LookupNormalizer { get; }
protected IdentityUserManager UserManager { get; }
protected IdentityRoleManager RoleManager { get; }
public IdentityDataSeeder(
IGuidGenerator guidGenerator,
@ -24,12 +24,12 @@ namespace Volo.Abp.Identity
IdentityUserManager userManager,
IdentityRoleManager roleManager)
{
_guidGenerator = guidGenerator;
_roleRepository = roleRepository;
_userRepository = userRepository;
_lookupNormalizer = lookupNormalizer;
_userManager = userManager;
_roleManager = roleManager;
GuidGenerator = guidGenerator;
RoleRepository = roleRepository;
UserRepository = userRepository;
LookupNormalizer = lookupNormalizer;
UserManager = userManager;
RoleManager = roleManager;
}
[UnitOfWork]
@ -45,8 +45,8 @@ namespace Volo.Abp.Identity
//"admin" user
const string adminUserName = "admin";
var adminUser = await _userRepository.FindByNormalizedUserNameAsync(
_lookupNormalizer.NormalizeName(adminUserName)
var adminUser = await UserRepository.FindByNormalizedUserNameAsync(
LookupNormalizer.NormalizeName(adminUserName)
);
if (adminUser != null)
@ -55,7 +55,7 @@ namespace Volo.Abp.Identity
}
adminUser = new IdentityUser(
_guidGenerator.Create(),
GuidGenerator.Create(),
adminUserName,
adminEmail,
tenantId
@ -64,16 +64,16 @@ namespace Volo.Abp.Identity
Name = adminUserName
};
(await _userManager.CreateAsync(adminUser, adminPassword)).CheckErrors();
(await UserManager.CreateAsync(adminUser, adminPassword)).CheckErrors();
result.CreatedAdminUser = true;
//"admin" role
const string adminRoleName = "admin";
var adminRole = await _roleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName(adminRoleName));
var adminRole = await RoleRepository.FindByNormalizedNameAsync(LookupNormalizer.NormalizeName(adminRoleName));
if (adminRole == null)
{
adminRole = new IdentityRole(
_guidGenerator.Create(),
GuidGenerator.Create(),
adminRoleName,
tenantId
)
@ -82,11 +82,11 @@ namespace Volo.Abp.Identity
IsPublic = true
};
(await _roleManager.CreateAsync(adminRole)).CheckErrors();
(await RoleManager.CreateAsync(adminRole)).CheckErrors();
result.CreatedAdminRole = true;
}
(await _userManager.AddToRoleAsync(adminUser, adminRoleName)).CheckErrors();
(await UserManager.AddToRoleAsync(adminUser, adminRoleName)).CheckErrors();
return result;
}

@ -15,10 +15,10 @@ namespace Volo.Abp.Identity
{
public class IdentityRoleManager : RoleManager<IdentityRole>, IDomainService
{
protected override CancellationToken CancellationToken => _cancellationTokenProvider.Token;
protected override CancellationToken CancellationToken => CancellationTokenProvider.Token;
private readonly IStringLocalizer<IdentityResource> _localizer;
private readonly ICancellationTokenProvider _cancellationTokenProvider;
protected IStringLocalizer<IdentityResource> Localizer { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
public IdentityRoleManager(
IdentityRoleStore store,
@ -35,8 +35,8 @@ namespace Volo.Abp.Identity
errors,
logger)
{
_localizer = localizer;
_cancellationTokenProvider = cancellationTokenProvider;
Localizer = localizer;
CancellationTokenProvider = cancellationTokenProvider;
}
public virtual async Task<IdentityRole> GetByIdAsync(Guid id)
@ -54,7 +54,7 @@ namespace Volo.Abp.Identity
{
if (role.IsStatic && role.Name != name)
{
throw new BusinessException(_localizer["Identity.StaticRoleRenamingErrorMessage"]); // TODO: localize & change exception type
throw new BusinessException(Localizer["Identity.StaticRoleRenamingErrorMessage"]); // TODO: localize & change exception type
}
return await base.SetRoleNameAsync(role, name);
@ -64,7 +64,7 @@ namespace Volo.Abp.Identity
{
if (role.IsStatic)
{
throw new BusinessException(_localizer["Identity.StaticRoleDeletionErrorMessage"]); // TODO: localize & change exception type
throw new BusinessException(Localizer["Identity.StaticRoleDeletionErrorMessage"]); // TODO: localize & change exception type
}
return await base.DeleteAsync(role);

@ -22,9 +22,9 @@ namespace Volo.Abp.Identity
IRoleClaimStore<IdentityRole>,
ITransientDependency
{
private readonly IIdentityRoleRepository _roleRepository;
private readonly ILogger<IdentityRoleStore> _logger;
private readonly IGuidGenerator _guidGenerator;
protected IIdentityRoleRepository RoleRepository { get; }
protected ILogger<IdentityRoleStore> Logger { get; }
protected IGuidGenerator GuidGenerator { get; }
/// <summary>
/// Constructs a new instance of <see cref="IdentityRoleStore"/>.
@ -35,9 +35,9 @@ namespace Volo.Abp.Identity
IGuidGenerator guidGenerator,
IdentityErrorDescriber describer = null)
{
_roleRepository = roleRepository;
_logger = logger;
_guidGenerator = guidGenerator;
RoleRepository = roleRepository;
Logger = logger;
GuidGenerator = guidGenerator;
ErrorDescriber = describer ?? new IdentityErrorDescriber();
}
@ -67,7 +67,7 @@ namespace Volo.Abp.Identity
Check.NotNull(role, nameof(role));
await _roleRepository.InsertAsync(role, AutoSaveChanges, cancellationToken);
await RoleRepository.InsertAsync(role, AutoSaveChanges, cancellationToken);
return IdentityResult.Success;
}
@ -86,11 +86,11 @@ namespace Volo.Abp.Identity
try
{
await _roleRepository.UpdateAsync(role, AutoSaveChanges, cancellationToken);
await RoleRepository.UpdateAsync(role, AutoSaveChanges, cancellationToken);
}
catch (AbpDbConcurrencyException ex)
{
_logger.LogWarning(ex.ToString()); //Trigger some AbpHandledException event
Logger.LogWarning(ex.ToString()); //Trigger some AbpHandledException event
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
}
@ -111,11 +111,11 @@ namespace Volo.Abp.Identity
try
{
await _roleRepository.DeleteAsync(role, AutoSaveChanges, cancellationToken);
await RoleRepository.DeleteAsync(role, AutoSaveChanges, cancellationToken);
}
catch (AbpDbConcurrencyException ex)
{
_logger.LogWarning(ex.ToString()); //Trigger some AbpHandledException event
Logger.LogWarning(ex.ToString()); //Trigger some AbpHandledException event
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
}
@ -128,7 +128,7 @@ namespace Volo.Abp.Identity
/// <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)
public virtual Task<string> GetRoleIdAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
@ -143,7 +143,7 @@ namespace Volo.Abp.Identity
/// <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)
public virtual Task<string> GetRoleNameAsync([NotNull] IdentityRole role, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
@ -159,7 +159,7 @@ namespace Volo.Abp.Identity
/// <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)
public virtual Task SetRoleNameAsync([NotNull] IdentityRole role, string roleName, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
@ -179,7 +179,7 @@ namespace Volo.Abp.Identity
{
cancellationToken.ThrowIfCancellationRequested();
return _roleRepository.FindAsync(Guid.Parse(id), cancellationToken: cancellationToken);
return RoleRepository.FindAsync(Guid.Parse(id), cancellationToken: cancellationToken);
}
/// <summary>
@ -194,7 +194,7 @@ namespace Volo.Abp.Identity
Check.NotNull(normalizedName, nameof(normalizedName));
return _roleRepository.FindByNormalizedNameAsync(normalizedName, cancellationToken: cancellationToken);
return RoleRepository.FindByNormalizedNameAsync(normalizedName, cancellationToken: cancellationToken);
}
/// <summary>
@ -233,7 +233,7 @@ namespace Volo.Abp.Identity
/// <summary>
/// Dispose the stores
/// </summary>
public void Dispose()
public virtual void Dispose()
{
}
@ -243,13 +243,13 @@ namespace Volo.Abp.Identity
/// <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)
public virtual 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);
await RoleRepository.EnsureCollectionLoadedAsync(role, r => r.Claims, cancellationToken);
return role.Claims.Select(c => c.ToClaim()).ToList();
}
@ -261,16 +261,16 @@ namespace Volo.Abp.Identity
/// <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)
public virtual 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);
await RoleRepository.EnsureCollectionLoadedAsync(role, r => r.Claims, cancellationToken);
role.AddClaim(_guidGenerator, claim);
role.AddClaim(GuidGenerator, claim);
}
/// <summary>
@ -280,12 +280,12 @@ namespace Volo.Abp.Identity
/// <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)
public virtual 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);
await RoleRepository.EnsureCollectionLoadedAsync(role, r => r.Claims, cancellationToken);
role.RemoveClaim(claim);
}

@ -68,7 +68,7 @@ namespace Volo.Abp.Identity
{
}
public UserLoginInfo ToUserLoginInfo()
public virtual UserLoginInfo ToUserLoginInfo()
{
return new UserLoginInfo(LoginProvider, ProviderKey, ProviderDisplayName);
}

@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Services;
using Volo.Abp.Threading;
@ -15,12 +16,17 @@ namespace Volo.Abp.Identity
{
public class IdentityUserManager : UserManager<IdentityUser>, IDomainService
{
protected override CancellationToken CancellationToken => _cancellationTokenProvider.Token;
protected IIdentityRoleRepository RoleRepository { get; }
protected IIdentityUserRepository UserRepository { get; }
private readonly ICancellationTokenProvider _cancellationTokenProvider;
protected override CancellationToken CancellationToken => CancellationTokenProvider.Token;
protected ICancellationTokenProvider CancellationTokenProvider { get; }
public IdentityUserManager(
IdentityUserStore store,
IIdentityRoleRepository roleRepository,
IIdentityUserRepository userRepository,
IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<IdentityUser> passwordHasher,
IEnumerable<IUserValidator<IdentityUser>> userValidators,
@ -41,7 +47,9 @@ namespace Volo.Abp.Identity
services,
logger)
{
_cancellationTokenProvider = cancellationTokenProvider;
RoleRepository = roleRepository;
UserRepository = userRepository;
CancellationTokenProvider = cancellationTokenProvider;
}
public virtual async Task<IdentityUser> GetByIdAsync(Guid id)
@ -76,5 +84,20 @@ namespace Volo.Abp.Identity
return IdentityResult.Success;
}
public virtual async Task<IdentityResult> AddDefaultRolesAsync([NotNull] IdentityUser user)
{
await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Roles, CancellationToken);
foreach (var role in await RoleRepository.GetDefaultOnesAsync(cancellationToken: CancellationToken))
{
if (!user.IsInRole(role.Id))
{
user.AddRole(role.Id);
}
}
return await UpdateUserAsync(user);
}
}
}

@ -9,15 +9,15 @@ namespace Volo.Abp.Identity
{
public class IdentityUserRepositoryExternalUserLookupServiceProvider : IExternalUserLookupServiceProvider, ITransientDependency
{
private readonly IIdentityUserRepository _userRepository;
private readonly ILookupNormalizer _lookupNormalizer;
protected IIdentityUserRepository UserRepository { get; }
protected ILookupNormalizer LookupNormalizer { get; }
public IdentityUserRepositoryExternalUserLookupServiceProvider(
IIdentityUserRepository userRepository,
ILookupNormalizer lookupNormalizer)
{
_userRepository = userRepository;
_lookupNormalizer = lookupNormalizer;
UserRepository = userRepository;
LookupNormalizer = lookupNormalizer;
}
public virtual async Task<IUserData> FindByIdAsync(
@ -25,12 +25,12 @@ namespace Volo.Abp.Identity
CancellationToken cancellationToken = default)
{
return (
await _userRepository.FindAsync(
id,
includeDetails: false,
cancellationToken: cancellationToken
)
)?.ToAbpUserData();
await UserRepository.FindAsync(
id,
includeDetails: false,
cancellationToken: cancellationToken
)
)?.ToAbpUserData();
}
public virtual async Task<IUserData> FindByUserNameAsync(
@ -38,12 +38,12 @@ namespace Volo.Abp.Identity
CancellationToken cancellationToken = default)
{
return (
await _userRepository.FindByNormalizedUserNameAsync(
_lookupNormalizer.NormalizeName(userName),
includeDetails: false,
cancellationToken: cancellationToken
)
)?.ToAbpUserData();
await UserRepository.FindByNormalizedUserNameAsync(
LookupNormalizer.NormalizeName(userName),
includeDetails: false,
cancellationToken: cancellationToken
)
)?.ToAbpUserData();
}
}
}

@ -50,10 +50,10 @@ namespace Volo.Abp.Identity
/// </value>
public bool AutoSaveChanges { get; set; } = true;
private readonly IIdentityRoleRepository _roleRepository;
private readonly IGuidGenerator _guidGenerator;
private readonly ILogger<IdentityRoleStore> _logger;
private readonly IIdentityUserRepository _userRepository;
protected IIdentityRoleRepository RoleRepository { get; }
protected IGuidGenerator GuidGenerator { get; }
protected ILogger<IdentityRoleStore> Logger { get; }
protected IIdentityUserRepository UserRepository { get; }
public IdentityUserStore(
IIdentityUserRepository userRepository,
@ -62,10 +62,10 @@ namespace Volo.Abp.Identity
ILogger<IdentityRoleStore> logger,
IdentityErrorDescriber describer = null)
{
_userRepository = userRepository;
_roleRepository = roleRepository;
_guidGenerator = guidGenerator;
_logger = logger;
UserRepository = userRepository;
RoleRepository = roleRepository;
GuidGenerator = guidGenerator;
Logger = logger;
ErrorDescriber = describer ?? new IdentityErrorDescriber();
}
@ -163,7 +163,7 @@ namespace Volo.Abp.Identity
Check.NotNull(user, nameof(user));
await _userRepository.InsertAsync(user, AutoSaveChanges, cancellationToken);
await UserRepository.InsertAsync(user, AutoSaveChanges, cancellationToken);
return IdentityResult.Success;
}
@ -182,11 +182,11 @@ namespace Volo.Abp.Identity
try
{
await _userRepository.UpdateAsync(user, AutoSaveChanges, cancellationToken);
await UserRepository.UpdateAsync(user, AutoSaveChanges, cancellationToken);
}
catch (AbpDbConcurrencyException ex)
{
_logger.LogWarning(ex.ToString()); //Trigger some AbpHandledException event
Logger.LogWarning(ex.ToString()); //Trigger some AbpHandledException event
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
}
@ -207,11 +207,11 @@ namespace Volo.Abp.Identity
try
{
await _userRepository.DeleteAsync(user, AutoSaveChanges, cancellationToken);
await UserRepository.DeleteAsync(user, AutoSaveChanges, cancellationToken);
}
catch (AbpDbConcurrencyException ex)
{
_logger.LogWarning(ex.ToString()); //Trigger some AbpHandledException event
Logger.LogWarning(ex.ToString()); //Trigger some AbpHandledException event
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
}
@ -230,7 +230,7 @@ namespace Volo.Abp.Identity
{
cancellationToken.ThrowIfCancellationRequested();
return _userRepository.FindAsync(Guid.Parse(userId), cancellationToken: cancellationToken);
return UserRepository.FindAsync(Guid.Parse(userId), cancellationToken: cancellationToken);
}
/// <summary>
@ -247,7 +247,7 @@ namespace Volo.Abp.Identity
Check.NotNull(normalizedUserName, nameof(normalizedUserName));
return _userRepository.FindByNormalizedUserNameAsync(normalizedUserName, includeDetails: false, cancellationToken: cancellationToken);
return UserRepository.FindByNormalizedUserNameAsync(normalizedUserName, includeDetails: false, cancellationToken: cancellationToken);
}
/// <summary>
@ -313,14 +313,14 @@ namespace Volo.Abp.Identity
Check.NotNull(user, nameof(user));
Check.NotNull(normalizedRoleName, nameof(normalizedRoleName));
var role = await _roleRepository.FindByNormalizedNameAsync(normalizedRoleName, cancellationToken: cancellationToken);
var role = await RoleRepository.FindByNormalizedNameAsync(normalizedRoleName, cancellationToken: cancellationToken);
if (role == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Role {0} does not exist!", normalizedRoleName));
}
await _userRepository.EnsureCollectionLoadedAsync(user, u => u.Roles, cancellationToken);
await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Roles, cancellationToken);
user.AddRole(role.Id);
}
@ -343,13 +343,13 @@ namespace Volo.Abp.Identity
throw new ArgumentException(nameof(normalizedRoleName) + " can not be null or whitespace");
}
var role = await _roleRepository.FindByNormalizedNameAsync(normalizedRoleName, cancellationToken: cancellationToken);
var role = await RoleRepository.FindByNormalizedNameAsync(normalizedRoleName, cancellationToken: cancellationToken);
if (role == null)
{
return;
}
await _userRepository.EnsureCollectionLoadedAsync(user, u => u.Roles, cancellationToken);
await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Roles, cancellationToken);
user.RemoveRole(role.Id);
}
@ -366,7 +366,7 @@ namespace Volo.Abp.Identity
Check.NotNull(user, nameof(user));
return await _userRepository.GetRoleNamesAsync(user.Id, cancellationToken: cancellationToken);
return await UserRepository.GetRoleNamesAsync(user.Id, cancellationToken: cancellationToken);
}
/// <summary>
@ -388,13 +388,13 @@ namespace Volo.Abp.Identity
throw new ArgumentException(nameof(normalizedRoleName) + " can not be null or whitespace");
}
var role = await _roleRepository.FindByNormalizedNameAsync(normalizedRoleName, cancellationToken: cancellationToken);
var role = await RoleRepository.FindByNormalizedNameAsync(normalizedRoleName, cancellationToken: cancellationToken);
if (role == null)
{
return false;
}
await _userRepository.EnsureCollectionLoadedAsync(user, u => u.Roles, cancellationToken);
await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Roles, cancellationToken);
return user.IsInRole(role.Id);
}
@ -411,7 +411,7 @@ namespace Volo.Abp.Identity
Check.NotNull(user, nameof(user));
await _userRepository.EnsureCollectionLoadedAsync(user, u => u.Claims, cancellationToken);
await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Claims, cancellationToken);
return user.Claims.Select(c => c.ToClaim()).ToList();
}
@ -430,9 +430,9 @@ namespace Volo.Abp.Identity
Check.NotNull(user, nameof(user));
Check.NotNull(claims, nameof(claims));
await _userRepository.EnsureCollectionLoadedAsync(user, u => u.Claims, cancellationToken);
await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Claims, cancellationToken);
user.AddClaims(_guidGenerator, claims);
user.AddClaims(GuidGenerator, claims);
}
/// <summary>
@ -451,7 +451,7 @@ namespace Volo.Abp.Identity
Check.NotNull(claim, nameof(claim));
Check.NotNull(newClaim, nameof(newClaim));
await _userRepository.EnsureCollectionLoadedAsync(user, u => u.Claims, cancellationToken);
await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Claims, cancellationToken);
user.ReplaceClaim(claim, newClaim);
}
@ -470,7 +470,7 @@ namespace Volo.Abp.Identity
Check.NotNull(user, nameof(user));
Check.NotNull(claims, nameof(claims));
await _userRepository.EnsureCollectionLoadedAsync(user, u => u.Claims, cancellationToken);
await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Claims, cancellationToken);
user.RemoveClaims(claims);
}
@ -489,7 +489,7 @@ namespace Volo.Abp.Identity
Check.NotNull(user, nameof(user));
Check.NotNull(login, nameof(login));
await _userRepository.EnsureCollectionLoadedAsync(user, u => u.Logins, cancellationToken);
await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Logins, cancellationToken);
user.AddLogin(login);
}
@ -510,7 +510,7 @@ namespace Volo.Abp.Identity
Check.NotNull(loginProvider, nameof(loginProvider));
Check.NotNull(providerKey, nameof(providerKey));
await _userRepository.EnsureCollectionLoadedAsync(user, u => u.Logins, cancellationToken);
await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Logins, cancellationToken);
user.RemoveLogin(loginProvider, providerKey);
}
@ -529,7 +529,7 @@ namespace Volo.Abp.Identity
Check.NotNull(user, nameof(user));
await _userRepository.EnsureCollectionLoadedAsync(user, u => u.Logins, cancellationToken);
await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Logins, cancellationToken);
return user.Logins.Select(l => l.ToUserLoginInfo()).ToList();
}
@ -550,7 +550,7 @@ namespace Volo.Abp.Identity
Check.NotNull(loginProvider, nameof(loginProvider));
Check.NotNull(providerKey, nameof(providerKey));
return _userRepository.FindByLoginAsync(loginProvider, providerKey, cancellationToken: cancellationToken);
return UserRepository.FindByLoginAsync(loginProvider, providerKey, cancellationToken: cancellationToken);
}
/// <summary>
@ -671,7 +671,7 @@ namespace Volo.Abp.Identity
{
cancellationToken.ThrowIfCancellationRequested();
return _userRepository.FindByNormalizedEmailAsync(normalizedEmail, includeDetails: false, cancellationToken: cancellationToken);
return UserRepository.FindByNormalizedEmailAsync(normalizedEmail, includeDetails: false, cancellationToken: cancellationToken);
}
/// <summary>
@ -950,7 +950,7 @@ namespace Volo.Abp.Identity
Check.NotNull(claim, nameof(claim));
return await _userRepository.GetListByClaimAsync(claim, cancellationToken: cancellationToken);
return await UserRepository.GetListByClaimAsync(claim, cancellationToken: cancellationToken);
}
/// <summary>
@ -970,7 +970,7 @@ namespace Volo.Abp.Identity
throw new ArgumentNullException(nameof(normalizedRoleName));
}
return await _userRepository.GetListByNormalizedRoleNameAsync(normalizedRoleName, cancellationToken: cancellationToken);
return await UserRepository.GetListByNormalizedRoleNameAsync(normalizedRoleName, cancellationToken: cancellationToken);
}
/// <summary>
@ -988,7 +988,7 @@ namespace Volo.Abp.Identity
Check.NotNull(user, nameof(user));
await _userRepository.EnsureCollectionLoadedAsync(user, u => u.Tokens, cancellationToken);
await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Tokens, cancellationToken);
user.SetToken(loginProvider, name, value);
}
@ -1001,13 +1001,13 @@ namespace Volo.Abp.Identity
/// <param name="name">The name of the token.</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 RemoveTokenAsync(IdentityUser user, string loginProvider, string name, CancellationToken cancellationToken = default)
public virtual async Task RemoveTokenAsync(IdentityUser user, string loginProvider, string name, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Check.NotNull(user, nameof(user));
await _userRepository.EnsureCollectionLoadedAsync(user, u => u.Tokens, cancellationToken);
await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Tokens, cancellationToken);
user.RemoveToken(loginProvider, name);
}
@ -1020,23 +1020,23 @@ namespace Volo.Abp.Identity
/// <param name="name">The name of the token.</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<string> GetTokenAsync(IdentityUser user, string loginProvider, string name, CancellationToken cancellationToken = default)
public virtual async Task<string> GetTokenAsync(IdentityUser user, string loginProvider, string name, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Check.NotNull(user, nameof(user));
await _userRepository.EnsureCollectionLoadedAsync(user, u => u.Tokens, cancellationToken);
await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Tokens, cancellationToken);
return user.FindToken(loginProvider, name)?.Value;
}
public Task SetAuthenticatorKeyAsync(IdentityUser user, string key, CancellationToken cancellationToken = default)
public virtual Task SetAuthenticatorKeyAsync(IdentityUser user, string key, CancellationToken cancellationToken = default)
{
return SetTokenAsync(user, InternalLoginProvider, AuthenticatorKeyTokenName, key, cancellationToken);
}
public Task<string> GetAuthenticatorKeyAsync(IdentityUser user, CancellationToken cancellationToken = default)
public virtual Task<string> GetAuthenticatorKeyAsync(IdentityUser user, CancellationToken cancellationToken = default)
{
return GetTokenAsync(user, InternalLoginProvider, AuthenticatorKeyTokenName, cancellationToken);
}
@ -1101,7 +1101,7 @@ namespace Volo.Abp.Identity
return false;
}
public void Dispose()
public virtual void Dispose()
{
}

@ -6,16 +6,16 @@ namespace Volo.Abp.Identity
{
public class UserRoleFinder : IUserRoleFinder, ITransientDependency
{
private readonly IIdentityUserRepository _identityUserRepository;
protected IIdentityUserRepository IdentityUserRepository { get; }
public UserRoleFinder(IIdentityUserRepository identityUserRepository)
{
_identityUserRepository = identityUserRepository;
IdentityUserRepository = identityUserRepository;
}
public virtual async Task<string[]> GetRolesAsync(Guid userId)
{
return (await _identityUserRepository.GetRoleNamesAsync(userId)).ToArray();
return (await IdentityUserRepository.GetRoleNamesAsync(userId)).ToArray();
}
}
}

@ -17,14 +17,14 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
}
public async Task<bool> AnyAsync(string name, Guid? ignoredId = null)
public virtual async Task<bool> AnyAsync(string name, Guid? ignoredId = null)
{
return await DbSet
.WhereIf(ignoredId != null, ct => ct.Id != ignoredId)
.CountAsync(ct => ct.Name == name) > 0;
}
public async Task<List<IdentityClaimType>> GetListAsync(string sorting, int maxResultCount, int skipCount, string filter)
public virtual async Task<List<IdentityClaimType>> GetListAsync(string sorting, int maxResultCount, int skipCount, string filter)
{
var identityClaimTypes = await DbSet
.WhereIf(

@ -9,21 +9,21 @@ namespace Volo.Abp.Identity
[Dependency(TryRegister = true)]
public class HttpClientExternalUserLookupServiceProvider : IExternalUserLookupServiceProvider, ITransientDependency
{
private readonly IIdentityUserLookupAppService _userLookupAppService;
protected IIdentityUserLookupAppService UserLookupAppService { get; }
public HttpClientExternalUserLookupServiceProvider(IIdentityUserLookupAppService userLookupAppService)
{
_userLookupAppService = userLookupAppService;
UserLookupAppService = userLookupAppService;
}
public async Task<IUserData> FindByIdAsync(Guid id, CancellationToken cancellationToken = default)
public virtual async Task<IUserData> FindByIdAsync(Guid id, CancellationToken cancellationToken = default)
{
return await _userLookupAppService.FindByIdAsync(id);
return await UserLookupAppService.FindByIdAsync(id);
}
public async Task<IUserData> FindByUserNameAsync(string userName, CancellationToken cancellationToken = default)
public virtual async Task<IUserData> FindByUserNameAsync(string userName, CancellationToken cancellationToken = default)
{
return await _userLookupAppService.FindByUserNameAsync(userName);
return await UserLookupAppService.FindByUserNameAsync(userName);
}
}
}

@ -8,14 +8,14 @@ namespace Volo.Abp.Identity
[Dependency(TryRegister = true)]
public class HttpClientUserRoleFinder : IUserRoleFinder, ITransientDependency
{
private readonly IIdentityUserAppService _userAppService;
protected IIdentityUserAppService _userAppService { get; }
public HttpClientUserRoleFinder(IIdentityUserAppService userAppService)
{
_userAppService = userAppService;
}
public async Task<string[]> GetRolesAsync(Guid userId)
public virtual async Task<string[]> GetRolesAsync(Guid userId)
{
var output = await _userAppService.GetRolesAsync(userId);
return output.Items.Select(r => r.Name).ToArray();

@ -13,51 +13,51 @@ namespace Volo.Abp.Identity
[Route("api/identity/roles")]
public class IdentityRoleController : AbpController, IIdentityRoleAppService
{
private readonly IIdentityRoleAppService _roleAppService;
protected IIdentityRoleAppService RoleAppService { get; }
public IdentityRoleController(IIdentityRoleAppService roleAppService)
{
_roleAppService = roleAppService;
RoleAppService = roleAppService;
}
[HttpGet]
[Route("all")]
public virtual Task<ListResultDto<IdentityRoleDto>> GetAllListAsync()
{
return _roleAppService.GetAllListAsync();
return RoleAppService.GetAllListAsync();
}
[HttpGet]
public virtual Task<PagedResultDto<IdentityRoleDto>> GetListAsync(PagedAndSortedResultRequestDto input)
{
return _roleAppService.GetListAsync(input);
return RoleAppService.GetListAsync(input);
}
[HttpGet]
[Route("{id}")]
public virtual Task<IdentityRoleDto> GetAsync(Guid id)
{
return _roleAppService.GetAsync(id);
return RoleAppService.GetAsync(id);
}
[HttpPost]
public virtual Task<IdentityRoleDto> CreateAsync(IdentityRoleCreateDto input)
{
return _roleAppService.CreateAsync(input);
return RoleAppService.CreateAsync(input);
}
[HttpPut]
[Route("{id}")]
public virtual Task<IdentityRoleDto> UpdateAsync(Guid id, IdentityRoleUpdateDto input)
{
return _roleAppService.UpdateAsync(id, input);
return RoleAppService.UpdateAsync(id, input);
}
[HttpDelete]
[Route("{id}")]
public virtual Task DeleteAsync(Guid id)
{
return _roleAppService.DeleteAsync(id);
return RoleAppService.DeleteAsync(id);
}
}
}

@ -12,72 +12,72 @@ namespace Volo.Abp.Identity
[Route("api/identity/users")]
public class IdentityUserController : AbpController, IIdentityUserAppService
{
private readonly IIdentityUserAppService _userAppService;
protected IIdentityUserAppService UserAppService { get; }
public IdentityUserController(IIdentityUserAppService userAppService)
{
_userAppService = userAppService;
UserAppService = userAppService;
}
[HttpGet]
[Route("{id}")]
public virtual Task<IdentityUserDto> GetAsync(Guid id)
{
return _userAppService.GetAsync(id);
return UserAppService.GetAsync(id);
}
[HttpGet]
public virtual Task<PagedResultDto<IdentityUserDto>> GetListAsync(GetIdentityUsersInput input)
{
return _userAppService.GetListAsync(input);
return UserAppService.GetListAsync(input);
}
[HttpPost]
public virtual Task<IdentityUserDto> CreateAsync(IdentityUserCreateDto input)
{
return _userAppService.CreateAsync(input);
return UserAppService.CreateAsync(input);
}
[HttpPut]
[Route("{id}")]
public virtual Task<IdentityUserDto> UpdateAsync(Guid id, IdentityUserUpdateDto input)
{
return _userAppService.UpdateAsync(id, input);
return UserAppService.UpdateAsync(id, input);
}
[HttpDelete]
[Route("{id}")]
public virtual Task DeleteAsync(Guid id)
{
return _userAppService.DeleteAsync(id);
return UserAppService.DeleteAsync(id);
}
[HttpGet]
[Route("{id}/roles")]
public virtual Task<ListResultDto<IdentityRoleDto>> GetRolesAsync(Guid id)
{
return _userAppService.GetRolesAsync(id);
return UserAppService.GetRolesAsync(id);
}
[HttpPut]
[Route("{id}/roles")]
public virtual Task UpdateRolesAsync(Guid id, IdentityUserUpdateRolesDto input)
{
return _userAppService.UpdateRolesAsync(id, input);
return UserAppService.UpdateRolesAsync(id, input);
}
[HttpGet]
[Route("by-username/{userName}")]
public virtual Task<IdentityUserDto> FindByUsernameAsync(string username)
{
return _userAppService.FindByUsernameAsync(username);
return UserAppService.FindByUsernameAsync(username);
}
[HttpGet]
[Route("by-email/{email}")]
public virtual Task<IdentityUserDto> FindByEmailAsync(string email)
{
return _userAppService.FindByEmailAsync(email);
return UserAppService.FindByEmailAsync(email);
}
}
}

@ -21,14 +21,14 @@ namespace Volo.Abp.Identity
[HttpGet]
[Route("{id}")]
public Task<UserData> FindByIdAsync(Guid id)
public virtual Task<UserData> FindByIdAsync(Guid id)
{
return LookupAppService.FindByIdAsync(id);
}
[HttpGet]
[Route("by-username/{userName}")]
public Task<UserData> FindByUserNameAsync(string userName)
public virtual Task<UserData> FindByUserNameAsync(string userName)
{
return LookupAppService.FindByUserNameAsync(userName);
}

@ -10,30 +10,30 @@ namespace Volo.Abp.Identity
[Route("/api/identity/my-profile")]
public class ProfileController : AbpController, IProfileAppService
{
private readonly IProfileAppService _profileAppService;
protected IProfileAppService ProfileAppService { get; }
public ProfileController(IProfileAppService profileAppService)
{
_profileAppService = profileAppService;
ProfileAppService = profileAppService;
}
[HttpGet]
public Task<ProfileDto> GetAsync()
public virtual Task<ProfileDto> GetAsync()
{
return _profileAppService.GetAsync();
return ProfileAppService.GetAsync();
}
[HttpPut]
public Task<ProfileDto> UpdateAsync(UpdateProfileDto input)
public virtual Task<ProfileDto> UpdateAsync(UpdateProfileDto input)
{
return _profileAppService.UpdateAsync(input);
return ProfileAppService.UpdateAsync(input);
}
[HttpPost]
[Route("change-password")]
public Task ChangePasswordAsync(ChangePasswordInput input)
public virtual Task ChangePasswordAsync(ChangePasswordInput input)
{
return _profileAppService.ChangePasswordAsync(input);
return ProfileAppService.ChangePasswordAsync(input);
}
}
}

@ -16,7 +16,7 @@ namespace Volo.Abp.Identity.MongoDB
{
}
public async Task<bool> AnyAsync(string name, Guid? ignoredId = null)
public virtual async Task<bool> AnyAsync(string name, Guid? ignoredId = null)
{
if (ignoredId == null)
{
@ -32,7 +32,7 @@ namespace Volo.Abp.Identity.MongoDB
}
}
public async Task<List<IdentityClaimType>> GetListAsync(string sorting, int maxResultCount, int skipCount, string filter)
public virtual async Task<List<IdentityClaimType>> GetListAsync(string sorting, int maxResultCount, int skipCount, string filter)
{
return await GetMongoQueryable()
.WhereIf<IdentityClaimType, IMongoQueryable<IdentityClaimType>>(

@ -14,12 +14,9 @@ namespace Volo.Abp.Identity.MongoDB
{
public class MongoIdentityRoleRepository : MongoDbRepository<IAbpIdentityMongoDbContext, IdentityRole, Guid>, IIdentityRoleRepository
{
private readonly IGuidGenerator _guidGenerator;
public MongoIdentityRoleRepository(IMongoDbContextProvider<IAbpIdentityMongoDbContext> dbContextProvider, IGuidGenerator guidGenerator)
public MongoIdentityRoleRepository(IMongoDbContextProvider<IAbpIdentityMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
_guidGenerator = guidGenerator;
}
public async Task<IdentityRole> FindByNormalizedNameAsync(

@ -15,15 +15,12 @@ namespace Volo.Abp.Identity.MongoDB
{
public class MongoIdentityUserRepository : MongoDbRepository<IAbpIdentityMongoDbContext, IdentityUser, Guid>, IIdentityUserRepository
{
private readonly IGuidGenerator _guidGenerator;
public MongoIdentityUserRepository(IMongoDbContextProvider<IAbpIdentityMongoDbContext> dbContextProvider, IGuidGenerator guidGenerator)
public MongoIdentityUserRepository(IMongoDbContextProvider<IAbpIdentityMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
_guidGenerator = guidGenerator;
}
public async Task<IdentityUser> FindByNormalizedUserNameAsync(
public virtual async Task<IdentityUser> FindByNormalizedUserNameAsync(
string normalizedUserName,
bool includeDetails = true,
CancellationToken cancellationToken = default)
@ -35,7 +32,7 @@ namespace Volo.Abp.Identity.MongoDB
);
}
public async Task<List<string>> GetRoleNamesAsync(
public virtual async Task<List<string>> GetRoleNamesAsync(
Guid id,
CancellationToken cancellationToken = default)
{
@ -44,7 +41,7 @@ namespace Volo.Abp.Identity.MongoDB
return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).Select(r => r.Name).ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<IdentityUser> FindByLoginAsync(
public virtual async Task<IdentityUser> FindByLoginAsync(
string loginProvider,
string providerKey,
bool includeDetails = true,
@ -55,7 +52,7 @@ namespace Volo.Abp.Identity.MongoDB
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
public async Task<IdentityUser> FindByNormalizedEmailAsync(
public virtual async Task<IdentityUser> FindByNormalizedEmailAsync(
string normalizedEmail,
bool includeDetails = true,
CancellationToken cancellationToken = default)
@ -63,7 +60,7 @@ namespace Volo.Abp.Identity.MongoDB
return await GetMongoQueryable().FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail, GetCancellationToken(cancellationToken));
}
public async Task<List<IdentityUser>> GetListByClaimAsync(
public virtual async Task<List<IdentityUser>> GetListByClaimAsync(
Claim claim,
bool includeDetails = false,
CancellationToken cancellationToken = default)
@ -73,7 +70,7 @@ namespace Volo.Abp.Identity.MongoDB
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<List<IdentityUser>> GetListByNormalizedRoleNameAsync(
public virtual async Task<List<IdentityUser>> GetListByNormalizedRoleNameAsync(
string normalizedRoleName,
bool includeDetails = false,
CancellationToken cancellationToken = default)
@ -90,7 +87,7 @@ namespace Volo.Abp.Identity.MongoDB
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<List<IdentityUser>> GetListAsync(
public virtual async Task<List<IdentityUser>> GetListAsync(
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
@ -111,7 +108,7 @@ namespace Volo.Abp.Identity.MongoDB
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<List<IdentityRole>> GetRolesAsync(
public virtual async Task<List<IdentityRole>> GetRolesAsync(
Guid id,
bool includeDetails = false,
CancellationToken cancellationToken = default)
@ -121,7 +118,7 @@ namespace Volo.Abp.Identity.MongoDB
return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<long> GetCountAsync(
public virtual async Task<long> GetCountAsync(
string filter = null,
CancellationToken cancellationToken = default)
{

@ -14,7 +14,7 @@ namespace Volo.Abp.Identity.Web
CreateRoleMappings();
}
private void CreateUserMappings()
protected virtual void CreateUserMappings()
{
//List
CreateMap<IdentityUserDto, EditUserModalModel.UserInfoViewModel>()
@ -35,7 +35,7 @@ namespace Volo.Abp.Identity.Web
.ForMember(dest => dest.IsAssigned, opt => opt.Ignore());
}
private void CreateRoleMappings()
protected virtual void CreateRoleMappings()
{
//List
CreateMap<IdentityRoleDto, EditModalModel.RoleInfoModel>();

@ -9,7 +9,7 @@ namespace Volo.Abp.Identity.Web.Navigation
{
public class AbpIdentityWebMainMenuContributor : IMenuContributor
{
public async Task ConfigureMenuAsync(MenuConfigurationContext context)
public virtual async Task ConfigureMenuAsync(MenuConfigurationContext context)
{
if (context.Menu.Name != StandardMenus.Main)
{

@ -9,19 +9,24 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Roles
[BindProperty]
public RoleInfoModel Role { get; set; }
private readonly IIdentityRoleAppService _identityRoleAppService;
protected IIdentityRoleAppService IdentityRoleAppService { get; }
public CreateModalModel(IIdentityRoleAppService identityRoleAppService)
{
_identityRoleAppService = identityRoleAppService;
IdentityRoleAppService = identityRoleAppService;
}
public async Task<IActionResult> OnPostAsync()
public virtual Task OnGetAsync()
{
return Task.CompletedTask;
}
public virtual async Task<IActionResult> OnPostAsync()
{
ValidateModel();
var input = ObjectMapper.Map<RoleInfoModel, IdentityRoleCreateDto>(Role);
await _identityRoleAppService.CreateAsync(input);
await IdentityRoleAppService.CreateAsync(input);
return NoContent();
}

@ -11,26 +11,26 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Roles
[BindProperty]
public RoleInfoModel Role { get; set; }
private readonly IIdentityRoleAppService _identityRoleAppService;
protected IIdentityRoleAppService IdentityRoleAppService { get; }
public EditModalModel(IIdentityRoleAppService identityRoleAppService)
{
_identityRoleAppService = identityRoleAppService;
IdentityRoleAppService = identityRoleAppService;
}
public async Task OnGetAsync(Guid id)
public virtual async Task OnGetAsync(Guid id)
{
Role = ObjectMapper.Map<IdentityRoleDto, RoleInfoModel>(
await _identityRoleAppService.GetAsync(id)
await IdentityRoleAppService.GetAsync(id)
);
}
public async Task<IActionResult> OnPostAsync()
public virtual async Task<IActionResult> OnPostAsync()
{
ValidateModel();
var input = ObjectMapper.Map<RoleInfoModel, IdentityRoleUpdateDto>(Role);
await _identityRoleAppService.UpdateAsync(Role.Id, input);
await IdentityRoleAppService.UpdateAsync(Role.Id, input);
return NoContent();
}

@ -1,9 +1,17 @@
using System.Threading.Tasks;
namespace Volo.Abp.Identity.Web.Pages.Identity.Roles
{
public class IndexModel : IdentityPageModel
{
public void OnGet()
public virtual Task OnGetAsync()
{
return Task.CompletedTask;
}
public virtual Task OnPostAsync()
{
return Task.CompletedTask;
}
}
}

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

Loading…
Cancel
Save