Browse Source

Merge branch 'rel-7.0' of https://github.com/abpframework/abp into fix/strict-mode-errors

pull/15750/head
muhammedaltug 3 years ago
parent
commit
56f3d5c9e2
  1. 8
      docs/en/Themes/LeptonXLite/Angular.md
  2. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs
  3. 2
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs
  4. 41
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableStringToGuidConverter.cs
  5. 36
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToGuidConverter.cs
  6. 23
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController.cs
  7. 12
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController_Tests.cs
  8. 85
      framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpStringToGuid_Tests.cs
  9. 6
      npm/ng-packs/packages/core/src/lib/models/auth.ts
  10. 17
      npm/ng-packs/packages/core/src/lib/tests/application-localization.service.spec.ts
  11. 17
      npm/ng-packs/packages/core/src/lib/tests/config-state.service.spec.ts
  12. 2
      npm/ng-packs/packages/core/src/lib/tests/date-utils.spec.ts
  13. 3
      npm/ng-packs/packages/core/src/lib/tests/localization-utils.spec.ts
  14. 9
      npm/ng-packs/packages/core/src/lib/tests/localization.service.spec.ts
  15. 4
      npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts
  16. 3
      npm/ng-packs/packages/core/src/lib/tokens/set-token-response-to-storage.token.ts
  17. 9
      npm/ng-packs/packages/oauth/src/lib/oauth.module.ts
  18. 25
      npm/ng-packs/packages/oauth/src/lib/utils/auth-utils.ts

8
docs/en/Themes/LeptonXLite/Angular.md

@ -14,11 +14,15 @@ To add `LeptonX-lite` into your project,
- Install `@abp/ng.theme.lepton-x`
`yarn add @abp/ng.theme.lepton-x@preview`
```bash
yarn add @abp/ng.theme.lepton-x
```
- Install `bootstrap-icons`
`yarn add bootstrap-icons`
```bash
yarn add bootstrap-icons
```
- Then, we need to edit the styles array in `angular.json` to replace the existing style with the new one in the following link :

2
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs

@ -20,6 +20,8 @@ public static class MvcCoreBuilderExtensions
options.JsonSerializerOptions.Converters.Add(new AbpStringToEnumFactory());
options.JsonSerializerOptions.Converters.Add(new AbpStringToBooleanConverter());
options.JsonSerializerOptions.Converters.Add(new AbpStringToGuidConverter());
options.JsonSerializerOptions.Converters.Add(new AbpNullableStringToGuidConverter());
options.JsonSerializerOptions.Converters.Add(new ObjectToInferredTypesConverter());
options.JsonSerializerOptions.TypeInfoResolver = new AbpDefaultJsonTypeInfoResolver(serviceProvider

2
framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs

@ -22,6 +22,8 @@ public class AbpJsonSystemTextJsonModule : AbpModule
options.JsonSerializerOptions.Converters.Add(new AbpStringToEnumFactory());
options.JsonSerializerOptions.Converters.Add(new AbpStringToBooleanConverter());
options.JsonSerializerOptions.Converters.Add(new AbpStringToGuidConverter());
options.JsonSerializerOptions.Converters.Add(new AbpNullableStringToGuidConverter());
options.JsonSerializerOptions.Converters.Add(new ObjectToInferredTypesConverter());
options.JsonSerializerOptions.TypeInfoResolver = new AbpDefaultJsonTypeInfoResolver(serviceProvider

41
framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableStringToGuidConverter.cs

@ -0,0 +1,41 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Volo.Abp.Json.SystemTextJson.JsonConverters;
public class AbpNullableStringToGuidConverter : JsonConverter<Guid?>
{
private JsonSerializerOptions _writeJsonSerializerOptions;
public override Guid? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
var guidString = reader.GetString();
string[] formats = { "N", "D", "B", "P", "X" };
foreach (var format in formats)
{
if (Guid.TryParseExact(guidString, format, out var guid))
{
return guid;
}
}
}
if (reader.TryGetGuid(out var guid2))
{
return guid2;
}
return null;
}
public override void Write(Utf8JsonWriter writer, Guid? value, JsonSerializerOptions options)
{
_writeJsonSerializerOptions ??= JsonSerializerOptionsHelper.Create(options, this);
var entityConverter = (JsonConverter<Guid?>)_writeJsonSerializerOptions.GetConverter(typeof(Guid?));
entityConverter.Write(writer, value, _writeJsonSerializerOptions);
}
}

36
framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToGuidConverter.cs

@ -0,0 +1,36 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Volo.Abp.Json.SystemTextJson.JsonConverters;
public class AbpStringToGuidConverter : JsonConverter<Guid>
{
private JsonSerializerOptions _writeJsonSerializerOptions;
public override Guid Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
var guidString = reader.GetString();
string[] formats = { "N", "D", "B", "P", "X" };
foreach (var format in formats)
{
if (Guid.TryParseExact(guidString, format, out var guid))
{
return guid;
}
}
}
return reader.GetGuid();
}
public override void Write(Utf8JsonWriter writer, Guid value, JsonSerializerOptions options)
{
_writeJsonSerializerOptions ??= JsonSerializerOptionsHelper.Create(options, this);
var entityConverter = (JsonConverter<Guid>)_writeJsonSerializerOptions.GetConverter(typeof(Guid));
entityConverter.Write(writer, value, _writeJsonSerializerOptions);
}
}

23
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController.cs

@ -49,6 +49,12 @@ public class ModelBindingController : AbpController
input.Time3.Value.Kind.ToString().ToLower() + "_" +
input.InnerModel.Time4.Kind.ToString().ToLower();
}
[HttpPost("Guid_Json_Test")]
public GuidJsonModel Guid_Json_Test([FromBody] GuidJsonModel input)
{
return input;
}
}
public class GetDateTimeKindModel
@ -68,3 +74,20 @@ public class GetDateTimeKindModel
public DateTime Time4 { get; set; }
}
}
public class GuidJsonModel
{
public Guid UserId { get; set; }
public Guid UserId2 { get; set; }
public Guid UserId3 { get; set; }
public Guid UserId4 { get; set; }
public Guid UserId5 { get; set; }
public Guid? TenantId { get; set; }
public Guid? TenantId2 { get; set; }
}

12
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController_Tests.cs

@ -106,6 +106,18 @@ public abstract class ModelBindingController_Tests : AspNetCoreMvcTestBase
var resultAsString = await response.Content.ReadAsStringAsync();
resultAsString.ShouldBe($"local_{Kind.ToString().ToLower()}_{Kind.ToString().ToLower()}_local");
}
[Fact]
public async Task Guid_Json_Test()
{
var guid = Guid.NewGuid();
var json = $"{{\"UserId\":\"{guid:B}\",\"UserId2\":\"{guid:N}\",\"UserId3\":\"{guid:D}\",\"UserId4\":\"{guid:P}\",\"UserId5\":\"{guid:x}\",\"TenantId\":null,\"TenantId2\":\"\"}}";
var response = await Client.PostAsync("/api/model-Binding-test/Guid_Json_Test", new StringContent(json, Encoding.UTF8, MimeTypes.Application.Json));
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var resultAsString = await response.Content.ReadAsStringAsync();
resultAsString.ShouldBe($"{{\"userId\":\"{guid:D}\",\"userId2\":\"{guid:D}\",\"userId3\":\"{guid:D}\",\"userId4\":\"{guid:D}\",\"userId5\":\"{guid:D}\",\"tenantId\":null,\"tenantId2\":null}}");
}
}
public class ModelBindingController_Utc_Tests : ModelBindingController_Tests

85
framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpStringToGuid_Tests.cs

@ -0,0 +1,85 @@
using System;
using System.Text.Json;
using Shouldly;
using Volo.Abp.Json.SystemTextJson.JsonConverters;
using Xunit;
namespace Volo.Abp.Json;
public class AbpStringToGuid_Tests
{
[Fact]
public void Test_Read()
{
var options = new JsonSerializerOptions()
{
Converters =
{
new AbpStringToGuidConverter(),
new AbpNullableStringToGuidConverter()
}
};
var guid = Guid.Parse("762DDB84-5225-4853-A566-FF0B3AF57585");
var testClass = JsonSerializer.Deserialize<TestClass>("{" +
$"\"Id\": \"{guid:N}\", " +
$"\"NullableId\": \"{guid:D}\", " +
$"\"NullableId2\": \"{guid:B}\", " +
$"\"NullableId3\": \"{guid:P}\", " +
$"\"NullableId4\": \"{guid:X}\", " +
"\"NullableId5\": \"\", " +
"\"NullableId6\": null}", options);
testClass.ShouldNotBeNull();
testClass.Id.ShouldBe(guid);
testClass.NullableId.ShouldBe(guid);
testClass.NullableId2.ShouldBe(guid);
testClass.NullableId3.ShouldBe(guid);
testClass.NullableId4.ShouldBe(guid);
testClass.NullableId5.ShouldBeNull();
testClass.NullableId6.ShouldBeNull();
}
[Fact]
public void Test_Write()
{
var options = new JsonSerializerOptions()
{
Converters =
{
new AbpStringToGuidConverter(),
new AbpNullableStringToGuidConverter()
}
};
var guid = Guid.Parse("762DDB84-5225-4853-A566-FF0B3AF57585");
var json = JsonSerializer.Serialize(new TestClass()
{
Id = guid,
NullableId = null,
NullableId2 = guid,
NullableId3 = null,
NullableId4 = guid,
NullableId5 = null,
NullableId6 = guid
}, options);
json.ShouldBe($"{{\"Id\":\"{guid:D}\",\"NullableId\":null,\"NullableId2\":\"{guid:D}\",\"NullableId3\":null,\"NullableId4\":\"{guid:D}\",\"NullableId5\":null,\"NullableId6\":\"{guid:D}\"}}");
}
class TestClass
{
public Guid Id { get; set; }
public Guid? NullableId { get; set; }
public Guid? NullableId2 { get; set; }
public Guid? NullableId3 { get; set; }
public Guid? NullableId4 { get; set; }
public Guid? NullableId5 { get; set; }
public Guid? NullableId6 { get; set; }
}
}

6
npm/ng-packs/packages/core/src/lib/models/auth.ts

@ -12,6 +12,8 @@ export type PipeToLoginFn = (
params: Pick<LoginParams, 'redirectUrl' | 'rememberMe'>,
injector: Injector,
) => UnaryFunction<any, any>;
export type SetTokenResponseToStorageFn<T = any> = (injector: Injector, tokenRes: T) => void;
/**
* @deprecated The interface should not be used anymore.
*/
export type SetTokenResponseToStorageFn<T = any> = (tokenRes: T) => void;
export type CheckAuthenticationStateFn = (injector: Injector) => void;

17
npm/ng-packs/packages/core/src/lib/tests/application-localization.service.spec.ts

@ -0,0 +1,17 @@
export const APPLICATION_LOCALIZATION_DATA = {
resources: {
Default: { texts: {}, baseResources: [] },
MyProjectName: {
texts: {
"'{0}' and '{1}' do not match.": "'{0}' and '{1}' do not match.",
},
baseResources: [],
},
AbpIdentity: {
texts: {
Identity: 'identity',
},
baseResources: [],
},
},
};

17
npm/ng-packs/packages/core/src/lib/tests/config-state.service.spec.ts

@ -8,6 +8,9 @@ import {
} from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/models';
import { ConfigStateService } from '../services';
import { CORE_OPTIONS } from '../tokens';
import { IncludeLocalizationResourcesProvider } from '../providers';
import { APPLICATION_LOCALIZATION_DATA } from './application-localization.service.spec';
import { AbpApplicationLocalizationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-localization.service';
export const CONFIG_STATE_DATA = {
environment: {
@ -34,14 +37,7 @@ export const CONFIG_STATE_DATA = {
layouts: [null, null, null],
},
localization: {
values: {
MyProjectName: {
"'{0}' and '{1}' do not match.": "'{0}' and '{1}' do not match.",
},
AbpIdentity: {
Identity: 'identity',
},
},
values: {},
languages: [
{
cultureName: 'cs',
@ -115,6 +111,11 @@ describe('ConfigStateService', () => {
provide: AbpApplicationConfigurationService,
useValue: { get: () => of(CONFIG_STATE_DATA) },
},
{
provide: AbpApplicationLocalizationService,
useValue: { get: () => APPLICATION_LOCALIZATION_DATA },
},
IncludeLocalizationResourcesProvider,
],
});

2
npm/ng-packs/packages/core/src/lib/tests/date-utils.spec.ts

@ -15,7 +15,7 @@ describe('Date Utils', () => {
let config: ConfigStateService;
beforeEach(() => {
config = new ConfigStateService(null);
config = new ConfigStateService(null, null, null);
});
describe('#getShortDateFormat', () => {

3
npm/ng-packs/packages/core/src/lib/tests/localization-utils.spec.ts

@ -57,6 +57,7 @@ describe('Localization Utils', () => {
languages: [],
languageFilesMap: null,
languagesMap: null,
resources: {},
});
test.each`
@ -100,6 +101,7 @@ describe('Localization Utils', () => {
languages: [],
languageFilesMap: null,
languagesMap: null,
resources: {},
});
test.each`
@ -148,6 +150,7 @@ describe('Localization Utils', () => {
languages: [],
languageFilesMap: null,
languagesMap: null,
resources: {},
});
test.each`

9
npm/ng-packs/packages/core/src/lib/tests/localization.service.spec.ts

@ -8,8 +8,12 @@ import { SessionStateService } from '../services/session-state.service';
import { LocalizationService } from '../services/localization.service';
import { CORE_OPTIONS } from '../tokens/options.token';
import { CONFIG_STATE_DATA } from './config-state.service.spec';
import { AbpApplicationLocalizationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-localization.service';
import { APPLICATION_LOCALIZATION_DATA } from './application-localization.service.spec';
import { IncludeLocalizationResourcesProvider } from '../providers';
const appConfigData$ = new BehaviorSubject(CONFIG_STATE_DATA);
const appLocalizationData$ = new BehaviorSubject(APPLICATION_LOCALIZATION_DATA);
describe('LocalizationService', () => {
let spectator: SpectatorService<LocalizationService>;
@ -22,6 +26,7 @@ describe('LocalizationService', () => {
entryComponents: [],
mocks: [Router],
providers: [
IncludeLocalizationResourcesProvider,
{
provide: CORE_OPTIONS,
useValue: { registerLocaleFn: () => Promise.resolve(), cultureNameLocaleFileMap: {} },
@ -30,6 +35,10 @@ describe('LocalizationService', () => {
provide: AbpApplicationConfigurationService,
useValue: { get: () => appConfigData$ },
},
{
provide: AbpApplicationLocalizationService,
useValue: { get: () => appLocalizationData$ },
},
],
});

4
npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts

@ -9,6 +9,7 @@ import { HttpErrorReporterService } from '../services/http-error-reporter.servic
import { PermissionService } from '../services/permission.service';
import { RoutesService } from '../services/routes.service';
import { CORE_OPTIONS } from '../tokens/options.token';
import { IncludeLocalizationResourcesProvider } from '../providers';
describe('PermissionGuard', () => {
let spectator: SpectatorService<PermissionGuard>;
@ -36,7 +37,7 @@ describe('PermissionGuard', () => {
},
},
],
{ relativeLinkResolution: 'legacy' },
{},
),
],
providers: [
@ -45,6 +46,7 @@ describe('PermissionGuard', () => {
useValue: '/',
},
{ provide: CORE_OPTIONS, useValue: { skipGetAppConfiguration: true } },
IncludeLocalizationResourcesProvider,
],
});

3
npm/ng-packs/packages/core/src/lib/tokens/set-token-response-to-storage.token.ts

@ -1,6 +1,9 @@
import { InjectionToken } from '@angular/core';
import { SetTokenResponseToStorageFn } from '../models';
/**
* @deprecated The token should not be used anymore.
*/
export const SET_TOKEN_RESPONSE_TO_STORAGE_FN_KEY = new InjectionToken<SetTokenResponseToStorageFn>(
'SET_TOKEN_RESPONSE_TO_STORAGE_FN_KEY',
);

9
npm/ng-packs/packages/oauth/src/lib/oauth.module.ts

@ -7,8 +7,7 @@ import {
AuthService,
CHECK_AUTHENTICATION_STATE_FN_KEY,
noop,
PIPE_TO_LOGIN_FN_KEY,
SET_TOKEN_RESPONSE_TO_STORAGE_FN_KEY,
PIPE_TO_LOGIN_FN_KEY
} from '@abp/ng.core';
import { storageFactory } from './utils/storage.factory';
import { AbpOAuthService } from './services';
@ -17,7 +16,7 @@ import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { OAuthApiInterceptor } from './interceptors/api.interceptor';
import { AbpOAuthGuard } from './guards/oauth.guard';
import { NavigateToManageProfileProvider } from './providers';
import { checkAccessToken, pipeToLogin, setTokenResponseToStorage } from './utils';
import { checkAccessToken, pipeToLogin } from './utils';
@NgModule({
imports: [CommonModule, OAuthModule],
@ -43,10 +42,6 @@ export class AbpOAuthModule {
provide: PIPE_TO_LOGIN_FN_KEY,
useValue: pipeToLogin,
},
{
provide: SET_TOKEN_RESPONSE_TO_STORAGE_FN_KEY,
useValue: setTokenResponseToStorage,
},
{
provide: CHECK_AUTHENTICATION_STATE_FN_KEY,
useValue: checkAccessToken,

25
npm/ng-packs/packages/oauth/src/lib/utils/auth-utils.ts

@ -1,4 +1,4 @@
import { Injector } from '@angular/core';
import { inject, Injector } from '@angular/core';
import { Router } from '@angular/router';
import { OAuthStorage, TokenResponse } from 'angular-oauth2-oidc';
import { pipe } from 'rxjs';
@ -29,29 +29,6 @@ export const pipeToLogin: PipeToLoginFn = function (
);
};
export const setTokenResponseToStorage: SetTokenResponseToStorageFn<TokenResponse> = function (
injector: Injector,
tokenRes: TokenResponse,
) {
const { access_token, refresh_token, scope: grantedScopes, expires_in } = tokenRes;
const storage = injector.get(OAuthStorage);
storage.setItem('access_token', access_token);
storage.setItem('refresh_token', refresh_token);
storage.setItem('access_token_stored_at', '' + Date.now());
if (grantedScopes) {
storage.setItem('granted_scopes', JSON.stringify(grantedScopes.split(' ')));
}
if (expires_in) {
const expiresInMilliSeconds = expires_in * 1000;
const now = new Date();
const expiresAt = now.getTime() + expiresInMilliSeconds;
storage.setItem('expires_at', '' + expiresAt);
}
};
export function setRememberMe(remember: boolean | undefined) {
removeRememberMe();
localStorage.setItem(storageKey, 'true');

Loading…
Cancel
Save