1,创建一个空解决方案
2,层结构
PM.Core[v:4.6]:类库
PM.EntityFramework[v:4.6]:类库(引用PM.Core)
PM.Application[v:4.6]:类库(引用PM.Core)
PM.WebApi[v:4.6]:类库(引用PM.Application、PM.Core)
PM.Web[v:4.6]:WebMvc5.X(引用PM.Core、PM.EntityFramework、PM.Application、PM.WebApi)
PM.Test[v:4.6]:(引用PM.EntityFramework、PM.Core、PM.Application)
1,NuGet安装Abp.Zero2.1.3
程序集引用:System.ComponentModel.DataAnnotations
2,基本结构
Authorization
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.MultiTenancy; using Abp.Zero.Configuration; namespace PM.Core.Authorization.Roles { public class PMRoleConfig { public static void Configure(IRoleManagementConfig roleManagementConfig) { //静态主机角色 roleManagementConfig.StaticRoles.Add(new StaticRoleDefinition( StaticRoleNames.Host.Admin , MultiTenancySides.Host)); //静态租户角色 roleManagementConfig.StaticRoles.Add(new StaticRoleDefinition( StaticRoleNames.Tenants.Admin, MultiTenancySides.Tenant)); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Authorization.Roles; using PM.Core.Users; namespace PM.Core.Authorization.Roles { public class Role : AbpRole<User> { } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Authorization; using Abp.Authorization.Roles; using Abp.Domain.Uow; using Abp.Runtime.Caching; using Abp.Zero.Configuration; using PM.Core.Users; namespace PM.Core.Authorization.Roles { public class RoleManager:AbpRoleManager<Role,User> { public RoleManager( RoleStore store, IPermissionManager permissionManager, IRoleManagementConfig roleManagementConfig, ICacheManager cacheManager, IUnitOfWorkManager unitOfWorkManager) : base(store, permissionManager, roleManagementConfig, cacheManager, unitOfWorkManager) { } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Authorization.Roles; using Abp.Authorization.Users; using Abp.Domain.Repositories; using PM.Core.Users; namespace PM.Core.Authorization.Roles { public class RoleStore:AbpRoleStore<Role,User> { public RoleStore( IRepository<Role> roleRepository, IRepository<UserRole, long> userRoleRepository, IRepository<RolePermissionSetting, long> rolePermissionSettingRepository) : base(roleRepository, userRoleRepository, rolePermissionSettingRepository) { } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PM.Core.Authorization.Roles { public class StaticRoleNames { public static class Host { public const string Admin = "Admin"; } public static class Tenants { public const string Admin = "Admin"; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Authorization; using Abp.Authorization.Roles; using Abp.Authorization.Users; using Abp.Configuration; using Abp.Domain.Repositories; using Abp.Domain.Uow; using Abp.IdentityFramework; using Abp.Localization; using Abp.Organizations; using Abp.Runtime.Caching; using PM.Core.Authorization.Roles; namespace PM.Core.Users { public class UserManager : AbpUserManager<Role, User> { public UserManager( UserStore userStore, RoleManager roleManager, IPermissionManager permissionManager, IUnitOfWorkManager unitOfWorkManager, ICacheManager cacheManager, IRepository<OrganizationUnit, long> organizationUnitRepository, IRepository<UserOrganizationUnit, long> userOrganizationUnitRepository, IOrganizationUnitSettings organizationUnitSettings, ILocalizationManager localizationManager, IdentityEmailMessageService emailService, ISettingManager settingManager, IUserTokenProviderAccessor userTokenProviderAccessor) : base( userStore, roleManager, permissionManager, unitOfWorkManager, cacheManager, organizationUnitRepository, userOrganizationUnitRepository, organizationUnitSettings, localizationManager, emailService, settingManager, userTokenProviderAccessor) { } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Authorization.Users; using Abp.Domain.Repositories; using Abp.Domain.Uow; using PM.Core.Authorization.Roles; namespace PM.Core.Users { public class UserStore:AbpUserStore<Role,User> { public UserStore( IRepository<User, long> userRepository, IRepository<UserLogin, long> userLoginRepository, IRepository<UserRole, long> userRoleRepository, IRepository<Role> roleRepository, IRepository<UserPermissionSetting, long> userPermissionSettingRepository, IUnitOfWorkManager unitOfWorkManager, IRepository<UserClaim, long> userClaimRepository) : base( userRepository, userLoginRepository, userRoleRepository, roleRepository, userPermissionSettingRepository, unitOfWorkManager, userClaimRepository) { } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Authorization; using Abp.Authorization.Roles; using Abp.Authorization.Users; using Abp.Configuration; using Abp.Configuration.Startup; using Abp.Dependency; using Abp.Domain.Repositories; using Abp.Domain.Uow; using Abp.Zero.Configuration; using PM.Core.Authorization.Roles; using PM.Core.MultiTenant; using PM.Core.Users; namespace PM.Core.Authorization { public class LogInManager : AbpLogInManager<Tenant,Role,User> { public LogInManager( UserManager userManager, IMultiTenancyConfig multiTenancyConfig, IRepository<Tenant> tenantRepository, IUnitOfWorkManager unitOfWorkManager, ISettingManager settingManager, IRepository<UserLoginAttempt, long> userLoginAttemptRepository, IUserManagementConfig userManagementConfig, IIocResolver iocResolver, RoleManager roleManager) : base( userManager, multiTenancyConfig, tenantRepository, unitOfWorkManager, settingManager, userLoginAttemptRepository, userManagementConfig, iocResolver, roleManager) { } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Authorization; using Abp.Authorization.Users; using PM.Core.Authorization.Roles; using PM.Core.Users; namespace PM.Core.Authorization { public class PermissionChecker:PermissionChecker<Role,User> { public PermissionChecker(UserManager userManager) : base(userManager) { } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PM.Core.Authorization { public class PermisstionNames { public const string Pages_Tenants = "Pages.Tenants"; public const string Pages_Users = "Pages.Users"; public const string Pages_Roles = "Pages.Roles"; } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Authorization; using Abp.Localization; using Abp.Localization.Sources; using Abp.MultiTenancy; namespace PM.Core.Authorization { public class PMProjectNameAuthorizationProvider: AuthorizationProvider { public override void SetPermissions(IPermissionDefinitionContext context) { context.CreatePermission(PermisstionNames.Pages_Users, L("Users")); context.CreatePermission(PermisstionNames.Pages_Roles, L("Roles")); context.CreatePermission(PermisstionNames.Pages_Tenants, L("Tenants"),multiTenancySides:MultiTenancySides.Host); } private static ILocalizableString L(string name) { return new LocalizableString(name, PMProjectNameConsts.LocalizationSourceName); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Authorization.Users; using Abp.Extensions; using Microsoft.AspNet.Identity; namespace PM.Core.Users { public class User:AbpUser<User> { public const string DefaultPassword = "123qwe"; /// <summary> /// 创建随机密码 /// </summary> /// <returns></returns> public static string CreateRandomPassword() { //截断16位 return Guid.NewGuid().ToString("N").Truncate(16); } public static User CreateTenantAdminUser(int tenantId, string emailAddress, string password) { return new User() { TenantId = tenantId, UserName = AdminUserName, Name = AdminUserName, Surname = AdminUserName, EmailAddress = emailAddress, Password = new PasswordHasher().HashPassword(password), IsEmailConfirmed = true, IsActive = true }; } } }
Configuration
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PM.Core.Configuration { public class PMSettingNames { public const string UiTheme = "App.UiTheme"; } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Configuration; namespace PM.Core.Configuration { public class PMSettingProvider:SettingProvider { public override IEnumerable<SettingDefinition> GetSettingDefinitions(SettingDefinitionProviderContext context) { return new[] { new SettingDefinition(PMSettingNames.UiTheme, "red", scopes: SettingScopes.Application | SettingScopes.Tenant | SettingScopes.User, isVisibleToClients: true) }; } } }
Editions
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Application.Editions; using Abp.Application.Features; using Abp.Domain.Repositories; namespace PM.Core.Editions { public class EditionManager:AbpEditionManager { public const string DefaultEditionName = "Standard"; public EditionManager( IRepository<Edition> editionRepository, IAbpZeroFeatureValueStore featureValueStore) : base(editionRepository, featureValueStore) { } } }
Features
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Application.Features; using Abp.Domain.Repositories; using Abp.Domain.Uow; using Abp.MultiTenancy; using Abp.Runtime.Caching; using PM.Core.MultiTenant; using PM.Core.Users; namespace PM.Core.Features { public class FeaturesValueStore:AbpFeatureValueStore<Tenant,User> { public FeaturesValueStore( ICacheManager cacheManager, IRepository<TenantFeatureSetting, long> tenantFeatureRepository, IRepository<Tenant> tenantRepository, IRepository<EditionFeatureSetting, long> editionFeatureRepository, IFeatureManager featureManager, IUnitOfWorkManager unitOfWorkManager) : base( cacheManager, tenantFeatureRepository, tenantRepository, editionFeatureRepository, featureManager, unitOfWorkManager) { } } }
Localization
<?xml version="1.0" encoding="utf-8" ?> <localizationDictionary culture="zh-CN"> <texts> <text name="Users" value="用户"/> <text name="Roles" value="角色"/> <text name="Tenants" value="租户"/> </texts> </localizationDictionary>
<?xml version="1.0" encoding="utf-8" ?> <localizationDictionary culture="en"> <texts> <text name="Users" value="Users"/> <text name="Roles" value="Roles"/> <text name="Tenants" value="Tenants"/> </texts> </localizationDictionary>
MultiTenant
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.MultiTenancy; using PM.Core.Users; namespace PM.Core.MultiTenant { public class Tenant:AbpTenant<User> { } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Application.Editions; using Abp.Application.Features; using Abp.Domain.Repositories; using Abp.MultiTenancy; using PM.Core.Users; namespace PM.Core.MultiTenant { public class TenantManager:AbpTenantManager<Tenant,User> { public TenantManager( IRepository<Tenant> tenantRepository, IRepository<TenantFeatureSetting, long> tenantFeatureRepository, AbpEditionManager editionManager, IAbpZeroFeatureValueStore featureValueStore) : base(tenantRepository, tenantFeatureRepository, editionManager, featureValueStore) { } } }
Validation
using Abp.Extensions; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace PM.Core.Validation { public class ValidationHelper { public const string EmailRegex = @"^w+([-+.']w+)*@w+([-.]w+)*.w+([-.]w+)*$"; public static bool IsEmail(string value) { if (value.IsNullOrEmpty()) { return false; } var regex = new Regex(EmailRegex); return regex.IsMatch(value); } } }
PMProjectNameConsts 公共常量类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PM.Core { public class PMProjectNameConsts { public const string LocalizationSourceName = "PMProjectName"; public const bool MultiTenantEnabled = true; } }
PMVersionHepler 版本帮助类
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Reflection.Extensions; namespace PM.Core { /// <summary> /// 应用版本中心 /// </summary> public class PMVersionHepler { /// <summary> /// 获取应用程序当前版本 /// 显示在网页中 /// </summary> public const string Version = "1.0.0.0"; /// <summary> /// 获取应用程序最后一次发布的时间 /// 它显示在网页中 /// </summary> public static DateTime ReleaseDate { get { return new FileInfo(typeof(PMVersionHepler).GetAssembly().Location).LastWriteTime; } } } }
PMCoreModule模块类
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using Abp.Localization.Dictionaries; using Abp.Localization.Dictionaries.Xml; using Abp.Modules; using Abp.Zero; using Abp.Zero.Configuration; using PM.Core.Authorization; using PM.Core.Authorization.Roles; using PM.Core.Configuration; using PM.Core.MultiTenant; using PM.Core.Users; namespace PM.Core { [DependsOn(typeof(AbpZeroCoreModule))] public class PMCoreModule:AbpModule { public override void PreInitialize() { //如果当前用户未登录,请设置为true以启用保存审核日志。默认值: Configuration.Auditing.IsEnabledForAnonymousUsers = true; //声明实体类型 Configuration.Modules.Zero().EntityTypes.Tenant = typeof (Tenant); Configuration.Modules.Zero().EntityTypes.Role = typeof (Role); Configuration.Modules.Zero().EntityTypes.User = typeof (User); //开启多租户 Configuration.MultiTenancy.IsEnabled = PMProjectNameConsts.MultiTenantEnabled; //添加删除本地化源 Configuration.Localization.Sources.Add( new DictionaryBasedLocalizationSource(PMProjectNameConsts.LocalizationSourceName, new XmlEmbeddedFileLocalizationDictionaryProvider(Assembly.GetExecutingAssembly(), "PM.Localization.Source"))); //设置静态角色 PMRoleConfig.Configure(Configuration.Modules.Zero().RoleManagement); //初始化权限 Configuration.Authorization.Providers.Add<PMProjectNameAuthorizationProvider>(); //初始化设置 Configuration.Settings.Providers.Add<PMSettingProvider>(); } public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } } }
1,NuGet安装Abp.Zero2.1.3、Abp.Zero.EntityFramework2.13
2,基本结构
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Domain.Entities; using Abp.EntityFramework; using Abp.EntityFramework.Repositories; namespace PM.EntityFramework.EntityFramework.Repositories { public class PMRepositoryBase<TEntity, TPrimaryKey> : EfRepositoryBase<PMDBContext, TEntity, TPrimaryKey> where TEntity:class,IEntity<TPrimaryKey> { public PMRepositoryBase(IDbContextProvider<PMDBContext> dbContextProvider) : base(dbContextProvider) { } //为所有存储库添加常用方法 } public class PMRepositoryBase<TEntity> : PMRepositoryBase<TEntity, int> where TEntity : class, IEntity<int> { public PMRepositoryBase(IDbContextProvider<PMDBContext> dbContextProvider) : base(dbContextProvider) { } //不要在这里添加任何方法,添加到上面的类(因为它继承它) } }
using System; using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Zero.EntityFramework; using PM.Core.Authorization.Roles; using PM.Core.MultiTenant; using PM.Core.Users; namespace PM.EntityFramework.EntityFramework { public class PMDBContext:AbpZeroDbContext<Tenant,Role,User> { /// <summary> /// 将“默认”设置为基类可帮助我们在Package Manager Console上执行迁移命令时使用。 /// 但是,在运行EF的Migrate.exe时可能会导致问题。 如果要在命令行上应用迁移,请不要将连接字符串名称传递给基类。 ABP工作方式。 /// </summary> public PMDBContext() : base("Default") { } /// <summary> /// ABP使用此构造函数传递PMDBContext.PreInitialize中定义的连接字符串。 /// 注意,实际上你不会直接创建一个PMDBContext的实例,因为ABP自动处理它。 /// </summary> /// <param name="nameOrnameOrConnectionString"></param> public PMDBContext(string nameOrnameOrConnectionString) : base(nameOrnameOrConnectionString) { } /// <summary> /// 这个构造函数用于测试 /// </summary> /// <param name="existingConnection"></param> public PMDBContext(DbConnection existingConnection) : base(existingConnection,false) { } public PMDBContext(DbConnection existingConnection, bool contextOwnsConnection) : base(existingConnection, contextOwnsConnection) { } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Application.Editions; using PM.Core.Editions; using PM.EntityFramework.EntityFramework; namespace PM.EntityFramework.Migrations.SeedData { /// <summary> /// 默认版本创建者 /// </summary> public class DefaultEditionsCreator { private readonly PMDBContext _context; public DefaultEditionsCreator(PMDBContext context) { _context = context; } public void Create() { CreateEdtions(); } private void CreateEdtions() { var defaultEdtion = _context.Editions.FirstOrDefault(e => e.Name == EditionManager.DefaultEditionName); if (defaultEdtion == null) { defaultEdtion = new Edition() { Name = EditionManager.DefaultEditionName, DisplayName = EditionManager.DefaultEditionName }; _context.Editions.Add(defaultEdtion); _context.SaveChanges(); //TODO:如果需要,可以在标准版中添加所需的功能! } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Localization; using PM.EntityFramework.EntityFramework; namespace PM.EntityFramework.Migrations.SeedData { /// <summary> /// 默认语言创建者 /// </summary> public class DefaultLanguagesCreator { public static List<ApplicationLanguage> InitialLanguages { get; private set; } private readonly PMDBContext _context; static DefaultLanguagesCreator() { InitialLanguages = new List<ApplicationLanguage> { new ApplicationLanguage(null, "en", "English", "famfamfam-flags gb"), new ApplicationLanguage(null, "tr", "Türkçe", "famfamfam-flags tr"), new ApplicationLanguage(null, "zh-CN", "简体中文", "famfamfam-flags cn"), new ApplicationLanguage(null, "pt-BR", "Português-BR", "famfamfam-flags br"), new ApplicationLanguage(null, "es", "Español", "famfamfam-flags es"), new ApplicationLanguage(null, "fr", "Français", "famfamfam-flags fr"), new ApplicationLanguage(null, "it", "Italiano", "famfamfam-flags it"), new ApplicationLanguage(null, "ja", "日本語", "famfamfam-flags jp"), new ApplicationLanguage(null, "nl-NL", "Nederlands", "famfamfam-flags nl"), new ApplicationLanguage(null, "lt", "Lietuvos", "famfamfam-flags lt"), new ApplicationLanguage(null, "vn", "Vietnamese", "famfamfam-flags vn") }; } public DefaultLanguagesCreator(PMDBContext context) { _context = context; } public void Create() { CreateLanguages(); } private void CreateLanguages() { foreach (var applicationLanguage in InitialLanguages) { AddLanguageIfNotExists(applicationLanguage); } } private void AddLanguageIfNotExists(ApplicationLanguage language) { if (_context.Languages.Any(l => l.TenantId == language.TenantId && l.Name == language.Name)) { return; } _context.Languages.Add(language); _context.SaveChanges(); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Configuration; using Abp.Localization; using Abp.Net.Mail; using PM.EntityFramework.EntityFramework; namespace PM.EntityFramework.Migrations.SeedData { /// <summary> /// 默认设置创建者 /// </summary> public class DefaultSettingsCreator { private readonly PMDBContext _context; public DefaultSettingsCreator(PMDBContext context) { _context = context; } public void Create() { //邮箱 AddSettingIfNotExists(EmailSettingNames.DefaultFromAddress, "qq962410314@163.com"); AddSettingIfNotExists(EmailSettingNames.DefaultFromDisplayName, "qq962410314@163.com"); //语言 AddSettingIfNotExists(LocalizationSettingNames.DefaultLanguage, "zh-CN"); } private void AddSettingIfNotExists(string name, string value, int? tenantId = null) { if (_context.Settings.Any(s => s.Name == name && s.TenantId == tenantId && s.UserId == null)) { return; } _context.Settings.Add(new Setting(tenantId, null, name, value)); _context.SaveChanges(); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using PM.Core.MultiTenant; using PM.EntityFramework.EntityFramework; namespace PM.EntityFramework.Migrations.SeedData { /// <summary> /// 默认租户创建者 /// </summary> public class DefaultTenantCreator { private readonly PMDBContext _context; public DefaultTenantCreator(PMDBContext context) { _context = context; } public void Create() { CreateUserAndRoles(); } private void CreateUserAndRoles() { //默认租户 var defaultTenant = _context.Tenants.FirstOrDefault(t => t.TenancyName == Tenant.DefaultTenantName); if (defaultTenant == null) { _context.Tenants.Add(new Tenant() { TenancyName = Tenant.DefaultTenantName, Name = Tenant.DefaultTenantName }); _context.SaveChanges(); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Authorization; using Abp.Authorization.Roles; using Abp.Authorization.Users; using Abp.MultiTenancy; using Microsoft.AspNet.Identity; using PM.Core.Authorization; using PM.Core.Authorization.Roles; using PM.Core.Users; using PM.EntityFramework.EntityFramework; namespace PM.EntityFramework.Migrations.SeedData { /// <summary> /// 主机admin创建者 /// </summary> public class HostRoleAndUserCreator { private readonly PMDBContext _context; public HostRoleAndUserCreator(PMDBContext context) { _context = context; } public void Create() { CreateHostRoleAndUsers(); } private void CreateHostRoleAndUsers() { //主机角色 var adminRoleForHost= _context.Roles.FirstOrDefault(r => r.TenantId == null && r.Name == StaticRoleNames.Host.Admin); if (adminRoleForHost == null) { adminRoleForHost = _context.Roles.Add(new Role() { Name = StaticRoleNames.Host.Admin, DisplayName = StaticRoleNames.Host.Admin, IsStatic = true }); _context.SaveChanges(); //授予所有租户权限 var permisstions = PermissionFinder.GetAllPermissions(new PMProjectNameAuthorizationProvider()) .Where(p => p.MultiTenancySides.HasFlag(MultiTenancySides.Host)) .ToList(); foreach (var permisstion in permisstions) { _context.Permissions.Add(new RolePermissionSetting() { Name = permisstion.Name, IsGranted = true, RoleId = adminRoleForHost.Id }); } _context.SaveChanges(); } //主机admin var adminUserForHost = _context.Users.FirstOrDefault(u => u.TenantId == null && u.UserName == User.AdminUserName); if (adminUserForHost == null) { adminUserForHost = _context.Users.Add(new User() { UserName = User.AdminUserName, Name = "System", Surname = "Administrator", EmailAddress = "qq962410314@163.com", IsEmailConfirmed = true, Password = new PasswordHasher().HashPassword(User.DefaultPassword) }); _context.SaveChanges(); _context.UserRoles.Add(new UserRole(null, adminUserForHost.Id, adminRoleForHost.Id)); _context.SaveChanges(); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using EntityFramework.DynamicFilters; using PM.EntityFramework.EntityFramework; namespace PM.EntityFramework.Migrations.SeedData { /// <summary> /// 初始化主机数据库提供者 /// </summary> public class InitialHostDbBuilder { private readonly PMDBContext _context; public InitialHostDbBuilder(PMDBContext context) { _context = context; } public void Create() { //禁用所有过滤器 _context.DisableAllFilters(); new DefaultEditionsCreator(_context).Create(); new DefaultLanguagesCreator(_context).Create(); new HostRoleAndUserCreator(_context).Create(); new DefaultSettingsCreator(_context).Create(); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Authorization; using Abp.Authorization.Roles; using Abp.Authorization.Users; using Abp.MultiTenancy; using PM.Core.Authorization; using PM.Core.Authorization.Roles; using PM.Core.Users; using PM.EntityFramework.EntityFramework; namespace PM.EntityFramework.Migrations.SeedData { /// <summary> /// 租户admin创建者 /// </summary> public class TenantRoleAndUserBuilder { private readonly PMDBContext _context; private readonly int _tenantId; public TenantRoleAndUserBuilder(PMDBContext context, int tenantId) { _context = context; _tenantId = tenantId; } public void Create() { CreateRolesAndUsers(); } private void CreateRolesAndUsers() { //租户角色 var adminRole = _context.Roles.FirstOrDefault(r => r.TenantId == _tenantId && r.Name == StaticRoleNames.Tenants.Admin); if (adminRole==null) { adminRole = _context.Roles.Add(new Role(_tenantId, StaticRoleNames.Tenants.Admin, StaticRoleNames.Tenants.Admin) { IsStatic = true }); _context.SaveChanges(); //授予管理员角色的所有权限 var permisstions = PermissionFinder.GetAllPermissions(new PMProjectNameAuthorizationProvider()) .Where(p => p.MultiTenancySides.HasFlag(MultiTenancySides.Tenant)) .ToList(); foreach (var permisstion in permisstions) { _context.Permissions.Add(new RolePermissionSetting() { TenantId = _tenantId, Name = permisstion.Name, IsGranted = true, RoleId = adminRole.Id }); } _context.SaveChanges(); } //租户admin var adminUser = _context.Users.FirstOrDefault(u => u.TenantId == _tenantId && u.UserName == User.AdminUserName); if (adminUser == null) { adminUser = User.CreateTenantAdminUser(_tenantId, "qq962410314@163.com", User.DefaultPassword); adminUser.IsEmailConfirmed = true; adminUser.IsActive = true; _context.Users.Add(adminUser); _context.SaveChanges(); _context.UserRoles.Add(new UserRole(_tenantId, adminUser.Id, adminRole.Id)); _context.SaveChanges(); } } } }
namespace PM.EntityFramework.Migrations { using System; using System.Collections.Generic; using System.Data.Entity.Infrastructure.Annotations; using System.Data.Entity.Migrations; public partial class init : DbMigration { public override void Up() { CreateTable( "dbo.AbpAuditLogs", c => new { Id = c.Long(nullable: false, identity: true), TenantId = c.Int(), UserId = c.Long(), ServiceName = c.String(maxLength: 256), MethodName = c.String(maxLength: 256), Parameters = c.String(maxLength: 1024), ExecutionTime = c.DateTime(nullable: false), ExecutionDuration = c.Int(nullable: false), ClientIpAddress = c.String(maxLength: 64), ClientName = c.String(maxLength: 128), BrowserInfo = c.String(maxLength: 256), Exception = c.String(maxLength: 2000), ImpersonatorUserId = c.Long(), ImpersonatorTenantId = c.Int(), CustomData = c.String(maxLength: 2000), }, annotations: new Dictionary<string, object> { { "DynamicFilter_AuditLog_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id); CreateTable( "dbo.AbpBackgroundJobs", c => new { Id = c.Long(nullable: false, identity: true), JobType = c.String(nullable: false, maxLength: 512), JobArgs = c.String(nullable: false), TryCount = c.Short(nullable: false), NextTryTime = c.DateTime(nullable: false), LastTryTime = c.DateTime(), IsAbandoned = c.Boolean(nullable: false), Priority = c.Byte(nullable: false), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }) .PrimaryKey(t => t.Id) .Index(t => new { t.IsAbandoned, t.NextTryTime }); CreateTable( "dbo.AbpFeatures", c => new { Id = c.Long(nullable: false, identity: true), Name = c.String(nullable: false, maxLength: 128), Value = c.String(nullable: false, maxLength: 2000), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), EditionId = c.Int(), TenantId = c.Int(), Discriminator = c.String(nullable: false, maxLength: 128), }, annotations: new Dictionary<string, object> { { "DynamicFilter_TenantFeatureSetting_MustHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.AbpEditions", t => t.EditionId, cascadeDelete: true) .Index(t => t.EditionId); CreateTable( "dbo.AbpEditions", c => new { Id = c.Int(nullable: false, identity: true), Name = c.String(nullable: false, maxLength: 32), DisplayName = c.String(nullable: false, maxLength: 64), IsDeleted = c.Boolean(nullable: false), DeleterUserId = c.Long(), DeletionTime = c.DateTime(), LastModificationTime = c.DateTime(), LastModifierUserId = c.Long(), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }, annotations: new Dictionary<string, object> { { "DynamicFilter_Edition_SoftDelete", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id); CreateTable( "dbo.AbpLanguages", c => new { Id = c.Int(nullable: false, identity: true), TenantId = c.Int(), Name = c.String(nullable: false, maxLength: 10), DisplayName = c.String(nullable: false, maxLength: 64), Icon = c.String(maxLength: 128), IsDisabled = c.Boolean(nullable: false), IsDeleted = c.Boolean(nullable: false), DeleterUserId = c.Long(), DeletionTime = c.DateTime(), LastModificationTime = c.DateTime(), LastModifierUserId = c.Long(), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }, annotations: new Dictionary<string, object> { { "DynamicFilter_ApplicationLanguage_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, { "DynamicFilter_ApplicationLanguage_SoftDelete", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id); CreateTable( "dbo.AbpLanguageTexts", c => new { Id = c.Long(nullable: false, identity: true), TenantId = c.Int(), LanguageName = c.String(nullable: false, maxLength: 10), Source = c.String(nullable: false, maxLength: 128), Key = c.String(nullable: false, maxLength: 256), Value = c.String(nullable: false), LastModificationTime = c.DateTime(), LastModifierUserId = c.Long(), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }, annotations: new Dictionary<string, object> { { "DynamicFilter_ApplicationLanguageText_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id); CreateTable( "dbo.AbpNotifications", c => new { Id = c.Guid(nullable: false), NotificationName = c.String(nullable: false, maxLength: 96), Data = c.String(), DataTypeName = c.String(maxLength: 512), EntityTypeName = c.String(maxLength: 250), EntityTypeAssemblyQualifiedName = c.String(maxLength: 512), EntityId = c.String(maxLength: 96), Severity = c.Byte(nullable: false), UserIds = c.String(), ExcludedUserIds = c.String(), TenantIds = c.String(), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }) .PrimaryKey(t => t.Id); CreateTable( "dbo.AbpNotificationSubscriptions", c => new { Id = c.Guid(nullable: false), TenantId = c.Int(), UserId = c.Long(nullable: false), NotificationName = c.String(maxLength: 96), EntityTypeName = c.String(maxLength: 250), EntityTypeAssemblyQualifiedName = c.String(maxLength: 512), EntityId = c.String(maxLength: 96), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }, annotations: new Dictionary<string, object> { { "DynamicFilter_NotificationSubscriptionInfo_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id) .Index(t => new { t.NotificationName, t.EntityTypeName, t.EntityId, t.UserId }); CreateTable( "dbo.AbpOrganizationUnits", c => new { Id = c.Long(nullable: false, identity: true), TenantId = c.Int(), ParentId = c.Long(), Code = c.String(nullable: false, maxLength: 95), DisplayName = c.String(nullable: false, maxLength: 128), IsDeleted = c.Boolean(nullable: false), DeleterUserId = c.Long(), DeletionTime = c.DateTime(), LastModificationTime = c.DateTime(), LastModifierUserId = c.Long(), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }, annotations: new Dictionary<string, object> { { "DynamicFilter_OrganizationUnit_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, { "DynamicFilter_OrganizationUnit_SoftDelete", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.AbpOrganizationUnits", t => t.ParentId) .Index(t => t.ParentId); CreateTable( "dbo.AbpPermissions", c => new { Id = c.Long(nullable: false, identity: true), TenantId = c.Int(), Name = c.String(nullable: false, maxLength: 128), IsGranted = c.Boolean(nullable: false), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), RoleId = c.Int(), UserId = c.Long(), Discriminator = c.String(nullable: false, maxLength: 128), }, annotations: new Dictionary<string, object> { { "DynamicFilter_PermissionSetting_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, { "DynamicFilter_RolePermissionSetting_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, { "DynamicFilter_UserPermissionSetting_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.AbpUsers", t => t.UserId, cascadeDelete: true) .ForeignKey("dbo.AbpRoles", t => t.RoleId, cascadeDelete: true) .Index(t => t.RoleId) .Index(t => t.UserId); CreateTable( "dbo.AbpRoles", c => new { Id = c.Int(nullable: false, identity: true), Description = c.String(), TenantId = c.Int(), Name = c.String(nullable: false, maxLength: 32), DisplayName = c.String(nullable: false, maxLength: 64), IsStatic = c.Boolean(nullable: false), IsDefault = c.Boolean(nullable: false), IsDeleted = c.Boolean(nullable: false), DeleterUserId = c.Long(), DeletionTime = c.DateTime(), LastModificationTime = c.DateTime(), LastModifierUserId = c.Long(), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }, annotations: new Dictionary<string, object> { { "DynamicFilter_Role_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, { "DynamicFilter_Role_SoftDelete", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.AbpUsers", t => t.CreatorUserId) .ForeignKey("dbo.AbpUsers", t => t.DeleterUserId) .ForeignKey("dbo.AbpUsers", t => t.LastModifierUserId) .Index(t => t.DeleterUserId) .Index(t => t.LastModifierUserId) .Index(t => t.CreatorUserId); CreateTable( "dbo.AbpUsers", c => new { Id = c.Long(nullable: false, identity: true), AuthenticationSource = c.String(maxLength: 64), UserName = c.String(nullable: false, maxLength: 32), TenantId = c.Int(), EmailAddress = c.String(nullable: false, maxLength: 256), Name = c.String(nullable: false, maxLength: 32), Surname = c.String(nullable: false, maxLength: 32), Password = c.String(nullable: false, maxLength: 128), EmailConfirmationCode = c.String(maxLength: 328), PasswordResetCode = c.String(maxLength: 328), LockoutEndDateUtc = c.DateTime(), AccessFailedCount = c.Int(nullable: false), IsLockoutEnabled = c.Boolean(nullable: false), PhoneNumber = c.String(), IsPhoneNumberConfirmed = c.Boolean(nullable: false), SecurityStamp = c.String(), IsTwoFactorEnabled = c.Boolean(nullable: false), IsEmailConfirmed = c.Boolean(nullable: false), IsActive = c.Boolean(nullable: false), LastLoginTime = c.DateTime(), IsDeleted = c.Boolean(nullable: false), DeleterUserId = c.Long(), DeletionTime = c.DateTime(), LastModificationTime = c.DateTime(), LastModifierUserId = c.Long(), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }, annotations: new Dictionary<string, object> { { "DynamicFilter_User_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, { "DynamicFilter_User_SoftDelete", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.AbpUsers", t => t.CreatorUserId) .ForeignKey("dbo.AbpUsers", t => t.DeleterUserId) .ForeignKey("dbo.AbpUsers", t => t.LastModifierUserId) .Index(t => t.DeleterUserId) .Index(t => t.LastModifierUserId) .Index(t => t.CreatorUserId); CreateTable( "dbo.AbpUserClaims", c => new { Id = c.Long(nullable: false, identity: true), TenantId = c.Int(), UserId = c.Long(nullable: false), ClaimType = c.String(), ClaimValue = c.String(), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }, annotations: new Dictionary<string, object> { { "DynamicFilter_UserClaim_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.AbpUsers", t => t.UserId, cascadeDelete: true) .Index(t => t.UserId); CreateTable( "dbo.AbpUserLogins", c => new { Id = c.Long(nullable: false, identity: true), TenantId = c.Int(), UserId = c.Long(nullable: false), LoginProvider = c.String(nullable: false, maxLength: 128), ProviderKey = c.String(nullable: false, maxLength: 256), }, annotations: new Dictionary<string, object> { { "DynamicFilter_UserLogin_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.AbpUsers", t => t.UserId, cascadeDelete: true) .Index(t => t.UserId); CreateTable( "dbo.AbpUserRoles", c => new { Id = c.Long(nullable: false, identity: true), TenantId = c.Int(), UserId = c.Long(nullable: false), RoleId = c.Int(nullable: false), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }, annotations: new Dictionary<string, object> { { "DynamicFilter_UserRole_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.AbpUsers", t => t.UserId, cascadeDelete: true) .Index(t => t.UserId); CreateTable( "dbo.AbpSettings", c => new { Id = c.Long(nullable: false, identity: true), TenantId = c.Int(), UserId = c.Long(), Name = c.String(nullable: false, maxLength: 256), Value = c.String(maxLength: 2000), LastModificationTime = c.DateTime(), LastModifierUserId = c.Long(), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }, annotations: new Dictionary<string, object> { { "DynamicFilter_Setting_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.AbpUsers", t => t.UserId) .Index(t => t.UserId); CreateTable( "dbo.AbpTenantNotifications", c => new { Id = c.Guid(nullable: false), TenantId = c.Int(), NotificationName = c.String(nullable: false, maxLength: 96), Data = c.String(), DataTypeName = c.String(maxLength: 512), EntityTypeName = c.String(maxLength: 250), EntityTypeAssemblyQualifiedName = c.String(maxLength: 512), EntityId = c.String(maxLength: 96), Severity = c.Byte(nullable: false), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }, annotations: new Dictionary<string, object> { { "DynamicFilter_TenantNotificationInfo_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id); CreateTable( "dbo.AbpTenants", c => new { Id = c.Int(nullable: false, identity: true), EditionId = c.Int(), Name = c.String(nullable: false, maxLength: 128), TenancyName = c.String(nullable: false, maxLength: 64), ConnectionString = c.String(maxLength: 1024), IsActive = c.Boolean(nullable: false), IsDeleted = c.Boolean(nullable: false), DeleterUserId = c.Long(), DeletionTime = c.DateTime(), LastModificationTime = c.DateTime(), LastModifierUserId = c.Long(), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }, annotations: new Dictionary<string, object> { { "DynamicFilter_Tenant_SoftDelete", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.AbpUsers", t => t.CreatorUserId) .ForeignKey("dbo.AbpUsers", t => t.DeleterUserId) .ForeignKey("dbo.AbpEditions", t => t.EditionId) .ForeignKey("dbo.AbpUsers", t => t.LastModifierUserId) .Index(t => t.EditionId) .Index(t => t.DeleterUserId) .Index(t => t.LastModifierUserId) .Index(t => t.CreatorUserId); CreateTable( "dbo.AbpUserAccounts", c => new { Id = c.Long(nullable: false, identity: true), TenantId = c.Int(), UserId = c.Long(nullable: false), UserLinkId = c.Long(), UserName = c.String(), EmailAddress = c.String(), LastLoginTime = c.DateTime(), IsDeleted = c.Boolean(nullable: false), DeleterUserId = c.Long(), DeletionTime = c.DateTime(), LastModificationTime = c.DateTime(), LastModifierUserId = c.Long(), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }, annotations: new Dictionary<string, object> { { "DynamicFilter_UserAccount_SoftDelete", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id); CreateTable( "dbo.AbpUserLoginAttempts", c => new { Id = c.Long(nullable: false, identity: true), TenantId = c.Int(), TenancyName = c.String(maxLength: 64), UserId = c.Long(), UserNameOrEmailAddress = c.String(maxLength: 255), ClientIpAddress = c.String(maxLength: 64), ClientName = c.String(maxLength: 128), BrowserInfo = c.String(maxLength: 256), Result = c.Byte(nullable: false), CreationTime = c.DateTime(nullable: false), }, annotations: new Dictionary<string, object> { { "DynamicFilter_UserLoginAttempt_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id) .Index(t => new { t.UserId, t.TenantId }) .Index(t => new { t.TenancyName, t.UserNameOrEmailAddress, t.Result }); CreateTable( "dbo.AbpUserNotifications", c => new { Id = c.Guid(nullable: false), TenantId = c.Int(), UserId = c.Long(nullable: false), TenantNotificationId = c.Guid(nullable: false), State = c.Int(nullable: false), CreationTime = c.DateTime(nullable: false), }, annotations: new Dictionary<string, object> { { "DynamicFilter_UserNotificationInfo_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id) .Index(t => new { t.UserId, t.State, t.CreationTime }); CreateTable( "dbo.AbpUserOrganizationUnits", c => new { Id = c.Long(nullable: false, identity: true), TenantId = c.Int(), UserId = c.Long(nullable: false), OrganizationUnitId = c.Long(nullable: false), CreationTime = c.DateTime(nullable: false), CreatorUserId = c.Long(), }, annotations: new Dictionary<string, object> { { "DynamicFilter_UserOrganizationUnit_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }) .PrimaryKey(t => t.Id); } public override void Down() { DropForeignKey("dbo.AbpTenants", "LastModifierUserId", "dbo.AbpUsers"); DropForeignKey("dbo.AbpTenants", "EditionId", "dbo.AbpEditions"); DropForeignKey("dbo.AbpTenants", "DeleterUserId", "dbo.AbpUsers"); DropForeignKey("dbo.AbpTenants", "CreatorUserId", "dbo.AbpUsers"); DropForeignKey("dbo.AbpPermissions", "RoleId", "dbo.AbpRoles"); DropForeignKey("dbo.AbpRoles", "LastModifierUserId", "dbo.AbpUsers"); DropForeignKey("dbo.AbpRoles", "DeleterUserId", "dbo.AbpUsers"); DropForeignKey("dbo.AbpRoles", "CreatorUserId", "dbo.AbpUsers"); DropForeignKey("dbo.AbpSettings", "UserId", "dbo.AbpUsers"); DropForeignKey("dbo.AbpUserRoles", "UserId", "dbo.AbpUsers"); DropForeignKey("dbo.AbpPermissions", "UserId", "dbo.AbpUsers"); DropForeignKey("dbo.AbpUserLogins", "UserId", "dbo.AbpUsers"); DropForeignKey("dbo.AbpUsers", "LastModifierUserId", "dbo.AbpUsers"); DropForeignKey("dbo.AbpUsers", "DeleterUserId", "dbo.AbpUsers"); DropForeignKey("dbo.AbpUsers", "CreatorUserId", "dbo.AbpUsers"); DropForeignKey("dbo.AbpUserClaims", "UserId", "dbo.AbpUsers"); DropForeignKey("dbo.AbpOrganizationUnits", "ParentId", "dbo.AbpOrganizationUnits"); DropForeignKey("dbo.AbpFeatures", "EditionId", "dbo.AbpEditions"); DropIndex("dbo.AbpUserNotifications", new[] { "UserId", "State", "CreationTime" }); DropIndex("dbo.AbpUserLoginAttempts", new[] { "TenancyName", "UserNameOrEmailAddress", "Result" }); DropIndex("dbo.AbpUserLoginAttempts", new[] { "UserId", "TenantId" }); DropIndex("dbo.AbpTenants", new[] { "CreatorUserId" }); DropIndex("dbo.AbpTenants", new[] { "LastModifierUserId" }); DropIndex("dbo.AbpTenants", new[] { "DeleterUserId" }); DropIndex("dbo.AbpTenants", new[] { "EditionId" }); DropIndex("dbo.AbpSettings", new[] { "UserId" }); DropIndex("dbo.AbpUserRoles", new[] { "UserId" }); DropIndex("dbo.AbpUserLogins", new[] { "UserId" }); DropIndex("dbo.AbpUserClaims", new[] { "UserId" }); DropIndex("dbo.AbpUsers", new[] { "CreatorUserId" }); DropIndex("dbo.AbpUsers", new[] { "LastModifierUserId" }); DropIndex("dbo.AbpUsers", new[] { "DeleterUserId" }); DropIndex("dbo.AbpRoles", new[] { "CreatorUserId" }); DropIndex("dbo.AbpRoles", new[] { "LastModifierUserId" }); DropIndex("dbo.AbpRoles", new[] { "DeleterUserId" }); DropIndex("dbo.AbpPermissions", new[] { "UserId" }); DropIndex("dbo.AbpPermissions", new[] { "RoleId" }); DropIndex("dbo.AbpOrganizationUnits", new[] { "ParentId" }); DropIndex("dbo.AbpNotificationSubscriptions", new[] { "NotificationName", "EntityTypeName", "EntityId", "UserId" }); DropIndex("dbo.AbpFeatures", new[] { "EditionId" }); DropIndex("dbo.AbpBackgroundJobs", new[] { "IsAbandoned", "NextTryTime" }); DropTable("dbo.AbpUserOrganizationUnits", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_UserOrganizationUnit_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpUserNotifications", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_UserNotificationInfo_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpUserLoginAttempts", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_UserLoginAttempt_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpUserAccounts", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_UserAccount_SoftDelete", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpTenants", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_Tenant_SoftDelete", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpTenantNotifications", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_TenantNotificationInfo_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpSettings", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_Setting_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpUserRoles", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_UserRole_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpUserLogins", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_UserLogin_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpUserClaims", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_UserClaim_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpUsers", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_User_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, { "DynamicFilter_User_SoftDelete", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpRoles", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_Role_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, { "DynamicFilter_Role_SoftDelete", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpPermissions", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_PermissionSetting_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, { "DynamicFilter_RolePermissionSetting_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, { "DynamicFilter_UserPermissionSetting_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpOrganizationUnits", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_OrganizationUnit_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, { "DynamicFilter_OrganizationUnit_SoftDelete", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpNotificationSubscriptions", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_NotificationSubscriptionInfo_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpNotifications"); DropTable("dbo.AbpLanguageTexts", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_ApplicationLanguageText_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpLanguages", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_ApplicationLanguage_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, { "DynamicFilter_ApplicationLanguage_SoftDelete", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpEditions", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_Edition_SoftDelete", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpFeatures", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_TenantFeatureSetting_MustHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); DropTable("dbo.AbpBackgroundJobs"); DropTable("dbo.AbpAuditLogs", removedAnnotations: new Dictionary<string, object> { { "DynamicFilter_AuditLog_MayHaveTenant", "EntityFramework.DynamicFilters.DynamicFilterDefinition" }, }); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Dependency; using Abp.Domain.Uow; using Abp.MultiTenancy; using Abp.Zero.EntityFramework; using PM.EntityFramework.EntityFramework; namespace PM.EntityFramework.Migrations { /// <summary> /// 执行数据库迁移 /// </summary> public class AbpZeroDbMigrator : AbpZeroDbMigrator<PMDBContext, Configuration> { public AbpZeroDbMigrator(IUnitOfWorkManager unitOfWorkManager, IDbPerTenantConnectionStringResolver connectionStringResolver, IIocResolver iocResolver) : base(unitOfWorkManager, connectionStringResolver, iocResolver) { } } }
using Abp.MultiTenancy; using Abp.Zero.EntityFramework; using EntityFramework.DynamicFilters; using PM.EntityFramework.Migrations.SeedData; namespace PM.EntityFramework.Migrations { using System; using System.Data.Entity; using System.Data.Entity.Migrations; using System.Linq; public sealed class Configuration : DbMigrationsConfiguration<PM.EntityFramework.EntityFramework.PMDBContext>,IMultiTenantSeed { public AbpTenantBase Tenant { get; set; } public Configuration() { AutomaticMigrationsEnabled = false; ContextKey = "PM"; } //Seed() 方法会在你每次你执行 Update-Database 指令时被呼叫一次 protected override void Seed(PM.EntityFramework.EntityFramework.PMDBContext context) { //禁用所有过滤 context.DisableAllFilters(); if (Tenant == null) { //主机种子 new InitialHostDbBuilder(context).Create(); //默认租户种子 new DefaultTenantCreator(context).Create(); new TenantRoleAndUserBuilder(context, 1).Create(); } else { //您可以为租户数据库添加种子并使用租户属性... } context.SaveChanges(); } } }
using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using Abp.Modules; using Abp.Zero.EntityFramework; using PM.Core; using PM.EntityFramework.EntityFramework; namespace PM.EntityFramework { [DependsOn(typeof(PMCoreModule),typeof(AbpZeroEntityFrameworkModule))] public class PMDataModule:AbpModule { public override void PreInitialize() { Database.SetInitializer(new CreateDatabaseIfNotExists<PMDBContext>()); Configuration.DefaultNameOrConnectionString = "Default"; } public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } } }
1,NuGet安装Abp.Zero2.1.3、Abp.AutoMapper2.1.3
程序集引用:System.ComponentModel.DataAnnotations
2,基本结构
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Application.Services; using Abp.IdentityFramework; using Abp.Runtime.Session; using Microsoft.AspNet.Identity; using PM.Core; using PM.Core.MultiTenant; using PM.Core.Users; namespace PM.Application { public class PMAppServiceBase:ApplicationService { public TenantManager TenantManager { get; set; } public UserManager UserManager { get; set; } protected PMAppServiceBase() { LocalizationSourceName = PMProjectNameConsts.LocalizationSourceName; } protected virtual Task<User> GetCurrentUserAsync() { var user= UserManager.FindByIdAsync(AbpSession.GetUserId()); if (user == null) { throw new ApplicationException("目前没有用户!"); } return user; } protected virtual Task<Tenant> GetCurrentTenantAsync() { return TenantManager.GetByIdAsync(AbpSession.GetTenantId()); } protected virtual void CheckErrors(IdentityResult identityResult) { identityResult.CheckErrors(LocalizationManager); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using Abp.Authorization; using Abp.Authorization.Roles; using Abp.AutoMapper; using Abp.Modules; using PM.Application.Roles.Dto; using PM.Application.Users.Dto; using PM.Core; using PM.Core.Authorization.Roles; using PM.Core.Users; namespace PM.Application { [DependsOn(typeof(PMCoreModule),typeof(AbpAutoMapperModule))] public class PMApplicationModule:AbpModule { public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); Configuration.Modules.AbpAutoMapper().Configurators.Add(cfg => { // Role and permission cfg.CreateMap<Permission, string>().ConvertUsing(r => r.Name); cfg.CreateMap<RolePermissionSetting, string>().ConvertUsing(r => r.Name); cfg.CreateMap<CreateRoleDto, Role>().ForMember(x => x.Permissions, opt => opt.Ignore()); cfg.CreateMap<RoleDto, Role>().ForMember(x => x.Permissions, opt => opt.Ignore()); cfg.CreateMap<UserDto, User>(); cfg.CreateMap<UserDto, User>().ForMember(x => x.Roles, opt => opt.Ignore()); cfg.CreateMap<CreateUserDto, User>(); cfg.CreateMap<CreateUserDto, User>().ForMember(x => x.Roles, opt => opt.Ignore()); }); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Zero.Configuration; using PM.Application.Authorization.Accounts.Dto; using PM.Core.Authorization.Users; using Abp.Configuration; namespace PM.Application.Authorization.Accounts { public class AccountAppService:PMAppServiceBase,IAccountAppService { private readonly UserRegistrationManager _userRegistrationManager; public AccountAppService(UserRegistrationManager userRegistrationManager) { _userRegistrationManager = userRegistrationManager; } public async Task<IsTenantAvaliableOutput> IsTenantAvaliable(IsTenantAvaliableInput input) { var tenant = await TenantManager.FindByTenancyNameAsync(input.TenantName); if (tenant == null) { return new IsTenantAvaliableOutput(TenantAvaliablityState.NotFound); } if (!tenant.IsActive) { return new IsTenantAvaliableOutput(TenantAvaliablityState.InActive); } return new IsTenantAvaliableOutput(TenantAvaliablityState.Avaliable, tenant.Id); } public async Task<RegisterOutput> Register(RegisterInput input) { var user =await _userRegistrationManager.RegisterAsync(input.Name, input.Surname, input.EmailAddress, input.UserName, input.Password, false); //电子邮件确认需要登录 var isEmailConfirmationRequiredForLogin = await SettingManager.GetSettingValueAsync<bool>( AbpZeroSettingNames.UserManagement.IsEmailConfirmationRequiredForLogin); return new RegisterOutput() { CanLogin = user.IsActive && (user.IsEmailConfirmed || !isEmailConfirmationRequiredForLogin) }; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Runtime.Session; using PM.Application.Configuration.Dto; using PM.Core.Configuration; namespace PM.Application.Configuration { public class ConfigurationAppService : PMAppServiceBase, IConfigurationAppService { public async Task ChangeUiTheme(ChangeUiThemeInput input) { await SettingManager.ChangeSettingForUserAsync(AbpSession.ToUserIdentifier(), PMSettingNames.UiTheme, input.Theme); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Application.Services; using Abp.Application.Services.Dto; using Abp.AutoMapper; using Abp.Domain.Repositories; using Abp.Extensions; using Abp.IdentityFramework; using Abp.MultiTenancy; using Abp.Runtime.Security; using Microsoft.AspNet.Identity; using PM.Application.MultiTenancy.Dto; using PM.Core.Authorization.Roles; using PM.Core.Editions; using PM.Core.MultiTenant; using PM.Core.Users; namespace PM.Application.MultiTenancy { public class TenantAppService : AsyncCrudAppService<Tenant, TenantDto, int, PagedResultRequestDto, CreateTenantDto, TenantDto>, ITenantAppService { private readonly TenantManager _tenantManager; private readonly EditionManager _editionManager; private readonly UserManager _userManager; private readonly RoleManager _roleManager; private readonly IAbpZeroDbMigrator _abpZeroDbMigrator; public TenantAppService( IRepository<Tenant, int> repository, TenantManager tenantManager, EditionManager editionManager, UserManager userManager, RoleManager roleManager, IAbpZeroDbMigrator abpZeroDbMigrator ) : base(repository) { _editionManager = editionManager; _tenantManager = tenantManager; _userManager = userManager; _roleManager = roleManager; _abpZeroDbMigrator = abpZeroDbMigrator; } private void CheckError(IdentityResult identityResult) { identityResult.CheckErrors(); } /// <summary> /// 创建租户 /// </summary> /// <param name="input"></param> /// <returns></returns> public override async Task<TenantDto> Create(CreateTenantDto input) { //判断是否已拥有此接口的权限(Create方法),需要赋值CreatePermissionName属性 CheckCreatePermission(); var tenant = input.MapTo<Tenant>(); //加密数据库链接字符串(采用AES对称加密) tenant.ConnectionString = input.ConnectionString.IsNullOrEmpty() ? null : SimpleStringCipher.Instance.Encrypt(input.ConnectionString); //当前租户使用的版本(Standard标准版) var defaultEdition = await _editionManager.FindByNameAsync(EditionManager.DefaultEditionName); if (defaultEdition != null) { tenant.EditionId = defaultEdition.Id; } //创建租户 await _tenantManager.CreateAsync(tenant); //获得租户的id await CurrentUnitOfWork.SaveChangesAsync(); //创建租户数据库 _abpZeroDbMigrator.CreateOrMigrateForTenant(tenant); using (CurrentUnitOfWork.SetTenantId(tenant.Id)) { //创建静态租户角色,该静态角色通过IRoleManagementConfig配置 CheckError(await _roleManager.CreateStaticRoles(tenant.Id)); await CurrentUnitOfWork.SaveChangesAsync();//获取静态角色id //授予管理员角色所有权限(该权限通过IPermissionDefinitionContext配置) var adminRole = _roleManager.Roles.Single(r => r.Name == StaticRoleNames.Tenants.Admin); await _roleManager.GrantAllPermissionsAsync(adminRole); //创建租户admin用户 var adminUser= User.CreateTenantAdminUser(tenant.Id, input.AdminEmailAddress, User.DefaultPassword); CheckError(await _userManager.CreateAsync(adminUser)); await CurrentUnitOfWork.SaveChangesAsync();//获取用户id //讲角色分配给租户admin用户 CheckError(await _userManager.AddToRoleAsync(adminUser.Id, adminRole.Name)); await CurrentUnitOfWork.SaveChangesAsync(); } return MapToEntityDto(tenant); } protected override void MapToEntity(TenantDto updateInput, Tenant entity) { //手动映射,因为TenantDto也包含不可编辑的属性。 entity.Name = updateInput.Name; entity.TenancyName = updateInput.TenancyName; entity.IsActive = updateInput.IsActive; } public override async Task Delete(EntityDto<int> input) { CheckDeletePermission(); var tenant =await _tenantManager.FindByIdAsync(input.Id); await _tenantManager.DeleteAsync(tenant); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Application.Services; using Abp.Application.Services.Dto; using Abp.Authorization.Users; using Abp.AutoMapper; using Abp.Domain.Repositories; using Abp.IdentityFramework; using Abp.UI; using Microsoft.AspNet.Identity; using PM.Application.Roles.Dto; using PM.Core.Authorization.Roles; using PM.Core.MultiTenant; using PM.Core.Users; namespace PM.Application.Roles { public class RoleAppService:AsyncCrudAppService<Role,RoleDto,Int32,PagedResultRequestDto,CreateRoleDto,RoleDto>,IRoleAppService { private readonly RoleManager _roleManager; private readonly UserManager _userManager; private readonly IRepository<User, long> _userRepository; private readonly IRepository<UserRole, long> _userRoleRepository; private readonly IRepository<Role> _roleRepository; public RoleAppService( IRepository<Role, int> repository, RoleManager roleManager, UserManager userManager, IRepository<User,long> userRepository, IRepository<UserRole,long> userRoleRepository, IRepository<Role> roleRepository ) : base(repository) { _roleManager = roleManager; _userManager = userManager; _userRepository = userRepository; _userRoleRepository = userRoleRepository; _roleRepository = roleRepository; } public override async Task<RoleDto> Create(CreateRoleDto input) { CheckCreatePermission(); var role = input.MapTo<Role>(); CheckErrors(await _roleManager.CreateAsync(role)); //查询权限 var grantedPermissions = PermissionManager.GetAllPermissions().Where(p => input.Permissions.Contains(p.Name)).ToList(); //给角色设置权限 await _roleManager.SetGrantedPermissionsAsync(role, grantedPermissions); return MapToEntityDto(role); } public override async Task Delete(EntityDto<int> input) { CheckDeletePermission(); var role = await _roleManager.FindByIdAsync(input.Id); if (role.IsStatic) { throw new UserFriendlyException("无法删除静态角色"); } //删除用户角色关联 var users = await GetUsersInRoleAsync(role.Name); foreach (var user in users) { CheckErrors(await _userManager.RemoveFromRoleAsync(user, role.Name)); } //删除角色 await _roleManager.DeleteAsync(role); } private Task<List<long>> GetUsersInRoleAsync(string roleName) { var users= (from user in _userRepository.GetAll() join userRole in _userRoleRepository.GetAll() on user.Id equals userRole.UserId join role in _roleRepository.GetAll() on userRole.RoleId equals role.Id where role.Name == roleName select user.Id).Distinct().ToList(); return Task.FromResult(users); } public Task<ListResultDto<PermissionDto>> GetAllPermissions() { var permissions = PermissionManager.GetAllPermissions(); return Task.FromResult(new ListResultDto<PermissionDto>(permissions.MapTo<List<PermissionDto>>())); } protected override Task<Role> GetEntityByIdAsync(int id) { //查询角色,并包含该角色的权限 var role = Repository.GetAllIncluding(x => x.Permissions).FirstOrDefault(x => x.Id == id); return Task.FromResult(role); } /// <summary> /// 创建过滤查询 /// </summary> /// <param name="input"></param> /// <returns></returns> protected override IQueryable<Role> CreateFilteredQuery(PagedResultRequestDto input) { return Repository.GetAllIncluding(x => x.Permissions); } /// <summary> /// 应用排序 /// </summary> /// <param name="query"></param> /// <param name="input"></param> /// <returns></returns> protected override IQueryable<Role> ApplySorting(IQueryable<Role> query, PagedResultRequestDto input) { return query.OrderBy(r => r.DisplayName); } private void CheckErrors(IdentityResult identityResult) { identityResult.CheckErrors(LocalizationManager); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Auditing; using Abp.AutoMapper; using PM.Application.Sessions.Dto; namespace PM.Application.Sessions { public class SessionAppService:PMAppServiceBase,ISessionAppService { [DisableAuditing] public async Task<GetCurrentLoginInformationsOutput> GetCurrentLoginInformations() { var output=new GetCurrentLoginInformationsOutput(); if (AbpSession.UserId.HasValue) { output.User = (await GetCurrentUserAsync()).MapTo<UserLoginInfoDto>(); } if (AbpSession.TenantId.HasValue) { output.Tenant = (await GetCurrentTenantAsync()).MapTo<TenantLoginInfoDto>(); } return output; } } }
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Application.Services; using Abp.Application.Services.Dto; using Abp.Authorization.Users; using Abp.AutoMapper; using Abp.Domain.Repositories; using Abp.IdentityFramework; using Microsoft.AspNet.Identity; using PM.Application.Roles.Dto; using PM.Application.Users.Dto; using PM.Core.Authorization.Roles; using PM.Core.Users; namespace PM.Application.Users { public class UserAppService:AsyncCrudAppService<User,UserDto,long,PagedResultRequestDto,CreateUserDto,UpdateUserDto>,IUserAppService { private readonly UserManager _userManager; private readonly IRepository<Role> _roleRepository; private readonly RoleManager _roleManager; public UserAppService( IRepository<User, long> repository, UserManager userManager, IRepository<Role> roleRepository, RoleManager roleManager ) : base(repository) { _userManager = userManager; _roleRepository = roleRepository; _roleManager = roleManager; } public override async Task<UserDto> Get(EntityDto<long> input) { var user = await base.Get(input); var userRoles = await _userManager.GetRolesAsync(user.Id); user.Roles = userRoles.ToArray(); return user; } public override async Task<UserDto> Create(CreateUserDto input) { CheckCreatePermission(); var user = input.MapTo<User>(); user.TenantId = AbpSession.TenantId; user.Password = new PasswordHasher().HashPassword(input.Password); user.IsEmailConfirmed = true; //分配角色(从租户的所有) user.Roles = new Collection<UserRole>(); foreach (var roleName in input.RoleNames) { var role = await _roleManager.GetRoleByNameAsync(roleName); user.Roles.Add(new UserRole(AbpSession.TenantId, user.Id, role.Id)); } CheckErrors(await _userManager.CreateAsync(user)); return MapToEntityDto(user); } public override async Task<UserDto> Update(UpdateUserDto input) { CheckUpdatePermission(); var user = await _userManager.GetUserByIdAsync(input.Id); //把有变动的属性赋值到user对象中 MapToEntity(input, user); CheckErrors(await _userManager.UpdateAsync(user)); if (input.RoleNames != null) { //_userManager.SetRoles方法的作用:变更角色(前提:用户表以已经创建) CheckErrors(await _userManager.SetRoles(user, input.RoleNames)); } return await Get(input); } public override async Task Delete(EntityDto<long> input) { var user = await _userManager.GetUserByIdAsync(input.Id); //admin用户不能被删除(删除用户的同时会删除UserRole) await _userManager.DeleteAsync(user); } public async Task<ListResultDto<RoleDto>> GetRoles() { var roles = await _roleRepository.GetAllListAsync(); return new ListResultDto<RoleDto>(roles.MapTo<List<RoleDto>>()); } protected override User MapToEntity(CreateUserDto createInput) { var user = ObjectMapper.Map<User>(createInput); return user; } protected override void MapToEntity(UpdateUserDto updateInput, User entity) { ObjectMapper.Map(updateInput, entity); } protected override IQueryable<User> CreateFilteredQuery(PagedResultRequestDto input) { return Repository.GetAllIncluding(x => x.Roles); } protected override async Task<User> GetEntityByIdAsync(long id) { var user = Repository.GetAllIncluding(x => x.Roles).FirstOrDefault(x => x.Id == id); return await Task.FromResult(user); } protected override IQueryable<User> ApplySorting(IQueryable<User> query, PagedResultRequestDto input) { return query.OrderBy(r => r.UserName); } private void CheckErrors(IdentityResult identityResult) { identityResult.CheckErrors(LocalizationManager); } } }
1,NuGet安装:
Abp.Zero、Abp.Web.Api、Abp.AutoMapper、Microsoft.Owin.Security.OAuth、Microsoft.AspNet.WebApi.Owin
System.ComponentModel.DataAnnotations
2,WebApiModule
using System.Web.Http; using Abp.Application.Services; using Abp.Configuration.Startup; using Abp.Modules; using Abp.WebApi; namespace MyPassword.Api { [DependsOn(typeof(AbpWebApiModule), typeof(MyPasswordApplicationModule))] public class MyPasswordWebApiModule : AbpModule { public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder .ForAll<IApplicationService>(typeof(MyPasswordApplicationModule).Assembly, "app") .Build(); //添加访问令牌类型(Access Token Types)过滤(不加这句话也支持Bearer) Configuration.Modules.AbpWebApi().HttpConfiguration.Filters.Add(new HostAuthenticationFilter("Bearer")); } } }
备注:访问令牌类型(Access Token Types)包括bearer类型或mac类型。
①bearer类型
[RFC6750]中定义的“bearer”令牌类型被简单地包含在请求中的访问令牌字符串中:
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: Bearer mF_9.B5f-4.1JqM
②mac类型
而[OAuth-HTTP-MAC]中定义的“mac”令牌类型是通过发送消息认证码(MAC)密钥与用于签署HTTP请求的某些组件的访问令牌一起使用的:
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: MAC id="h480djs93hd8",
nonce="274312:dj83hs9s",
mac="kDZvddkndxvhGRXZhvuDjEWhGeE="
3,AccountController(获取访问令牌)
using System; using System.Threading.Tasks; using System.Web.Http; using Abp.Authorization; using Abp.Authorization.Users; using Abp.UI; using Abp.Web.Models; using Abp.WebApi.Controllers; using MyPassword.Api.Models; using MyPassword.Authorization; using MyPassword.Authorization.Users; using MyPassword.MultiTenancy; using MyPassword.Users; using Microsoft.Owin.Infrastructure; using Microsoft.Owin.Security; using Microsoft.Owin.Security.OAuth; namespace MyPassword.Api.Controllers { public class AccountController : AbpApiController { public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; } private readonly LogInManager _logInManager; static AccountController() { OAuthBearerOptions = new OAuthBearerAuthenticationOptions(); } public AccountController(LogInManager logInManager) { _logInManager = logInManager; LocalizationSourceName = MyPasswordConsts.LocalizationSourceName; } //获取访问令牌 [HttpPost] public async Task<AjaxResponse> Authenticate(LoginModel loginModel) { CheckModelState(); var loginResult = await GetLoginResultAsync( loginModel.UsernameOrEmailAddress, loginModel.Password, loginModel.TenancyName ); var ticket = new AuthenticationTicket(loginResult.Identity, new AuthenticationProperties()); var currentUtc = new SystemClock().UtcNow; ticket.Properties.IssuedUtc = currentUtc; ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(30)); return new AjaxResponse(OAuthBearerOptions.AccessTokenFormat.Protect(ticket)); } private async Task<AbpLoginResult<Tenant, User>> GetLoginResultAsync(string usernameOrEmailAddress, string password, string tenancyName) { var loginResult = await _logInManager.LoginAsync(usernameOrEmailAddress, password, tenancyName); switch (loginResult.Result) { case AbpLoginResultType.Success: return loginResult; default: throw CreateExceptionForFailedLoginAttempt(loginResult.Result, usernameOrEmailAddress, tenancyName); } } private Exception CreateExceptionForFailedLoginAttempt(AbpLoginResultType result, string usernameOrEmailAddress, string tenancyName) { switch (result) { case AbpLoginResultType.Success: return new ApplicationException("Don't call this method with a success result!"); case AbpLoginResultType.InvalidUserNameOrEmailAddress: case AbpLoginResultType.InvalidPassword: return new UserFriendlyException(L("LoginFailed"), L("InvalidUserNameOrPassword")); case AbpLoginResultType.InvalidTenancyName: return new UserFriendlyException(L("LoginFailed"), L("ThereIsNoTenantDefinedWithName{0}", tenancyName)); case AbpLoginResultType.TenantIsNotActive: return new UserFriendlyException(L("LoginFailed"), L("TenantIsNotActive", tenancyName)); case AbpLoginResultType.UserIsNotActive: return new UserFriendlyException(L("LoginFailed"), L("UserIsNotActiveAndCanNotLogin", usernameOrEmailAddress)); case AbpLoginResultType.UserEmailIsNotConfirmed: return new UserFriendlyException(L("LoginFailed"), "Your email address is not confirmed. You can not login"); //TODO: localize message default: //Can not fall to default actually. But other result types can be added in the future and we may forget to handle it Logger.Warn("Unhandled login fail reason: " + result); return new UserFriendlyException(L("LoginFailed")); } } protected virtual void CheckModelState() { if (!ModelState.IsValid) { throw new UserFriendlyException("Invalid request!"); } } } }
4,Web工程下的Startup.cs
app.UseOAuthBearerAuthentication(AccountController.OAuthBearerOptions);
将Bearer Token处理添加到OWIN应用程序管道。
这个中间件理解适当的格式化和安全的令牌出现在请求头。
如果Options.AuthenticationMode处于Active状态,则不记名令牌(bearer token)中的声明将被添加到当前请求的IPrincipal用户。
如果Options.AuthenticationMode是Passive的,那么当前请求不被修改,但IAuthenticationManager AuthenticateAsync可以随时用来从请求的不记名令牌(bearer token)中获得请求。
另见http://tools.ietf.org/html/rfc6749
5,案例
请求授权接口
返回令牌
请求受保护的资源
1,NuGet安装:Abp.Zero、Abp.EntityFramework、Abp.Zero.EntityFramework、Abp.Web.Api、Abp.Web.Mvc、Abp.AutoMapper、Abp.Castle.Log4Net、Abp.Owin
可选则安装:Abp.Web.SignalR
注意,先安装Abp.EntityFramework再安装Abp.Zero.EntityFramework
针对通用的依赖类型的解析与创建,微软默认定义了4种类别的生命周期,分别如下:
类型 | 描述 |
---|---|
Instance | 任何时间都只能使用特定的实例对象,开发人员需要负责该对象的初始化工作。 |
Transient | 每次都重新创建一个实例。 |
Singleton | 创建一个单例,以后每次调用的时候都返回该单例对象。 |
Scoped | 在当前作用域内,不管调用多少次,都是一个实例,换了作用域就会再次创建实例,类似于特定作用内的单例。 |
前端笔记
1,按钮
<button type="button" class="btn btn-primary btn-circle waves-effect waves-circle waves-float" data-toggle="modal"><i class="material-icons">add</i></button>
btn-circle:圆形按钮
pull-right:右浮动
waves-effect:点击按钮波浪效果
waves-block:块状效果
waves-circle:圆状效果
waves-float:效果浮动
2, 模态框
<a href="#" class="waves-effect waves-block edit-role" data-role-id="@role.Id" data-toggle="modal" data-target="#RoleEditModal"><i class="material-icons">edit</i>@L("Edit")</a> <div class="modal fade" id="RoleEditModal" tabindex="-1" role="dialog" aria-labelledby="RoleEditModalLabel" data-backdrop="static"> <div class="modal-dialog" role="document"> <div class="modal-content"> </div> </div> </div>
<div class="modal fade" id="RoleCreateModal" tabindex="-1" role="dialog" aria-labelledby="RoleCreateModalLabel" data-backdrop="static"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title"> <span>@L("CreateNewRole")</span> </h4> </div> <div class="modal-body"> <form name="roleCreateForm" role="form" novalidate class="form-validation"> <div class="row clearfix"> <div class="col-sm-12"> <div class="form-group form-float"> <div class="form-line"> <input id="rolename" type="text" name="Name" required maxlength="32" minlength="2" class="validate form-control"> <label for="rolename" class="form-label">@L("RoleName")</label> </div> </div> </div> </div> <div class="row clearfix"> <div class="col-sm-12"> <div class="form-group form-float"> <div class="form-line"> <input id="displayname" type="text" name="DisplayName" required maxlength="32" minlength="2" class="validate form-control"> <label for="displayname" class="form-label">@L("DisplayName")</label> </div> </div> </div> </div> <div class="row"> <div class="col-sm-12"> <div class="form-group form-float"> <div class="form-line"> <textarea id="role-description" name="Description" class="validate form-control"></textarea> <label for="role-description" class="form-label">Role Description</label> </div> </div> </div> </div> <div class="row clearfix"> <div class="col-sm-12"> <h4>Permissions</h4> @foreach (var permission in Model.Permissions) { <div class="col-sm-6"> <input type="checkbox" name="permission" value="@permission.Name" class="filled-in" id="@string.Format("permission{0}",permission.Name)" checked="checked" /> <label for="@string.Format("permission{0}",permission.Name)">@permission.DisplayName</label> </div> } </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default waves-effect" data-dismiss="modal">@L("Cancel")</button> <button type="submit" class="btn btn-primary waves-effect">@L("Save")</button> </div> </form> </div> </div> </div> </div>
3,for属性
在用户注册的时候,常常用户点击文字就需要将光标聚焦到对应的表单上面,这个是怎么实现的呢?就是下面我要介绍的<label>标签的for属性
定义:for 属性规定 label 与哪个表单元素绑定
<div class="form-line"> <input id="rolename" type="text" name="Name" required maxlength="32" minlength="2" class="validate form-control"> <label for="rolename" class="form-label">@L("RoleName")</label> </div>
1,NuGet安装:
Abp.TestBase、Abp.EntityFramework、Effort.EF6、xunit、Shouldly、xunit.runner.visualstudio、Abp.Zero.EntityFramework、NSubstitute
2,基本结构
using System; using System.Collections.Generic; using System.Data.Common; using System.Data.Entity; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp; using Abp.Configuration.Startup; using Abp.Domain.Uow; using Abp.Runtime.Session; using Abp.TestBase; using Castle.MicroKernel.Registration; using Effort; using EntityFramework.DynamicFilters; using PM.Core.MultiTenant; using PM.Core.Users; using PM.EntityFramework.EntityFramework; using PM.EntityFramework.Migrations.SeedData; namespace PM.Test { public class PMTestBase: AbpIntegratedTestBase<PMTestModule> { private DbConnection _hostDb; private Dictionary<int, DbConnection> _tenantDbs; //only used for db per tenant architecture protected PMTestBase() { //Seed initial data for host AbpSession.TenantId = null; UsingDbContext(context => { new InitialHostDbBuilder(context).Create(); new DefaultTenantCreator(context).Create(); }); //Seed initial data for default tenant AbpSession.TenantId = 1; UsingDbContext(context => { new TenantRoleAndUserBuilder(context, 1).Create(); }); LoginAsDefaultTenantAdmin(); } protected override void PreInitialize() { base.PreInitialize(); /* You can switch database architecture here: */ UseSingleDatabase(); //UseDatabasePerTenant(); } /* Uses single database for host and all tenants. */ private void UseSingleDatabase() { _hostDb = DbConnectionFactory.CreateTransient(); LocalIocManager.IocContainer.Register( Component.For<DbConnection>() .UsingFactoryMethod(() => _hostDb) .LifestyleSingleton() ); } /* Uses single database for host and Default tenant, * but dedicated databases for all other tenants. */ private void UseDatabasePerTenant() { _hostDb = DbConnectionFactory.CreateTransient(); _tenantDbs = new Dictionary<int, DbConnection>(); LocalIocManager.IocContainer.Register( Component.For<DbConnection>() .UsingFactoryMethod((kernel) => { lock (_tenantDbs) { var currentUow = kernel.Resolve<ICurrentUnitOfWorkProvider>().Current; var abpSession = kernel.Resolve<IAbpSession>(); var tenantId = currentUow != null ? currentUow.GetTenantId() : abpSession.TenantId; if (tenantId == null || tenantId == 1) //host and default tenant are stored in host db { return _hostDb; } if (!_tenantDbs.ContainsKey(tenantId.Value)) { _tenantDbs[tenantId.Value] = DbConnectionFactory.CreateTransient(); } return _tenantDbs[tenantId.Value]; } }, true) .LifestyleTransient() ); } #region UsingDbContext protected IDisposable UsingTenantId(int? tenantId) { var previousTenantId = AbpSession.TenantId; AbpSession.TenantId = tenantId; return new DisposeAction(() => AbpSession.TenantId = previousTenantId); } protected void UsingDbContext(Action<PMDBContext> action) { UsingDbContext(AbpSession.TenantId, action); } protected Task UsingDbContextAsync(Func<PMDBContext, Task> action) { return UsingDbContextAsync(AbpSession.TenantId, action); } protected T UsingDbContext<T>(Func<PMDBContext, T> func) { return UsingDbContext(AbpSession.TenantId, func); } protected Task<T> UsingDbContextAsync<T>(Func<PMDBContext, Task<T>> func) { return UsingDbContextAsync(AbpSession.TenantId, func); } protected void UsingDbContext(int? tenantId, Action<PMDBContext> action) { using (UsingTenantId(tenantId)) { using (var context = LocalIocManager.Resolve<PMDBContext>()) { context.DisableAllFilters(); action(context); context.SaveChanges(); } } } protected async Task UsingDbContextAsync(int? tenantId, Func<PMDBContext, Task> action) { using (UsingTenantId(tenantId)) { using (var context = LocalIocManager.Resolve<PMDBContext>()) { context.DisableAllFilters(); await action(context); await context.SaveChangesAsync(); } } } protected T UsingDbContext<T>(int? tenantId, Func<PMDBContext, T> func) { T result; using (UsingTenantId(tenantId)) { using (var context = LocalIocManager.Resolve<PMDBContext>()) { context.DisableAllFilters(); result = func(context); context.SaveChanges(); } } return result; } protected async Task<T> UsingDbContextAsync<T>(int? tenantId, Func<PMDBContext, Task<T>> func) { T result; using (UsingTenantId(tenantId)) { using (var context = LocalIocManager.Resolve<PMDBContext>()) { context.DisableAllFilters(); result = await func(context); await context.SaveChangesAsync(); } } return result; } #endregion #region Login protected void LoginAsHostAdmin() { LoginAsHost(User.AdminUserName); } protected void LoginAsDefaultTenantAdmin() { LoginAsTenant(Tenant.DefaultTenantName, User.AdminUserName); } protected void LogoutAsDefaultTenant() { LogoutAsTenant(Tenant.DefaultTenantName); } protected void LoginAsHost(string userName) { AbpSession.TenantId = null; var user = UsingDbContext( context => context.Users.FirstOrDefault(u => u.TenantId == AbpSession.TenantId && u.UserName == userName)); if (user == null) { throw new Exception("There is no user: " + userName + " for host."); } AbpSession.UserId = user.Id; } protected void LogoutAsHost() { Resolve<IMultiTenancyConfig>().IsEnabled = true; AbpSession.TenantId = null; AbpSession.UserId = null; } protected void LoginAsTenant(string tenancyName, string userName) { var tenant = UsingDbContext(context => context.Tenants.FirstOrDefault(t => t.TenancyName == tenancyName)); if (tenant == null) { throw new Exception("There is no tenant: " + tenancyName); } AbpSession.TenantId = tenant.Id; var user = UsingDbContext( context => context.Users.FirstOrDefault(u => u.TenantId == AbpSession.TenantId && u.UserName == userName)); if (user == null) { throw new Exception("There is no user: " + userName + " for tenant: " + tenancyName); } AbpSession.UserId = user.Id; } protected void LogoutAsTenant(string tenancyName) { var tenant = UsingDbContext(context => context.Tenants.FirstOrDefault(t => t.TenancyName == tenancyName)); if (tenant == null) { throw new Exception("There is no tenant: " + tenancyName); } AbpSession.TenantId = tenant.Id; AbpSession.UserId = null; } #endregion /// <summary> /// Gets current user if <see cref="IAbpSession.UserId"/> is not null. /// Throws exception if it's null. /// </summary> protected async Task<Core.Users.User> GetCurrentUserAsync() { var userId = AbpSession.GetUserId(); return await UsingDbContext(context => context.Users.SingleAsync(u => u.Id == userId)); } /// <summary> /// Gets current tenant if <see cref="IAbpSession.TenantId"/> is not null. /// Throws exception if there is no current tenant. /// </summary> protected async Task<Tenant> GetCurrentTenantAsync() { var tenantId = AbpSession.GetTenantId(); return await UsingDbContext(context => context.Tenants.SingleAsync(t => t.Id == tenantId)); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Abp.Modules; using Abp.MultiTenancy; using Abp.TestBase; using Abp.Zero.Configuration; using Castle.MicroKernel.Registration; using NSubstitute; using PM.Application; using PM.EntityFramework; namespace PM.Test { [DependsOn( typeof(PMDataModule), typeof(PMApplicationModule), typeof(AbpTestBaseModule) )] public class PMTestModule:AbpModule { public override void PreInitialize() { //使用数据库进行语言管理 Configuration.Modules.Zero().LanguageManagement.EnableDbLocalization(); //注册伪服务 IocManager.IocContainer.Register( Component.For<IAbpZeroDbMigrator>() .UsingFactoryMethod(() => Substitute.For<IAbpZeroDbMigrator>()) .LifestyleSingleton() ); } } }
using Xunit; namespace AbpCompanyName.AbpProjectName.Tests { public sealed class MultiTenantFactAttribute : FactAttribute { public MultiTenantFactAttribute() { if (!AbpProjectNameConsts.MultiTenancyEnabled) { Skip = "MultiTenancy is disabled."; } } } }