番外篇--Moddule Zero安裝


返回總目錄:ABP+AdminLTE+Bootstrap Table權限管理系統一期

Moddule Zero

安裝

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>
{

}

你可以在這里添加自定義屬性。通過這種方式,我們可以根據我們的需要擴展基用戶,角色和租戶類。

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)
    {

    }
}

別擔心依賴列表。他們可能會在下一個版本改變。如果需要的話只是組織構造函數。角色存儲和角色管理也類似:

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)
    {
    }
}

最后,我們要創建一個類租戶管理類(這里沒有租戶存儲):

public class TenantManager : AbpTenantManager<Tenant, Role, User>
{
    public TenantManager(
        IRepository<Tenant> tenantRepository, 
        IRepository<TenantFeatureSetting, long> tenantFeatureRepository, 
        EditionManager editionManager) : 
        base(
            tenantRepository, 
            tenantFeatureRepository, 
            editionManager
        )
    {
    }
}

最后是功能值存儲類以及版本管理類:

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
        )
    {

    }
}

1.2.6 權限檢查器

為了使授權系統工作,我們應該實現權限檢查器:

public class PermissionChecker : PermissionChecker<Tenant, Role, User>
{
    public PermissionChecker(UserManager userManager)
        : base(userManager)
    {

    }
}

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>
{
    //...
}

從而,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();
    }
}

在這里,我們禁用數據過濾器(所以我們可以自由地操縱數據庫),並使用的初始數據生成器類。

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");
    }
}

附一個簡單的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.
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM