Browse Source

Merge pull request #15417 from abpframework/auto-merge/rel-7-0/1654

Merge branch dev with rel-7.0
pull/15423/head
maliming 4 years ago
committed by GitHub
parent
commit
ae4736152a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      docs/en/Migration-Guides/OpenIddict-Angular.md
  2. 2
      docs/en/Migration-Guides/OpenIddict-Blazor-Server.md
  3. 2
      docs/en/Migration-Guides/OpenIddict-Blazor.md
  4. 2
      docs/en/Migration-Guides/OpenIddict-Mvc.md
  5. 2
      docs/en/Migration-Guides/OpenIddict-Step-by-Step.md
  6. 80
      modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor
  7. 2
      modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs
  8. 7
      npm/ng-packs/packages/core/src/lib/core.module.ts
  9. 6
      npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts
  10. 11
      npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts
  11. 1
      npm/ng-packs/packages/core/src/lib/tokens/index.ts
  12. 4
      npm/ng-packs/packages/core/src/lib/tokens/queue.token.ts
  13. 1
      npm/ng-packs/packages/core/src/lib/utils/index.ts
  14. 48
      npm/ng-packs/packages/core/src/lib/utils/queue.ts
  15. 3
      npm/ng-packs/packages/oauth/src/lib/tests/api.interceptor.spec.ts
  16. 29
      npm/ng-packs/packages/oauth/src/lib/tests/initial-utils.spec.ts

2
docs/en/Migration-Guides/OpenIddict-Angular.md

@ -112,7 +112,7 @@
## IdentityServer
This project is renamed to **AuthServer** after v6.0.0-rc1. You can also refactor and rename your project to *AuthServer* for easier updates in the future.
This project is renamed to **AuthServer** after v6.0.0. You can also refactor and rename your project to *AuthServer* for easier updates in the future.
- In **MyApplication.IdentityServer.csproj** replace **project references**:

2
docs/en/Migration-Guides/OpenIddict-Blazor-Server.md

@ -103,7 +103,7 @@
## IdentityServer
This project is renamed to **AuthServer** after v6.0.0-rc1. You can also refactor and rename your project to *AuthServer* for easier updates in the future.
This project is renamed to **AuthServer** after v6.0.0. You can also refactor and rename your project to *AuthServer* for easier updates in the future.
- In **MyApplication.IdentityServer.csproj** replace **project references**:

2
docs/en/Migration-Guides/OpenIddict-Blazor.md

@ -131,7 +131,7 @@
## IdentityServer
This project is renamed to **AuthServer** after v6.0.0-rc1. You can also refactor and rename your project to *AuthServer* for easier updates in the future.
This project is renamed to **AuthServer** after v6.0.0. You can also refactor and rename your project to *AuthServer* for easier updates in the future.
- In **MyApplication.IdentityServer.csproj** replace **project references**:

2
docs/en/Migration-Guides/OpenIddict-Mvc.md

@ -111,7 +111,7 @@ Replace role scope to **roles** and add **UsePkce** and **SignoutScheme** option
## IdentityServer
This project is renamed to **AuthServer** after v6.0.0-rc1. You can also refactor and rename your project to *AuthServer* for easier updates in the future.
This project is renamed to **AuthServer** after v6.0.0. You can also refactor and rename your project to *AuthServer* for easier updates in the future.
- In **MyApplication.IdentityServer.csproj** replace **project references**:

2
docs/en/Migration-Guides/OpenIddict-Step-by-Step.md

@ -1,6 +1,6 @@
# Migrating from IdentityServer to OpenIddict Step by Step Guide
This guide provides layer-by-layer guidance for migrating your existing application to [OpenIddict](https://github.com/openiddict/openiddict-core) from IdentityServer. ABP startup templates use `OpenIddict` OpenId provider from v6.0.0-rc1 by default and `IdentityServer` projects are renamed to `AuthServer` in tiered/separated solutions. Since OpenIddict is only available with ABP v6.0, you will need to update your existing application in order to apply OpenIddict changes.
This guide provides layer-by-layer guidance for migrating your existing application to [OpenIddict](https://github.com/openiddict/openiddict-core) from IdentityServer. ABP startup templates use `OpenIddict` OpenId provider from v6.0.0 by default and `IdentityServer` projects are renamed to `AuthServer` in tiered/separated solutions. Since OpenIddict is only available with ABP v6.0, you will need to update your existing application in order to apply OpenIddict changes.
## History
We are not removing Identity Server packages and we will continue to release new versions of IdentityServer-related NuGet/NPM packages. That means you won't have an issue while upgrading to v6.0 when the stable version releases. We will continue to fix bugs in our packages for a while. ABP 7.0 will be based on .NET 7. If Identity Server continues to work with .NET 7, we will also continue to ship NuGet packages for our IDS integration.

80
modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor

@ -16,15 +16,17 @@
BreadcrumbItems="@BreadcrumbItems"
Toolbar="@Toolbar" />
</CardHeader>
<CardBody>
<Row>
<Column ColumnSize="ColumnSize.Is3">
<Field>
<FieldLabel>@L["Search"]</FieldLabel>
<TextEdit Size="Size.Small" Text="@GetListInput.Filter" TextChanged="@OnSearchTextChanged" />
</Field>
</Column>
</Row>
<CardBody class="row">
<Column ColumnSize="ColumnSize.Is8">
</Column>
<Column ColumnSize="ColumnSize.Is4" class="form-group row" style="text-align:right;">
<label for="inputPassword" class="col-sm-4 col-form-label pt-1"> @L["Search"] </label>
<div class="col-sm-8">
<TextEdit class="form-control-sm" id="inputPassword" Text="@GetListInput.Filter" TextChanged="@OnSearchTextChanged" />
</div>
</Column>
@* ************************* DATA GRID ************************* *@
<AbpExtensibleDataGrid TItem="IdentityUserDto"
Data="Entities"
@ -39,14 +41,14 @@
</Card>
@* ************************* CREATE MODAL ************************* *@
@if ( HasCreatePermission )
@if (HasCreatePermission)
{
<Modal @ref="CreateModal" Closing="@ClosingCreateModal">
<ModalContent Centered="true">
<Form>
<ModalHeader>
<ModalTitle>@L["NewUser"]</ModalTitle>
<CloseButton Clicked="CloseCreateModalAsync"/>
<CloseButton Clicked="CloseCreateModalAsync" />
</ModalHeader>
<ModalBody>
<Validations @ref="@CreateValidationsRef" Model="@NewEntity" ValidateOnLoad="false">
@ -62,7 +64,7 @@
<FieldLabel>@L["DisplayName:UserName"] *</FieldLabel>
<TextEdit @bind-Text="NewEntity.UserName" Autofocus="true">
<Feedback>
<ValidationError/>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
@ -72,7 +74,7 @@
<FieldLabel>@L["DisplayName:Name"]</FieldLabel>
<TextEdit @bind-Text="NewEntity.Name">
<Feedback>
<ValidationError/>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
@ -82,7 +84,7 @@
<FieldLabel>@L["DisplayName:Surname"]</FieldLabel>
<TextEdit @bind-Text="NewEntity.Surname">
<Feedback>
<ValidationError/>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
@ -101,7 +103,7 @@
</Button>
</Addon>
</Addons>
<ValidationError Style="display: block"/>
<ValidationError Style="display: block" />
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
@ -109,7 +111,7 @@
<FieldLabel>@L["DisplayName:Email"] *</FieldLabel>
<TextEdit @bind-Text="NewEntity.Email">
<Feedback>
<ValidationError/>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
@ -119,7 +121,7 @@
<FieldLabel>@L["DisplayName:PhoneNumber"]</FieldLabel>
<TextEdit @bind-Text="NewEntity.PhoneNumber">
<Feedback>
<ValidationError/>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
@ -130,15 +132,15 @@
<Field>
<Check TValue="bool" @bind-Checked="@NewEntity.LockoutEnabled">@L["DisplayName:LockoutEnabled"]</Check>
</Field>
<ExtensionProperties TEntityType="IdentityUserCreateDto" TResourceType="IdentityResource" Entity="@NewEntity" LH="@LH"/>
<ExtensionProperties TEntityType="IdentityUserCreateDto" TResourceType="IdentityResource" Entity="@NewEntity" LH="@LH" />
</TabPanel>
<TabPanel Name="Roles">
@if ( NewUserRoles != null )
@if (NewUserRoles != null)
{
@foreach ( var role in NewUserRoles )
@foreach (var role in NewUserRoles)
{
<Field>
<input type="hidden" @bind-value="@role.Name"/>
<input type="hidden" @bind-value="@role.Name" />
<Check TValue="bool" @bind-Checked="@role.IsAssigned">@role.Name</Check>
</Field>
}
@ -150,7 +152,7 @@
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary" Clicked="CloseCreateModalAsync">@L["Cancel"]</Button>
<SubmitButton Clicked="@CreateEntityAsync"/>
<SubmitButton Clicked="@CreateEntityAsync" />
</ModalFooter>
</Form>
</ModalContent>
@ -158,18 +160,18 @@
}
@* ************************* EDIT MODAL ************************* *@
@if ( HasUpdatePermission )
@if (HasUpdatePermission)
{
<Modal @ref="EditModal" Closing="@ClosingEditModal">
<ModalContent Centered="true">
<Form>
<ModalHeader>
<ModalTitle>@L["Edit"]</ModalTitle>
<CloseButton Clicked="CloseEditModalAsync"/>
<CloseButton Clicked="CloseEditModalAsync" />
</ModalHeader>
<ModalBody>
<Validations @ref="@EditValidationsRef" Model="@EditingEntity" ValidateOnLoad="false">
<input type="hidden" name="ConcurrencyStamp" @bind-value="EditingEntity.ConcurrencyStamp"/>
<input type="hidden" name="ConcurrencyStamp" @bind-value="EditingEntity.ConcurrencyStamp" />
<Tabs @bind-SelectedTab="@EditModalSelectedTab">
<Items>
@ -183,7 +185,7 @@
<FieldLabel>@L["DisplayName:UserName"] *</FieldLabel>
<TextEdit @bind-Text="EditingEntity.UserName" Autofocus="true">
<Feedback>
<ValidationError/>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
@ -193,7 +195,7 @@
<FieldLabel>@L["DisplayName:Name"]</FieldLabel>
<TextEdit @bind-Text="EditingEntity.Name">
<Feedback>
<ValidationError/>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
@ -203,7 +205,7 @@
<FieldLabel>@L["DisplayName:Surname"]</FieldLabel>
<TextEdit @bind-Text="EditingEntity.Surname">
<Feedback>
<ValidationError/>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
@ -222,7 +224,7 @@
</Button>
</Addon>
</Addons>
<ValidationError Style="display: block"/>
<ValidationError Style="display: block" />
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
@ -230,7 +232,7 @@
<FieldLabel>@L["DisplayName:Email"] *</FieldLabel>
<TextEdit @bind-Text="EditingEntity.Email">
<Feedback>
<ValidationError/>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
@ -240,7 +242,7 @@
<FieldLabel>@L["DisplayName:PhoneNumber"]</FieldLabel>
<TextEdit @bind-Text="EditingEntity.PhoneNumber">
<Feedback>
<ValidationError/>
<ValidationError />
</Feedback>
</TextEdit>
</Field>
@ -251,15 +253,15 @@
<Field>
<Check TValue="bool" @bind-Checked="EditingEntity.LockoutEnabled">@L["DisplayName:LockoutEnabled"]</Check>
</Field>
<ExtensionProperties TEntityType="IdentityUserUpdateDto" TResourceType="IdentityResource" Entity="@EditingEntity" LH="@LH"/>
<ExtensionProperties TEntityType="IdentityUserUpdateDto" TResourceType="IdentityResource" Entity="@EditingEntity" LH="@LH" />
</TabPanel>
<TabPanel Name="Roles">
@if ( EditUserRoles != null )
@if (EditUserRoles != null)
{
@foreach ( var role in EditUserRoles )
@foreach (var role in EditUserRoles)
{
<Field>
<input type="hidden" @bind-value="@role.Name"/>
<input type="hidden" @bind-value="@role.Name" />
<Check TValue="bool" @bind-Checked="@role.IsAssigned">@role.Name</Check>
</Field>
}
@ -271,14 +273,14 @@
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary" Clicked="CloseEditModalAsync">@L["Cancel"]</Button>
<SubmitButton Clicked="@UpdateEntityAsync"/>
<SubmitButton Clicked="@UpdateEntityAsync" />
</ModalFooter>
</Form>
</ModalContent>
</Modal>
}
@if ( HasManagePermissionsPermission )
@if (HasManagePermissionsPermission)
{
<PermissionManagementModal @ref="PermissionManagementModal"/>
}
<PermissionManagementModal @ref="PermissionManagementModal" />
}

2
modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs

@ -74,7 +74,7 @@ public class MongoOpenIddictAuthorizationRepository : MongoDbRepository<OpenIddi
await DeleteManyAsync(await (await GetMongoQueryableAsync(cancellationToken))
.Where(x => x.CreationDate < date)
.Where(x => x.Status == OpenIddictConstants.Statuses.Valid || (x.Type == OpenIddictConstants.AuthorizationTypes.AdHoc && !tokens.Contains(x.Id)))
.Where(x => x.Status != OpenIddictConstants.Statuses.Valid || (x.Type == OpenIddictConstants.AuthorizationTypes.AdHoc && !tokens.Contains(x.Id)))
.ToListAsync(cancellationToken: cancellationToken), cancellationToken: cancellationToken);
}
}

7
npm/ng-packs/packages/core/src/lib/core.module.ts

@ -33,8 +33,9 @@ import { getInitialData, localeInitializer } from './utils/initial-utils';
import { ShortDateTimePipe } from './pipes/short-date-time.pipe';
import { ShortTimePipe } from './pipes/short-time.pipe';
import { ShortDatePipe } from './pipes/short-date.pipe';
import { QUEUE_MANAGER } from './tokens/queue.token';
import { DefaultQueueManager } from './utils/queue';
import { IncludeLocalizationResourcesProvider } from './providers/include-localization-resources.provider';
import { AuthGuard } from './abstracts/auth.guard';
/**
* BaseCoreModule is the module that holds
@ -171,6 +172,10 @@ export class CoreModule {
useValue: localizationContributor(options.localizations),
deps: [LocalizationService],
},
{
provide: QUEUE_MANAGER,
useClass: DefaultQueueManager,
},
IncludeLocalizationResourcesProvider,
],
};

6
npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts

@ -2,6 +2,7 @@ import {
AfterViewInit,
ChangeDetectorRef,
Directive,
Inject,
Input,
OnChanges,
OnDestroy,
@ -12,6 +13,8 @@ import {
import { ReplaySubject, Subscription } from 'rxjs';
import { distinctUntilChanged, take } from 'rxjs/operators';
import { PermissionService } from '../services/permission.service';
import { QUEUE_MANAGER } from '../tokens/queue.token';
import { QueueManager } from '../utils/queue';
@Directive({
selector: '[abpPermission]',
@ -32,6 +35,7 @@ export class PermissionDirective implements OnDestroy, OnChanges, AfterViewInit
private vcRef: ViewContainerRef,
private permissionService: PermissionService,
private cdRef: ChangeDetectorRef,
@Inject(QUEUE_MANAGER) public queue: QueueManager,
) {}
private check() {
@ -66,7 +70,7 @@ export class PermissionDirective implements OnDestroy, OnChanges, AfterViewInit
}
ngAfterViewInit() {
this.cdrSubject.pipe(take(1)).subscribe(() => this.cdRef.detectChanges());
this.cdrSubject.pipe(take(1)).subscribe(() => this.queue.add(() => this.cdRef.detectChanges()));
this.rendered = true;
}
}

11
npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts

@ -12,6 +12,7 @@ import { getInitialData, localeInitializer } from '../utils/initial-utils';
import * as environmentUtils from '../utils/environment-utils';
import * as multiTenancyUtils from '../utils/multi-tenancy-utils';
import { RestService } from '../services/rest.service';
import { CHECK_AUTHENTICATION_STATE_FN_KEY } from '../tokens/check-authentication-state';
const environment = { oAuthConfig: { issuer: 'test' } };
@ -41,6 +42,10 @@ describe('InitialUtils', () => {
registerLocaleFn: () => Promise.resolve(),
},
},
{
provide: CHECK_AUTHENTICATION_STATE_FN_KEY,
useValue: () => {},
},
],
});
@ -51,6 +56,9 @@ describe('InitialUtils', () => {
const environmentService = spectator.inject(EnvironmentService);
const configStateService = spectator.inject(ConfigStateService);
const sessionStateService = spectator.inject(SessionStateService);
//const checkAuthenticationState = spectator.inject(CHECK_AUTHENTICATION_STATE_FN_KEY);
const authService = spectator.inject(AuthService);
const parseTenantFromUrlSpy = jest.spyOn(multiTenancyUtils, 'parseTenantFromUrl');
const getRemoteEnvSpy = jest.spyOn(environmentUtils, 'getRemoteEnv');
@ -65,7 +73,7 @@ describe('InitialUtils', () => {
const configRefreshAppStateSpy = jest.spyOn(configStateService, 'refreshAppState');
configRefreshAppStateSpy.mockReturnValue(of(appConfigRes));
const sessionSetTenantSpy = jest.spyOn(sessionStateService, 'setTenant');
const authServiceInitSpy = jest.spyOn(authService, 'init');
const configStateGetOneSpy = jest.spyOn(configStateService, 'getOne');
configStateGetOneSpy.mockReturnValue(appConfigRes.currentTenant);
@ -79,6 +87,7 @@ describe('InitialUtils', () => {
expect(configRefreshAppStateSpy).toHaveBeenCalled();
expect(environmentSetStateSpy).toHaveBeenCalledWith(environment);
expect(sessionSetTenantSpy).toHaveBeenCalledWith(appConfigRes.currentTenant);
expect(authServiceInitSpy).toHaveBeenCalled();
});
});

1
npm/ng-packs/packages/core/src/lib/tokens/index.ts

@ -5,6 +5,7 @@ export * from './localization.token';
export * from './lodaer-delay.token';
export * from './manage-profile.token';
export * from './options.token';
export * from './queue.token';
export * from './tenant-key.token';
export * from './include-localization-resources.token';
export * from './pipe-to-login.token';

4
npm/ng-packs/packages/core/src/lib/tokens/queue.token.ts

@ -0,0 +1,4 @@
import { QueueManager } from "../utils/queue";
import { InjectionToken } from "@angular/core";
export const QUEUE_MANAGER = new InjectionToken<QueueManager>("QUEUE_MANAGER");

1
npm/ng-packs/packages/core/src/lib/utils/index.ts

@ -14,6 +14,7 @@ export * from './localization-utils';
export * from './multi-tenancy-utils';
export * from './number-utils';
export * from './object-utils';
export * from './queue';
export * from './route-utils';
export * from './string-utils';
export * from './tree-utils';

48
npm/ng-packs/packages/core/src/lib/utils/queue.ts

@ -0,0 +1,48 @@
export interface QueueManager {
add(fn: () => void): void;
init(interval: number, stackSize: number): void;
}
export class DefaultQueueManager implements QueueManager {
private queue: Array<() => void> = [];
private isRunning = false;
private stack = 0;
private interval = 0;
private stackSize = 100;
public init(interval: number, stackSize: number) {
this.interval = interval;
this.stackSize = stackSize;
}
public add(fn: () => void) {
this.queue.push(fn);
this.run();
}
private run() {
if (this.isRunning) return;
this.stack++;
this.isRunning = true;
const fn = this.queue.shift();
if (!fn) {
this.isRunning = false;
return;
}
fn();
if (this.stack > this.stackSize) {
setTimeout(() => {
this.isRunning = false;
this.run();
this.stack = 0;
}, this.interval);
} else {
this.isRunning = false;
this.run();
}
}
}

3
npm/ng-packs/packages/oauth/src/lib/tests/api.interceptor.spec.ts

@ -3,8 +3,7 @@ import { SpyObject } from '@ngneat/spectator';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest';
import { OAuthService } from 'angular-oauth2-oidc';
import { Subject, timer } from 'rxjs';
import { ApiInterceptor } from '../interceptors/api.interceptor';
import { HttpWaitService, SessionStateService, TENANT_KEY } from '@abp/ng.core';
import { ApiInterceptor, HttpWaitService, SessionStateService, TENANT_KEY } from '@abp/ng.core';
describe('ApiInterceptor', () => {
let spectator: SpectatorService<ApiInterceptor>;

29
npm/ng-packs/packages/oauth/src/lib/tests/initial-utils.spec.ts

@ -9,10 +9,8 @@ import {
ConfigStateService,
AbpApplicationConfigurationService,
SessionStateService,
ApplicationConfigurationDto,
} from '@abp/ng.core';
import * as clearOAuthStorageDefault from '../utils/clear-o-auth-storage';
import { of } from 'rxjs';
import { checkAccessToken } from '../utils/check-access-token';
const environment = { oAuthConfig: { issuer: 'test' } };
@ -49,33 +47,6 @@ describe('InitialUtils', () => {
beforeEach(() => (spectator = createComponent()));
describe('#getInitialData', () => {
let mockInjector;
let configStateService;
let authService;
beforeEach(() => {
mockInjector = {
get: spectator.inject,
};
configStateService = spectator.inject(ConfigStateService);
authService = spectator.inject(AuthService);
});
test('should called configStateService.refreshAppState', async () => {
const configRefreshAppStateSpy = jest.spyOn(configStateService, 'refreshAppState');
const appConfigRes = {
currentTenant: { id: 'test', name: 'testing' },
} as ApplicationConfigurationDto;
configRefreshAppStateSpy.mockReturnValue(of(appConfigRes));
// Todo: refactor it
// await initFactory(mockInjector)();
expect(configRefreshAppStateSpy).toHaveBeenCalled();
});
});
describe('#checkAccessToken', () => {
let injector;
let injectorSpy;

Loading…
Cancel
Save