mirror of https://github.com/abpframework/abp.git
50 changed files with 1174 additions and 159 deletions
@ -0,0 +1,95 @@ |
|||
# ContentStrategy |
|||
|
|||
`ContentStrategy` is an abstract class exposed by @abp/ng.core package. It helps you create inline scripts or styles. |
|||
|
|||
## API |
|||
|
|||
|
|||
### constructor |
|||
|
|||
```js |
|||
constructor( |
|||
public content: string, |
|||
protected domStrategy?: DomStrategy, |
|||
protected contentSecurityStrategy?: ContentSecurityStrategy |
|||
) |
|||
``` |
|||
|
|||
- `content` is set to `<script>` and `<style>` elements as `textContent` property. |
|||
- `domStrategy` is the `DomStrategy` that will be used when inserting the created element. (_default: AppendToHead_) |
|||
- `contentSecurityStrategy` is the `ContentSecurityStrategy` that will be used on the created element before inserting it. (_default: None_) |
|||
|
|||
Please refer to [DomStrategy](./Dom-Strategy.md) and [ContentSecurityStrategy](./Content-Security-Strategy.md) documentation for their usage. |
|||
|
|||
|
|||
### createElement |
|||
|
|||
```js |
|||
createElement(): HTMLScriptElement | HTMLStyleElement |
|||
``` |
|||
|
|||
This method creates and returns a `<script>` or `<style>` element with `content` set as `textContent`. |
|||
|
|||
|
|||
### insertElement |
|||
|
|||
```js |
|||
insertElement(): void |
|||
``` |
|||
|
|||
This method creates and inserts a `<script>` or `<style>` element. |
|||
|
|||
|
|||
## ScriptContentStrategy |
|||
|
|||
`ScriptContentStrategy` is a class that extends `ContentStrategy`. It lets you **insert a `<script>` element to the DOM**. |
|||
|
|||
## StyleContentStrategy |
|||
|
|||
`StyleContentStrategy` is a class that extends `ContentStrategy`. It lets you **insert a `<style>` element to the DOM**. |
|||
|
|||
|
|||
## Predefined Content Strategies |
|||
|
|||
Predefined content strategies are accessible via `CONTENT_STRATEGY` constant. |
|||
|
|||
|
|||
### AppendScriptToBody |
|||
|
|||
```js |
|||
CONTENT_STRATEGY.AppendScriptToBody(content: string) |
|||
``` |
|||
|
|||
Creates a `<script>` element with the given content and places it at the **end** of `<body>` tag in the document. |
|||
|
|||
|
|||
### AppendScriptToHead |
|||
|
|||
```js |
|||
CONTENT_STRATEGY.AppendScriptToHead(content: string) |
|||
``` |
|||
|
|||
Creates a `<script>` element with the given content and places it at the **end** of `<head>` tag in the document. |
|||
|
|||
|
|||
### AppendStyleToHead |
|||
|
|||
```js |
|||
CONTENT_STRATEGY.AppendStyleToHead(content: string) |
|||
``` |
|||
|
|||
Creates a `<style>` element with the given content and places it at the **end** of `<head>` tag in the document. |
|||
|
|||
|
|||
### PrependStyleToHead |
|||
|
|||
```js |
|||
CONTENT_STRATEGY.PrependStyleToHead(content: string) |
|||
``` |
|||
|
|||
Creates a `<style>` element with the given content and places it at the **beginning** of `<head>` tag in the document. |
|||
|
|||
|
|||
## See Also |
|||
|
|||
- [DomInsertionService](./Dom-Insertion-Service.md) |
|||
@ -0,0 +1,91 @@ |
|||
# How to Insert Scripts and Styles |
|||
|
|||
You can use the `DomInsertionService` in @abp/ng.core package in order to insert scripts and styles in an easy and explicit way. |
|||
|
|||
|
|||
## Getting Started |
|||
|
|||
You do not have to provide the `DomInsertionService` at module or component level, because it is already **provided in root**. You can inject and start using it immediately in your components, directives, or services. |
|||
|
|||
```js |
|||
import { DomInsertionService } from '@abp/ng.core'; |
|||
|
|||
@Component({ |
|||
/* class metadata here */ |
|||
}) |
|||
class DemoComponent { |
|||
constructor(private domInsertionService: DomInsertionService) {} |
|||
} |
|||
``` |
|||
|
|||
## Usage |
|||
|
|||
You can use the `insertContent` method of `DomInsertionService` to create a `<script>` or `<style>` element with given content in the DOM at the desired position. |
|||
|
|||
|
|||
### How to Insert Scripts |
|||
|
|||
The first parameter of `insertContent` method expects a `ContentStrategy`. If you pass a `ScriptContentStrategy` instance, the `DomInsertionService` will create a `<script>` element with given `content` and place it in the designated DOM position. |
|||
|
|||
```js |
|||
import { DomInsertionService, CONTENT_STRATEGY } from '@abp/ng.core'; |
|||
|
|||
@Component({ |
|||
/* class metadata here */ |
|||
}) |
|||
class DemoComponent { |
|||
constructor(private domInsertionService: DomInsertionService) {} |
|||
|
|||
ngOnInit() { |
|||
this.domInsertionService.insertContent( |
|||
CONTENT_STRATEGY.AppendScriptToBody('alert()') |
|||
); |
|||
} |
|||
} |
|||
``` |
|||
|
|||
In the example above, `<script>alert()</script>` element will place at the **end** of `<body>`. |
|||
|
|||
Please refer to [ContentStrategy](./Content-Strategy.md) to see all available content strategies and how you can build your own content strategy. |
|||
|
|||
|
|||
### How to Insert Styles |
|||
|
|||
If you pass a `StyleContentStrategy` instance as the first parameter of `insertContent` method, the `DomInsertionService` will create a `<style>` element with given `content` and place it in the designated DOM position. |
|||
|
|||
```js |
|||
import { DomInsertionService, CONTENT_STRATEGY } from '@abp/ng.core'; |
|||
|
|||
@Component({ |
|||
/* class metadata here */ |
|||
}) |
|||
class DemoComponent { |
|||
constructor(private domInsertionService: DomInsertionService) {} |
|||
|
|||
ngOnInit() { |
|||
this.domInsertionService.insertContent( |
|||
CONTENT_STRATEGY.AppendStyleToHead('body {margin: 0;}') |
|||
); |
|||
} |
|||
} |
|||
``` |
|||
|
|||
In the example above, `<style>body {margin: 0;}</style>` element will place at the **end** of `<head>`. |
|||
|
|||
Please refer to [ContentStrategy](./Content-Strategy.md) to see all available content strategies and how you can build your own content strategy. |
|||
|
|||
|
|||
## API |
|||
|
|||
### insertContent |
|||
|
|||
```js |
|||
insertContent(strategy: ContentStrategy): void |
|||
``` |
|||
|
|||
`strategy` parameter is the primary focus here and is explained above. |
|||
|
|||
|
|||
## What's Next? |
|||
|
|||
- [TrackByService](./Track-By-Service.md) |
|||
@ -0,0 +1,3 @@ |
|||
# 如何对MVC / Razor页面应用程序使用Azure Active Directory身份验证 |
|||
|
|||
TODO... |
|||
@ -0,0 +1,113 @@ |
|||
# 如何为MVC / Razor页面应用程序自定义登录页面 |
|||
|
|||
当你使用[应用程序启动模板](../Startup-Templates/Application.md)创建了一个新的应用程序, 登录页面的源代码并不在你的解决方案中,所以你不能直接更改. 它来自[账户模块](../Modules/Account.md),使用[NuGet包](https://www.nuget.org/packages/Volo.Abp.Account.Web)引用. |
|||
|
|||
本文介绍了如何为自己的应用程序自定义登录页面. |
|||
|
|||
## 创建登录 PageModel |
|||
|
|||
创建一个新的类继承账户模块的[LoginModel](https://github.com/abpframework/abp/blob/037ef9abe024c03c1f89ab6c933710bcfe3f5c93/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs). |
|||
|
|||
````csharp |
|||
public class CustomLoginModel : LoginModel |
|||
{ |
|||
public CustomLoginModel( |
|||
Microsoft.AspNetCore.Authentication.IAuthenticationSchemeProvider schemeProvider, |
|||
Microsoft.Extensions.Options.IOptions<Volo.Abp.Account.Web.AbpAccountOptions> accountOptions) |
|||
: base(schemeProvider, accountOptions) |
|||
{ |
|||
} |
|||
} |
|||
```` |
|||
|
|||
> 在这里命令约定很重要. 如果你的类名不是以 `LoginModel` 结束,你需要手动在[依赖注入](../Dependency-Injection.md)系统替换 `LoginModel`. |
|||
|
|||
然后你可以覆盖任何方法并添加用户界面需要的新方法和属性. |
|||
|
|||
## 重写登录页面UI |
|||
|
|||
在 **Pages** 目录下创建名为 **Account** 的文件夹,并在这个文件夹中创建 `Login.cshtml` ,借助[虚拟文件系统](../Virtual-File-System.md)它会自动覆盖账户模块的页面文件. |
|||
|
|||
自定义页面一个很好的开始是复制它的源代码. [点击这里](https://github.com/abpframework/abp/blob/dev/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml)找到登录页面的源码. 在编写本文档时,源代码如下: |
|||
|
|||
````xml |
|||
@page |
|||
@using Volo.Abp.Account.Settings |
|||
@using Volo.Abp.Settings |
|||
@model Acme.BookStore.Web.Pages.Account.CustomLoginModel |
|||
@inherits Volo.Abp.Account.Web.Pages.Account.AccountPage |
|||
@inject Volo.Abp.Settings.ISettingProvider SettingProvider |
|||
@if (Model.EnableLocalLogin) |
|||
{ |
|||
<div class="card mt-3 shadow-sm rounded"> |
|||
<div class="card-body p-5"> |
|||
<h4>@L["Login"]</h4> |
|||
@if (await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled)) |
|||
{ |
|||
<strong> |
|||
@L["AreYouANewUser"] |
|||
<a href="@Url.Page("./Register", new {returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash})" class="text-decoration-none">@L["Register"]</a> |
|||
</strong> |
|||
} |
|||
<form method="post" class="mt-4"> |
|||
<input asp-for="ReturnUrl" /> |
|||
<input asp-for="ReturnUrlHash" /> |
|||
<div class="form-group"> |
|||
<label asp-for="LoginInput.UserNameOrEmailAddress"></label> |
|||
<input asp-for="LoginInput.UserNameOrEmailAddress" class="form-control" /> |
|||
<span asp-validation-for="LoginInput.UserNameOrEmailAddress" class="text-danger"></span> |
|||
</div> |
|||
<div class="form-group"> |
|||
<label asp-for="LoginInput.Password"></label> |
|||
<input asp-for="LoginInput.Password" class="form-control" /> |
|||
<span asp-validation-for="LoginInput.Password" class="text-danger"></span> |
|||
</div> |
|||
<div class="form-check"> |
|||
<label asp-for="LoginInput.RememberMe" class="form-check-label"> |
|||
<input asp-for="LoginInput.RememberMe" class="form-check-input" /> |
|||
@Html.DisplayNameFor(m => m.LoginInput.RememberMe) |
|||
</label> |
|||
</div> |
|||
<abp-button type="submit" button-type="Primary" name="Action" value="Login" class="btn-block btn-lg mt-3">@L["Login"]</abp-button> |
|||
</form> |
|||
</div> |
|||
|
|||
<div class="card-footer text-center border-0"> |
|||
<abp-button type="button" button-type="Link" name="Action" value="Cancel" class="px-2 py-0">@L["Cancel"]</abp-button> @* TODO: Only show if identity server is used *@ |
|||
</div> |
|||
</div> |
|||
} |
|||
|
|||
@if (Model.VisibleExternalProviders.Any()) |
|||
{ |
|||
<div class="col-md-6"> |
|||
<h4>@L["UseAnotherServiceToLogIn"]</h4> |
|||
<form asp-page="./Login" asp-page-handler="ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" asp-route-returnUrlHash="@Model.ReturnUrlHash" method="post"> |
|||
<input asp-for="ReturnUrl" /> |
|||
<input asp-for="ReturnUrlHash" /> |
|||
@foreach (var provider in Model.VisibleExternalProviders) |
|||
{ |
|||
<button type="submit" class="btn btn-primary" name="provider" value="@provider.AuthenticationScheme" title="@L["GivenTenantIsNotAvailable", provider.DisplayName]">@provider.DisplayName</button> |
|||
} |
|||
</form> |
|||
</div> |
|||
} |
|||
|
|||
@if (!Model.EnableLocalLogin && !Model.VisibleExternalProviders.Any()) |
|||
{ |
|||
<div class="alert alert-warning"> |
|||
<strong>@L["InvalidLoginRequest"]</strong> |
|||
@L["ThereAreNoLoginSchemesConfiguredForThisClient"] |
|||
</div> |
|||
} |
|||
```` |
|||
|
|||
只需更改 `@model` 为 `Acme.BookStore.Web.Pages.Account.CustomLoginModel` 使用自定义的 `PageModel` 类. 你可以做任何应用程序需要的更改. |
|||
|
|||
## 本文的源代码 |
|||
|
|||
你可以在[这里](https://github.com/abpframework/abp-samples/tree/master/aspnet-core/Authentication-Customization)找到已完成的示例源码. |
|||
|
|||
## 另请参阅 |
|||
|
|||
* [ASP.NET Core (MVC / Razor Pages) 用户界面自定义指南](../UI/AspNetCore/Customization-User-Interface.md). |
|||
@ -0,0 +1,3 @@ |
|||
# 如何为ABP应用程序定制SignIn Manager |
|||
|
|||
TODO... |
|||
@ -0,0 +1,9 @@ |
|||
# "如何" 指南 |
|||
|
|||
本部分包含一些常见问题的 "如何" 指南. 尽管其中是一些常见的开发任务和ABP并不直接相关,但我们认为有一些具体的示例可以直接与基于ABP的应用程序一起使用. |
|||
|
|||
## Authentication |
|||
|
|||
* [如何为MVC / Razor页面应用程序自定义登录页面](Customize-Login-Page-MVC.md) |
|||
* [如何对MVC / Razor页面应用程序使用Azure Active Directory身份验证](Azure-Active-Directory-Authentication-MVC.md) |
|||
* [如何为ABP应用程序定制SignIn Manager](Customize-SignIn-Manager.md) |
|||
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 120 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 88 KiB |
@ -0,0 +1,34 @@ |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.Authorization.Permissions |
|||
{ |
|||
public static class PermissionDefinitionContextExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Finds and disables a permission with the given <paramref name="name"/>.
|
|||
/// Returns false if given permission was not found.
|
|||
/// </summary>
|
|||
/// <param name="context">Permission definition context</param>
|
|||
/// <param name="name">Name of the permission</param>
|
|||
/// <returns>
|
|||
/// Returns true if given permission was found.
|
|||
/// Returns false if given permission was not found.
|
|||
/// </returns>
|
|||
public static bool TryDisablePermission( |
|||
[NotNull] this IPermissionDefinitionContext context, |
|||
[NotNull] string name) |
|||
{ |
|||
Check.NotNull(context, nameof(context)); |
|||
Check.NotNull(name, nameof(name)); |
|||
|
|||
var permission = context.GetPermissionOrNull(name); |
|||
if (permission == null) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
permission.IsEnabled = false; |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue