|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 29 KiB |
@ -1,86 +1,16 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Duende.IdentityModel.Client; |
|||
using Microsoft.AspNetCore.Authentication.OpenIdConnect; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace Microsoft.AspNetCore.Authentication.Cookies; |
|||
|
|||
public static class CookieAuthenticationOptionsExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Introspect access token on validating the principal.
|
|||
/// Check the access_token is expired or inactive.
|
|||
/// </summary>
|
|||
/// <param name="options"></param>
|
|||
/// <param name="oidcAuthenticationScheme"></param>
|
|||
/// <returns></returns>
|
|||
[Obsolete("Use CheckTokenExpiration method instead.")] |
|||
public static CookieAuthenticationOptions IntrospectAccessToken(this CookieAuthenticationOptions options, string oidcAuthenticationScheme = "oidc") |
|||
{ |
|||
options.Events.OnValidatePrincipal = async principalContext => |
|||
{ |
|||
if (principalContext.Principal == null || principalContext.Principal.Identity == null || !principalContext.Principal.Identity.IsAuthenticated) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var logger = principalContext.HttpContext.RequestServices.GetRequiredService<ILogger<CookieAuthenticationOptions>>(); |
|||
|
|||
var accessToken = principalContext.Properties.GetTokenValue("access_token"); |
|||
if (!accessToken.IsNullOrWhiteSpace()) |
|||
{ |
|||
var openIdConnectOptions = await GetOpenIdConnectOptions(principalContext, oidcAuthenticationScheme); |
|||
var response = await openIdConnectOptions.Backchannel.IntrospectTokenAsync(new TokenIntrospectionRequest |
|||
{ |
|||
Address = openIdConnectOptions.Configuration?.IntrospectionEndpoint ?? openIdConnectOptions.Authority!.EnsureEndsWith('/') + "connect/introspect", |
|||
ClientId = openIdConnectOptions.ClientId!, |
|||
ClientSecret = openIdConnectOptions.ClientSecret, |
|||
Token = accessToken |
|||
}); |
|||
|
|||
if (response.IsError) |
|||
{ |
|||
logger.LogError(response.Error); |
|||
await SignOutAsync(principalContext); |
|||
return; |
|||
} |
|||
|
|||
if (!response.IsActive) |
|||
{ |
|||
logger.LogError("The access_token is not active."); |
|||
await SignOutAsync(principalContext); |
|||
return; |
|||
} |
|||
|
|||
logger.LogInformation("The access_token is active."); |
|||
} |
|||
else |
|||
{ |
|||
logger.LogError("The access_token is not found in the cookie properties, Please make sure SaveTokens of OpenIdConnectOptions is set as true."); |
|||
await SignOutAsync(principalContext); |
|||
} |
|||
}; |
|||
|
|||
return options; |
|||
} |
|||
|
|||
private async static Task<OpenIdConnectOptions> GetOpenIdConnectOptions(CookieValidatePrincipalContext principalContext, string oidcAuthenticationScheme) |
|||
{ |
|||
var openIdConnectOptions = principalContext.HttpContext.RequestServices.GetRequiredService<IOptionsMonitor<OpenIdConnectOptions>>().Get(oidcAuthenticationScheme); |
|||
if (openIdConnectOptions.Configuration == null && openIdConnectOptions.ConfigurationManager != null) |
|||
{ |
|||
var cancellationTokenProvider = principalContext.HttpContext.RequestServices.GetRequiredService<ICancellationTokenProvider>(); |
|||
openIdConnectOptions.Configuration = await openIdConnectOptions.ConfigurationManager.GetConfigurationAsync(cancellationTokenProvider.Token); |
|||
} |
|||
|
|||
return openIdConnectOptions; |
|||
} |
|||
|
|||
private async static Task SignOutAsync(CookieValidatePrincipalContext principalContext) |
|||
{ |
|||
principalContext.RejectPrincipal(); |
|||
await principalContext.HttpContext.SignOutAsync(principalContext.Scheme.Name); |
|||
return options.CheckTokenExpiration(oidcAuthenticationScheme, null, TimeSpan.FromMinutes(1)); |
|||
} |
|||
} |
|||
|
|||
@ -1,84 +1,43 @@ |
|||
using System; |
|||
using System.Globalization; |
|||
using System.Linq; |
|||
using System.Text.Json; |
|||
using System.Text.Json.Serialization; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Timing; |
|||
|
|||
namespace Volo.Abp.Json.SystemTextJson.JsonConverters; |
|||
|
|||
public class AbpDateTimeConverter : JsonConverter<DateTime>, ITransientDependency |
|||
public class AbpDateTimeConverter : AbpDateTimeConverterBase<DateTime>, ITransientDependency |
|||
{ |
|||
private readonly IClock _clock; |
|||
private readonly AbpJsonOptions _options; |
|||
private bool _skipDateTimeNormalization; |
|||
|
|||
public AbpDateTimeConverter(IClock clock, IOptions<AbpJsonOptions> abpJsonOptions) |
|||
public AbpDateTimeConverter( |
|||
IClock clock, |
|||
IOptions<AbpJsonOptions> abpJsonOptions, |
|||
ICurrentTimezoneProvider currentTimezoneProvider, |
|||
ITimezoneProvider timezoneProvider) |
|||
: base(clock, abpJsonOptions, currentTimezoneProvider, timezoneProvider) |
|||
{ |
|||
_clock = clock; |
|||
_options = abpJsonOptions.Value; |
|||
} |
|||
|
|||
public virtual AbpDateTimeConverter SkipDateTimeNormalization() |
|||
{ |
|||
_skipDateTimeNormalization = true; |
|||
IsSkipDateTimeNormalization = true; |
|||
return this; |
|||
} |
|||
|
|||
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
|||
{ |
|||
if (_options.InputDateTimeFormats.Any()) |
|||
{ |
|||
if (reader.TokenType == JsonTokenType.String) |
|||
{ |
|||
foreach (var format in _options.InputDateTimeFormats) |
|||
{ |
|||
var s = reader.GetString(); |
|||
if (DateTime.TryParseExact(s, format, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1)) |
|||
{ |
|||
return Normalize(d1); |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
throw new JsonException("Reader's TokenType is not String!"); |
|||
} |
|||
} |
|||
|
|||
if (reader.TryGetDateTime(out var d3)) |
|||
{ |
|||
return Normalize(d3); |
|||
} |
|||
|
|||
var dateText = reader.GetString(); |
|||
if (!dateText.IsNullOrWhiteSpace()) |
|||
if (Options.InputDateTimeFormats.Any() && reader.TokenType != JsonTokenType.String) |
|||
{ |
|||
if (DateTime.TryParse(dateText, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d4)) |
|||
{ |
|||
return Normalize(d4); |
|||
} |
|||
throw new JsonException("Reader's TokenType is not String!"); |
|||
} |
|||
|
|||
throw new JsonException("Can't get datetime from the reader!"); |
|||
return TryReadDateTime(ref reader, out var result) |
|||
? result |
|||
: throw new JsonException("Can't get datetime from the reader!"); |
|||
} |
|||
|
|||
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) |
|||
{ |
|||
if (_options.OutputDateTimeFormat.IsNullOrWhiteSpace()) |
|||
{ |
|||
writer.WriteStringValue(Normalize(value)); |
|||
} |
|||
else |
|||
{ |
|||
writer.WriteStringValue(Normalize(value).ToString(_options.OutputDateTimeFormat, CultureInfo.CurrentUICulture)); |
|||
} |
|||
} |
|||
|
|||
protected virtual DateTime Normalize(DateTime dateTime) |
|||
{ |
|||
return _skipDateTimeNormalization ? dateTime : _clock.Normalize(dateTime); |
|||
WriteDateTime(writer, value); |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,116 @@ |
|||
using System; |
|||
using System.Globalization; |
|||
using System.Linq; |
|||
using System.Text.Json; |
|||
using System.Text.Json.Serialization; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Timing; |
|||
|
|||
namespace Volo.Abp.Json.SystemTextJson.JsonConverters; |
|||
|
|||
public abstract class AbpDateTimeConverterBase<T> : JsonConverter<T> |
|||
{ |
|||
public ILogger<AbpDateTimeConverterBase<T>> Logger { get; set; } |
|||
|
|||
protected IClock Clock { get; } |
|||
protected AbpJsonOptions Options { get; } |
|||
protected ICurrentTimezoneProvider CurrentTimezoneProvider { get; } |
|||
protected ITimezoneProvider TimezoneProvider { get; } |
|||
protected bool IsSkipDateTimeNormalization { get; set; } |
|||
|
|||
protected AbpDateTimeConverterBase( |
|||
IClock clock, |
|||
IOptions<AbpJsonOptions> abpJsonOptions, |
|||
ICurrentTimezoneProvider currentTimezoneProvider, |
|||
ITimezoneProvider timezoneProvider) |
|||
{ |
|||
Logger = NullLogger<AbpDateTimeConverterBase<T>>.Instance; |
|||
|
|||
Clock = clock; |
|||
CurrentTimezoneProvider = currentTimezoneProvider; |
|||
TimezoneProvider = timezoneProvider; |
|||
Options = abpJsonOptions.Value; |
|||
} |
|||
|
|||
protected bool TryReadDateTime(ref Utf8JsonReader reader, out DateTime value) |
|||
{ |
|||
value = default; |
|||
|
|||
if (Options.InputDateTimeFormats.Any()) |
|||
{ |
|||
if (reader.TokenType != JsonTokenType.String) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
var s = reader.GetString(); |
|||
foreach (var format in Options.InputDateTimeFormats) |
|||
{ |
|||
if (!DateTime.TryParseExact(s, format, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
value = Normalize(d1); |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
if (reader.TryGetDateTime(out var d2)) |
|||
{ |
|||
value = Normalize(d2); |
|||
return true; |
|||
} |
|||
|
|||
var dateText = reader.GetString(); |
|||
if (dateText.IsNullOrWhiteSpace()) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
if (!DateTime.TryParse(dateText, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d3)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
value = Normalize(d3); |
|||
return true; |
|||
|
|||
} |
|||
|
|||
protected void WriteDateTime(Utf8JsonWriter writer, DateTime value) |
|||
{ |
|||
if (Options.OutputDateTimeFormat.IsNullOrWhiteSpace()) |
|||
{ |
|||
writer.WriteStringValue(Normalize(value)); |
|||
} |
|||
else |
|||
{ |
|||
writer.WriteStringValue(Normalize(value).ToString(Options.OutputDateTimeFormat, CultureInfo.CurrentUICulture)); |
|||
} |
|||
} |
|||
|
|||
protected virtual DateTime Normalize(DateTime dateTime) |
|||
{ |
|||
if (dateTime.Kind != DateTimeKind.Unspecified || |
|||
!Clock.SupportsMultipleTimezone || |
|||
CurrentTimezoneProvider.TimeZone.IsNullOrWhiteSpace()) |
|||
{ |
|||
return IsSkipDateTimeNormalization ? dateTime : Clock.Normalize(dateTime); |
|||
} |
|||
|
|||
try |
|||
{ |
|||
var timezoneInfo = TimezoneProvider.GetTimeZoneInfo(CurrentTimezoneProvider.TimeZone); |
|||
dateTime = new DateTimeOffset(dateTime, timezoneInfo.GetUtcOffset(dateTime)).UtcDateTime; |
|||
} |
|||
catch |
|||
{ |
|||
Logger.LogWarning("Could not convert DateTime with unspecified Kind using timezone '{TimeZone}'.", CurrentTimezoneProvider.TimeZone); |
|||
} |
|||
|
|||
return IsSkipDateTimeNormalization ? dateTime : Clock.Normalize(dateTime); |
|||
} |
|||
} |
|||
@ -1,45 +1,61 @@ |
|||
<div class="abp-lookup-container position-relative"> |
|||
@if (label()) { |
|||
<label class="form-label">{{ label() | abpLocalization }}</label> |
|||
<label class="form-label">{{ label() | abpLocalization }}</label> |
|||
} |
|||
|
|||
<div class="input-group"> |
|||
<input type="text" class="form-control" [placeholder]="placeholder() | abpLocalization" [ngModel]="displayValue()" |
|||
(ngModelChange)="onSearchInput($event)" (focus)="onSearchFocus()" (blur)="onSearchBlur($event)" |
|||
[disabled]="disabled()" /> |
|||
<input |
|||
type="text" |
|||
class="form-control" |
|||
[placeholder]="placeholder() | abpLocalization" |
|||
[ngModel]="displayValue()" |
|||
(ngModelChange)="onSearchInput($event)" |
|||
(focus)="onSearchFocus()" |
|||
(blur)="onSearchBlur($event)" |
|||
[disabled]="disabled()" |
|||
/> |
|||
@if (displayValue() && !disabled()) { |
|||
<button type="button" class="btn btn-outline-secondary" (mousedown)="clearSelection()" tabindex="-1"> |
|||
<i class="fa fa-times"></i> |
|||
</button> |
|||
<button |
|||
type="button" |
|||
class="btn btn-outline-secondary" |
|||
(mousedown)="clearSelection()" |
|||
tabindex="-1" |
|||
> |
|||
<i class="fa fa-times"></i> |
|||
</button> |
|||
} |
|||
</div> |
|||
|
|||
@if (showDropdown() && !disabled()) { |
|||
<div class="abp-lookup-dropdown list-group position-absolute w-100 shadow"> |
|||
@if (isLoading()) { |
|||
<div class="list-group-item text-center py-3"> |
|||
<i class="fa fa-spinner fa-spin me-2"></i> |
|||
{{ 'AbpUi::Loading' | abpLocalization }} |
|||
</div> |
|||
} @else if (searchResults().length > 0) { |
|||
@for (item of searchResults(); track item.key) { |
|||
<button type="button" class="list-group-item list-group-item-action" (mousedown)="selectItem(item)"> |
|||
@if (itemTemplate()) { |
|||
<ng-container *ngTemplateOutlet="itemTemplate()!; context: { $implicit: item }" /> |
|||
} @else { |
|||
{{ getDisplayValue(item) }} |
|||
<div class="abp-lookup-dropdown list-group position-absolute w-100"> |
|||
@if (isLoading()) { |
|||
<div class="list-group-item text-center py-3"> |
|||
<i class="fa fa-spinner fa-spin me-2"></i> |
|||
{{ 'AbpUi::Loading' | abpLocalization }} |
|||
</div> |
|||
} @else if (searchResults().length > 0) { |
|||
@for (item of searchResults(); track item.key) { |
|||
<button |
|||
type="button" |
|||
class="list-group-item list-group-item-action" |
|||
(mousedown)="selectItem(item)" |
|||
> |
|||
@if (itemTemplate()) { |
|||
<ng-container *ngTemplateOutlet="itemTemplate()!; context: { $implicit: item }" /> |
|||
} @else { |
|||
{{ getDisplayValue(item) }} |
|||
} |
|||
</button> |
|||
} |
|||
} @else if (displayValue()) { |
|||
@if (noResultsTemplate()) { |
|||
<ng-container *ngTemplateOutlet="noResultsTemplate()!" /> |
|||
} @else { |
|||
<div class="list-group-item text-muted"> |
|||
{{ 'AbpUi::NoDataAvailableInDatatable' | abpLocalization }} |
|||
</div> |
|||
} |
|||
} |
|||
</button> |
|||
} |
|||
} @else if (displayValue()) { |
|||
@if (noResultsTemplate()) { |
|||
<ng-container *ngTemplateOutlet="noResultsTemplate()!" /> |
|||
} @else { |
|||
<div class="list-group-item text-muted"> |
|||
{{ 'AbpUi::NoRecordsFound' | abpLocalization }} |
|||
</div> |
|||
} |
|||
} |
|||
</div> |
|||
} |
|||
</div> |
|||
</div> |
|||
|
|||
@ -1,5 +1,8 @@ |
|||
.abp-lookup-dropdown { |
|||
z-index: 1050; |
|||
max-height: 200px; |
|||
overflow-y: auto; |
|||
z-index: 1060; |
|||
max-height: 200px; |
|||
overflow-y: auto; |
|||
top: 100%; |
|||
margin-top: 0.25rem; |
|||
background-color: var(--lpx-content-bg); |
|||
} |
|||
|
|||
@ -1,25 +1,33 @@ |
|||
<div class="mb-3"> |
|||
@if (showTitle()) { |
|||
@if (showTitle()) { |
|||
<h5>{{ title() | abpLocalization }}</h5> |
|||
} |
|||
<div class="form-check form-switch mb-2"> |
|||
<input class="form-check-input" type="checkbox" id="grantAll-{{ idPrefix() }}" |
|||
[checked]="state.allPermissionsSelected()" |
|||
(change)="state.toggleAllPermissions(!state.allPermissionsSelected())" /> |
|||
<label class="form-check-label" for="grantAll-{{ idPrefix() }}"> |
|||
{{ 'AbpPermissionManagement::GrantAllResourcePermissions' | abpLocalization }} |
|||
} |
|||
<div class="form-check form-switch mb-2"> |
|||
<input |
|||
class="form-check-input" |
|||
type="checkbox" |
|||
id="grantAll-{{ idPrefix() }}" |
|||
[checked]="state.allPermissionsSelected()" |
|||
(change)="state.toggleAllPermissions(!state.allPermissionsSelected())" |
|||
/> |
|||
<label class="form-check-label" for="grantAll-{{ idPrefix() }}"> |
|||
{{ 'AbpPermissionManagement::GrantAllResourcePermissions' | abpLocalization }} |
|||
</label> |
|||
</div> |
|||
<div class="abp-permission-list-container border rounded p-3"> |
|||
@for (perm of permissions(); track perm.name) { |
|||
<div class="form-check"> |
|||
<input |
|||
class="form-check-input" |
|||
type="checkbox" |
|||
id="perm-{{ idPrefix() }}-{{ perm.name }}" |
|||
[checked]="state.isPermissionSelected(perm.name || '')" |
|||
(change)="state.togglePermission(perm.name || '')" |
|||
/> |
|||
<label class="form-check-label" for="perm-{{ idPrefix() }}-{{ perm.name }}"> |
|||
{{ perm.displayName }} |
|||
</label> |
|||
</div> |
|||
<div class="abp-permission-list-container border rounded p-3"> |
|||
@for (perm of permissions(); track perm.name) { |
|||
<div class="form-check"> |
|||
<input class="form-check-input" type="checkbox" id="perm-{{ idPrefix() }}-{{ perm.name }}" |
|||
[checked]="state.isPermissionSelected(perm.name || '')" |
|||
(change)="state.togglePermission(perm.name || '')" /> |
|||
<label class="form-check-label" for="perm-{{ idPrefix() }}-{{ perm.name }}"> |
|||
{{ perm.displayName }} |
|||
</label> |
|||
</div> |
|||
} |
|||
</div> |
|||
</div> |
|||
</div> |
|||
} |
|||
</div> |
|||
</div> |
|||
|
|||
@ -1,4 +1,10 @@ |
|||
<abp-lookup-search label="AbpPermissionManagement::SearchProviderKey" |
|||
placeholder="AbpPermissionManagement::SearchProviderKey" [searchFn]="searchFn" [displayValue]="state.searchFilter()" |
|||
(displayValueChange)="state.searchFilter.set($event)" [selectedValue]="state.selectedProviderKey()" |
|||
(selectedValueChange)="state.selectedProviderKey.set($event)" (itemSelected)="onItemSelected($event)" /> |
|||
<abp-lookup-search |
|||
label="AbpPermissionManagement::SearchProviderKey" |
|||
placeholder="AbpPermissionManagement::SearchProviderKey" |
|||
[searchFn]="searchFn" |
|||
[displayValue]="state.searchFilter()" |
|||
(displayValueChange)="state.searchFilter.set($event)" |
|||
[selectedValue]="state.selectedProviderKey()" |
|||
(selectedValueChange)="state.selectedProviderKey.set($event)" |
|||
(itemSelected)="onItemSelected($event)" |
|||
/> |
|||
|
|||
@ -1,28 +1,37 @@ |
|||
@if (mode() === eResourcePermissionViewModes.Add) { |
|||
<div class="mb-3"> |
|||
<div class="mb-3"> |
|||
<label class="form-label fw-bold"> |
|||
{{ 'AbpPermissionManagement::SelectProvider' | abpLocalization }} |
|||
{{ 'AbpPermissionManagement::SelectProvider' | abpLocalization }} |
|||
</label> |
|||
<div class="mb-2"> |
|||
@for (provider of state.providers(); track provider.name; let i = $index) { |
|||
@for (provider of state.providers(); track provider.name; let i = $index) { |
|||
<div class="form-check form-check-inline"> |
|||
<input class="form-check-input" type="radio" [id]="'provider-' + i" [value]="provider.name" |
|||
[checked]="state.selectedProviderName() === provider.name" |
|||
(change)="state.onProviderChange(provider.name || '')" /> |
|||
<label class="form-check-label" [for]="'provider-' + i"> |
|||
{{ provider.displayName }} |
|||
</label> |
|||
<input |
|||
class="form-check-input" |
|||
type="radio" |
|||
[id]="'provider-' + i" |
|||
[value]="provider.name" |
|||
[checked]="state.selectedProviderName() === provider.name" |
|||
(change)="state.onProviderChange(provider.name || '')" |
|||
/> |
|||
<label class="form-check-label" [for]="'provider-' + i"> |
|||
{{ provider.displayName }} |
|||
</label> |
|||
</div> |
|||
} |
|||
} |
|||
</div> |
|||
|
|||
<abp-provider-key-search [resourceName]="resourceName()" /> |
|||
</div> |
|||
</div> |
|||
|
|||
<abp-permission-checkbox-list [permissions]="state.permissionDefinitions()" idPrefix="add" /> |
|||
<abp-permission-checkbox-list [permissions]="state.permissionDefinitions()" idPrefix="add" /> |
|||
} @else { |
|||
<div class="mb-3" id="permissionList"> |
|||
<div class="mb-3" id="permissionList"> |
|||
<h4>{{ 'AbpPermissionManagement::Permissions' | abpLocalization }}</h4> |
|||
<abp-permission-checkbox-list [permissions]="state.permissionsWithProvider()" idPrefix="edit" [showTitle]="false" /> |
|||
</div> |
|||
} |
|||
<abp-permission-checkbox-list |
|||
[permissions]="state.permissionsWithProvider()" |
|||
idPrefix="edit" |
|||
[showTitle]="false" |
|||
/> |
|||
</div> |
|||
} |
|||
|
|||
@ -1,60 +1,67 @@ |
|||
<abp-modal [(visible)]="visible" [busy]="state.modalBusy()" [options]="{ size: 'xl', scrollable: false }"> |
|||
<ng-template #abpHeader> |
|||
<h5 class="modal-title"> |
|||
@switch (state.viewMode()) { |
|||
@case (eResourcePermissionViewModes.Edit) { |
|||
{{ 'AbpPermissionManagement::UpdatePermission' | abpLocalization }} |
|||
} |
|||
@case (eResourcePermissionViewModes.Add) { |
|||
{{ 'AbpPermissionManagement::AddResourcePermission' | abpLocalization }} |
|||
} |
|||
@default { |
|||
{{ 'AbpPermissionManagement::ResourcePermissions' | abpLocalization }} |
|||
@if (resourceDisplayName()) { |
|||
<abp-modal |
|||
[(visible)]="visible" |
|||
[busy]="state.modalBusy()" |
|||
[options]="{ size: 'xl', scrollable: false }" |
|||
> |
|||
<ng-template #abpHeader> |
|||
<h5 class="modal-title"> |
|||
@switch (state.viewMode()) { |
|||
@case (eResourcePermissionViewModes.Edit) { |
|||
{{ 'AbpPermissionManagement::UpdatePermission' | abpLocalization }} |
|||
} |
|||
@case (eResourcePermissionViewModes.Add) { |
|||
{{ 'AbpPermissionManagement::AddResourcePermission' | abpLocalization }} |
|||
} |
|||
@default { |
|||
{{ 'AbpPermissionManagement::ResourcePermissions' | abpLocalization }} |
|||
@if (resourceDisplayName()) { |
|||
- {{ resourceDisplayName() }} |
|||
} |
|||
} |
|||
} |
|||
</h5> |
|||
</ng-template> |
|||
} |
|||
} |
|||
} |
|||
</h5> |
|||
</ng-template> |
|||
|
|||
<ng-template #abpBody> |
|||
@if (!state.hasResourcePermission() || !state.hasProviderKeyLookupService()) { |
|||
<div class="alert alert-warning" role="alert"> |
|||
@if (!state.hasResourcePermission()) { |
|||
{{ 'AbpPermissionManagement::NoResourcePermissionFound' | abpLocalization }} |
|||
} @else { |
|||
{{ 'AbpPermissionManagement::NoResourceProviderKeyLookupServiceFound' | abpLocalization }} |
|||
} |
|||
</div> |
|||
<ng-template #abpBody> |
|||
@if (!state.hasResourcePermission() || !state.hasProviderKeyLookupService()) { |
|||
<div class="alert alert-warning" role="alert"> |
|||
@if (!state.hasResourcePermission()) { |
|||
{{ 'AbpPermissionManagement::NoResourcePermissionFound' | abpLocalization }} |
|||
} @else { |
|||
@switch (state.viewMode()) { |
|||
{{ 'AbpPermissionManagement::NoResourceProviderKeyLookupServiceFound' | abpLocalization }} |
|||
} |
|||
</div> |
|||
} @else { |
|||
@switch (state.viewMode()) { |
|||
@case (eResourcePermissionViewModes.List) { |
|||
<abp-resource-permission-list (addClicked)="onAddClicked()" (editClicked)="onEditClicked($event)" |
|||
(deleteClicked)="onDeleteClicked($event)" /> |
|||
<abp-resource-permission-list |
|||
(addClicked)="onAddClicked()" |
|||
(editClicked)="onEditClicked($event)" |
|||
(deleteClicked)="onDeleteClicked($event)" |
|||
/> |
|||
} |
|||
@case (eResourcePermissionViewModes.Add) { |
|||
<abp-resource-permission-form mode="add" [resourceName]="resourceName()" /> |
|||
<abp-resource-permission-form mode="add" [resourceName]="resourceName()" /> |
|||
} |
|||
@case (eResourcePermissionViewModes.Edit) { |
|||
<abp-resource-permission-form mode="edit" [resourceName]="resourceName()" /> |
|||
} |
|||
} |
|||
<abp-resource-permission-form mode="edit" [resourceName]="resourceName()" /> |
|||
} |
|||
</ng-template> |
|||
} |
|||
} |
|||
</ng-template> |
|||
|
|||
<ng-template #abpFooter> |
|||
@if (state.isListMode()) { |
|||
<button type="button" class="btn btn-outline-primary" abpClose> |
|||
{{ 'AbpUi::Close' | abpLocalization }} |
|||
</button> |
|||
} @else { |
|||
<button type="button" class="btn btn-outline-secondary" (click)="state.goToListMode()"> |
|||
{{ 'AbpUi::Cancel' | abpLocalization }} |
|||
</button> |
|||
<abp-button iconClass="fa fa-check" (click)="savePermission()"> |
|||
{{ 'AbpUi::Save' | abpLocalization }} |
|||
</abp-button> |
|||
} |
|||
</ng-template> |
|||
</abp-modal> |
|||
<ng-template #abpFooter> |
|||
@if (state.isListMode()) { |
|||
<button type="button" class="btn btn-outline-primary" abpClose> |
|||
{{ 'AbpUi::Close' | abpLocalization }} |
|||
</button> |
|||
} @else { |
|||
<button type="button" class="btn btn-outline-secondary" (click)="state.goToListMode()"> |
|||
{{ 'AbpUi::Cancel' | abpLocalization }} |
|||
</button> |
|||
<abp-button iconClass="fa fa-check" (click)="savePermission()"> |
|||
{{ 'AbpUi::Save' | abpLocalization }} |
|||
</abp-button> |
|||
} |
|||
</ng-template> |
|||
</abp-modal> |
|||
|
|||
@ -1,32 +0,0 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.EventBus; |
|||
using Volo.Abp.StaticDefinitions; |
|||
using Volo.Abp.TextTemplating; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace Volo.Abp.TextTemplateManagement; |
|||
|
|||
public class StaticTemplateDefinitionChangedEventHandler : ILocalEventHandler<StaticTemplateDefinitionChangedEvent>, ITransientDependency |
|||
{ |
|||
protected IStaticDefinitionCache<TemplateDefinition, Dictionary<string, TemplateDefinition>> DefinitionCache { get; } |
|||
protected TextTemplateDynamicInitializer TextTemplateDynamicInitializer { get; } |
|||
protected ICancellationTokenProvider CancellationTokenProvider { get; } |
|||
|
|||
public StaticTemplateDefinitionChangedEventHandler( |
|||
IStaticDefinitionCache<TemplateDefinition, Dictionary<string, TemplateDefinition>> definitionCache, |
|||
TextTemplateDynamicInitializer textTemplateDynamicInitializer, |
|||
ICancellationTokenProvider cancellationTokenProvider) |
|||
{ |
|||
DefinitionCache = definitionCache; |
|||
TextTemplateDynamicInitializer = textTemplateDynamicInitializer; |
|||
CancellationTokenProvider = cancellationTokenProvider; |
|||
} |
|||
|
|||
public virtual async Task HandleEventAsync(StaticTemplateDefinitionChangedEvent eventData) |
|||
{ |
|||
await DefinitionCache.ClearAsync(); |
|||
await TextTemplateDynamicInitializer.InitializeAsync(false, CancellationTokenProvider.Token); |
|||
} |
|||
} |
|||