mirror of https://github.com/abpframework/abp.git
committed by
GitHub
706 changed files with 122492 additions and 382 deletions
@ -0,0 +1,60 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.Cli.ProjectBuilding.Files; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps |
||||
|
{ |
||||
|
public static class RenameHelper |
||||
|
{ |
||||
|
public static void RenameAll(List<FileEntry> entries, string placeHolder, string name) |
||||
|
{ |
||||
|
RenameDirectoryRecursively(entries, placeHolder, name); |
||||
|
RenameAllFiles(entries, placeHolder, name); |
||||
|
ReplaceContent(entries, placeHolder, name); |
||||
|
} |
||||
|
|
||||
|
private static void RenameDirectoryRecursively(List<FileEntry> entries, string placeHolder, string name) |
||||
|
{ |
||||
|
foreach (var entry in entries.Where(e => e.IsDirectory)) |
||||
|
{ |
||||
|
if (entry.Name.Contains(placeHolder)) |
||||
|
{ |
||||
|
entry.SetName(entry.Name.Replace(placeHolder, name)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static void RenameAllFiles(List<FileEntry> entries, string placeHolder, string name) |
||||
|
{ |
||||
|
foreach (var entry in entries.Where(e => !e.IsDirectory)) |
||||
|
{ |
||||
|
if (entry.Name.Contains(placeHolder)) |
||||
|
{ |
||||
|
entry.SetName(entry.Name.Replace(placeHolder, name)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static void ReplaceContent(List<FileEntry> entries, string placeHolder, string name) |
||||
|
{ |
||||
|
foreach (var entry in entries.Where(e => !e.IsDirectory)) |
||||
|
{ |
||||
|
if (entry.Content.Length < placeHolder.Length) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
if (entry.IsBinaryFile) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
var newContent = entry.Content.Replace(placeHolder, name); |
||||
|
if (newContent != entry.Content) |
||||
|
{ |
||||
|
entry.SetContent(newContent); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,80 +0,0 @@ |
|||||
using System; |
|
||||
using Volo.Abp.Cli.ProjectBuilding.Files; |
|
||||
|
|
||||
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps |
|
||||
{ |
|
||||
public class SwitchEntityFrameworkCoreToMongoDbStep : ProjectBuildPipelineStep |
|
||||
{ |
|
||||
public override void Execute(ProjectBuildContext context) |
|
||||
{ |
|
||||
ChangeProjectReference(context); |
|
||||
ChangeWebModuleUsage(context); |
|
||||
ChangeConnectionString(context); |
|
||||
} |
|
||||
|
|
||||
private void ChangeProjectReference(ProjectBuildContext context) |
|
||||
{ |
|
||||
var file = context.GetFile("/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj"); |
|
||||
|
|
||||
file.NormalizeLineEndings(); |
|
||||
|
|
||||
var lines = file.GetLines(); |
|
||||
for (var i = 0; i < lines.Length; i++) |
|
||||
{ |
|
||||
if (lines[i].Contains("ProjectReference") && lines[i].Contains("MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations")) |
|
||||
{ |
|
||||
lines[i] = lines[i].Replace("EntityFrameworkCore.DbMigrations", "MongoDB"); |
|
||||
file.SetLines(lines); |
|
||||
return; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
throw new ApplicationException("Could not find the EntityFrameworkCore reference in the MyCompanyName.MyProjectName.Web.csproj!"); |
|
||||
} |
|
||||
|
|
||||
private void ChangeWebModuleUsage(ProjectBuildContext context) |
|
||||
{ |
|
||||
var file = context.GetFile("/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs"); |
|
||||
|
|
||||
file.NormalizeLineEndings(); |
|
||||
|
|
||||
file.RemoveTemplateCodeIfNot("EntityFrameworkCore"); |
|
||||
|
|
||||
var lines = file.GetLines(); |
|
||||
|
|
||||
for (var i = 0; i < lines.Length; i++) |
|
||||
{ |
|
||||
if (lines[i].Contains("using MyCompanyName.MyProjectName.EntityFrameworkCore")) |
|
||||
{ |
|
||||
lines[i] = "using MyCompanyName.MyProjectName.MongoDb;"; |
|
||||
} |
|
||||
else if (lines[i].Contains("MyProjectNameEntityFrameworkCoreModule")) |
|
||||
{ |
|
||||
lines[i] = lines[i].Replace("MyProjectNameEntityFrameworkCoreModule", "MyProjectNameMongoDbModule"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
file.SetLines(lines); |
|
||||
} |
|
||||
|
|
||||
private void ChangeConnectionString(ProjectBuildContext context) |
|
||||
{ |
|
||||
var file = context.GetFile("/src/MyCompanyName.MyProjectName.Web/appsettings.json"); |
|
||||
|
|
||||
file.NormalizeLineEndings(); |
|
||||
|
|
||||
var lines = file.GetLines(); |
|
||||
for (var i = 0; i < lines.Length; i++) |
|
||||
{ |
|
||||
if (lines[i].Contains("Default") && lines[i].Contains("Database")) |
|
||||
{ |
|
||||
lines[i] = " \"Default\": \"mongodb://localhost:27017|MyProjectName\""; |
|
||||
file.SetLines(lines); |
|
||||
return; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
throw new ApplicationException("Could not find the 'Default' connection string in appsettings.json file!"); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,29 @@ |
|||||
|
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
|
using Volo.Abp.Cli.ProjectBuilding.Building.Steps; |
||||
|
using Volo.Abp.Cli.ProjectBuilding.Files; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectBuilding.Templates.Mvc |
||||
|
{ |
||||
|
public class MvcTemplateProjectRenameStep : ProjectBuildPipelineStep |
||||
|
{ |
||||
|
private readonly string _oldProjectName; |
||||
|
private readonly string _newProjectName; |
||||
|
|
||||
|
public MvcTemplateProjectRenameStep( |
||||
|
string oldProjectName, |
||||
|
string newProjectName) |
||||
|
{ |
||||
|
_oldProjectName = oldProjectName; |
||||
|
_newProjectName = newProjectName; |
||||
|
} |
||||
|
|
||||
|
public override void Execute(ProjectBuildContext context) |
||||
|
{ |
||||
|
context |
||||
|
.GetFile("/MyCompanyName.MyProjectName.sln") |
||||
|
.ReplaceText(_oldProjectName, _newProjectName); |
||||
|
|
||||
|
RenameHelper.RenameAll(context.Files, _oldProjectName, _newProjectName); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,173 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectBuilding.Templates.Mvc |
||||
|
{ |
||||
|
public class MvcTemplateSwitchEntityFrameworkCoreToMongoDbStep : ProjectBuildPipelineStep |
||||
|
{ |
||||
|
public override void Execute(ProjectBuildContext context) |
||||
|
{ |
||||
|
//MyCompanyName.MyProjectName.Web
|
||||
|
|
||||
|
ChangeProjectReference( |
||||
|
context, |
||||
|
"/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj", |
||||
|
"EntityFrameworkCore.DbMigrations", |
||||
|
"MongoDB" |
||||
|
); |
||||
|
|
||||
|
ChangeModuleDependency( |
||||
|
context, |
||||
|
"/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs", |
||||
|
"MyCompanyName.MyProjectName.EntityFrameworkCore", |
||||
|
"MyCompanyName.MyProjectName.MongoDb", |
||||
|
"MyProjectNameEntityFrameworkCoreModule", |
||||
|
"MyProjectNameMongoDbModule" |
||||
|
); |
||||
|
|
||||
|
ChangeConnectionStringToMongoDb( |
||||
|
context, |
||||
|
"/src/MyCompanyName.MyProjectName.Web/appsettings.json" |
||||
|
); |
||||
|
|
||||
|
//MyCompanyName.MyProjectName.IdentityServer
|
||||
|
|
||||
|
ChangeProjectReference( |
||||
|
context, |
||||
|
"/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj", |
||||
|
"EntityFrameworkCore.DbMigrations", |
||||
|
"MongoDB" |
||||
|
); |
||||
|
|
||||
|
ChangeModuleDependency( |
||||
|
context, |
||||
|
"/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs", |
||||
|
"MyCompanyName.MyProjectName.EntityFrameworkCore", |
||||
|
"MyCompanyName.MyProjectName.MongoDb", |
||||
|
"MyProjectNameEntityFrameworkCoreModule", |
||||
|
"MyProjectNameMongoDbModule" |
||||
|
); |
||||
|
|
||||
|
ChangeConnectionStringToMongoDb( |
||||
|
context, |
||||
|
"/src/MyCompanyName.MyProjectName.IdentityServer/appsettings.json" |
||||
|
); |
||||
|
|
||||
|
//MyCompanyName.MyProjectName.HttpApi.Host
|
||||
|
|
||||
|
ChangeProjectReference( |
||||
|
context, |
||||
|
"/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj", |
||||
|
"EntityFrameworkCore.DbMigrations", |
||||
|
"MongoDB" |
||||
|
); |
||||
|
|
||||
|
ChangeModuleDependency( |
||||
|
context, |
||||
|
"/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs", |
||||
|
"MyCompanyName.MyProjectName.EntityFrameworkCore", |
||||
|
"MyCompanyName.MyProjectName.MongoDb", |
||||
|
"MyProjectNameEntityFrameworkCoreModule", |
||||
|
"MyProjectNameMongoDbModule" |
||||
|
); |
||||
|
|
||||
|
ChangeConnectionStringToMongoDb( |
||||
|
context, |
||||
|
"/src/MyCompanyName.MyProjectName.HttpApi.Host/appsettings.json" |
||||
|
); |
||||
|
|
||||
|
//MyCompanyName.MyProjectName.Domain.Tests
|
||||
|
|
||||
|
ChangeProjectReference( |
||||
|
context, |
||||
|
"/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj", |
||||
|
"EntityFrameworkCore.Tests", |
||||
|
"MongoDB.Tests" |
||||
|
); |
||||
|
|
||||
|
ChangeModuleDependency( |
||||
|
context, |
||||
|
"/test/MyCompanyName.MyProjectName.Domain.Tests/MyProjectNameDomainTestModule.cs", |
||||
|
"MyCompanyName.MyProjectName.EntityFrameworkCore", |
||||
|
"MyCompanyName.MyProjectName.MongoDb", |
||||
|
"MyProjectNameEntityFrameworkCoreTestModule", |
||||
|
"MyProjectNameMongoDbTestModule" |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
private void ChangeProjectReference( |
||||
|
ProjectBuildContext context, |
||||
|
string targetProjectFilePath, |
||||
|
string oldReference, |
||||
|
string newReference) |
||||
|
{ |
||||
|
var file = context.GetFile(targetProjectFilePath); |
||||
|
|
||||
|
file.NormalizeLineEndings(); |
||||
|
|
||||
|
var lines = file.GetLines(); |
||||
|
for (var i = 0; i < lines.Length; i++) |
||||
|
{ |
||||
|
if (lines[i].Contains("ProjectReference") && lines[i].Contains(oldReference)) |
||||
|
{ |
||||
|
lines[i] = lines[i].Replace(oldReference, newReference); |
||||
|
file.SetLines(lines); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
throw new ApplicationException($"Could not find the '{oldReference}' reference in the project '{targetProjectFilePath}'!"); |
||||
|
} |
||||
|
|
||||
|
private void ChangeModuleDependency( |
||||
|
ProjectBuildContext context, |
||||
|
string targetModuleFilePath, |
||||
|
string oldNamespace, |
||||
|
string newNamespace, |
||||
|
string oldModuleName, |
||||
|
string newModuleName) |
||||
|
{ |
||||
|
var file = context.GetFile(targetModuleFilePath); |
||||
|
|
||||
|
file.NormalizeLineEndings(); |
||||
|
|
||||
|
var lines = file.GetLines(); |
||||
|
|
||||
|
for (var i = 0; i < lines.Length; i++) |
||||
|
{ |
||||
|
if (lines[i].Contains($"using {oldNamespace};")) |
||||
|
{ |
||||
|
lines[i] = $"using {newNamespace};"; |
||||
|
} |
||||
|
else if (lines[i].Contains(oldModuleName)) |
||||
|
{ |
||||
|
lines[i] = lines[i].Replace(oldModuleName, newModuleName); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
file.SetLines(lines); |
||||
|
} |
||||
|
|
||||
|
private void ChangeConnectionStringToMongoDb( |
||||
|
ProjectBuildContext context, |
||||
|
string appsettingFilePath) |
||||
|
{ |
||||
|
var file = context.GetFile(appsettingFilePath); |
||||
|
|
||||
|
file.NormalizeLineEndings(); |
||||
|
|
||||
|
var lines = file.GetLines(); |
||||
|
for (var i = 0; i < lines.Length; i++) |
||||
|
{ |
||||
|
if (lines[i].Contains("Default") && lines[i].Contains("Database")) |
||||
|
{ |
||||
|
lines[i] = " \"Default\": \"mongodb://localhost:27017|MyProjectName\""; |
||||
|
file.SetLines(lines); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
throw new ApplicationException("Could not find the 'Default' connection string in appsettings.json file!"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
|
using Volo.Abp.Cli.ProjectBuilding.Files; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectBuilding.Templates.Mvc |
||||
|
{ |
||||
|
public class MyTemplateChangeConsoleTestClientPortSettingsStep : ProjectBuildPipelineStep |
||||
|
{ |
||||
|
public override void Execute(ProjectBuildContext context) |
||||
|
{ |
||||
|
context |
||||
|
.GetFile("/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/appsettings.json") |
||||
|
.ReplaceText("44395", "44361") |
||||
|
.ReplaceText("44348", "44361"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
using Shouldly; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace System |
||||
|
{ |
||||
|
public class AbpTypeExtensions_Tests |
||||
|
{ |
||||
|
[Fact] |
||||
|
public void GetBaseClasses() |
||||
|
{ |
||||
|
var baseClasses = typeof(MyClass).GetBaseClasses(includeObject: false); |
||||
|
baseClasses.Length.ShouldBe(2); |
||||
|
baseClasses[0].ShouldBe(typeof(MyBaseClass1)); |
||||
|
baseClasses[1].ShouldBe(typeof(MyBaseClass2)); |
||||
|
} |
||||
|
|
||||
|
public abstract class MyBaseClass1 |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public class MyBaseClass2 : MyBaseClass1 |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public class MyClass : MyBaseClass2 |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace>MyCompanyName.MyProjectName</RootNamespace> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\MyCompanyName.MyProjectName.Domain.Shared\MyCompanyName.MyProjectName.Domain.Shared.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.Application.Contracts\Volo.Abp.Identity.Application.Contracts.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.Application.Contracts\Volo.Abp.PermissionManagement.Application.Contracts.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.Application.Contracts\Volo.Abp.TenantManagement.Application.Contracts.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.Application.Contracts\Volo.Abp.FeatureManagement.Application.Contracts.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,20 @@ |
|||||
|
using Volo.Abp.FeatureManagement; |
||||
|
using Volo.Abp.Identity; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.PermissionManagement; |
||||
|
using Volo.Abp.TenantManagement; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(MyProjectNameDomainSharedModule), |
||||
|
typeof(AbpFeatureManagementApplicationContractsModule), |
||||
|
typeof(AbpIdentityApplicationContractsModule), |
||||
|
typeof(AbpPermissionManagementApplicationContractsModule), |
||||
|
typeof(AbpTenantManagementApplicationContractsModule) |
||||
|
)] |
||||
|
public class MyProjectNameApplicationContractsModule : AbpModule |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -1,6 +1,6 @@ |
|||||
using Volo.Abp.Localization; |
using Volo.Abp.Localization; |
||||
|
|
||||
namespace MyCompanyName.MyProjectName.Localization.MyProjectName |
namespace MyCompanyName.MyProjectName.Localization |
||||
{ |
{ |
||||
[LocalizationResourceName("MyProjectName")] |
[LocalizationResourceName("MyProjectName")] |
||||
public class MyProjectNameResource |
public class MyProjectNameResource |
||||
@ -0,0 +1,11 @@ |
|||||
|
namespace MyCompanyName.MyProjectName.MultiTenancy |
||||
|
{ |
||||
|
public static class MultiTenancyConsts |
||||
|
{ |
||||
|
/* Enable/disable multi-tenancy easily in a single point. |
||||
|
* If you will never need to multi-tenancy, you can remove |
||||
|
* related modules and code parts, including this file. |
||||
|
*/ |
||||
|
public const bool IsMultiTenancyEnabled = true; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace>MyCompanyName.MyProjectName</RootNamespace> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.Domain.Shared\Volo.Abp.Identity.Domain.Shared.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\identityserver\src\Volo.Abp.IdentityServer.Domain.Shared\Volo.Abp.IdentityServer.Domain.Shared.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\background-jobs\src\Volo.Abp.BackgroundJobs.Domain.Shared\Volo.Abp.BackgroundJobs.Domain.Shared.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\audit-logging\src\Volo.Abp.AuditLogging.Domain.Shared\Volo.Abp.AuditLogging.Domain.Shared.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.Domain.Shared\Volo.Abp.TenantManagement.Domain.Shared.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.Domain.Shared\Volo.Abp.FeatureManagement.Domain.Shared.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.Domain.Shared\Volo.Abp.PermissionManagement.Domain.Shared.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.Domain.Shared\Volo.Abp.SettingManagement.Domain.Shared.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<EmbeddedResource Include="Localization\MyProjectName\*.json" /> |
||||
|
<Content Remove="Localization\MyProjectName\*.json" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace MyCompanyName.MyProjectName |
||||
|
{ |
||||
|
public static class MyProjectNameDomainErrorCodes |
||||
|
{ |
||||
|
/* You can add your business exception error codes here, as constants */ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
using MyCompanyName.MyProjectName.Localization; |
||||
|
using Volo.Abp.AuditLogging; |
||||
|
using Volo.Abp.BackgroundJobs; |
||||
|
using Volo.Abp.FeatureManagement; |
||||
|
using Volo.Abp.Identity; |
||||
|
using Volo.Abp.IdentityServer; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Localization.Resources.AbpValidation; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.PermissionManagement; |
||||
|
using Volo.Abp.SettingManagement; |
||||
|
using Volo.Abp.TenantManagement; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpAuditLoggingDomainSharedModule), |
||||
|
typeof(BackgroundJobsDomainSharedModule), |
||||
|
typeof(AbpFeatureManagementDomainSharedModule), |
||||
|
typeof(AbpIdentityDomainSharedModule), |
||||
|
typeof(AbpIdentityServerDomainSharedModule), |
||||
|
typeof(AbpPermissionManagementDomainSharedModule), |
||||
|
typeof(AbpSettingManagementDomainSharedModule), |
||||
|
typeof(AbpTenantManagementDomainSharedModule) |
||||
|
)] |
||||
|
public class MyProjectNameDomainSharedModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<VirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.AddEmbedded<MyProjectNameDomainSharedModule>("MyCompanyName.MyProjectName"); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Add<MyProjectNameResource>("en") |
||||
|
.AddBaseTypes(typeof(AbpValidationResource)) |
||||
|
.AddVirtualJson("/Localization/MyProjectName"); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.Threading; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Data |
||||
|
{ |
||||
|
public static class DataSeedHelper |
||||
|
{ |
||||
|
public static void Seed(ApplicationInitializationContext context) |
||||
|
{ |
||||
|
AsyncHelper.RunSync(async () => |
||||
|
{ |
||||
|
using (var scope = context.ServiceProvider.CreateScope()) |
||||
|
{ |
||||
|
await scope.ServiceProvider |
||||
|
.GetRequiredService<IDataSeeder>() |
||||
|
.SeedAsync(); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,202 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Authorization.Permissions; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Guids; |
||||
|
using Volo.Abp.IdentityServer.ApiResources; |
||||
|
using Volo.Abp.IdentityServer.Clients; |
||||
|
using Volo.Abp.IdentityServer.IdentityResources; |
||||
|
using Volo.Abp.PermissionManagement; |
||||
|
using Volo.Abp.Uow; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.IdentityServer |
||||
|
{ |
||||
|
public class IdentityServerDataSeeder : IDataSeedContributor, ITransientDependency |
||||
|
{ |
||||
|
private readonly IApiResourceRepository _apiResourceRepository; |
||||
|
private readonly IClientRepository _clientRepository; |
||||
|
private readonly IIdentityResourceDataSeeder _identityResourceDataSeeder; |
||||
|
private readonly IGuidGenerator _guidGenerator; |
||||
|
private readonly IPermissionDataSeeder _permissionDataSeeder; |
||||
|
|
||||
|
public IdentityServerDataSeeder( |
||||
|
IClientRepository clientRepository, |
||||
|
IApiResourceRepository apiResourceRepository, |
||||
|
IIdentityResourceDataSeeder identityResourceDataSeeder, |
||||
|
IGuidGenerator guidGenerator, |
||||
|
IPermissionDataSeeder permissionDataSeeder) |
||||
|
{ |
||||
|
_clientRepository = clientRepository; |
||||
|
_apiResourceRepository = apiResourceRepository; |
||||
|
_identityResourceDataSeeder = identityResourceDataSeeder; |
||||
|
_guidGenerator = guidGenerator; |
||||
|
_permissionDataSeeder = permissionDataSeeder; |
||||
|
} |
||||
|
|
||||
|
[UnitOfWork] |
||||
|
public virtual async Task SeedAsync(DataSeedContext context) |
||||
|
{ |
||||
|
await _identityResourceDataSeeder.CreateStandardResourcesAsync(); |
||||
|
await CreateApiResourcesAsync(); |
||||
|
await CreateClientsAsync(); |
||||
|
} |
||||
|
|
||||
|
private async Task CreateApiResourcesAsync() |
||||
|
{ |
||||
|
var commonApiUserClaims = new[] |
||||
|
{ |
||||
|
"email", |
||||
|
"email_verified", |
||||
|
"name", |
||||
|
"phone_number", |
||||
|
"phone_number_verified", |
||||
|
"role" |
||||
|
}; |
||||
|
|
||||
|
await CreateApiResourceAsync("MyProjectName", commonApiUserClaims); |
||||
|
} |
||||
|
|
||||
|
private async Task<ApiResource> CreateApiResourceAsync(string name, IEnumerable<string> claims) |
||||
|
{ |
||||
|
var apiResource = await _apiResourceRepository.FindByNameAsync(name); |
||||
|
if (apiResource == null) |
||||
|
{ |
||||
|
apiResource = await _apiResourceRepository.InsertAsync( |
||||
|
new ApiResource( |
||||
|
_guidGenerator.Create(), |
||||
|
name, |
||||
|
name + " API" |
||||
|
), |
||||
|
autoSave: true |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
foreach (var claim in claims) |
||||
|
{ |
||||
|
if (apiResource.FindClaim(claim) == null) |
||||
|
{ |
||||
|
apiResource.AddUserClaim(claim); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return await _apiResourceRepository.UpdateAsync(apiResource); |
||||
|
} |
||||
|
|
||||
|
private async Task CreateClientsAsync() |
||||
|
{ |
||||
|
const string commonSecret = "E5Xd4yMqjP5kjWFKrYgySBju6JVfCzMyFp7n2QmMrME="; |
||||
|
|
||||
|
var commonScopes = new[] |
||||
|
{ |
||||
|
"email", |
||||
|
"openid", |
||||
|
"profile", |
||||
|
"role", |
||||
|
"phone", |
||||
|
"address", |
||||
|
"MyProjectName" |
||||
|
}; |
||||
|
|
||||
|
/* MyProjectName_Web client is only needed if you created tiered |
||||
|
* solution. Otherwise, delete this client. */ |
||||
|
await CreateClientAsync( |
||||
|
"MyProjectName_Web", |
||||
|
commonScopes, |
||||
|
new[] { "hybrid" }, |
||||
|
commonSecret, |
||||
|
redirectUri: "https://localhost:44314/signin-oidc", |
||||
|
postLogoutRedirectUri: "https://localhost:44314/signout-callback-oidc" |
||||
|
); |
||||
|
|
||||
|
await CreateClientAsync( |
||||
|
"MyCompanyName_ConsoleTestApp", |
||||
|
commonScopes, |
||||
|
new[] { "password", "client_credentials" }, |
||||
|
commonSecret |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
private async Task<Client> CreateClientAsync( |
||||
|
string name, |
||||
|
IEnumerable<string> scopes, |
||||
|
IEnumerable<string> grantTypes, |
||||
|
string secret, |
||||
|
string redirectUri = null, |
||||
|
string postLogoutRedirectUri = null, |
||||
|
IEnumerable<string> permissions = null) |
||||
|
{ |
||||
|
var client = await _clientRepository.FindByCliendIdAsync(name); |
||||
|
if (client == null) |
||||
|
{ |
||||
|
client = await _clientRepository.InsertAsync( |
||||
|
new Client( |
||||
|
_guidGenerator.Create(), |
||||
|
name |
||||
|
) |
||||
|
{ |
||||
|
ClientName = name, |
||||
|
ProtocolType = "oidc", |
||||
|
Description = name, |
||||
|
AlwaysIncludeUserClaimsInIdToken = true, |
||||
|
AllowOfflineAccess = true, |
||||
|
AbsoluteRefreshTokenLifetime = 31536000, //365 days
|
||||
|
AccessTokenLifetime = 31536000, //365 days
|
||||
|
AuthorizationCodeLifetime = 300, |
||||
|
IdentityTokenLifetime = 300, |
||||
|
RequireConsent = false |
||||
|
}, |
||||
|
autoSave: true |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
foreach (var scope in scopes) |
||||
|
{ |
||||
|
if (client.FindScope(scope) == null) |
||||
|
{ |
||||
|
client.AddScope(scope); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
foreach (var grantType in grantTypes) |
||||
|
{ |
||||
|
if (client.FindGrantType(grantType) == null) |
||||
|
{ |
||||
|
client.AddGrantType(grantType); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (client.FindSecret(secret) == null) |
||||
|
{ |
||||
|
client.AddSecret(secret); |
||||
|
} |
||||
|
|
||||
|
if (redirectUri != null) |
||||
|
{ |
||||
|
if (client.FindRedirectUri(redirectUri) == null) |
||||
|
{ |
||||
|
client.AddRedirectUri(redirectUri); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (postLogoutRedirectUri != null) |
||||
|
{ |
||||
|
if (client.FindPostLogoutRedirectUri(postLogoutRedirectUri) == null) |
||||
|
{ |
||||
|
client.AddPostLogoutRedirectUri(postLogoutRedirectUri); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (permissions != null) |
||||
|
{ |
||||
|
await _permissionDataSeeder.SeedAsync( |
||||
|
ClientPermissionValueProvider.ProviderName, |
||||
|
name, |
||||
|
permissions |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
return await _clientRepository.UpdateAsync(client); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,25 +1,27 @@ |
|||||
<Project Sdk="Microsoft.NET.Sdk"> |
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
<Import Project="..\..\common.props" /> |
<Import Project="..\..\common.props" /> |
||||
|
|
||||
<PropertyGroup> |
<PropertyGroup> |
||||
<TargetFramework>netcoreapp2.2</TargetFramework> |
<TargetFramework>netcoreapp2.2</TargetFramework> |
||||
<RootNamespace>MyCompanyName.MyProjectName</RootNamespace> |
<RootNamespace>MyCompanyName.MyProjectName</RootNamespace> |
||||
</PropertyGroup> |
</PropertyGroup> |
||||
|
|
||||
<ItemGroup> |
<ItemGroup> |
||||
|
<ProjectReference Include="..\MyCompanyName.MyProjectName.Domain.Shared\MyCompanyName.MyProjectName.Domain.Shared.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.DataAnnotations" Version="2.2.0" /> |
||||
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.Domain\Volo.Abp.Identity.Domain.csproj" /> |
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.Domain\Volo.Abp.Identity.Domain.csproj" /> |
||||
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.PermissionManagement.Domain.Identity\Volo.Abp.PermissionManagement.Domain.Identity.csproj" /> |
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.PermissionManagement.Domain.Identity\Volo.Abp.PermissionManagement.Domain.Identity.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\identityserver\src\Volo.Abp.IdentityServer.Domain\Volo.Abp.IdentityServer.Domain.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\identityserver\src\Volo.Abp.PermissionManagement.Domain.IdentityServer\Volo.Abp.PermissionManagement.Domain.IdentityServer.csproj" /> |
||||
<ProjectReference Include="..\..\..\..\modules\background-jobs\src\Volo.Abp.BackgroundJobs.Domain\Volo.Abp.BackgroundJobs.Domain.csproj" /> |
<ProjectReference Include="..\..\..\..\modules\background-jobs\src\Volo.Abp.BackgroundJobs.Domain\Volo.Abp.BackgroundJobs.Domain.csproj" /> |
||||
<ProjectReference Include="..\..\..\..\modules\audit-logging\src\Volo.Abp.AuditLogging.Domain\Volo.Abp.AuditLogging.Domain.csproj" /> |
<ProjectReference Include="..\..\..\..\modules\audit-logging\src\Volo.Abp.AuditLogging.Domain\Volo.Abp.AuditLogging.Domain.csproj" /> |
||||
<ProjectReference Include="..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.Domain\Volo.Abp.TenantManagement.Domain.csproj" /> |
<ProjectReference Include="..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.Domain\Volo.Abp.TenantManagement.Domain.csproj" /> |
||||
<ProjectReference Include="..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.Domain\Volo.Abp.FeatureManagement.Domain.csproj" /> |
<ProjectReference Include="..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.Domain\Volo.Abp.FeatureManagement.Domain.csproj" /> |
||||
<ProjectReference Include="..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.Domain\Volo.Abp.SettingManagement.Domain.csproj" /> |
<ProjectReference Include="..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.Domain\Volo.Abp.SettingManagement.Domain.csproj" /> |
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.DataAnnotations" Version="2.2.0" /> |
|
||||
</ItemGroup> |
|
||||
|
|
||||
<ItemGroup> |
|
||||
<EmbeddedResource Include="Localization\MyProjectName\*.json" /> |
|
||||
</ItemGroup> |
</ItemGroup> |
||||
|
|
||||
</Project> |
</Project> |
||||
|
|||||
@ -0,0 +1,21 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace>MyCompanyName.MyProjectName</RootNamespace> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\MyCompanyName.MyProjectName.Application.Contracts\MyCompanyName.MyProjectName.Application.Contracts.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.HttpApi.Client\Volo.Abp.Identity.HttpApi.Client.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.HttpApi.Client\Volo.Abp.PermissionManagement.HttpApi.Client.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.HttpApi.Client\Volo.Abp.TenantManagement.HttpApi.Client.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.HttpApi.Client\Volo.Abp.FeatureManagement.HttpApi.Client.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,29 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.FeatureManagement; |
||||
|
using Volo.Abp.Identity; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.PermissionManagement; |
||||
|
using Volo.Abp.TenantManagement; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(MyProjectNameApplicationContractsModule), |
||||
|
typeof(AbpIdentityHttpApiClientModule), |
||||
|
typeof(AbpPermissionManagementHttpApiClientModule), |
||||
|
typeof(AbpTenantManagementHttpApiClientModule), |
||||
|
typeof(AbpFeatureManagementHttpApiClientModule) |
||||
|
)] |
||||
|
public class MyProjectNameHttpApiClientModule : AbpModule |
||||
|
{ |
||||
|
public const string RemoteServiceName = "Default"; |
||||
|
|
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddHttpClientProxies( |
||||
|
typeof(MyProjectNameApplicationContractsModule).Assembly, |
||||
|
RemoteServiceName |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Controllers |
||||
|
{ |
||||
|
public class HomeController : AbpController |
||||
|
{ |
||||
|
public ActionResult Index() |
||||
|
{ |
||||
|
return Redirect("/swagger"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.Web"> |
||||
|
|
||||
|
<Import Project="..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netcoreapp2.2</TargetFramework> |
||||
|
<RootNamespace>MyCompanyName.MyProjectName</RootNamespace> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.App" /> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" /> |
||||
|
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" /> |
||||
|
<PackageReference Include="Serilog.Sinks.File" Version="4.0.0" /> |
||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="4.0.1" /> |
||||
|
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.7.0" /> |
||||
|
<PackageReference Include="Microsoft.Extensions.Caching.Redis" Version="2.2.0" /> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="2.2.0" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.AspNetCore.MultiTenancy\Volo.Abp.AspNetCore.MultiTenancy.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" /> |
||||
|
<ProjectReference Include="..\MyCompanyName.MyProjectName.Application\MyCompanyName.MyProjectName.Application.csproj" /> |
||||
|
<ProjectReference Include="..\MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations\MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj" /> |
||||
|
<ProjectReference Include="..\MyCompanyName.MyProjectName.HttpApi\MyCompanyName.MyProjectName.HttpApi.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<Compile Remove="Logs\**" /> |
||||
|
<Content Remove="Logs\**" /> |
||||
|
<EmbeddedResource Remove="Logs\**" /> |
||||
|
<None Remove="Logs\**" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<Target Name="ChangeAliasesOfStrongNameAssemblies" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences"> |
||||
|
<ItemGroup> |
||||
|
<ReferencePath Condition="'%(FileName)' == 'StackExchange.Redis.StrongName'"> |
||||
|
<Aliases>signed</Aliases> |
||||
|
</ReferencePath> |
||||
|
</ItemGroup> |
||||
|
</Target> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,138 @@ |
|||||
|
using System.IO; |
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.AspNetCore.DataProtection; |
||||
|
using Microsoft.AspNetCore.Hosting; |
||||
|
using Microsoft.Extensions.Configuration; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using MyCompanyName.MyProjectName.EntityFrameworkCore; |
||||
|
using MyCompanyName.MyProjectName.MultiTenancy; |
||||
|
using StackExchange.Redis; |
||||
|
using Swashbuckle.AspNetCore.Swagger; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.AspNetCore.MultiTenancy; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.Abp.Autofac; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(MyProjectNameHttpApiModule), |
||||
|
typeof(AbpAutofacModule), |
||||
|
typeof(AbpAspNetCoreMultiTenancyModule), |
||||
|
typeof(MyProjectNameApplicationModule), |
||||
|
typeof(MyProjectNameEntityFrameworkCoreModule) |
||||
|
)] |
||||
|
public class MyProjectNameHttpApiHostModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
var configuration = context.Services.GetConfiguration(); |
||||
|
var hostingEnvironment = context.Services.GetHostingEnvironment(); |
||||
|
|
||||
|
ConfigureConventionalControllers(); |
||||
|
ConfigureAuthentication(context); |
||||
|
ConfigureSwagger(context); |
||||
|
ConfigureLocalization(); |
||||
|
ConfigureVirtualFileSystem(context); |
||||
|
ConfigureRedis(context, configuration, hostingEnvironment); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureVirtualFileSystem(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
var hostingEnvironment = context.Services.GetHostingEnvironment(); |
||||
|
|
||||
|
if (hostingEnvironment.IsDevelopment()) |
||||
|
{ |
||||
|
Configure<VirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<MyProjectNameDomainSharedModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Domain.Shared", Path.DirectorySeparatorChar))); |
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<MyProjectNameDomainModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); |
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<MyProjectNameApplicationContractsModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Application.Contracts", Path.DirectorySeparatorChar))); |
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<MyProjectNameApplicationModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}MyCompanyName.MyProjectName.Application", Path.DirectorySeparatorChar))); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void ConfigureConventionalControllers() |
||||
|
{ |
||||
|
Configure<AbpAspNetCoreMvcOptions>(options => |
||||
|
{ |
||||
|
options.ConventionalControllers.Create(typeof(MyProjectNameApplicationModule).Assembly); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureAuthentication(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddAuthentication("Bearer") |
||||
|
.AddIdentityServerAuthentication(options => |
||||
|
{ |
||||
|
options.Authority = "https://localhost:44348"; |
||||
|
options.RequireHttpsMetadata = true; |
||||
|
options.ApiName = "MyProjectName"; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private static void ConfigureSwagger(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddSwaggerGen( |
||||
|
options => |
||||
|
{ |
||||
|
options.SwaggerDoc("v1", new Info {Title = "MyProjectName API", Version = "v1"}); |
||||
|
options.DocInclusionPredicate((docName, description) => true); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureLocalization() |
||||
|
{ |
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Languages.Add(new LanguageInfo("en", "en", "English")); |
||||
|
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); |
||||
|
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); |
||||
|
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureRedis( |
||||
|
ServiceConfigurationContext context, |
||||
|
IConfigurationRoot configuration, |
||||
|
IHostingEnvironment hostingEnvironment) |
||||
|
{ |
||||
|
context.Services.AddDistributedRedisCache(options => |
||||
|
{ |
||||
|
options.Configuration = configuration["Redis:Configuration"]; |
||||
|
}); |
||||
|
|
||||
|
if (!hostingEnvironment.IsDevelopment()) |
||||
|
{ |
||||
|
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); |
||||
|
context.Services |
||||
|
.AddDataProtection() |
||||
|
.PersistKeysToStackExchangeRedis(redis, "MyProjectName-Protection-Keys"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
||||
|
{ |
||||
|
var app = context.GetApplicationBuilder(); |
||||
|
|
||||
|
app.UseVirtualFiles(); |
||||
|
app.UseAuthentication(); |
||||
|
if (MultiTenancyConsts.IsMultiTenancyEnabled) |
||||
|
{ |
||||
|
app.UseMultiTenancy(); |
||||
|
} |
||||
|
app.UseAbpRequestLocalization(); |
||||
|
app.UseSwagger(); |
||||
|
app.UseSwaggerUI(options => |
||||
|
{ |
||||
|
options.SwaggerEndpoint("/swagger/v1/swagger.json", "MyProjectName API"); |
||||
|
}); |
||||
|
app.UseAuditing(); |
||||
|
app.UseMvcWithDefaultRouteAndArea(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
using System; |
||||
|
using System.IO; |
||||
|
using Microsoft.AspNetCore.Hosting; |
||||
|
using Serilog; |
||||
|
using Serilog.Events; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName |
||||
|
{ |
||||
|
public class Program |
||||
|
{ |
||||
|
public static int Main(string[] args) |
||||
|
{ |
||||
|
Log.Logger = new LoggerConfiguration() |
||||
|
#if DEBUG
|
||||
|
.MinimumLevel.Debug() |
||||
|
#else
|
||||
|
.MinimumLevel.Information() |
||||
|
#endif
|
||||
|
.MinimumLevel.Override("Microsoft", LogEventLevel.Information) |
||||
|
.Enrich.FromLogContext() |
||||
|
.WriteTo.File("Logs/logs.txt") |
||||
|
.CreateLogger(); |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
Log.Information("Starting MyCompanyName.MyProjectName.HttpApi.Host."); |
||||
|
BuildWebHostInternal(args).Run(); |
||||
|
return 0; |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
Log.Fatal(ex, "Host terminated unexpectedly!"); |
||||
|
return 1; |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
Log.CloseAndFlush(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static IWebHost BuildWebHostInternal(string[] args) => |
||||
|
new WebHostBuilder() |
||||
|
.UseKestrel() |
||||
|
.UseContentRoot(Directory.GetCurrentDirectory()) |
||||
|
.UseIISIntegration() |
||||
|
.UseStartup<Startup>() |
||||
|
.UseSerilog() |
||||
|
.Build(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
{ |
||||
|
"iisSettings": { |
||||
|
"windowsAuthentication": false, |
||||
|
"anonymousAuthentication": true, |
||||
|
"iisExpress": { |
||||
|
"applicationUrl": "http://localhost:50904", |
||||
|
"sslPort": 44395 |
||||
|
} |
||||
|
}, |
||||
|
"profiles": { |
||||
|
"IIS Express": { |
||||
|
"commandName": "IISExpress", |
||||
|
"launchBrowser": true, |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
}, |
||||
|
"MyCompanyName.MyProjectName.HttpApi.Host": { |
||||
|
"commandName": "Project", |
||||
|
"launchBrowser": true, |
||||
|
"applicationUrl": "https://localhost:5001;http://localhost:5000", |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using System; |
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.AspNetCore.Hosting; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName |
||||
|
{ |
||||
|
public class Startup |
||||
|
{ |
||||
|
public IServiceProvider ConfigureServices(IServiceCollection services) |
||||
|
{ |
||||
|
services.AddApplication<MyProjectNameHttpApiHostModule>(options => |
||||
|
{ |
||||
|
options.UseAutofac(); |
||||
|
}); |
||||
|
|
||||
|
return services.BuildServiceProviderFromFactory(); |
||||
|
} |
||||
|
|
||||
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) |
||||
|
{ |
||||
|
app.InitializeApplication(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,2 @@ |
|||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"ConnectionStrings": { |
||||
|
"Default": "Server=localhost;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true" |
||||
|
}, |
||||
|
"Redis": { |
||||
|
"Configuration": "127.0.0.1" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
{"KeyId":"600caa200caf5d805eba9f06ace9e236","Parameters":{"D":"KCNDHA96eimN+UqchSKocgYITGflaAIwxzCS5KqSTkYAFliPthQx7LySuLor4F1+uLvwnh3ZocyI3y43GZu+eVHD256sxdV8/UsQz1HC23RRFqcUiAZjze8K5VMVStrBOxaa/Ds1U9/bpuNE7jZdcgFIEHsdZtCACqwtlE4nlIs1/GLiokqjBOESgxJMy9WUeDbWcvoo+YdwgKf5jt6AZHOYSS+TokLL+Y7TEfGMXe3jZD9VtSMkBSM8wGB89zNGR0FZB9maCG/BCoRJqxdYRyeb4FFXJclQtK3DexyDVqlNZQaNKVHu0tVAnVNKKcd7Iex8gA+5DNqqucUA7C/F6Q==","DP":"fr9iaNb1W4YZ/NJ56+N3SCeDQYuKobq1qeaQWmHlQsOHKoHhNZJQZ5x0M9PQilou16AwVlNGCJncMwxsSUxXn6itG0LcBnvfMeo2v3xKcij1BtFR9qfXecwEn2nnhI3mpXtZxyCdP3NIYUp9qViLJUjGJqrbQk+OIAGRQd2rRe0=","DQ":"o1umLkDodtwvpCsDguQYSjd3iob+WHNmfe/9HyjADmUehP8b9SpUgcrb+QF301J8YmQMnYZKWW5rEwKOtwsWNswgXfMnXeWerlZmz0tj9y38YczS70liU0vETsRefhrRCaXHraMvneqYNNedhsrCNalWK+DNwcixi4L59vA8ofs=","Exponent":"AQAB","InverseQ":"btd1nwwxl/E3ryfDi2bN12TuVDvv7yoPvryIlLgu+FiLpe4vaA1omDLliQBcl7oeyA563HBUop4D5oE7si+jD64N8XgFz37dD3KqUokeQ4lrTSSOePT1K+nWIl30sqDd7YE4auz4CvSjm2wXmN31+CXW1hp3YWN2972yrUt+R5U=","Modulus":"uwMB6reAVtm/Cq0BRPZ0ozBq6g3wDh2kzqFKBf8I7u8d9p7i5ExLSrOWPupHwPr/IW1VUn2TKHrJ8OnyYhznKIRxqlxj0U3D2GXijz5kfFOoHK+mlfKaDMqweRoS0UzEz58kMlgwUoDraUj6dTHTPCVPo3TqA2ImRw50j6D+jobFrY5321EFvlirZViMPDAgB8Ca7wGCqNBcCxvIPYw1O6WZmcVmjG7umelD3XjcUIQlEbIyAmi/3gXAo7NdPmgOamla6bnSWsy429HfsNpXyCfPBzV3QS3ubpTekWPoPcOVZbWwVPYtFQbhRh8PmWATRx0cV6oePZNZGxGeJl8WYQ==","P":"wplelBfVmiOPmr6iUxtOgIzuvwSqvP6Rqmh8dhaGDiJjU8OqZ0tZhuh0G+xnMLPIHb2fMeg0dqZMJZ5iXaIi1QycYn/JKz1i4cUonJ6IIQeKKf67tvzn/BY0V0N8rJw8hVfzou+/5sRBCbiHtJ2KIN1YJQuWGFFfrZJOJzc95ss=","Q":"9gTGKoDiOdrY8kqIXJ2nMhoeNryAH4q3EUrROJ7simqc28oYlGx24Sco/wOoeB2xxrdcF5JYOlyJ7H2YY/huLvJISaw/wHLPskiKiYQ78tuNwW0ip+5ceB1dSToHcEe3sR30+OeTh0Z4ZKoqthKziFGIt3EhEgiGq1gjZuWB5gM="}} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using MyCompanyName.MyProjectName.Localization; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Controllers |
||||
|
{ |
||||
|
public abstract class MyProjectNameController : AbpController |
||||
|
{ |
||||
|
protected MyProjectNameController() |
||||
|
{ |
||||
|
LocalizationResource = typeof(MyProjectNameResource); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using MyCompanyName.MyProjectName.Models.Test; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Controllers |
||||
|
{ |
||||
|
[Route("api/test")] |
||||
|
public class TestController : MyProjectNameController |
||||
|
{ |
||||
|
public TestController() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("")] |
||||
|
public async Task<List<TestModel>> GetAsync() |
||||
|
{ |
||||
|
return new List<TestModel> |
||||
|
{ |
||||
|
new TestModel {Name = "John", BirthDate = new DateTime(1942, 11, 18)}, |
||||
|
new TestModel {Name = "Adams", BirthDate = new DateTime(1997, 05, 24)} |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Models.Test |
||||
|
{ |
||||
|
public class TestModel |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public DateTime BirthDate { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netcoreapp2.2</TargetFramework> |
||||
|
<RootNamespace>MyCompanyName.MyProjectName</RootNamespace> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\MyCompanyName.MyProjectName.Application.Contracts\MyCompanyName.MyProjectName.Application.Contracts.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.HttpApi\Volo.Abp.Identity.HttpApi.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.HttpApi\Volo.Abp.PermissionManagement.HttpApi.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.HttpApi\Volo.Abp.TenantManagement.HttpApi.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\feature-management\src\Volo.Abp.FeatureManagement.HttpApi\Volo.Abp.FeatureManagement.HttpApi.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,20 @@ |
|||||
|
using Volo.Abp.FeatureManagement; |
||||
|
using Volo.Abp.Identity; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.PermissionManagement.HttpApi; |
||||
|
using Volo.Abp.TenantManagement; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(MyProjectNameApplicationContractsModule), |
||||
|
typeof(AbpIdentityHttpApiModule), |
||||
|
typeof(AbpPermissionManagementHttpApiModule), |
||||
|
typeof(AbpTenantManagementHttpApiModule), |
||||
|
typeof(AbpFeatureManagementHttpApiModule) |
||||
|
)] |
||||
|
public class MyProjectNameHttpApiModule : AbpModule |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.Web"> |
||||
|
|
||||
|
<Import Project="..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netcoreapp2.2</TargetFramework> |
||||
|
<RootNamespace>MyCompanyName.MyProjectName</RootNamespace> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<Compile Remove="Logs\**" /> |
||||
|
<Content Remove="Logs\**" /> |
||||
|
<EmbeddedResource Remove="Logs\**" /> |
||||
|
<None Remove="Logs\**" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<None Include="Pages\Index.cshtml" /> |
||||
|
<None Include="Pages\_ViewImports.cshtml" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.App" /> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" /> |
||||
|
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" /> |
||||
|
<PackageReference Include="Serilog.Sinks.File" Version="4.0.0" /> |
||||
|
<PackageReference Include="Microsoft.Extensions.Caching.Redis" Version="2.2.0" /> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="2.2.0" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.Web.IdentityServer\Volo.Abp.Account.Web.IdentityServer.csproj" /> |
||||
|
<ProjectReference Include="..\MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations\MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<Target Name="ChangeAliasesOfStrongNameAssemblies" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences"> |
||||
|
<ItemGroup> |
||||
|
<ReferencePath Condition="'%(FileName)' == 'StackExchange.Redis.StrongName'"> |
||||
|
<Aliases>signed</Aliases> |
||||
|
</ReferencePath> |
||||
|
</ItemGroup> |
||||
|
</Target> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,118 @@ |
|||||
|
using System.IO; |
||||
|
using Localization.Resources.AbpUi; |
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.AspNetCore.DataProtection; |
||||
|
using Microsoft.AspNetCore.Hosting; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using MyCompanyName.MyProjectName.EntityFrameworkCore; |
||||
|
using MyCompanyName.MyProjectName.Localization; |
||||
|
using MyCompanyName.MyProjectName.MultiTenancy; |
||||
|
using StackExchange.Redis; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Account.Web; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; |
||||
|
using Volo.Abp.Auditing; |
||||
|
using Volo.Abp.Autofac; |
||||
|
using Volo.Abp.BackgroundJobs; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.Ui.Navigation.Urls; |
||||
|
using Volo.Abp.UI; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpAutofacModule), |
||||
|
typeof(AbpAccountWebIdentityServerModule), |
||||
|
typeof(AbpAspNetCoreMvcUiBasicThemeModule), |
||||
|
typeof(MyProjectNameEntityFrameworkCoreModule) |
||||
|
)] |
||||
|
public class MyProjectNameIdentityServerModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
var hostingEnvironment = context.Services.GetHostingEnvironment(); |
||||
|
var configuration = context.Services.GetConfiguration(); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Get<MyProjectNameResource>() |
||||
|
.AddBaseTypes( |
||||
|
typeof(AbpUiResource) |
||||
|
); |
||||
|
|
||||
|
options.Languages.Add(new LanguageInfo("en", "en", "English")); |
||||
|
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); |
||||
|
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); |
||||
|
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpAuditingOptions>(options => |
||||
|
{ |
||||
|
options.IsEnabledForGetRequests = true; |
||||
|
options.ApplicationName = "AuthServer"; |
||||
|
}); |
||||
|
|
||||
|
if (hostingEnvironment.IsDevelopment()) |
||||
|
{ |
||||
|
Configure<VirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<MyProjectNameDomainModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}MyCompanyName.MyProjectName.Domain", Path.DirectorySeparatorChar))); |
||||
|
//<TEMPLATE-REMOVE>
|
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<AbpUiModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.UI", Path.DirectorySeparatorChar))); |
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<AbpAspNetCoreMvcUiModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI", Path.DirectorySeparatorChar))); |
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<AbpAspNetCoreMvcUiBootstrapModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI.Bootstrap", Path.DirectorySeparatorChar))); |
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<AbpAspNetCoreMvcUiThemeSharedModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared", Path.DirectorySeparatorChar))); |
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<AbpAspNetCoreMvcUiBasicThemeModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic", Path.DirectorySeparatorChar))); |
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<AbpAccountWebModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}modules{0}account{0}src{0}Volo.Abp.Account.Web", Path.DirectorySeparatorChar))); |
||||
|
//</TEMPLATE-REMOVE>
|
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
Configure<AppUrlOptions>(options => |
||||
|
{ |
||||
|
options.Applications["MVC"].RootUrl = "https://localhost:44348/"; |
||||
|
}); |
||||
|
|
||||
|
Configure<BackgroundJobOptions>(options => |
||||
|
{ |
||||
|
options.IsJobExecutionEnabled = false; |
||||
|
}); |
||||
|
|
||||
|
context.Services.AddDistributedRedisCache(options => |
||||
|
{ |
||||
|
options.Configuration = configuration["Redis:Configuration"]; |
||||
|
}); |
||||
|
|
||||
|
if (!hostingEnvironment.IsDevelopment()) |
||||
|
{ |
||||
|
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); |
||||
|
context.Services |
||||
|
.AddDataProtection() |
||||
|
.PersistKeysToStackExchangeRedis(redis, "MyProjectName-Protection-Keys"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
||||
|
{ |
||||
|
var app = context.GetApplicationBuilder(); |
||||
|
|
||||
|
app.UseCorrelationId(); |
||||
|
app.UseVirtualFiles(); |
||||
|
app.UseAuthentication(); |
||||
|
if (MultiTenancyConsts.IsMultiTenancyEnabled) |
||||
|
{ |
||||
|
app.UseMultiTenancy(); |
||||
|
} |
||||
|
app.UseIdentityServer(); |
||||
|
app.UseAbpRequestLocalization(); |
||||
|
app.UseAuditing(); |
||||
|
app.UseMvcWithDefaultRouteAndArea(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
@page |
||||
|
@using MyCompanyName.MyProjectName.Pages |
||||
|
@using Volo.Abp.Users |
||||
|
@model MyCompanyName.MyProjectName.Pages.IndexModel |
||||
|
@inject ICurrentUser CurrentUser |
||||
|
@if (CurrentUser.IsAuthenticated) |
||||
|
{ |
||||
|
<div> |
||||
|
<abp-row> |
||||
|
<abp-column size-md="_3" class="text-center"> |
||||
|
<i class="fa fa-user d-block" style="font-size: 10em; color: #12b900"></i> |
||||
|
<a abp-button="Primary" asp-controller="Logout" asp-action="Index" asp-area="Account">Logout</a> |
||||
|
</abp-column> |
||||
|
<abp-column size-md="_9"> |
||||
|
<h2>@CurrentUser.UserName</h2> |
||||
|
<h5 class="text-muted">@CurrentUser.Email</h5> |
||||
|
<div> |
||||
|
<strong>Roles</strong>: @CurrentUser.Roles.JoinAsString(", ") |
||||
|
<br /> |
||||
|
<strong>Claims</strong>: <br /> |
||||
|
@Html.Raw(CurrentUser.GetAllClaims().Select(c => $"{c.Type}={c.Value}").JoinAsString(" <br /> ")) |
||||
|
</div> |
||||
|
</abp-column> |
||||
|
</abp-row> |
||||
|
</div> |
||||
|
} |
||||
|
|
||||
|
@if (!CurrentUser.IsAuthenticated) |
||||
|
{ |
||||
|
<div class="text-center"> |
||||
|
<i class="fa fa-user d-block" style="font-size: 10em; color: #aaa"></i><br/><br /> |
||||
|
<a abp-button="Primary" asp-page="/Account/Login">Login</a> |
||||
|
</div> |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Pages |
||||
|
{ |
||||
|
public class IndexModel : AbpPageModel |
||||
|
{ |
||||
|
public void OnGet() |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,4 @@ |
|||||
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers |
||||
|
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI |
||||
|
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap |
||||
|
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling |
||||
@ -0,0 +1,50 @@ |
|||||
|
using System; |
||||
|
using System.IO; |
||||
|
using Microsoft.AspNetCore.Hosting; |
||||
|
using Serilog; |
||||
|
using Serilog.Events; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName |
||||
|
{ |
||||
|
public class Program |
||||
|
{ |
||||
|
public static int Main(string[] args) |
||||
|
{ |
||||
|
Log.Logger = new LoggerConfiguration() |
||||
|
#if DEBUG
|
||||
|
.MinimumLevel.Debug() |
||||
|
#else
|
||||
|
.MinimumLevel.Information() |
||||
|
#endif
|
||||
|
.MinimumLevel.Override("Microsoft", LogEventLevel.Information) |
||||
|
.Enrich.FromLogContext() |
||||
|
.WriteTo.File("Logs/logs.txt") |
||||
|
.CreateLogger(); |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
Log.Information("Starting MyCompanyName.MyProjectName.IdentityServer."); |
||||
|
BuildWebHostInternal(args).Run(); |
||||
|
return 0; |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
Log.Fatal(ex, "MyCompanyName.MyProjectName.IdentityServer terminated unexpectedly!"); |
||||
|
return 1; |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
Log.CloseAndFlush(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
internal static IWebHost BuildWebHostInternal(string[] args) => |
||||
|
new WebHostBuilder() |
||||
|
.UseKestrel() |
||||
|
.UseContentRoot(Directory.GetCurrentDirectory()) |
||||
|
.UseIISIntegration() |
||||
|
.UseStartup<Startup>() |
||||
|
.UseSerilog() |
||||
|
.Build(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
{ |
||||
|
"iisSettings": { |
||||
|
"windowsAuthentication": false, |
||||
|
"anonymousAuthentication": true, |
||||
|
"iisExpress": { |
||||
|
"applicationUrl": "http://localhost:55993", |
||||
|
"sslPort": 44348 |
||||
|
} |
||||
|
}, |
||||
|
"profiles": { |
||||
|
"IIS Express": { |
||||
|
"commandName": "IISExpress", |
||||
|
"launchBrowser": true, |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
}, |
||||
|
"MyCompanyName.MyProjectName.IdentityServer": { |
||||
|
"commandName": "Project", |
||||
|
"launchBrowser": true, |
||||
|
"applicationUrl": "https://localhost:5001;http://localhost:5000", |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
using System; |
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName |
||||
|
{ |
||||
|
public class Startup |
||||
|
{ |
||||
|
public IServiceProvider ConfigureServices(IServiceCollection services) |
||||
|
{ |
||||
|
services.AddApplication<MyProjectNameIdentityServerModule>(options => |
||||
|
{ |
||||
|
options.UseAutofac(); |
||||
|
}); |
||||
|
|
||||
|
return services.BuildServiceProviderFromFactory(); |
||||
|
} |
||||
|
|
||||
|
public void Configure(IApplicationBuilder app) |
||||
|
{ |
||||
|
app.InitializeApplication(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
module.exports = { |
||||
|
aliases: { |
||||
|
|
||||
|
}, |
||||
|
clean: [ |
||||
|
|
||||
|
], |
||||
|
mappings: { |
||||
|
|
||||
|
} |
||||
|
}; |
||||
@ -0,0 +1,2 @@ |
|||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"ConnectionStrings": { |
||||
|
"Default": "Server=localhost;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true" |
||||
|
}, |
||||
|
"Redis": { |
||||
|
"Configuration": "127.0.0.1" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
"use strict"; |
||||
|
|
||||
|
var gulp = require("gulp"), |
||||
|
path = require('path'), |
||||
|
copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js'); |
||||
|
|
||||
|
copyResources.init(path.resolve('./')); |
||||
|
|
||||
|
gulp.task('default', [copyResources.taskName], function () { |
||||
|
|
||||
|
}); |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"version": "0.1.0", |
||||
|
"name": "my-app-identityserver", |
||||
|
"private": true, |
||||
|
"dependencies": { |
||||
|
"@abp/aspnetcore.mvc.ui.theme.basic": "^0.4.9" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
{"KeyId":"ac0d2edf3c04d13cd95cc41b9b33ab03","Parameters":{"D":"FFymEWbX3XBT5YnTngOKwtz3XKsyaQbyDvvw9jbmkdvLKUmrb1hkmylqVYwU/3G1u79rrD8AZXJDoYVLegyZymK/iNeePMLI4i5vScF7PdQXn/g6CvQ8j3J60YYyfDWuxjBH8nCEUIfQIv14BpcH6CWi1BVZUbnbWcpe2ji8D5I3FHOZpvksQztst5eE836ODdN9jgk35kgrdUQ14MEFHA6m6fAzvFI1csFxD3Kwej4rI8RYZ0WYLkndz9ID88+v9VxqI8+wN6wR6tIOR510uT1FI5wONBVBUzgeZ6cCEpg0jC9tgqcP03gMDpmE7vKp34ExxH/iOWyhQ0gAxHOVlQ==","DP":"qSQfNZvEkepgY12d+uwTbRoOp+0g1CBiMU9kqyoIB56hAUnzENSCDzunjLRrvDLFPgXiUcoccskyVRnKKOGPOqPE6VjgzBrdLgA/hBf8hPg0GnTVoPyLxR9G6GsGUKsAYVn8G7cnK5wXzK4jCjsflkfxCzFfdASJ/+sa5QPWZMM=","DQ":"u+56T1+rhMvlurid9kBS2Ypfm4vOiNAXLD9kGz2wx8Ob0yYlWo55kn11qPs6Ej9bnQIY3N+TY2tXMamfhAhntoHaKrFjOpCmlHZ0GAeQOJVuWSlFvu/NBoxfjZzcUCNua22oJjy++wSdkkLLGEqau62byaQoSSqUxUzwL36RexM=","Exponent":"AQAB","InverseQ":"E+uq9g6D5LjUk+M7gtt0srnT8duwu8P83AgFqjtGOnSCy71omSboxb4zC9bGq/WaEFauFBwqxbkXwFyXuYNfIelfmSERulU9jgf0+KH6QmFdtjrJ5UO7VArqET1WUquwiDvOyO8udCxi8RRAiM5G3dTzIs5JTalGhlKEZSAgPtQ=","Modulus":"rgHACxzqvuE72RF/NdDTLsIEy3F/n6P4lkgrER60FU8uRNwSmAMRxvxYOaE3Ot/krRYcw2+MP8ewR1VBXywXVT1zuACA3SacMHJYmZQ2UkuwsD9bmpjvqoMhR/hjsI74jTzKpclHtEu7D7WYDZaIPAEIs/8+5H/z1mXVfgACaeaQt3C0OhwXSOPPDP71VKGfoFucXYED1keZ0PKxYAlhiHOe7cnSlfJseujwD2Rhyq8mUhe6aEMTYBjuruWgpfvnSOARAqu5vwzK35KpAirHwa1DJSZyanNMFdlLkVNKWUKEqd6PwRneiHacmaaDF6oQQstuSbf9cuJeSMbKh7WVQQ==","P":"0CJDit2NHk0Z1bN5ZVIYZRUYbrAI2bEOafAKqfffcA/Os7yXsY14Ye4pSpDxfdZGcPGRL04HPkJsogFtyI7k4ujrvsC66I5cg45+BhBMM0zyLJ7LZkD2HGwX2+a/xrXhhIIOnGWWy2zzW3dkayRhi1bR9krfTA5uBw1LX9qZ3Yc=","Q":"1gZITAaB+r0+PgOfyDCeVzSnTyQuKSkgbUkIgQP9jQZa6edrbAXogdJipxmUTrW7JaxifG1z9ubK+TOqhjZHqT4gd8U8Bh7jCBizZNVe60pez1OtNGpEOW2N+ZrXBSMNcV8PFaMg/B+fcaX+i7NWpTqmztR/V0DGXmD+XosuaPc="}} |
||||
@ -0,0 +1,546 @@ |
|||||
|
var abp = abp || {}; |
||||
|
(function () { |
||||
|
|
||||
|
/* Application paths *****************************************/ |
||||
|
|
||||
|
//Current application root path (including virtual directory if exists).
|
||||
|
abp.appPath = abp.appPath || '/'; |
||||
|
|
||||
|
abp.pageLoadTime = new Date(); |
||||
|
|
||||
|
//Converts given path to absolute path using abp.appPath variable.
|
||||
|
abp.toAbsAppPath = function (path) { |
||||
|
if (path.indexOf('/') == 0) { |
||||
|
path = path.substring(1); |
||||
|
} |
||||
|
|
||||
|
return abp.appPath + path; |
||||
|
}; |
||||
|
|
||||
|
/* LOGGING ***************************************************/ |
||||
|
//Implements Logging API that provides secure & controlled usage of console.log
|
||||
|
|
||||
|
abp.log = abp.log || {}; |
||||
|
|
||||
|
abp.log.levels = { |
||||
|
DEBUG: 1, |
||||
|
INFO: 2, |
||||
|
WARN: 3, |
||||
|
ERROR: 4, |
||||
|
FATAL: 5 |
||||
|
}; |
||||
|
|
||||
|
abp.log.level = abp.log.levels.DEBUG; |
||||
|
|
||||
|
abp.log.log = function (logObject, logLevel) { |
||||
|
if (!window.console || !window.console.log) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (logLevel != undefined && logLevel < abp.log.level) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
console.log(logObject); |
||||
|
}; |
||||
|
|
||||
|
abp.log.debug = function (logObject) { |
||||
|
abp.log.log("DEBUG: ", abp.log.levels.DEBUG); |
||||
|
abp.log.log(logObject, abp.log.levels.DEBUG); |
||||
|
}; |
||||
|
|
||||
|
abp.log.info = function (logObject) { |
||||
|
abp.log.log("INFO: ", abp.log.levels.INFO); |
||||
|
abp.log.log(logObject, abp.log.levels.INFO); |
||||
|
}; |
||||
|
|
||||
|
abp.log.warn = function (logObject) { |
||||
|
abp.log.log("WARN: ", abp.log.levels.WARN); |
||||
|
abp.log.log(logObject, abp.log.levels.WARN); |
||||
|
}; |
||||
|
|
||||
|
abp.log.error = function (logObject) { |
||||
|
abp.log.log("ERROR: ", abp.log.levels.ERROR); |
||||
|
abp.log.log(logObject, abp.log.levels.ERROR); |
||||
|
}; |
||||
|
|
||||
|
abp.log.fatal = function (logObject) { |
||||
|
abp.log.log("FATAL: ", abp.log.levels.FATAL); |
||||
|
abp.log.log(logObject, abp.log.levels.FATAL); |
||||
|
}; |
||||
|
|
||||
|
/* LOCALIZATION ***********************************************/ |
||||
|
|
||||
|
abp.localization = abp.localization || {}; |
||||
|
|
||||
|
abp.localization.values = {}; |
||||
|
|
||||
|
abp.localization.localize = function (key, sourceName) { |
||||
|
sourceName = sourceName || abp.localization.defaultResourceName; |
||||
|
|
||||
|
var source = abp.localization.values[sourceName]; |
||||
|
|
||||
|
if (!source) { |
||||
|
abp.log.warn('Could not find localization source: ' + sourceName); |
||||
|
return key; |
||||
|
} |
||||
|
|
||||
|
var value = source[key]; |
||||
|
if (value == undefined) { |
||||
|
return key; |
||||
|
} |
||||
|
|
||||
|
var copiedArguments = Array.prototype.slice.call(arguments, 0); |
||||
|
copiedArguments.splice(1, 1); |
||||
|
copiedArguments[0] = value; |
||||
|
|
||||
|
return abp.utils.formatString.apply(this, copiedArguments); |
||||
|
}; |
||||
|
|
||||
|
abp.localization.getResource = function (name) { |
||||
|
return function () { |
||||
|
var copiedArguments = Array.prototype.slice.call(arguments, 0); |
||||
|
copiedArguments.splice(1, 0, name); |
||||
|
return abp.localization.localize.apply(this, copiedArguments); |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
abp.localization.defaultResourceName = undefined; |
||||
|
|
||||
|
/* AUTHORIZATION **********************************************/ |
||||
|
|
||||
|
abp.auth = abp.auth || {}; |
||||
|
|
||||
|
abp.auth.policies = abp.auth.policies || {}; |
||||
|
|
||||
|
abp.auth.grantedPolicies = abp.auth.grantedPolicies || {}; |
||||
|
|
||||
|
abp.auth.isGranted = function (policyName) { |
||||
|
return abp.auth.policies[policyName] != undefined && abp.auth.grantedPolicies[policyName] != undefined; |
||||
|
}; |
||||
|
|
||||
|
abp.auth.isAnyGranted = function () { |
||||
|
if (!arguments || arguments.length <= 0) { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
for (var i = 0; i < arguments.length; i++) { |
||||
|
if (abp.auth.isGranted(arguments[i])) { |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
}; |
||||
|
|
||||
|
abp.auth.areAllGranted = function () { |
||||
|
if (!arguments || arguments.length <= 0) { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
for (var i = 0; i < arguments.length; i++) { |
||||
|
if (!abp.auth.isGranted(arguments[i])) { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
}; |
||||
|
|
||||
|
abp.auth.tokenCookieName = 'Abp.AuthToken'; |
||||
|
|
||||
|
abp.auth.setToken = function (authToken, expireDate) { |
||||
|
abp.utils.setCookieValue(abp.auth.tokenCookieName, authToken, expireDate, abp.appPath, abp.domain); |
||||
|
}; |
||||
|
|
||||
|
abp.auth.getToken = function () { |
||||
|
return abp.utils.getCookieValue(abp.auth.tokenCookieName); |
||||
|
} |
||||
|
|
||||
|
abp.auth.clearToken = function () { |
||||
|
abp.auth.setToken(); |
||||
|
} |
||||
|
|
||||
|
/* NOTIFICATION *********************************************/ |
||||
|
//Defines Notification API, not implements it
|
||||
|
|
||||
|
abp.notify = abp.notify || {}; |
||||
|
|
||||
|
abp.notify.success = function (message, title, options) { |
||||
|
abp.log.warn('abp.notify.success is not implemented!'); |
||||
|
}; |
||||
|
|
||||
|
abp.notify.info = function (message, title, options) { |
||||
|
abp.log.warn('abp.notify.info is not implemented!'); |
||||
|
}; |
||||
|
|
||||
|
abp.notify.warn = function (message, title, options) { |
||||
|
abp.log.warn('abp.notify.warn is not implemented!'); |
||||
|
}; |
||||
|
|
||||
|
abp.notify.error = function (message, title, options) { |
||||
|
abp.log.warn('abp.notify.error is not implemented!'); |
||||
|
}; |
||||
|
|
||||
|
/* MESSAGE **************************************************/ |
||||
|
//Defines Message API, not implements it
|
||||
|
|
||||
|
abp.message = abp.message || {}; |
||||
|
|
||||
|
abp.message._showMessage = function (message, title) { |
||||
|
alert((title || '') + ' ' + message); |
||||
|
}; |
||||
|
|
||||
|
abp.message.info = function (message, title) { |
||||
|
abp.log.warn('abp.message.info is not implemented!'); |
||||
|
return abp.message._showMessage(message, title); |
||||
|
}; |
||||
|
|
||||
|
abp.message.success = function (message, title) { |
||||
|
abp.log.warn('abp.message.success is not implemented!'); |
||||
|
return abp.message._showMessage(message, title); |
||||
|
}; |
||||
|
|
||||
|
abp.message.warn = function (message, title) { |
||||
|
abp.log.warn('abp.message.warn is not implemented!'); |
||||
|
return abp.message._showMessage(message, title); |
||||
|
}; |
||||
|
|
||||
|
abp.message.error = function (message, title) { |
||||
|
abp.log.warn('abp.message.error is not implemented!'); |
||||
|
return abp.message._showMessage(message, title); |
||||
|
}; |
||||
|
|
||||
|
abp.message.confirm = function (message, titleOrCallback, callback) { |
||||
|
abp.log.warn('abp.message.confirm is not properly implemented!'); |
||||
|
|
||||
|
if (titleOrCallback && !(typeof titleOrCallback == 'string')) { |
||||
|
callback = titleOrCallback; |
||||
|
} |
||||
|
|
||||
|
var result = confirm(message); |
||||
|
callback && callback(result); |
||||
|
}; |
||||
|
|
||||
|
/* UI *******************************************************/ |
||||
|
|
||||
|
abp.ui = abp.ui || {}; |
||||
|
|
||||
|
/* UI BLOCK */ |
||||
|
//Defines UI Block API, not implements it
|
||||
|
|
||||
|
abp.ui.block = function (elm) { |
||||
|
abp.log.warn('abp.ui.block is not implemented!'); |
||||
|
}; |
||||
|
|
||||
|
abp.ui.unblock = function (elm) { |
||||
|
abp.log.warn('abp.ui.unblock is not implemented!'); |
||||
|
}; |
||||
|
|
||||
|
/* UI BUSY */ |
||||
|
//Defines UI Busy API, not implements it
|
||||
|
|
||||
|
abp.ui.setBusy = function (elm, optionsOrPromise) { |
||||
|
abp.log.warn('abp.ui.setBusy is not implemented!'); |
||||
|
}; |
||||
|
|
||||
|
abp.ui.clearBusy = function (elm) { |
||||
|
abp.log.warn('abp.ui.clearBusy is not implemented!'); |
||||
|
}; |
||||
|
|
||||
|
/* SIMPLE EVENT BUS *****************************************/ |
||||
|
|
||||
|
abp.event = (function () { |
||||
|
|
||||
|
var _callbacks = {}; |
||||
|
|
||||
|
var on = function (eventName, callback) { |
||||
|
if (!_callbacks[eventName]) { |
||||
|
_callbacks[eventName] = []; |
||||
|
} |
||||
|
|
||||
|
_callbacks[eventName].push(callback); |
||||
|
}; |
||||
|
|
||||
|
var off = function (eventName, callback) { |
||||
|
var callbacks = _callbacks[eventName]; |
||||
|
if (!callbacks) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var index = -1; |
||||
|
for (var i = 0; i < callbacks.length; i++) { |
||||
|
if (callbacks[i] === callback) { |
||||
|
index = i; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (index < 0) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
_callbacks[eventName].splice(index, 1); |
||||
|
}; |
||||
|
|
||||
|
var trigger = function (eventName) { |
||||
|
var callbacks = _callbacks[eventName]; |
||||
|
if (!callbacks || !callbacks.length) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var args = Array.prototype.slice.call(arguments, 1); |
||||
|
for (var i = 0; i < callbacks.length; i++) { |
||||
|
callbacks[i].apply(this, args); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Public interface ///////////////////////////////////////////////////
|
||||
|
|
||||
|
return { |
||||
|
on: on, |
||||
|
off: off, |
||||
|
trigger: trigger |
||||
|
}; |
||||
|
})(); |
||||
|
|
||||
|
|
||||
|
/* UTILS ***************************************************/ |
||||
|
|
||||
|
abp.utils = abp.utils || {}; |
||||
|
|
||||
|
/* Creates a name namespace. |
||||
|
* Example: |
||||
|
* var taskService = abp.utils.createNamespace(abp, 'services.task'); |
||||
|
* taskService will be equal to abp.services.task |
||||
|
* first argument (root) must be defined first |
||||
|
************************************************************/ |
||||
|
abp.utils.createNamespace = function (root, ns) { |
||||
|
var parts = ns.split('.'); |
||||
|
for (var i = 0; i < parts.length; i++) { |
||||
|
if (typeof root[parts[i]] == 'undefined') { |
||||
|
root[parts[i]] = {}; |
||||
|
} |
||||
|
|
||||
|
root = root[parts[i]]; |
||||
|
} |
||||
|
|
||||
|
return root; |
||||
|
}; |
||||
|
|
||||
|
/* Find and replaces a string (search) to another string (replacement) in |
||||
|
* given string (str). |
||||
|
* Example: |
||||
|
* abp.utils.replaceAll('This is a test string', 'is', 'X') = 'ThX X a test string' |
||||
|
************************************************************/ |
||||
|
abp.utils.replaceAll = function (str, search, replacement) { |
||||
|
var fix = search.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); |
||||
|
return str.replace(new RegExp(fix, 'g'), replacement); |
||||
|
}; |
||||
|
|
||||
|
/* Formats a string just like string.format in C#. |
||||
|
* Example: |
||||
|
* abp.utils.formatString('Hello {0}','Tuana') = 'Hello Tuana' |
||||
|
************************************************************/ |
||||
|
abp.utils.formatString = function () { |
||||
|
if (arguments.length < 1) { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
var str = arguments[0]; |
||||
|
|
||||
|
for (var i = 1; i < arguments.length; i++) { |
||||
|
var placeHolder = '{' + (i - 1) + '}'; |
||||
|
str = abp.utils.replaceAll(str, placeHolder, arguments[i]); |
||||
|
} |
||||
|
|
||||
|
return str; |
||||
|
}; |
||||
|
|
||||
|
abp.utils.toPascalCase = function (str) { |
||||
|
if (!str || !str.length) { |
||||
|
return str; |
||||
|
} |
||||
|
|
||||
|
if (str.length === 1) { |
||||
|
return str.charAt(0).toUpperCase(); |
||||
|
} |
||||
|
|
||||
|
return str.charAt(0).toUpperCase() + str.substr(1); |
||||
|
} |
||||
|
|
||||
|
abp.utils.toCamelCase = function (str) { |
||||
|
if (!str || !str.length) { |
||||
|
return str; |
||||
|
} |
||||
|
|
||||
|
if (str.length === 1) { |
||||
|
return str.charAt(0).toLowerCase(); |
||||
|
} |
||||
|
|
||||
|
return str.charAt(0).toLowerCase() + str.substr(1); |
||||
|
} |
||||
|
|
||||
|
abp.utils.truncateString = function (str, maxLength) { |
||||
|
if (!str || !str.length || str.length <= maxLength) { |
||||
|
return str; |
||||
|
} |
||||
|
|
||||
|
return str.substr(0, maxLength); |
||||
|
}; |
||||
|
|
||||
|
abp.utils.truncateStringWithPostfix = function (str, maxLength, postfix) { |
||||
|
postfix = postfix || '...'; |
||||
|
|
||||
|
if (!str || !str.length || str.length <= maxLength) { |
||||
|
return str; |
||||
|
} |
||||
|
|
||||
|
if (maxLength <= postfix.length) { |
||||
|
return postfix.substr(0, maxLength); |
||||
|
} |
||||
|
|
||||
|
return str.substr(0, maxLength - postfix.length) + postfix; |
||||
|
}; |
||||
|
|
||||
|
abp.utils.isFunction = function (obj) { |
||||
|
return !!(obj && obj.constructor && obj.call && obj.apply); |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* parameterInfos should be an array of { name, value } objects |
||||
|
* where name is query string parameter name and value is it's value. |
||||
|
* includeQuestionMark is true by default. |
||||
|
*/ |
||||
|
abp.utils.buildQueryString = function (parameterInfos, includeQuestionMark) { |
||||
|
if (includeQuestionMark === undefined) { |
||||
|
includeQuestionMark = true; |
||||
|
} |
||||
|
|
||||
|
var qs = ''; |
||||
|
|
||||
|
function addSeperator() { |
||||
|
if (!qs.length) { |
||||
|
if (includeQuestionMark) { |
||||
|
qs = qs + '?'; |
||||
|
} |
||||
|
} else { |
||||
|
qs = qs + '&'; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (var i = 0; i < parameterInfos.length; ++i) { |
||||
|
var parameterInfo = parameterInfos[i]; |
||||
|
if (parameterInfo.value === undefined) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
if (parameterInfo.value === null) { |
||||
|
parameterInfo.value = ''; |
||||
|
} |
||||
|
|
||||
|
addSeperator(); |
||||
|
|
||||
|
if (parameterInfo.value.toJSON && typeof parameterInfo.value.toJSON === "function") { |
||||
|
qs = qs + parameterInfo.name + '=' + encodeURIComponent(parameterInfo.value.toJSON()); |
||||
|
} else if (Array.isArray(parameterInfo.value) && parameterInfo.value.length) { |
||||
|
for (var j = 0; j < parameterInfo.value.length; j++) { |
||||
|
if (j > 0) { |
||||
|
addSeperator(); |
||||
|
} |
||||
|
|
||||
|
qs = qs + parameterInfo.name + '[' + j + ']=' + encodeURIComponent(parameterInfo.value[j]); |
||||
|
} |
||||
|
} else { |
||||
|
qs = qs + parameterInfo.name + '=' + encodeURIComponent(parameterInfo.value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return qs; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Sets a cookie value for given key. |
||||
|
* This is a simple implementation created to be used by ABP. |
||||
|
* Please use a complete cookie library if you need. |
||||
|
* @param {string} key |
||||
|
* @param {string} value |
||||
|
* @param {Date} expireDate (optional). If not specified the cookie will expire at the end of session. |
||||
|
* @param {string} path (optional) |
||||
|
*/ |
||||
|
abp.utils.setCookieValue = function (key, value, expireDate, path) { |
||||
|
var cookieValue = encodeURIComponent(key) + '='; |
||||
|
|
||||
|
if (value) { |
||||
|
cookieValue = cookieValue + encodeURIComponent(value); |
||||
|
} |
||||
|
|
||||
|
if (expireDate) { |
||||
|
cookieValue = cookieValue + "; expires=" + expireDate.toUTCString(); |
||||
|
} |
||||
|
|
||||
|
if (path) { |
||||
|
cookieValue = cookieValue + "; path=" + path; |
||||
|
} |
||||
|
|
||||
|
document.cookie = cookieValue; |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Gets a cookie with given key. |
||||
|
* This is a simple implementation created to be used by ABP. |
||||
|
* Please use a complete cookie library if you need. |
||||
|
* @param {string} key |
||||
|
* @returns {string} Cookie value or null |
||||
|
*/ |
||||
|
abp.utils.getCookieValue = function (key) { |
||||
|
var equalities = document.cookie.split('; '); |
||||
|
for (var i = 0; i < equalities.length; i++) { |
||||
|
if (!equalities[i]) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
var splitted = equalities[i].split('='); |
||||
|
if (splitted.length != 2) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
if (decodeURIComponent(splitted[0]) === key) { |
||||
|
return decodeURIComponent(splitted[1] || ''); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Deletes cookie for given key. |
||||
|
* This is a simple implementation created to be used by ABP. |
||||
|
* Please use a complete cookie library if you need. |
||||
|
* @param {string} key |
||||
|
* @param {string} path (optional) |
||||
|
*/ |
||||
|
abp.utils.deleteCookie = function (key, path) { |
||||
|
var cookieValue = encodeURIComponent(key) + '='; |
||||
|
|
||||
|
cookieValue = cookieValue + "; expires=" + (new Date(new Date().getTime() - 86400000)).toUTCString(); |
||||
|
|
||||
|
if (path) { |
||||
|
cookieValue = cookieValue + "; path=" + path; |
||||
|
} |
||||
|
|
||||
|
document.cookie = cookieValue; |
||||
|
} |
||||
|
|
||||
|
/* SECURITY ***************************************/ |
||||
|
abp.security = abp.security || {}; |
||||
|
abp.security.antiForgery = abp.security.antiForgery || {}; |
||||
|
|
||||
|
abp.security.antiForgery.tokenCookieName = 'XSRF-TOKEN'; |
||||
|
abp.security.antiForgery.tokenHeaderName = 'X-XSRF-TOKEN'; |
||||
|
|
||||
|
abp.security.antiForgery.getToken = function () { |
||||
|
return abp.utils.getCookieValue(abp.security.antiForgery.tokenCookieName); |
||||
|
}; |
||||
|
|
||||
|
})(); |
||||
@ -0,0 +1,389 @@ |
|||||
|
var abp = abp || {}; |
||||
|
(function($) { |
||||
|
|
||||
|
if (!$) { |
||||
|
throw "abp/jquery library requires the jquery library included to the page!"; |
||||
|
} |
||||
|
|
||||
|
// ABP CORE OVERRIDES /////////////////////////////////////////////////////
|
||||
|
|
||||
|
abp.message._showMessage = function (message, title) { |
||||
|
alert((title || '') + ' ' + message); |
||||
|
|
||||
|
return $.Deferred(function ($dfd) { |
||||
|
$dfd.resolve(); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
abp.message.confirm = function (message, titleOrCallback, callback) { |
||||
|
if (titleOrCallback && !(typeof titleOrCallback == 'string')) { |
||||
|
callback = titleOrCallback; |
||||
|
} |
||||
|
|
||||
|
var result = confirm(message); |
||||
|
callback && callback(result); |
||||
|
|
||||
|
return $.Deferred(function ($dfd) { |
||||
|
$dfd.resolve(result); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
abp.utils.isFunction = function (obj) { |
||||
|
return $.isFunction(obj); |
||||
|
}; |
||||
|
|
||||
|
// JQUERY EXTENSIONS //////////////////////////////////////////////////////
|
||||
|
|
||||
|
$.fn.findWithSelf = function (selector) { |
||||
|
return this.filter(selector).add(this.find(selector)); |
||||
|
}; |
||||
|
|
||||
|
// DOM ////////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
abp.dom = abp.dom || {}; |
||||
|
|
||||
|
abp.dom.onNodeAdded = function (callback) { |
||||
|
abp.event.on('abp.dom.nodeAdded', callback); |
||||
|
}; |
||||
|
|
||||
|
abp.dom.onNodeRemoved = function (callback) { |
||||
|
abp.event.on('abp.dom.nodeRemoved', callback); |
||||
|
}; |
||||
|
|
||||
|
var mutationObserverCallback = function (mutationsList) { |
||||
|
for (var i = 0; i < mutationsList.length; i++) { |
||||
|
var mutation = mutationsList[i]; |
||||
|
if (mutation.type === 'childList') { |
||||
|
if (mutation.addedNodes && mutation.removedNodes.length) { |
||||
|
for (var k = 0; k < mutation.removedNodes.length; k++) { |
||||
|
abp.event.trigger( |
||||
|
'abp.dom.nodeRemoved', |
||||
|
{ |
||||
|
$el: $(mutation.removedNodes[k]) |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (mutation.addedNodes && mutation.addedNodes.length) { |
||||
|
for (var j = 0; j < mutation.addedNodes.length; j++) { |
||||
|
abp.event.trigger( |
||||
|
'abp.dom.nodeAdded', |
||||
|
{ |
||||
|
$el: $(mutation.addedNodes[j]) |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
new MutationObserver(mutationObserverCallback).observe( |
||||
|
$('body')[0], |
||||
|
{ |
||||
|
subtree: true, |
||||
|
childList: true |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
// AJAX ///////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
abp.ajax = function (userOptions) { |
||||
|
userOptions = userOptions || {}; |
||||
|
|
||||
|
var options = $.extend(true, {}, abp.ajax.defaultOpts, userOptions); |
||||
|
|
||||
|
options.success = undefined; |
||||
|
options.error = undefined; |
||||
|
|
||||
|
return $.Deferred(function ($dfd) { |
||||
|
$.ajax(options) |
||||
|
.done(function (data, textStatus, jqXHR) { |
||||
|
$dfd.resolve(data); |
||||
|
userOptions.success && userOptions.success(data); |
||||
|
}).fail(function (jqXHR) { |
||||
|
if (jqXHR.getResponseHeader('_AbpErrorFormat') === 'true') { |
||||
|
abp.ajax.handleAbpErrorResponse(jqXHR, userOptions, $dfd); |
||||
|
} else { |
||||
|
abp.ajax.handleNonAbpErrorResponse(jqXHR, userOptions, $dfd); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
$.extend(abp.ajax, { |
||||
|
defaultOpts: { |
||||
|
dataType: 'json', |
||||
|
type: 'POST', |
||||
|
contentType: 'application/json', |
||||
|
headers: { |
||||
|
'X-Requested-With': 'XMLHttpRequest' |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
defaultError: { |
||||
|
message: 'An error has occurred!', |
||||
|
details: 'Error detail not sent by server.' |
||||
|
}, |
||||
|
|
||||
|
defaultError401: { |
||||
|
message: 'You are not authenticated!', |
||||
|
details: 'You should be authenticated (sign in) in order to perform this operation.' |
||||
|
}, |
||||
|
|
||||
|
defaultError403: { |
||||
|
message: 'You are not authorized!', |
||||
|
details: 'You are not allowed to perform this operation.' |
||||
|
}, |
||||
|
|
||||
|
defaultError404: { |
||||
|
message: 'Resource not found!', |
||||
|
details: 'The resource requested could not found on the server.' |
||||
|
}, |
||||
|
|
||||
|
logError: function (error) { |
||||
|
abp.log.error(error); |
||||
|
}, |
||||
|
|
||||
|
showError: function (error) { |
||||
|
if (error.details) { |
||||
|
return abp.message.error(error.details, error.message); |
||||
|
} else { |
||||
|
return abp.message.error(error.message || abp.ajax.defaultError.message); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
handleTargetUrl: function (targetUrl) { |
||||
|
if (!targetUrl) { |
||||
|
location.href = abp.appPath; |
||||
|
} else { |
||||
|
location.href = targetUrl; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
handleErrorStatusCode: function (status) { |
||||
|
switch (status) { |
||||
|
case 401: |
||||
|
abp.ajax.handleUnAuthorizedRequest( |
||||
|
abp.ajax.showError(abp.ajax.defaultError401), |
||||
|
abp.appPath |
||||
|
); |
||||
|
break; |
||||
|
case 403: |
||||
|
abp.ajax.showError(abp.ajax.defaultError403); |
||||
|
break; |
||||
|
case 404: |
||||
|
abp.ajax.showError(abp.ajax.defaultError404); |
||||
|
break; |
||||
|
default: |
||||
|
abp.ajax.showError(abp.ajax.defaultError); |
||||
|
break; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
handleNonAbpErrorResponse: function (jqXHR, userOptions, $dfd) { |
||||
|
if (userOptions.abpHandleError !== false) { |
||||
|
abp.ajax.handleErrorStatusCode(jqXHR.status); |
||||
|
} |
||||
|
|
||||
|
$dfd.reject.apply(this, arguments); |
||||
|
userOptions.error && userOptions.error.apply(this, arguments); |
||||
|
}, |
||||
|
|
||||
|
handleAbpErrorResponse: function (jqXHR, userOptions, $dfd) { |
||||
|
var messagePromise = null; |
||||
|
|
||||
|
if (userOptions.abpHandleError !== false) { |
||||
|
messagePromise = abp.ajax.showError(jqXHR.responseJSON.error); |
||||
|
} |
||||
|
|
||||
|
abp.ajax.logError(jqXHR.responseJSON.error); |
||||
|
|
||||
|
$dfd && $dfd.reject(jqXHR.responseJSON.error, jqXHR); |
||||
|
userOptions.error && userOptions.error(jqXHR.responseJSON.error, jqXHR); |
||||
|
|
||||
|
if (jqXHR.status === 401 && userOptions.abpHandleError !== false) { |
||||
|
abp.ajax.handleUnAuthorizedRequest(messagePromise); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
handleUnAuthorizedRequest: function (messagePromise, targetUrl) { |
||||
|
if (messagePromise) { |
||||
|
messagePromise.done(function () { |
||||
|
abp.ajax.handleTargetUrl(targetUrl); |
||||
|
}); |
||||
|
} else { |
||||
|
abp.ajax.handleTargetUrl(targetUrl); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
blockUI: function (options) { |
||||
|
if (options.blockUI) { |
||||
|
if (options.blockUI === true) { //block whole page
|
||||
|
abp.ui.setBusy(); |
||||
|
} else { //block an element
|
||||
|
abp.ui.setBusy(options.blockUI); |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
unblockUI: function (options) { |
||||
|
if (options.blockUI) { |
||||
|
if (options.blockUI === true) { //unblock whole page
|
||||
|
abp.ui.clearBusy(); |
||||
|
} else { //unblock an element
|
||||
|
abp.ui.clearBusy(options.blockUI); |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
ajaxSendHandler: function (event, request, settings) { |
||||
|
var token = abp.security.antiForgery.getToken(); |
||||
|
if (!token) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!settings.headers || settings.headers[abp.security.antiForgery.tokenHeaderName] === undefined) { |
||||
|
request.setRequestHeader(abp.security.antiForgery.tokenHeaderName, token); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
$(document).ajaxSend(function (event, request, settings) { |
||||
|
return abp.ajax.ajaxSendHandler(event, request, settings); |
||||
|
}); |
||||
|
|
||||
|
abp.event.on('abp.configurationInitialized', function () { |
||||
|
var l = abp.localization.getResource('AbpUi'); |
||||
|
|
||||
|
abp.ajax.defaultError.message = l('DefaultErrorMessage'); |
||||
|
abp.ajax.defaultError.details = l('DefaultErrorMessageDetail'); |
||||
|
abp.ajax.defaultError401.message = l('DefaultErrorMessage401'); |
||||
|
abp.ajax.defaultError401.details = l('DefaultErrorMessage401Detail'); |
||||
|
abp.ajax.defaultError403.message = l('DefaultErrorMessage403'); |
||||
|
abp.ajax.defaultError403.details = l('DefaultErrorMessage403Detail'); |
||||
|
abp.ajax.defaultError404.message = l('DefaultErrorMessage404'); |
||||
|
abp.ajax.defaultError404.details = l('DefaultErrorMessage404Detail'); |
||||
|
}); |
||||
|
|
||||
|
// RESOURCE LOADER ////////////////////////////////////////////////////////
|
||||
|
|
||||
|
/* UrlStates enum */ |
||||
|
var UrlStates = { |
||||
|
LOADING: 'LOADING', |
||||
|
LOADED: 'LOADED', |
||||
|
FAILED: 'FAILED' |
||||
|
}; |
||||
|
|
||||
|
/* UrlInfo class */ |
||||
|
function UrlInfo(url) { |
||||
|
this.url = url; |
||||
|
this.state = UrlStates.LOADING; |
||||
|
this.loadCallbacks = []; |
||||
|
this.failCallbacks = []; |
||||
|
} |
||||
|
|
||||
|
UrlInfo.prototype.succeed = function () { |
||||
|
this.state = UrlStates.LOADED; |
||||
|
for (var i = 0; i < this.loadCallbacks.length; i++) { |
||||
|
this.loadCallbacks[i](); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
UrlInfo.prototype.failed = function () { |
||||
|
this.state = UrlStates.FAILED; |
||||
|
for (var i = 0; i < this.failCallbacks.length; i++) { |
||||
|
this.failCallbacks[i](); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
UrlInfo.prototype.handleCallbacks = function (loadCallback, failCallback) { |
||||
|
switch (this.state) { |
||||
|
case UrlStates.LOADED: |
||||
|
loadCallback && loadCallback(); |
||||
|
break; |
||||
|
case UrlStates.FAILED: |
||||
|
failCallback && failCallback(); |
||||
|
break; |
||||
|
case UrlStates.LOADING: |
||||
|
this.addCallbacks(loadCallback, failCallback); |
||||
|
break; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
UrlInfo.prototype.addCallbacks = function (loadCallback, failCallback) { |
||||
|
loadCallback && this.loadCallbacks.push(loadCallback); |
||||
|
failCallback && this.failCallbacks.push(failCallback); |
||||
|
}; |
||||
|
|
||||
|
/* ResourceLoader API */ |
||||
|
|
||||
|
abp.ResourceLoader = (function () { |
||||
|
|
||||
|
var _urlInfos = {}; |
||||
|
|
||||
|
function getCacheKey(url) { |
||||
|
return url; |
||||
|
} |
||||
|
|
||||
|
function appendTimeToUrl(url) { |
||||
|
|
||||
|
if (url.indexOf('?') < 0) { |
||||
|
url += '?'; |
||||
|
} else { |
||||
|
url += '&'; |
||||
|
} |
||||
|
|
||||
|
url += '_=' + new Date().getTime(); |
||||
|
|
||||
|
return url; |
||||
|
} |
||||
|
|
||||
|
var _loadFromUrl = function (url, loadCallback, failCallback, serverLoader) { |
||||
|
|
||||
|
var cacheKey = getCacheKey(url); |
||||
|
|
||||
|
var urlInfo = _urlInfos[cacheKey]; |
||||
|
|
||||
|
if (urlInfo) { |
||||
|
urlInfo.handleCallbacks(loadCallback, failCallback); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
_urlInfos[cacheKey] = urlInfo = new UrlInfo(url); |
||||
|
urlInfo.addCallbacks(loadCallback, failCallback); |
||||
|
|
||||
|
serverLoader(urlInfo); |
||||
|
}; |
||||
|
|
||||
|
var _loadScript = function (url, loadCallback, failCallback) { |
||||
|
_loadFromUrl(url, loadCallback, failCallback, function (urlInfo) { |
||||
|
$.getScript(url) |
||||
|
.done(function () { |
||||
|
urlInfo.succeed(); |
||||
|
}) |
||||
|
.fail(function () { |
||||
|
urlInfo.failed(); |
||||
|
}); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
var _loadStyle = function (url) { |
||||
|
_loadFromUrl(url, undefined, undefined, function (urlInfo) { |
||||
|
|
||||
|
$('<link/>', { |
||||
|
rel: 'stylesheet', |
||||
|
type: 'text/css', |
||||
|
href: appendTimeToUrl(url) |
||||
|
}).appendTo('head'); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
return { |
||||
|
loadScript: _loadScript, |
||||
|
loadStyle: _loadStyle |
||||
|
} |
||||
|
})(); |
||||
|
|
||||
|
})(jQuery); |
||||
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,206 @@ |
|||||
|
table.dataTable { |
||||
|
clear: both; |
||||
|
margin-top: 6px !important; |
||||
|
margin-bottom: 6px !important; |
||||
|
max-width: none !important; |
||||
|
border-collapse: separate !important; |
||||
|
border-spacing: 0; |
||||
|
} |
||||
|
table.dataTable td, |
||||
|
table.dataTable th { |
||||
|
-webkit-box-sizing: content-box; |
||||
|
box-sizing: content-box; |
||||
|
} |
||||
|
table.dataTable td.dataTables_empty, |
||||
|
table.dataTable th.dataTables_empty { |
||||
|
text-align: center; |
||||
|
} |
||||
|
table.dataTable.nowrap th, |
||||
|
table.dataTable.nowrap td { |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
div.dataTables_wrapper div.dataTables_length label { |
||||
|
font-weight: normal; |
||||
|
text-align: left; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
div.dataTables_wrapper div.dataTables_length select { |
||||
|
width: auto; |
||||
|
display: inline-block; |
||||
|
} |
||||
|
div.dataTables_wrapper div.dataTables_filter { |
||||
|
text-align: right; |
||||
|
} |
||||
|
div.dataTables_wrapper div.dataTables_filter label { |
||||
|
font-weight: normal; |
||||
|
white-space: nowrap; |
||||
|
text-align: left; |
||||
|
} |
||||
|
div.dataTables_wrapper div.dataTables_filter input { |
||||
|
margin-left: 0.5em; |
||||
|
display: inline-block; |
||||
|
width: auto; |
||||
|
} |
||||
|
div.dataTables_wrapper div.dataTables_info { |
||||
|
padding-top: 0.85em; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
div.dataTables_wrapper div.dataTables_paginate { |
||||
|
margin: 0; |
||||
|
white-space: nowrap; |
||||
|
text-align: right; |
||||
|
} |
||||
|
div.dataTables_wrapper div.dataTables_paginate ul.pagination { |
||||
|
margin: 2px 0; |
||||
|
white-space: nowrap; |
||||
|
justify-content: flex-end; |
||||
|
} |
||||
|
div.dataTables_wrapper div.dataTables_processing { |
||||
|
position: absolute; |
||||
|
top: 50%; |
||||
|
left: 50%; |
||||
|
width: 200px; |
||||
|
margin-left: -100px; |
||||
|
margin-top: -26px; |
||||
|
text-align: center; |
||||
|
padding: 1em 0; |
||||
|
} |
||||
|
|
||||
|
table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting, |
||||
|
table.dataTable thead > tr > td.sorting_asc, |
||||
|
table.dataTable thead > tr > td.sorting_desc, |
||||
|
table.dataTable thead > tr > td.sorting { |
||||
|
padding-right: 30px; |
||||
|
} |
||||
|
table.dataTable thead > tr > th:active, |
||||
|
table.dataTable thead > tr > td:active { |
||||
|
outline: none; |
||||
|
} |
||||
|
table.dataTable thead .sorting, |
||||
|
table.dataTable thead .sorting_asc, |
||||
|
table.dataTable thead .sorting_desc, |
||||
|
table.dataTable thead .sorting_asc_disabled, |
||||
|
table.dataTable thead .sorting_desc_disabled { |
||||
|
cursor: pointer; |
||||
|
position: relative; |
||||
|
} |
||||
|
table.dataTable thead .sorting:before, table.dataTable thead .sorting:after, |
||||
|
table.dataTable thead .sorting_asc:before, |
||||
|
table.dataTable thead .sorting_asc:after, |
||||
|
table.dataTable thead .sorting_desc:before, |
||||
|
table.dataTable thead .sorting_desc:after, |
||||
|
table.dataTable thead .sorting_asc_disabled:before, |
||||
|
table.dataTable thead .sorting_asc_disabled:after, |
||||
|
table.dataTable thead .sorting_desc_disabled:before, |
||||
|
table.dataTable thead .sorting_desc_disabled:after { |
||||
|
position: absolute; |
||||
|
bottom: 0.9em; |
||||
|
display: block; |
||||
|
opacity: 0.3; |
||||
|
} |
||||
|
table.dataTable thead .sorting:before, |
||||
|
table.dataTable thead .sorting_asc:before, |
||||
|
table.dataTable thead .sorting_desc:before, |
||||
|
table.dataTable thead .sorting_asc_disabled:before, |
||||
|
table.dataTable thead .sorting_desc_disabled:before { |
||||
|
right: 1em; |
||||
|
content: "\2191"; |
||||
|
} |
||||
|
table.dataTable thead .sorting:after, |
||||
|
table.dataTable thead .sorting_asc:after, |
||||
|
table.dataTable thead .sorting_desc:after, |
||||
|
table.dataTable thead .sorting_asc_disabled:after, |
||||
|
table.dataTable thead .sorting_desc_disabled:after { |
||||
|
right: 0.5em; |
||||
|
content: "\2193"; |
||||
|
} |
||||
|
table.dataTable thead .sorting_asc:before, |
||||
|
table.dataTable thead .sorting_desc:after { |
||||
|
opacity: 1; |
||||
|
} |
||||
|
table.dataTable thead .sorting_asc_disabled:before, |
||||
|
table.dataTable thead .sorting_desc_disabled:after { |
||||
|
opacity: 0; |
||||
|
} |
||||
|
|
||||
|
div.dataTables_scrollHead table.dataTable { |
||||
|
margin-bottom: 0 !important; |
||||
|
} |
||||
|
|
||||
|
div.dataTables_scrollBody table { |
||||
|
border-top: none; |
||||
|
margin-top: 0 !important; |
||||
|
margin-bottom: 0 !important; |
||||
|
} |
||||
|
div.dataTables_scrollBody table thead .sorting:before, |
||||
|
div.dataTables_scrollBody table thead .sorting_asc:before, |
||||
|
div.dataTables_scrollBody table thead .sorting_desc:before, |
||||
|
div.dataTables_scrollBody table thead .sorting:after, |
||||
|
div.dataTables_scrollBody table thead .sorting_asc:after, |
||||
|
div.dataTables_scrollBody table thead .sorting_desc:after { |
||||
|
display: none; |
||||
|
} |
||||
|
div.dataTables_scrollBody table tbody tr:first-child th, |
||||
|
div.dataTables_scrollBody table tbody tr:first-child td { |
||||
|
border-top: none; |
||||
|
} |
||||
|
|
||||
|
div.dataTables_scrollFoot > .dataTables_scrollFootInner { |
||||
|
box-sizing: content-box; |
||||
|
} |
||||
|
div.dataTables_scrollFoot > .dataTables_scrollFootInner > table { |
||||
|
margin-top: 0 !important; |
||||
|
border-top: none; |
||||
|
} |
||||
|
|
||||
|
@media screen and (max-width: 767px) { |
||||
|
div.dataTables_wrapper div.dataTables_length, |
||||
|
div.dataTables_wrapper div.dataTables_filter, |
||||
|
div.dataTables_wrapper div.dataTables_info, |
||||
|
div.dataTables_wrapper div.dataTables_paginate { |
||||
|
text-align: center; |
||||
|
} |
||||
|
} |
||||
|
table.dataTable.table-sm > thead > tr > th { |
||||
|
padding-right: 20px; |
||||
|
} |
||||
|
table.dataTable.table-sm .sorting:before, |
||||
|
table.dataTable.table-sm .sorting_asc:before, |
||||
|
table.dataTable.table-sm .sorting_desc:before { |
||||
|
top: 5px; |
||||
|
right: 0.85em; |
||||
|
} |
||||
|
table.dataTable.table-sm .sorting:after, |
||||
|
table.dataTable.table-sm .sorting_asc:after, |
||||
|
table.dataTable.table-sm .sorting_desc:after { |
||||
|
top: 5px; |
||||
|
} |
||||
|
|
||||
|
table.table-bordered.dataTable th, |
||||
|
table.table-bordered.dataTable td { |
||||
|
border-left-width: 0; |
||||
|
} |
||||
|
table.table-bordered.dataTable th:last-child, table.table-bordered.dataTable th:last-child, |
||||
|
table.table-bordered.dataTable td:last-child, |
||||
|
table.table-bordered.dataTable td:last-child { |
||||
|
border-right-width: 0; |
||||
|
} |
||||
|
table.table-bordered.dataTable tbody th, |
||||
|
table.table-bordered.dataTable tbody td { |
||||
|
border-bottom-width: 0; |
||||
|
} |
||||
|
|
||||
|
div.dataTables_scrollHead table.table-bordered { |
||||
|
border-bottom-width: 0; |
||||
|
} |
||||
|
|
||||
|
div.table-responsive > div.dataTables_wrapper > div.row { |
||||
|
margin: 0; |
||||
|
} |
||||
|
div.table-responsive > div.dataTables_wrapper > div.row > div[class^="col-"]:first-child { |
||||
|
padding-left: 0; |
||||
|
} |
||||
|
div.table-responsive > div.dataTables_wrapper > div.row > div[class^="col-"]:last-child { |
||||
|
padding-right: 0; |
||||
|
} |
||||
@ -0,0 +1,184 @@ |
|||||
|
/*! DataTables Bootstrap 4 integration |
||||
|
* ©2011-2017 SpryMedia Ltd - datatables.net/license |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* DataTables integration for Bootstrap 4. This requires Bootstrap 4 and |
||||
|
* DataTables 1.10 or newer. |
||||
|
* |
||||
|
* This file sets the defaults and adds options to DataTables to style its |
||||
|
* controls using Bootstrap. See http://datatables.net/manual/styling/bootstrap
|
||||
|
* for further information. |
||||
|
*/ |
||||
|
(function( factory ){ |
||||
|
if ( typeof define === 'function' && define.amd ) { |
||||
|
// AMD
|
||||
|
define( ['jquery', 'datatables.net'], function ( $ ) { |
||||
|
return factory( $, window, document ); |
||||
|
} ); |
||||
|
} |
||||
|
else if ( typeof exports === 'object' ) { |
||||
|
// CommonJS
|
||||
|
module.exports = function (root, $) { |
||||
|
if ( ! root ) { |
||||
|
root = window; |
||||
|
} |
||||
|
|
||||
|
if ( ! $ || ! $.fn.dataTable ) { |
||||
|
// Require DataTables, which attaches to jQuery, including
|
||||
|
// jQuery if needed and have a $ property so we can access the
|
||||
|
// jQuery object that is used
|
||||
|
$ = require('datatables.net')(root, $).$; |
||||
|
} |
||||
|
|
||||
|
return factory( $, root, root.document ); |
||||
|
}; |
||||
|
} |
||||
|
else { |
||||
|
// Browser
|
||||
|
factory( jQuery, window, document ); |
||||
|
} |
||||
|
}(function( $, window, document, undefined ) { |
||||
|
'use strict'; |
||||
|
var DataTable = $.fn.dataTable; |
||||
|
|
||||
|
|
||||
|
/* Set the defaults for DataTables initialisation */ |
||||
|
$.extend( true, DataTable.defaults, { |
||||
|
dom: |
||||
|
"<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>>" + |
||||
|
"<'row'<'col-sm-12'tr>>" + |
||||
|
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>", |
||||
|
renderer: 'bootstrap' |
||||
|
} ); |
||||
|
|
||||
|
|
||||
|
/* Default class modification */ |
||||
|
$.extend( DataTable.ext.classes, { |
||||
|
sWrapper: "dataTables_wrapper dt-bootstrap4", |
||||
|
sFilterInput: "form-control form-control-sm", |
||||
|
sLengthSelect: "custom-select custom-select-sm form-control form-control-sm", |
||||
|
sProcessing: "dataTables_processing card", |
||||
|
sPageButton: "paginate_button page-item" |
||||
|
} ); |
||||
|
|
||||
|
|
||||
|
/* Bootstrap paging button renderer */ |
||||
|
DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) { |
||||
|
var api = new DataTable.Api( settings ); |
||||
|
var classes = settings.oClasses; |
||||
|
var lang = settings.oLanguage.oPaginate; |
||||
|
var aria = settings.oLanguage.oAria.paginate || {}; |
||||
|
var btnDisplay, btnClass, counter=0; |
||||
|
|
||||
|
var attach = function( container, buttons ) { |
||||
|
var i, ien, node, button; |
||||
|
var clickHandler = function ( e ) { |
||||
|
e.preventDefault(); |
||||
|
if ( !$(e.currentTarget).hasClass('disabled') && api.page() != e.data.action ) { |
||||
|
api.page( e.data.action ).draw( 'page' ); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
for ( i=0, ien=buttons.length ; i<ien ; i++ ) { |
||||
|
button = buttons[i]; |
||||
|
|
||||
|
if ( $.isArray( button ) ) { |
||||
|
attach( container, button ); |
||||
|
} |
||||
|
else { |
||||
|
btnDisplay = ''; |
||||
|
btnClass = ''; |
||||
|
|
||||
|
switch ( button ) { |
||||
|
case 'ellipsis': |
||||
|
btnDisplay = '…'; |
||||
|
btnClass = 'disabled'; |
||||
|
break; |
||||
|
|
||||
|
case 'first': |
||||
|
btnDisplay = lang.sFirst; |
||||
|
btnClass = button + (page > 0 ? |
||||
|
'' : ' disabled'); |
||||
|
break; |
||||
|
|
||||
|
case 'previous': |
||||
|
btnDisplay = lang.sPrevious; |
||||
|
btnClass = button + (page > 0 ? |
||||
|
'' : ' disabled'); |
||||
|
break; |
||||
|
|
||||
|
case 'next': |
||||
|
btnDisplay = lang.sNext; |
||||
|
btnClass = button + (page < pages-1 ? |
||||
|
'' : ' disabled'); |
||||
|
break; |
||||
|
|
||||
|
case 'last': |
||||
|
btnDisplay = lang.sLast; |
||||
|
btnClass = button + (page < pages-1 ? |
||||
|
'' : ' disabled'); |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
btnDisplay = button + 1; |
||||
|
btnClass = page === button ? |
||||
|
'active' : ''; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
if ( btnDisplay ) { |
||||
|
node = $('<li>', { |
||||
|
'class': classes.sPageButton+' '+btnClass, |
||||
|
'id': idx === 0 && typeof button === 'string' ? |
||||
|
settings.sTableId +'_'+ button : |
||||
|
null |
||||
|
} ) |
||||
|
.append( $('<a>', { |
||||
|
'href': '#', |
||||
|
'aria-controls': settings.sTableId, |
||||
|
'aria-label': aria[ button ], |
||||
|
'data-dt-idx': counter, |
||||
|
'tabindex': settings.iTabIndex, |
||||
|
'class': 'page-link' |
||||
|
} ) |
||||
|
.html( btnDisplay ) |
||||
|
) |
||||
|
.appendTo( container ); |
||||
|
|
||||
|
settings.oApi._fnBindAction( |
||||
|
node, {action: button}, clickHandler |
||||
|
); |
||||
|
|
||||
|
counter++; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// IE9 throws an 'unknown error' if document.activeElement is used
|
||||
|
// inside an iframe or frame.
|
||||
|
var activeEl; |
||||
|
|
||||
|
try { |
||||
|
// Because this approach is destroying and recreating the paging
|
||||
|
// elements, focus is lost on the select button which is bad for
|
||||
|
// accessibility. So we want to restore focus once the draw has
|
||||
|
// completed
|
||||
|
activeEl = $(host).find(document.activeElement).data('dt-idx'); |
||||
|
} |
||||
|
catch (e) {} |
||||
|
|
||||
|
attach( |
||||
|
$(host).empty().html('<ul class="pagination"/>').children('ul'), |
||||
|
buttons |
||||
|
); |
||||
|
|
||||
|
if ( activeEl !== undefined ) { |
||||
|
$(host).find( '[data-dt-idx='+activeEl+']' ).focus(); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
return DataTable; |
||||
|
})); |
||||
File diff suppressed because it is too large
File diff suppressed because it is too large
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 434 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -0,0 +1,432 @@ |
|||||
|
// Unobtrusive validation support library for jQuery and jQuery Validate
|
||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
// @version v3.2.11
|
||||
|
|
||||
|
/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */ |
||||
|
/*global document: false, jQuery: false */ |
||||
|
|
||||
|
(function (factory) { |
||||
|
if (typeof define === 'function' && define.amd) { |
||||
|
// AMD. Register as an anonymous module.
|
||||
|
define("jquery.validate.unobtrusive", ['jquery-validation'], factory); |
||||
|
} else if (typeof module === 'object' && module.exports) { |
||||
|
// CommonJS-like environments that support module.exports
|
||||
|
module.exports = factory(require('jquery-validation')); |
||||
|
} else { |
||||
|
// Browser global
|
||||
|
jQuery.validator.unobtrusive = factory(jQuery); |
||||
|
} |
||||
|
}(function ($) { |
||||
|
var $jQval = $.validator, |
||||
|
adapters, |
||||
|
data_validation = "unobtrusiveValidation"; |
||||
|
|
||||
|
function setValidationValues(options, ruleName, value) { |
||||
|
options.rules[ruleName] = value; |
||||
|
if (options.message) { |
||||
|
options.messages[ruleName] = options.message; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function splitAndTrim(value) { |
||||
|
return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g); |
||||
|
} |
||||
|
|
||||
|
function escapeAttributeValue(value) { |
||||
|
// As mentioned on http://api.jquery.com/category/selectors/
|
||||
|
return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1"); |
||||
|
} |
||||
|
|
||||
|
function getModelPrefix(fieldName) { |
||||
|
return fieldName.substr(0, fieldName.lastIndexOf(".") + 1); |
||||
|
} |
||||
|
|
||||
|
function appendModelPrefix(value, prefix) { |
||||
|
if (value.indexOf("*.") === 0) { |
||||
|
value = value.replace("*.", prefix); |
||||
|
} |
||||
|
return value; |
||||
|
} |
||||
|
|
||||
|
function onError(error, inputElement) { // 'this' is the form element
|
||||
|
var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"), |
||||
|
replaceAttrValue = container.attr("data-valmsg-replace"), |
||||
|
replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null; |
||||
|
|
||||
|
container.removeClass("field-validation-valid").addClass("field-validation-error"); |
||||
|
error.data("unobtrusiveContainer", container); |
||||
|
|
||||
|
if (replace) { |
||||
|
container.empty(); |
||||
|
error.removeClass("input-validation-error").appendTo(container); |
||||
|
} |
||||
|
else { |
||||
|
error.hide(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function onErrors(event, validator) { // 'this' is the form element
|
||||
|
var container = $(this).find("[data-valmsg-summary=true]"), |
||||
|
list = container.find("ul"); |
||||
|
|
||||
|
if (list && list.length && validator.errorList.length) { |
||||
|
list.empty(); |
||||
|
container.addClass("validation-summary-errors").removeClass("validation-summary-valid"); |
||||
|
|
||||
|
$.each(validator.errorList, function () { |
||||
|
$("<li />").html(this.message).appendTo(list); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function onSuccess(error) { // 'this' is the form element
|
||||
|
var container = error.data("unobtrusiveContainer"); |
||||
|
|
||||
|
if (container) { |
||||
|
var replaceAttrValue = container.attr("data-valmsg-replace"), |
||||
|
replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null; |
||||
|
|
||||
|
container.addClass("field-validation-valid").removeClass("field-validation-error"); |
||||
|
error.removeData("unobtrusiveContainer"); |
||||
|
|
||||
|
if (replace) { |
||||
|
container.empty(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function onReset(event) { // 'this' is the form element
|
||||
|
var $form = $(this), |
||||
|
key = '__jquery_unobtrusive_validation_form_reset'; |
||||
|
if ($form.data(key)) { |
||||
|
return; |
||||
|
} |
||||
|
// Set a flag that indicates we're currently resetting the form.
|
||||
|
$form.data(key, true); |
||||
|
try { |
||||
|
$form.data("validator").resetForm(); |
||||
|
} finally { |
||||
|
$form.removeData(key); |
||||
|
} |
||||
|
|
||||
|
$form.find(".validation-summary-errors") |
||||
|
.addClass("validation-summary-valid") |
||||
|
.removeClass("validation-summary-errors"); |
||||
|
$form.find(".field-validation-error") |
||||
|
.addClass("field-validation-valid") |
||||
|
.removeClass("field-validation-error") |
||||
|
.removeData("unobtrusiveContainer") |
||||
|
.find(">*") // If we were using valmsg-replace, get the underlying error
|
||||
|
.removeData("unobtrusiveContainer"); |
||||
|
} |
||||
|
|
||||
|
function validationInfo(form) { |
||||
|
var $form = $(form), |
||||
|
result = $form.data(data_validation), |
||||
|
onResetProxy = $.proxy(onReset, form), |
||||
|
defaultOptions = $jQval.unobtrusive.options || {}, |
||||
|
execInContext = function (name, args) { |
||||
|
var func = defaultOptions[name]; |
||||
|
func && $.isFunction(func) && func.apply(form, args); |
||||
|
}; |
||||
|
|
||||
|
if (!result) { |
||||
|
result = { |
||||
|
options: { // options structure passed to jQuery Validate's validate() method
|
||||
|
errorClass: defaultOptions.errorClass || "input-validation-error", |
||||
|
errorElement: defaultOptions.errorElement || "span", |
||||
|
errorPlacement: function () { |
||||
|
onError.apply(form, arguments); |
||||
|
execInContext("errorPlacement", arguments); |
||||
|
}, |
||||
|
invalidHandler: function () { |
||||
|
onErrors.apply(form, arguments); |
||||
|
execInContext("invalidHandler", arguments); |
||||
|
}, |
||||
|
messages: {}, |
||||
|
rules: {}, |
||||
|
success: function () { |
||||
|
onSuccess.apply(form, arguments); |
||||
|
execInContext("success", arguments); |
||||
|
} |
||||
|
}, |
||||
|
attachValidation: function () { |
||||
|
$form |
||||
|
.off("reset." + data_validation, onResetProxy) |
||||
|
.on("reset." + data_validation, onResetProxy) |
||||
|
.validate(this.options); |
||||
|
}, |
||||
|
validate: function () { // a validation function that is called by unobtrusive Ajax
|
||||
|
$form.validate(); |
||||
|
return $form.valid(); |
||||
|
} |
||||
|
}; |
||||
|
$form.data(data_validation, result); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
$jQval.unobtrusive = { |
||||
|
adapters: [], |
||||
|
|
||||
|
parseElement: function (element, skipAttach) { |
||||
|
/// <summary>
|
||||
|
/// Parses a single HTML element for unobtrusive validation attributes.
|
||||
|
/// </summary>
|
||||
|
/// <param name="element" domElement="true">The HTML element to be parsed.</param>
|
||||
|
/// <param name="skipAttach" type="Boolean">[Optional] true to skip attaching the
|
||||
|
/// validation to the form. If parsing just this single element, you should specify true.
|
||||
|
/// If parsing several elements, you should specify false, and manually attach the validation
|
||||
|
/// to the form when you are finished. The default is false.</param>
|
||||
|
var $element = $(element), |
||||
|
form = $element.parents("form")[0], |
||||
|
valInfo, rules, messages; |
||||
|
|
||||
|
if (!form) { // Cannot do client-side validation without a form
|
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
valInfo = validationInfo(form); |
||||
|
valInfo.options.rules[element.name] = rules = {}; |
||||
|
valInfo.options.messages[element.name] = messages = {}; |
||||
|
|
||||
|
$.each(this.adapters, function () { |
||||
|
var prefix = "data-val-" + this.name, |
||||
|
message = $element.attr(prefix), |
||||
|
paramValues = {}; |
||||
|
|
||||
|
if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy)
|
||||
|
prefix += "-"; |
||||
|
|
||||
|
$.each(this.params, function () { |
||||
|
paramValues[this] = $element.attr(prefix + this); |
||||
|
}); |
||||
|
|
||||
|
this.adapt({ |
||||
|
element: element, |
||||
|
form: form, |
||||
|
message: message, |
||||
|
params: paramValues, |
||||
|
rules: rules, |
||||
|
messages: messages |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
$.extend(rules, { "__dummy__": true }); |
||||
|
|
||||
|
if (!skipAttach) { |
||||
|
valInfo.attachValidation(); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
parse: function (selector) { |
||||
|
/// <summary>
|
||||
|
/// Parses all the HTML elements in the specified selector. It looks for input elements decorated
|
||||
|
/// with the [data-val=true] attribute value and enables validation according to the data-val-*
|
||||
|
/// attribute values.
|
||||
|
/// </summary>
|
||||
|
/// <param name="selector" type="String">Any valid jQuery selector.</param>
|
||||
|
|
||||
|
// $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one
|
||||
|
// element with data-val=true
|
||||
|
var $selector = $(selector), |
||||
|
$forms = $selector.parents() |
||||
|
.addBack() |
||||
|
.filter("form") |
||||
|
.add($selector.find("form")) |
||||
|
.has("[data-val=true]"); |
||||
|
|
||||
|
$selector.find("[data-val=true]").each(function () { |
||||
|
$jQval.unobtrusive.parseElement(this, true); |
||||
|
}); |
||||
|
|
||||
|
$forms.each(function () { |
||||
|
var info = validationInfo(this); |
||||
|
if (info) { |
||||
|
info.attachValidation(); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
adapters = $jQval.unobtrusive.adapters; |
||||
|
|
||||
|
adapters.add = function (adapterName, params, fn) { |
||||
|
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation.</summary>
|
||||
|
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
|
||||
|
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
|
||||
|
/// <param name="params" type="Array" optional="true">[Optional] An array of parameter names (strings) that will
|
||||
|
/// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and
|
||||
|
/// mmmm is the parameter name).</param>
|
||||
|
/// <param name="fn" type="Function">The function to call, which adapts the values from the HTML
|
||||
|
/// attributes into jQuery Validate rules and/or messages.</param>
|
||||
|
/// <returns type="jQuery.validator.unobtrusive.adapters" />
|
||||
|
if (!fn) { // Called with no params, just a function
|
||||
|
fn = params; |
||||
|
params = []; |
||||
|
} |
||||
|
this.push({ name: adapterName, params: params, adapt: fn }); |
||||
|
return this; |
||||
|
}; |
||||
|
|
||||
|
adapters.addBool = function (adapterName, ruleName) { |
||||
|
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
|
||||
|
/// the jQuery Validate validation rule has no parameter values.</summary>
|
||||
|
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
|
||||
|
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
|
||||
|
/// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
|
||||
|
/// of adapterName will be used instead.</param>
|
||||
|
/// <returns type="jQuery.validator.unobtrusive.adapters" />
|
||||
|
return this.add(adapterName, function (options) { |
||||
|
setValidationValues(options, ruleName || adapterName, true); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) { |
||||
|
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
|
||||
|
/// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and
|
||||
|
/// one for min-and-max). The HTML parameters are expected to be named -min and -max.</summary>
|
||||
|
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
|
||||
|
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
|
||||
|
/// <param name="minRuleName" type="String">The name of the jQuery Validate rule to be used when you only
|
||||
|
/// have a minimum value.</param>
|
||||
|
/// <param name="maxRuleName" type="String">The name of the jQuery Validate rule to be used when you only
|
||||
|
/// have a maximum value.</param>
|
||||
|
/// <param name="minMaxRuleName" type="String">The name of the jQuery Validate rule to be used when you
|
||||
|
/// have both a minimum and maximum value.</param>
|
||||
|
/// <param name="minAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
|
||||
|
/// contains the minimum value. The default is "min".</param>
|
||||
|
/// <param name="maxAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
|
||||
|
/// contains the maximum value. The default is "max".</param>
|
||||
|
/// <returns type="jQuery.validator.unobtrusive.adapters" />
|
||||
|
return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) { |
||||
|
var min = options.params.min, |
||||
|
max = options.params.max; |
||||
|
|
||||
|
if (min && max) { |
||||
|
setValidationValues(options, minMaxRuleName, [min, max]); |
||||
|
} |
||||
|
else if (min) { |
||||
|
setValidationValues(options, minRuleName, min); |
||||
|
} |
||||
|
else if (max) { |
||||
|
setValidationValues(options, maxRuleName, max); |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
adapters.addSingleVal = function (adapterName, attribute, ruleName) { |
||||
|
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
|
||||
|
/// the jQuery Validate validation rule has a single value.</summary>
|
||||
|
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
|
||||
|
/// in the data-val-nnnn HTML attribute(where nnnn is the adapter name).</param>
|
||||
|
/// <param name="attribute" type="String">[Optional] The name of the HTML attribute that contains the value.
|
||||
|
/// The default is "val".</param>
|
||||
|
/// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
|
||||
|
/// of adapterName will be used instead.</param>
|
||||
|
/// <returns type="jQuery.validator.unobtrusive.adapters" />
|
||||
|
return this.add(adapterName, [attribute || "val"], function (options) { |
||||
|
setValidationValues(options, ruleName || adapterName, options.params[attribute]); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
$jQval.addMethod("__dummy__", function (value, element, params) { |
||||
|
return true; |
||||
|
}); |
||||
|
|
||||
|
$jQval.addMethod("regex", function (value, element, params) { |
||||
|
var match; |
||||
|
if (this.optional(element)) { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
match = new RegExp(params).exec(value); |
||||
|
return (match && (match.index === 0) && (match[0].length === value.length)); |
||||
|
}); |
||||
|
|
||||
|
$jQval.addMethod("nonalphamin", function (value, element, nonalphamin) { |
||||
|
var match; |
||||
|
if (nonalphamin) { |
||||
|
match = value.match(/\W/g); |
||||
|
match = match && match.length >= nonalphamin; |
||||
|
} |
||||
|
return match; |
||||
|
}); |
||||
|
|
||||
|
if ($jQval.methods.extension) { |
||||
|
adapters.addSingleVal("accept", "mimtype"); |
||||
|
adapters.addSingleVal("extension", "extension"); |
||||
|
} else { |
||||
|
// for backward compatibility, when the 'extension' validation method does not exist, such as with versions
|
||||
|
// of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for
|
||||
|
// validating the extension, and ignore mime-type validations as they are not supported.
|
||||
|
adapters.addSingleVal("extension", "extension", "accept"); |
||||
|
} |
||||
|
|
||||
|
adapters.addSingleVal("regex", "pattern"); |
||||
|
adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"); |
||||
|
adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range"); |
||||
|
adapters.addMinMax("minlength", "minlength").addMinMax("maxlength", "minlength", "maxlength"); |
||||
|
adapters.add("equalto", ["other"], function (options) { |
||||
|
var prefix = getModelPrefix(options.element.name), |
||||
|
other = options.params.other, |
||||
|
fullOtherName = appendModelPrefix(other, prefix), |
||||
|
element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0]; |
||||
|
|
||||
|
setValidationValues(options, "equalTo", element); |
||||
|
}); |
||||
|
adapters.add("required", function (options) { |
||||
|
// jQuery Validate equates "required" with "mandatory" for checkbox elements
|
||||
|
if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") { |
||||
|
setValidationValues(options, "required", true); |
||||
|
} |
||||
|
}); |
||||
|
adapters.add("remote", ["url", "type", "additionalfields"], function (options) { |
||||
|
var value = { |
||||
|
url: options.params.url, |
||||
|
type: options.params.type || "GET", |
||||
|
data: {} |
||||
|
}, |
||||
|
prefix = getModelPrefix(options.element.name); |
||||
|
|
||||
|
$.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) { |
||||
|
var paramName = appendModelPrefix(fieldName, prefix); |
||||
|
value.data[paramName] = function () { |
||||
|
var field = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']"); |
||||
|
// For checkboxes and radio buttons, only pick up values from checked fields.
|
||||
|
if (field.is(":checkbox")) { |
||||
|
return field.filter(":checked").val() || field.filter(":hidden").val() || ''; |
||||
|
} |
||||
|
else if (field.is(":radio")) { |
||||
|
return field.filter(":checked").val() || ''; |
||||
|
} |
||||
|
return field.val(); |
||||
|
}; |
||||
|
}); |
||||
|
|
||||
|
setValidationValues(options, "remote", value); |
||||
|
}); |
||||
|
adapters.add("password", ["min", "nonalphamin", "regex"], function (options) { |
||||
|
if (options.params.min) { |
||||
|
setValidationValues(options, "minlength", options.params.min); |
||||
|
} |
||||
|
if (options.params.nonalphamin) { |
||||
|
setValidationValues(options, "nonalphamin", options.params.nonalphamin); |
||||
|
} |
||||
|
if (options.params.regex) { |
||||
|
setValidationValues(options, "regex", options.params.regex); |
||||
|
} |
||||
|
}); |
||||
|
adapters.add("fileextensions", ["extensions"], function (options) { |
||||
|
setValidationValues(options, "extension", options.params.extensions); |
||||
|
}); |
||||
|
|
||||
|
$(function () { |
||||
|
$jQval.unobtrusive.parse(document); |
||||
|
}); |
||||
|
|
||||
|
return $jQval.unobtrusive; |
||||
|
})); |
||||
File diff suppressed because it is too large
@ -0,0 +1,35 @@ |
|||||
|
(function( factory ) { |
||||
|
if ( typeof define === "function" && define.amd ) { |
||||
|
define( ["jquery", "../jquery.validate"], factory ); |
||||
|
} else if (typeof module === "object" && module.exports) { |
||||
|
module.exports = factory( require( "jquery" ) ); |
||||
|
} else { |
||||
|
factory( jQuery ); |
||||
|
} |
||||
|
}(function( $ ) { |
||||
|
|
||||
|
/* |
||||
|
* Translated default messages for the jQuery validation plugin. |
||||
|
* Locale: AR (Arabic; العربية) |
||||
|
*/ |
||||
|
$.extend( $.validator.messages, { |
||||
|
required: "هذا الحقل إلزامي", |
||||
|
remote: "يرجى تصحيح هذا الحقل للمتابعة", |
||||
|
email: "رجاء إدخال عنوان بريد إلكتروني صحيح", |
||||
|
url: "رجاء إدخال عنوان موقع إلكتروني صحيح", |
||||
|
date: "رجاء إدخال تاريخ صحيح", |
||||
|
dateISO: "رجاء إدخال تاريخ صحيح (ISO)", |
||||
|
number: "رجاء إدخال عدد بطريقة صحيحة", |
||||
|
digits: "رجاء إدخال أرقام فقط", |
||||
|
creditcard: "رجاء إدخال رقم بطاقة ائتمان صحيح", |
||||
|
equalTo: "رجاء إدخال نفس القيمة", |
||||
|
extension: "رجاء إدخال ملف بامتداد موافق عليه", |
||||
|
maxlength: $.validator.format( "الحد الأقصى لعدد الحروف هو {0}" ), |
||||
|
minlength: $.validator.format( "الحد الأدنى لعدد الحروف هو {0}" ), |
||||
|
rangelength: $.validator.format( "عدد الحروف يجب أن يكون بين {0} و {1}" ), |
||||
|
range: $.validator.format( "رجاء إدخال عدد قيمته بين {0} و {1}" ), |
||||
|
max: $.validator.format( "رجاء إدخال عدد أقل من أو يساوي {0}" ), |
||||
|
min: $.validator.format( "رجاء إدخال عدد أكبر من أو يساوي {0}" ) |
||||
|
} ); |
||||
|
return $; |
||||
|
})); |
||||
@ -0,0 +1,4 @@ |
|||||
|
/*! jQuery Validation Plugin - v1.19.0 - 11/28/2018 |
||||
|
* https://jqueryvalidation.org/
|
||||
|
* Copyright (c) 2018 Jörn Zaefferer; Licensed MIT */ |
||||
|
!function(a){"function"==typeof define&&define.amd?define(["jquery","../jquery.validate.min"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){return a.extend(a.validator.messages,{required:"هذا الحقل إلزامي",remote:"يرجى تصحيح هذا الحقل للمتابعة",email:"رجاء إدخال عنوان بريد إلكتروني صحيح",url:"رجاء إدخال عنوان موقع إلكتروني صحيح",date:"رجاء إدخال تاريخ صحيح",dateISO:"رجاء إدخال تاريخ صحيح (ISO)",number:"رجاء إدخال عدد بطريقة صحيحة",digits:"رجاء إدخال أرقام فقط",creditcard:"رجاء إدخال رقم بطاقة ائتمان صحيح",equalTo:"رجاء إدخال نفس القيمة",extension:"رجاء إدخال ملف بامتداد موافق عليه",maxlength:a.validator.format("الحد الأقصى لعدد الحروف هو {0}"),minlength:a.validator.format("الحد الأدنى لعدد الحروف هو {0}"),rangelength:a.validator.format("عدد الحروف يجب أن يكون بين {0} و {1}"),range:a.validator.format("رجاء إدخال عدد قيمته بين {0} و {1}"),max:a.validator.format("رجاء إدخال عدد أقل من أو يساوي {0}"),min:a.validator.format("رجاء إدخال عدد أكبر من أو يساوي {0}")}),a}); |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue