1.2ABPZero-安装

ABP官方翻译文档

1.2 ABPZero – 安装

1.2.1 从模板创建

使用ABP和module-zero开始一个新项目最简单的方式是使用启动模板。详细了解请参考启动模板文档

1.2.2 手动安装

如果你有一个预先创建的应用程序,稍后再安装module-zero,您可以按照本部分的说明。

在本文中,我将假定您的解决方案具有以下项目:

  • AbpZeroSample.Core
  • AbpZeroSample.Application
  • AbpZeroSample.EntityFramework
  • AbpZeroSample.Web
  • AbpZeroSample.WebApi

1.2.3 核心(领域)层

安装Abp.Zero的NuGet包到时Core工程。然后进入到核心模块类(在此示例中为AbpZeroSampleCoreModule类),并添加DependsOn属性AbpZeroCoreModule如下图所示:

[DependsOn(typeof(AbpZeroCoreModule))]
public class AbpZeroSampleCoreModule : AbpModule
{
    public override void Initialize()
    {
        IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
    }
}

1.2.4 领域类(实体)

Module-zero提供了 User,Role和Tenant 类的抽象。所以,我们应该实现它们,如下所示:

public class User : AbpUser<tenant user="">
{

}

public class Role : AbpRole<tenant user="">
{

}

public class Tenant : AbpTenant<tenant user="">
{

}</tenant></tenant></tenant>

你可以在这里添加自定义属性。通过这种方式,我们可以根据我们的需要扩展基用户,角色和租户类。

1.2.5 管理类(领域服务)

我们应该先实现管理基类和存储基类,因为他们是抽象的。

从启动用户存储和用户管理开始:

public class UserStore : AbpUserStore<tenant 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
        )
        : base(
            userRepository,
            userLoginRepository,
            userRoleRepository,
            roleRepository,
            userPermissionSettingRepository,
            unitOfWorkManager
        )
    {
    }
}

public class UserManager : AbpUserManager<tenant role="" user="">
{
    public UserManager(
        UserStore userStore,
        RoleManager roleManager,
        IRepository<tenant> tenantRepository,
        IMultiTenancyConfig multiTenancyConfig,
        IPermissionManager permissionManager,
        IUnitOfWorkManager unitOfWorkManager,
        ISettingManager settingManager,
        IUserManagementConfig userManagementConfig,
        IIocResolver iocResolver,
        ICacheManager cacheManager,
        IRepository<organizationunit long=""> organizationUnitRepository,
        IRepository<userorganizationunit long=""> userOrganizationUnitRepository,
        IOrganizationUnitSettings organizationUnitSettings)
        : base(
            userStore,
            roleManager,
            tenantRepository,
            multiTenancyConfig,
            permissionManager,
            unitOfWorkManager,
            settingManager,
            userManagementConfig,
            iocResolver,
            cacheManager,
            organizationUnitRepository,
            userOrganizationUnitRepository,
            organizationUnitSettings)
    {

    }
}</userorganizationunit></organizationunit></tenant></tenant></userpermissionsetting></role></userrole></userlogin></user></tenant>

别担心依赖列表。他们可能会在下一个版本改变。如果需要的话只是组织构造函数。角色存储和角色管理也类似:

public class RoleStore : AbpRoleStore<tenant role="" user="">
{
    public RoleStore(
        IRepository<role> roleRepository,
        IRepository<userrole long=""> userRoleRepository,
        IRepository<rolepermissionsetting long=""> rolePermissionSettingRepository)
        : base(
            roleRepository,
            userRoleRepository,
            rolePermissionSettingRepository
        )
    {

    }
}

public class RoleManager : AbpRoleManager<tenant role="" user="">
{
    public RoleManager(
        RoleStore store, 
        IPermissionManager permissionManager, 
        IRoleManagementConfig roleManagementConfig, 
        ICacheManager cacheManager)
        : base(
            store, 
            permissionManager, 
            roleManagementConfig, 
            cacheManager)
    {
    }
}</tenant></rolepermissionsetting></userrole></role></tenant>

最后,我们要创建一个类租户管理类(这里没有租户存储):

public class TenantManager : AbpTenantManager<tenant role="" user="">
{
    public TenantManager(
        IRepository<tenant> tenantRepository, 
        IRepository<tenantfeaturesetting long=""> tenantFeatureRepository, 
        EditionManager editionManager) : 
        base(
            tenantRepository, 
            tenantFeatureRepository, 
            editionManager
        )
    {
    }
}</tenantfeaturesetting></tenant></tenant>

最后是功能值存储类以及版本管理类:

public class FeatureValueStore : AbpFeatureValueStore<tenant role="" user="">
{
    public FeatureValueStore(TenantManager tenantManager)
        : base(tenantManager)
    {

    }
}

public class EditionManager : AbpEditionManager
{
    public const string DefaultEditionName = Standard;

    public EditionManager(
        IRepository<edition> editionRepository, 
        IRepository<editionfeaturesetting long=""> editionFeatureRepository) 
        : base(
            editionRepository, 
            editionFeatureRepository
        )
    {

    }
}</editionfeaturesetting></edition></tenant>

1.2.6 权限检查器

为了使授权系统工作,我们应该实现权限检查器:

public class PermissionChecker : PermissionChecker<tenant role="" user="">
{
    public PermissionChecker(UserManager userManager)
        : base(userManager)
    {

    }
}</tenant>

1.2.7 基础设施层

1. Entity Framework

如果您选择Entity Framework,我们应该配置它以便使用module-zero。安装Abp.Zero.EntityFramework的NuGet包到EntityFramework项目。然后进入到模块文件(此示例中为AbpZeroSampleDataModule)和改变AbpEntityFrameworkModule依赖到AbpZeroEntityFrameworkModule如下图所示:

[DependsOn(typeof(AbpZeroEntityFrameworkModule), typeof(AbpZeroSampleCoreModule))]
public class AbpZeroSampleDataModule : AbpModule
{
    //...
}

2. DbContext

转到您的DbContext类,并改变基类AbpDbContext为AbpZeroDbContext;如下所示:

public class AbpZeroSampleDbContext : AbpZeroDbContext<tenant role="" user="">
{
    //...
}</tenant>

从而,module-zero里的基础实体被添加到你的数据库环境中。

3. 数据库迁移

现在,我们应该创建数据库迁移,因为我们的数据库上下文被更改了。打开包管理器控制台,然后键入以下命令:

Add-Migration AbpZero_Installed

当然,你可以选择不同的迁移名称。不要忘了在包管理器控制台中选择默认工程为AbpZeroSample.EntityFramework(对于你的例子AbpZeroSample将是不同的)。执行这个命令之后,一个新的迁移文件被添加到工程中。检查它,如果你需要可以改变它。然后键入以下命令来更新数据库模式:

Update-Database

您可以检查EntityFramework的代码优先迁移文档以获取更多信息。

4. 初始化数据

如果你检查你的数据库,你会看到表已经被创建,但它们是空的。您可以使用EntityFramework的播种以填补初始数据。您可以使用这样的类作为初始数据生成器:

public class DefaultTenantRoleAndUserBuilder
{
    private readonly AbpZeroSampleDbContext _context;

    public DefaultTenantRoleAndUserBuilder(AbpZeroSampleDbContext context)
    {
        _context = context;
    }

    public void Build()
    {
        CreateUserAndRoles();
    }

    private void CreateUserAndRoles()
    {
        //Admin role for tenancy owner

        var adminRoleForTenancyOwner = _context.Roles.FirstOrDefault(r => r.TenantId == null && r.Name == Admin);
        if (adminRoleForTenancyOwner == null)
        {
            adminRoleForTenancyOwner = _context.Roles.Add(new Role {Name = Admin, DisplayName = Admin});
            _context.SaveChanges();
        }

        //Admin user for tenancy owner

        var adminUserForTenancyOwner = _context.Users.FirstOrDefault(u => u.TenantId == null && u.UserName == admin);
        if (adminUserForTenancyOwner == null)
        {
            adminUserForTenancyOwner = _context.Users.Add(
                new User
                {
                    TenantId = null,
                    UserName = admin,
                    Name = System,
                    Surname = Administrator,
                    EmailAddress = admin@aspnetboilerplate.com,
                    IsEmailConfirmed = true,
                    Password = AM4OLBpptxBYmM79lGOX9egzZk3vIQU3d/gFCJzaBjAPXzYIK3tQ2N7X4fcrHtElTw== //123qwe
                });

            _context.SaveChanges();

            _context.UserRoles.Add(new UserRole(adminUserForTenancyOwner.Id, adminRoleForTenancyOwner.Id));

            _context.SaveChanges();
        }

        //Default tenant

        var defaultTenant = _context.Tenants.FirstOrDefault(t => t.TenancyName == Default);
        if (defaultTenant == null)
        {
            defaultTenant = _context.Tenants.Add(new Tenant {TenancyName = Default, Name = Default});
            _context.SaveChanges();
        }

        //Admin role for 'Default' tenant

        var adminRoleForDefaultTenant = _context.Roles.FirstOrDefault(r => r.TenantId == defaultTenant.Id && r.Name == Admin);
        if (adminRoleForDefaultTenant == null)
        {
            adminRoleForDefaultTenant = _context.Roles.Add(new Role { TenantId = defaultTenant.Id, Name = Admin, DisplayName = Admin });
            _context.SaveChanges();
        }

        //Admin for 'Default' tenant

        var adminUserForDefaultTenant = _context.Users.FirstOrDefault(u => u.TenantId == defaultTenant.Id && u.UserName == admin);
        if (adminUserForDefaultTenant == null)
        {
            adminUserForDefaultTenant = _context.Users.Add(
                new User
                {
                    TenantId = defaultTenant.Id,
                    UserName = admin,
                    Name = System,
                    Surname = Administrator,
                    EmailAddress = admin@aspnetboilerplate.com,
                    IsEmailConfirmed = true,
                    Password = AM4OLBpptxBYmM79lGOX9egzZk3vIQU3d/gFCJzaBjAPXzYIK3tQ2N7X4fcrHtElTw== //123qwe
                });
            _context.SaveChanges();

            _context.UserRoles.Add(new UserRole(adminUserForDefaultTenant.Id, adminRoleForDefaultTenant.Id));
            _context.SaveChanges();
        }
    }
}

该类创建默认租户,角色和用户。我们可以用它在EF的配置类中初始化我们的数据库数据:

internal sealed class Configuration : DbMigrationsConfiguration<abpzerosample.entityframework.abpzerosampledbcontext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        ContextKey = AbpZeroSample;
    }

    protected override void Seed(AbpZeroSample.EntityFramework.AbpZeroSampleDbContext context)
    {
        context.DisableAllFilters();
        new DefaultTenantRoleAndUserBuilder(context).Build();
    }
}</abpzerosample.entityframework.abpzerosampledbcontext>

在这里,我们禁用数据过滤器(所以我们可以自由地操纵数据库),并使用的初始数据生成器类。

1.2.8 表示层

1. NuGet包

添加以下的NuGet包到.Web工程:

  • Abp.Zero.EntityFramework(这也将增加Abp.Zero和所有的依赖)
  • Microsoft.AspNet.Identity.Owin
  • Microsoft.Owin.Host.SystemWeb

2. Owin启动类

添加这样一个Owin启动类:

using AbpZeroSample.Web;
using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;

[assembly: OwinStartup(typeof(Startup))]

namespace AbpZeroSample.Web{ public class Startup { public void Configuration(IAppBuilder app) { //对当前应用开启cookie功能,使用它来存储已登录的用户信息 app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString(/Account/Login) }); //使用cookie来临时性的存储一个已经登录的用户信息,该登录配置的是使用第三方登录提供器 app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); } }}

3. 账户控制器

我们可以创建一个控制器用于登录/注销,如下所示:

public class AccountController : AbpZeroSampleControllerBase
{
    private readonly UserManager _userManager;

    private IAuthenticationManager AuthenticationManager
    {
        get
        {
            return HttpContext.GetOwinContext().Authentication;
        }
    }

    public AccountController(UserManager userManager)
    {
        _userManager = userManager;
    }

    public ActionResult Login(string returnUrl = )
    {
        if (string.IsNullOrWhiteSpace(returnUrl))
        {
            returnUrl = Request.ApplicationPath;
        }

        ViewBag.ReturnUrl = returnUrl;

        return View();
    }

    [HttpPost]
    public async Task<jsonresult> Login(LoginViewModel loginModel, string returnUrl = )
    {
        if (!ModelState.IsValid)
        {
            throw new UserFriendlyException(Your form is invalid!);
        }

        var loginResult = await _userManager.LoginAsync(
            loginModel.UsernameOrEmailAddress,
            loginModel.Password,
            loginModel.TenancyName
            );

        switch (loginResult.Result)
        {
            case AbpLoginResultType.Success:
                break;
            case AbpLoginResultType.InvalidUserNameOrEmailAddress:
            case AbpLoginResultType.InvalidPassword:
                throw new UserFriendlyException(Invalid user name or password!);
            case AbpLoginResultType.InvalidTenancyName:
                throw new UserFriendlyException(No tenant with name:  + loginModel.TenancyName);
            case AbpLoginResultType.TenantIsNotActive:
                throw new UserFriendlyException(Tenant is not active:  + loginModel.TenancyName);
            case AbpLoginResultType.UserIsNotActive:
                throw new UserFriendlyException(User is not active:  + loginModel.UsernameOrEmailAddress);
            case AbpLoginResultType.UserEmailIsNotConfirmed:
                throw new UserFriendlyException(Your email address is not confirmed!);
            default: //Can not fall to default for now. But other result types can be added in the future and we may forget to handle it
                throw new UserFriendlyException(Unknown problem with login:  + loginResult.Result);
        }

        AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
        AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = loginModel.RememberMe }, loginResult.Identity);

        if (string.IsNullOrWhiteSpace(returnUrl))
        {
            returnUrl = Request.ApplicationPath;
        }

        return Json(new MvcAjaxResponse { TargetUrl = returnUrl });
    }

    public ActionResult Logout()
    {
        AuthenticationManager.SignOut();
        return RedirectToAction(Login);
    }
}</jsonresult>

附一个简单的LoginViewModel:

public class LoginViewModel
{
    public string TenancyName { get; set; }

    [Required]
    public string UsernameOrEmailAddress { get; set; }

    [Required]
    public string Password { get; set; }

    public bool RememberMe { get; set; }
}

1.2.9 登录视图

为了能够使用的AccountController,我们应该创建一个登录页面。这由你决定创建一个登录表单。只需通过AJAX使用适当的参数调用AccountController.Login。

1. 确保应用程序安全

现在,我们可以添加一个AbpAuthorize特性到HomeController,以确保只有合法的用户才能进入到页面:

[AbpMvcAuthorize]
public class HomeController : AbpZeroSampleControllerBase
{
    public ActionResult Index()
    {
        return View(~/App/Main/views/layout/layout.cshtml); //Layout of the angular application.
    }
原文出处:https://github.com/ABPFrameWorkGroup/AbpDocument2Chinese

原文链接:

本文观点不代表 .Net中文网 立场,转载请联系原作者。

发表评论

登录后才能评论