@intellegens/cornerstone-client 0.0.9999-alpha-9 → 0.0.9999-alpha-10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demo/index.ts +29 -0
- package/demo/public_html/favicon.ico +0 -0
- package/demo/public_html/index.html +106 -0
- package/demo/public_html/websettings.json +3 -0
- package/jest.config.js +29 -0
- package/package.json +1 -1
- package/src/adapters/CollectionViewAdapter/index.ts +390 -0
- package/src/adapters/index.ts +1 -0
- package/src/data/api/dto/PropertyPathDto.ts +4 -0
- package/src/data/api/dto/ReadOptionsDto.ts +8 -0
- package/src/data/api/dto/ReadResultDto.ts +13 -0
- package/src/data/api/dto/ReadResultMetadataDto.ts +8 -0
- package/src/data/api/dto/crud/CrudMetadataDto.ts +4 -0
- package/src/data/api/dto/crud/index.ts +1 -0
- package/src/data/api/dto/index.ts +4 -0
- package/src/data/api/dto/read/ReadMetadataDto.ts +8 -0
- package/src/data/api/dto/read/ReadSelectedDefinitionDto.ts +21 -0
- package/src/data/api/dto/read/ReadSelectedNestedCollectionCriteriaDto.ts +25 -0
- package/src/data/api/dto/read/ReadSelectedNestedCriteriaDto.ts +20 -0
- package/src/data/api/dto/read/ReadSelectedOrderingDefinitionDto.ts +8 -0
- package/src/data/api/dto/read/ReadSelectedOrderingPropertyDefinitionDto.ts +16 -0
- package/src/data/api/dto/read/ReadSelectedPaginationDefinitionDto.ts +13 -0
- package/src/data/api/dto/read/ReadSelectedSearchDefinitionDto.ts +43 -0
- package/src/data/api/dto/read/ReadSelectedSearchPropertyDefinitionDto.ts +186 -0
- package/src/data/api/dto/read/index.ts +9 -0
- package/src/data/api/dto/response/ApiErrorDto.ts +21 -0
- package/src/data/api/dto/response/ApiErrorResponseDto.ts +13 -0
- package/src/data/api/dto/response/ApiResponseDto.ts +7 -0
- package/src/data/api/dto/response/ApiSuccessResponseDto.ts +13 -0
- package/src/data/api/dto/response/MetadataDto.ts +24 -0
- package/src/data/api/dto/response/index.ts +5 -0
- package/src/data/api/enum/index.ts +2 -0
- package/src/data/api/enum/read/ReadSelectedCollectionOperator.ts +17 -0
- package/src/data/api/enum/read/ReadSelectedComparisonOperator.ts +96 -0
- package/src/data/api/enum/read/ReadSelectedLogicalOperator.ts +16 -0
- package/src/data/api/enum/read/ReadSelectedOrderingDirection.ts +13 -0
- package/src/data/api/enum/read/ReadSelectedPropertyType.ts +86 -0
- package/src/data/api/enum/read/index.ts +5 -0
- package/src/data/api/enum/response/ErrorCode.ts +13 -0
- package/src/data/api/enum/response/index.ts +1 -0
- package/src/data/api/index.ts +3 -0
- package/src/data/api/interface/IConcurrencySafe.ts +9 -0
- package/src/data/api/interface/IIdentifiable.ts +12 -0
- package/src/data/api/interface/IIdentifiableSecondary.ts +9 -0
- package/src/data/api/interface/index.ts +3 -0
- package/src/data/auth/dto/ClaimDto.ts +4 -0
- package/src/data/auth/dto/RegisterRequestDto.ts +4 -0
- package/src/data/auth/dto/RoleDto.ts +6 -0
- package/src/data/auth/dto/SignInRequestDto.ts +4 -0
- package/src/data/auth/dto/TokensDto.ts +4 -0
- package/src/data/auth/dto/UserDto.ts +18 -0
- package/src/data/auth/dto/UserInfoDto.ts +15 -0
- package/src/data/auth/dto/index.ts +4 -0
- package/src/data/auth/index.ts +2 -0
- package/src/data/auth/policy.ts +63 -0
- package/src/data/index.ts +2 -0
- package/src/index.ts +4 -0
- package/src/services/api/ApiCrudControllerClient/index.ts +129 -0
- package/src/services/api/ApiInitializationService/index.ts +254 -0
- package/src/services/api/ApiReadControllerClient/index.ts +137 -0
- package/src/services/api/HttpService/FetchHttpService.ts +34 -0
- package/src/services/api/HttpService/HttpRequestConfig.ts +10 -0
- package/src/services/api/HttpService/HttpResponse.ts +14 -0
- package/src/services/api/HttpService/IHttpService.ts +17 -0
- package/src/services/api/HttpService/README.md +106 -0
- package/src/services/api/HttpService/index.ts +12 -0
- package/src/services/api/UserManagementControllerClient/index.ts +160 -0
- package/src/services/api/index.ts +5 -0
- package/src/services/auth/client/AuthService/index.ts +187 -0
- package/src/services/auth/client/AuthorizationManagementControllerClient/index.ts +165 -0
- package/src/services/auth/client/index.ts +2 -0
- package/src/services/auth/index.ts +1 -0
- package/src/services/index.ts +2 -0
- package/src/utils/authorization/index.ts +47 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/result/index.ts +25 -0
- package/src/utils/search/index.ts +150 -0
- package/tests/ApiClients.test.ts +284 -0
- package/tests/CollectionViewAdapter.test.ts +392 -0
- package/tests/HttpService.test.ts +303 -0
- package/tests/setup.ts +76 -0
- package/tsconfig.json +19 -0
- package/LICENSE.md +0 -7
- /package/{adapters → dist/adapters}/CollectionViewAdapter/index.d.ts +0 -0
- /package/{adapters → dist/adapters}/CollectionViewAdapter/index.js +0 -0
- /package/{adapters → dist/adapters}/index.d.ts +0 -0
- /package/{adapters → dist/adapters}/index.js +0 -0
- /package/{data → dist/data}/api/dto/PropertyPathDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/PropertyPathDto.js +0 -0
- /package/{data → dist/data}/api/dto/ReadOptionsDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/ReadOptionsDto.js +0 -0
- /package/{data → dist/data}/api/dto/ReadResultDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/ReadResultDto.js +0 -0
- /package/{data → dist/data}/api/dto/ReadResultMetadataDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/ReadResultMetadataDto.js +0 -0
- /package/{data → dist/data}/api/dto/crud/CrudMetadataDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/crud/CrudMetadataDto.js +0 -0
- /package/{data → dist/data}/api/dto/crud/index.d.ts +0 -0
- /package/{data → dist/data}/api/dto/crud/index.js +0 -0
- /package/{data → dist/data}/api/dto/index.d.ts +0 -0
- /package/{data → dist/data}/api/dto/index.js +0 -0
- /package/{data → dist/data}/api/dto/read/ReadMetadataDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/read/ReadMetadataDto.js +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedDefinitionDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedDefinitionDto.js +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedNestedCollectionCriteriaDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedNestedCollectionCriteriaDto.js +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedNestedCriteriaDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedNestedCriteriaDto.js +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedOrderingDefinitionDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedOrderingDefinitionDto.js +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedOrderingPropertyDefinitionDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedOrderingPropertyDefinitionDto.js +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedPaginationDefinitionDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedPaginationDefinitionDto.js +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedSearchDefinitionDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedSearchDefinitionDto.js +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedSearchPropertyDefinitionDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/read/ReadSelectedSearchPropertyDefinitionDto.js +0 -0
- /package/{data → dist/data}/api/dto/read/index.d.ts +0 -0
- /package/{data → dist/data}/api/dto/read/index.js +0 -0
- /package/{data → dist/data}/api/dto/response/ApiErrorDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/response/ApiErrorDto.js +0 -0
- /package/{data → dist/data}/api/dto/response/ApiErrorResponseDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/response/ApiErrorResponseDto.js +0 -0
- /package/{data → dist/data}/api/dto/response/ApiResponseDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/response/ApiResponseDto.js +0 -0
- /package/{data → dist/data}/api/dto/response/ApiSuccessResponseDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/response/ApiSuccessResponseDto.js +0 -0
- /package/{data → dist/data}/api/dto/response/EmptyMetadataDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/response/EmptyMetadataDto.js +0 -0
- /package/{data → dist/data}/api/dto/response/MetadataDto.d.ts +0 -0
- /package/{data → dist/data}/api/dto/response/MetadataDto.js +0 -0
- /package/{data → dist/data}/api/dto/response/index.d.ts +0 -0
- /package/{data → dist/data}/api/dto/response/index.js +0 -0
- /package/{data → dist/data}/api/enum/index.d.ts +0 -0
- /package/{data → dist/data}/api/enum/index.js +0 -0
- /package/{data → dist/data}/api/enum/read/ReadSelectedCollectionOperator.d.ts +0 -0
- /package/{data → dist/data}/api/enum/read/ReadSelectedCollectionOperator.js +0 -0
- /package/{data → dist/data}/api/enum/read/ReadSelectedComparisonOperator.d.ts +0 -0
- /package/{data → dist/data}/api/enum/read/ReadSelectedComparisonOperator.js +0 -0
- /package/{data → dist/data}/api/enum/read/ReadSelectedLogicalOperator.d.ts +0 -0
- /package/{data → dist/data}/api/enum/read/ReadSelectedLogicalOperator.js +0 -0
- /package/{data → dist/data}/api/enum/read/ReadSelectedOrderingDirection.d.ts +0 -0
- /package/{data → dist/data}/api/enum/read/ReadSelectedOrderingDirection.js +0 -0
- /package/{data → dist/data}/api/enum/read/ReadSelectedPropertyType.d.ts +0 -0
- /package/{data → dist/data}/api/enum/read/ReadSelectedPropertyType.js +0 -0
- /package/{data → dist/data}/api/enum/read/index.d.ts +0 -0
- /package/{data → dist/data}/api/enum/read/index.js +0 -0
- /package/{data → dist/data}/api/enum/response/ApiErrorCodes.d.ts +0 -0
- /package/{data → dist/data}/api/enum/response/ApiErrorCodes.js +0 -0
- /package/{data → dist/data}/api/enum/response/ErrorCode.d.ts +0 -0
- /package/{data → dist/data}/api/enum/response/ErrorCode.js +0 -0
- /package/{data → dist/data}/api/enum/response/index.d.ts +0 -0
- /package/{data → dist/data}/api/enum/response/index.js +0 -0
- /package/{data → dist/data}/api/index.d.ts +0 -0
- /package/{data → dist/data}/api/index.js +0 -0
- /package/{data → dist/data}/api/interface/IConcurrencySafe.d.ts +0 -0
- /package/{data → dist/data}/api/interface/IConcurrencySafe.js +0 -0
- /package/{data → dist/data}/api/interface/IIdentifiable.d.ts +0 -0
- /package/{data → dist/data}/api/interface/IIdentifiable.js +0 -0
- /package/{data → dist/data}/api/interface/IIdentifiableSecondary.d.ts +0 -0
- /package/{data → dist/data}/api/interface/IIdentifiableSecondary.js +0 -0
- /package/{data → dist/data}/api/interface/index.d.ts +0 -0
- /package/{data → dist/data}/api/interface/index.js +0 -0
- /package/{data → dist/data}/auth/dto/ClaimDto.d.ts +0 -0
- /package/{data → dist/data}/auth/dto/ClaimDto.js +0 -0
- /package/{data → dist/data}/auth/dto/RegisterRequestDto.d.ts +0 -0
- /package/{data → dist/data}/auth/dto/RegisterRequestDto.js +0 -0
- /package/{data → dist/data}/auth/dto/RoleDto.d.ts +0 -0
- /package/{data → dist/data}/auth/dto/RoleDto.js +0 -0
- /package/{data → dist/data}/auth/dto/SignInRequestDto.d.ts +0 -0
- /package/{data → dist/data}/auth/dto/SignInRequestDto.js +0 -0
- /package/{data → dist/data}/auth/dto/TokensDto.d.ts +0 -0
- /package/{data → dist/data}/auth/dto/TokensDto.js +0 -0
- /package/{data → dist/data}/auth/dto/UserDto.d.ts +0 -0
- /package/{data → dist/data}/auth/dto/UserDto.js +0 -0
- /package/{data → dist/data}/auth/dto/UserInfoDto.d.ts +0 -0
- /package/{data → dist/data}/auth/dto/UserInfoDto.js +0 -0
- /package/{data → dist/data}/auth/dto/index.d.ts +0 -0
- /package/{data → dist/data}/auth/dto/index.js +0 -0
- /package/{data → dist/data}/auth/index.d.ts +0 -0
- /package/{data → dist/data}/auth/index.js +0 -0
- /package/{data → dist/data}/auth/policy.d.ts +0 -0
- /package/{data → dist/data}/auth/policy.js +0 -0
- /package/{data → dist/data}/index.d.ts +0 -0
- /package/{data → dist/data}/index.js +0 -0
- /package/{index.d.ts → dist/index.d.ts} +0 -0
- /package/{index.js → dist/index.js} +0 -0
- /package/{services → dist/services}/api/ApiCrudControllerClient/index.d.ts +0 -0
- /package/{services → dist/services}/api/ApiCrudControllerClient/index.js +0 -0
- /package/{services → dist/services}/api/ApiInitializationService/index.d.ts +0 -0
- /package/{services → dist/services}/api/ApiInitializationService/index.js +0 -0
- /package/{services → dist/services}/api/ApiReadControllerClient/index.d.ts +0 -0
- /package/{services → dist/services}/api/ApiReadControllerClient/index.js +0 -0
- /package/{services → dist/services}/api/HttpService/FetchHttpService.d.ts +0 -0
- /package/{services → dist/services}/api/HttpService/FetchHttpService.js +0 -0
- /package/{services → dist/services}/api/HttpService/HttpRequestConfig.d.ts +0 -0
- /package/{services → dist/services}/api/HttpService/HttpRequestConfig.js +0 -0
- /package/{services → dist/services}/api/HttpService/HttpResponse.d.ts +0 -0
- /package/{services → dist/services}/api/HttpService/HttpResponse.js +0 -0
- /package/{services → dist/services}/api/HttpService/IHttpService.d.ts +0 -0
- /package/{services → dist/services}/api/HttpService/IHttpService.js +0 -0
- /package/{services → dist/services}/api/HttpService/index.d.ts +0 -0
- /package/{services → dist/services}/api/HttpService/index.js +0 -0
- /package/{services → dist/services}/api/UserManagementControllerClient/index.d.ts +0 -0
- /package/{services → dist/services}/api/UserManagementControllerClient/index.js +0 -0
- /package/{services → dist/services}/api/index.d.ts +0 -0
- /package/{services → dist/services}/api/index.js +0 -0
- /package/{services → dist/services}/auth/client/AuthService/index.d.ts +0 -0
- /package/{services → dist/services}/auth/client/AuthService/index.js +0 -0
- /package/{services → dist/services}/auth/client/AuthorizationManagementControllerClient/index.d.ts +0 -0
- /package/{services → dist/services}/auth/client/AuthorizationManagementControllerClient/index.js +0 -0
- /package/{services → dist/services}/auth/client/index.d.ts +0 -0
- /package/{services → dist/services}/auth/client/index.js +0 -0
- /package/{services → dist/services}/auth/index.d.ts +0 -0
- /package/{services → dist/services}/auth/index.js +0 -0
- /package/{services → dist/services}/index.d.ts +0 -0
- /package/{services → dist/services}/index.js +0 -0
- /package/{utils → dist/utils}/authorization/index.d.ts +0 -0
- /package/{utils → dist/utils}/authorization/index.js +0 -0
- /package/{utils → dist/utils}/index.d.ts +0 -0
- /package/{utils → dist/utils}/index.js +0 -0
- /package/{utils → dist/utils}/result/index.d.ts +0 -0
- /package/{utils → dist/utils}/result/index.js +0 -0
- /package/{utils → dist/utils}/search/index.d.ts +0 -0
- /package/{utils → dist/utils}/search/index.js +0 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { apiInitializationService } from '../ApiInitializationService';
|
|
2
|
+
import {
|
|
3
|
+
ApiErrorResponseDto,
|
|
4
|
+
ApiResponseDto,
|
|
5
|
+
ApiSuccessResponseDto,
|
|
6
|
+
EmptyMetadataDto,
|
|
7
|
+
ReadMetadataDto,
|
|
8
|
+
ReadSelectedDefinitionDto,
|
|
9
|
+
} from '../../../data/api/dto';
|
|
10
|
+
import { IIdentifiable } from '../../../data/api/interface';
|
|
11
|
+
import { IHttpService } from '../HttpService';
|
|
12
|
+
import { fail, ok } from '@utils/result';
|
|
13
|
+
import { ErrorCode } from '@data';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Base client for read-only API controllers
|
|
17
|
+
*/
|
|
18
|
+
export class ApiReadControllerClient<TKey, TDto extends IIdentifiable<TKey>> {
|
|
19
|
+
/**
|
|
20
|
+
* Constructor
|
|
21
|
+
* @param baseControllerPath Base path to API controller
|
|
22
|
+
* @param httpService HTTP service implementation to use for requests
|
|
23
|
+
*/
|
|
24
|
+
constructor(
|
|
25
|
+
protected readonly baseControllerPath: string,
|
|
26
|
+
httpService?: IHttpService,
|
|
27
|
+
) {
|
|
28
|
+
this._httpService = httpService;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// #region HTTP service
|
|
32
|
+
private readonly _httpService?: IHttpService = undefined;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Gets globally selected HTTP service
|
|
36
|
+
*/
|
|
37
|
+
protected get httpService(): IHttpService {
|
|
38
|
+
return this._httpService || apiInitializationService._getHttpService();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// #endregion
|
|
42
|
+
|
|
43
|
+
// #region API
|
|
44
|
+
/**
|
|
45
|
+
* Fetches all entities from the read controller.
|
|
46
|
+
* @param {AbortSignal} [signal] - Optional cancellation signal
|
|
47
|
+
* @returns {Promise<ApiSuccessResponseDto<TDto>[], ReadMetadataDto>>} List of all entities with metadata
|
|
48
|
+
*/
|
|
49
|
+
public async readAll(signal?: AbortSignal): Promise<ApiResponseDto<TDto[], ReadMetadataDto>> {
|
|
50
|
+
try {
|
|
51
|
+
const url = await apiInitializationService.getApiUrl(this.baseControllerPath, `/ReadAll`);
|
|
52
|
+
const res = await this.httpService.request(url, { method: 'GET', credentials: 'include', signal });
|
|
53
|
+
|
|
54
|
+
if (!res.ok) {
|
|
55
|
+
return fail<ApiSuccessResponseDto<TDto[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return ok<ApiSuccessResponseDto<TDto[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error(err);
|
|
61
|
+
|
|
62
|
+
return fail<ApiSuccessResponseDto<TDto[], ReadMetadataDto>, ApiErrorResponseDto>({
|
|
63
|
+
error: {
|
|
64
|
+
code: ErrorCode.UnknownError,
|
|
65
|
+
message: 'Unknown error fetching all records',
|
|
66
|
+
metadata: {} as EmptyMetadataDto,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Fetches selected entities based on a filter definition.
|
|
74
|
+
* @param {any} definition - The filter definition object
|
|
75
|
+
* @param {AbortSignal} [signal] - Optional cancellation signal
|
|
76
|
+
* @returns {Promise<ApiSuccessResponseDto<TDto>[], ReadMetadataDto>>} The result of the read operation with metadata
|
|
77
|
+
*/
|
|
78
|
+
public async readSelected(definition: ReadSelectedDefinitionDto<TDto>, signal?: AbortSignal): Promise<ApiResponseDto<TDto[], ReadMetadataDto>> {
|
|
79
|
+
try {
|
|
80
|
+
const url = await apiInitializationService.getApiUrl(this.baseControllerPath, `/ReadSelected`);
|
|
81
|
+
const res = await this.httpService.request(url, {
|
|
82
|
+
method: 'POST',
|
|
83
|
+
headers: { 'Content-Type': 'application/json' },
|
|
84
|
+
body: JSON.stringify(definition),
|
|
85
|
+
credentials: 'include',
|
|
86
|
+
signal,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (!res.ok) {
|
|
90
|
+
return fail<ApiSuccessResponseDto<TDto[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return ok<ApiSuccessResponseDto<TDto[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
94
|
+
} catch (err) {
|
|
95
|
+
console.error(err);
|
|
96
|
+
|
|
97
|
+
return fail<ApiSuccessResponseDto<TDto[], ReadMetadataDto>, ApiErrorResponseDto>({
|
|
98
|
+
error: {
|
|
99
|
+
code: ErrorCode.UnknownError,
|
|
100
|
+
message: 'Unknown error fetching selected records',
|
|
101
|
+
metadata: {} as EmptyMetadataDto,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Fetches a single entity by its ID.
|
|
109
|
+
* @param {TKey} id - The ID of the entity
|
|
110
|
+
* @param {AbortSignal} [signal] - Optional cancellation signal
|
|
111
|
+
* @returns {Promise<ApiSuccessResponseDto<TDto, EmptyMetadataDto>>} The requested entity
|
|
112
|
+
*/
|
|
113
|
+
public async readSingle(id: TKey, signal?: AbortSignal): Promise<ApiResponseDto<TDto, EmptyMetadataDto>> {
|
|
114
|
+
try {
|
|
115
|
+
const url = await apiInitializationService.getApiUrl(this.baseControllerPath, `/ReadSingle?id=${encodeURIComponent(String(id))}`);
|
|
116
|
+
const res = await this.httpService.request(url, { method: 'GET', credentials: 'include', signal });
|
|
117
|
+
|
|
118
|
+
if (!res.ok) {
|
|
119
|
+
return fail<ApiSuccessResponseDto<TDto, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return ok<ApiSuccessResponseDto<TDto, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
123
|
+
} catch (err) {
|
|
124
|
+
console.error(err);
|
|
125
|
+
|
|
126
|
+
return fail<ApiSuccessResponseDto<TDto, EmptyMetadataDto>, ApiErrorResponseDto>({
|
|
127
|
+
error: {
|
|
128
|
+
code: ErrorCode.UnknownError,
|
|
129
|
+
message: `Unknown error fetching record with id ${id}`,
|
|
130
|
+
metadata: {} as EmptyMetadataDto,
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// #endregion
|
|
137
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Ignore eslint any error in this file
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
|
|
4
|
+
import { HttpRequestConfig, HttpResponse, IHttpService } from '@/services';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Default HTTP service implementation using the Fetch API
|
|
8
|
+
*/
|
|
9
|
+
export class FetchHttpService implements IHttpService {
|
|
10
|
+
public async request<T = any>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>> {
|
|
11
|
+
const response = await fetch(url, {
|
|
12
|
+
method: config?.method || 'GET',
|
|
13
|
+
headers: config?.headers,
|
|
14
|
+
body: config?.body,
|
|
15
|
+
credentials: config?.credentials || 'include',
|
|
16
|
+
signal: config?.signal,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Convert Headers to a plain object
|
|
20
|
+
const headers: Record<string, string> = {};
|
|
21
|
+
response.headers.forEach((value, key) => {
|
|
22
|
+
headers[key] = value;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
ok: response.ok,
|
|
27
|
+
status: response.status,
|
|
28
|
+
statusText: response.statusText,
|
|
29
|
+
headers,
|
|
30
|
+
json: () => response.json(),
|
|
31
|
+
text: () => response.text(),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP request configuration interface
|
|
3
|
+
*/
|
|
4
|
+
export interface HttpRequestConfig {
|
|
5
|
+
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
6
|
+
headers?: Record<string, string>;
|
|
7
|
+
body?: string;
|
|
8
|
+
credentials?: RequestCredentials;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Ignore eslint any error in this file
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* HTTP response interface
|
|
6
|
+
*/
|
|
7
|
+
export interface HttpResponse<T = any> {
|
|
8
|
+
ok: boolean;
|
|
9
|
+
status: number;
|
|
10
|
+
statusText: string;
|
|
11
|
+
headers: Record<string, string>;
|
|
12
|
+
json(): Promise<T>;
|
|
13
|
+
text(): Promise<string>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Ignore eslint any error in this file
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
|
|
4
|
+
import { HttpRequestConfig, HttpResponse } from '@/services';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Abstract HTTP service interface that can be implemented by different HTTP clients
|
|
8
|
+
*/
|
|
9
|
+
export interface IHttpService {
|
|
10
|
+
/**
|
|
11
|
+
* Performs an HTTP request
|
|
12
|
+
* @param url - The URL to make the request to
|
|
13
|
+
* @param config - Request configuration
|
|
14
|
+
* @returns Promise that resolves to the HTTP response
|
|
15
|
+
*/
|
|
16
|
+
request<T = any>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# HTTP Service Abstraction
|
|
2
|
+
|
|
3
|
+
This module provides an abstraction layer for HTTP requests, allowing you to plug in different HTTP client implementations (Fetch API, Angular HttpClient, etc.) while maintaining the same interface.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The HTTP service abstraction consists of:
|
|
8
|
+
|
|
9
|
+
- `IHttpService` - Interface that all HTTP implementations must follow
|
|
10
|
+
- `FetchHttpService` - Default implementation using the Fetch API
|
|
11
|
+
- `AngularHttpService` - Implementation using Angular's HttpClient
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### Using the Default Fetch Implementation
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { ApiReadControllerClient, defaultHttpService } from '@services';
|
|
19
|
+
|
|
20
|
+
// Uses FetchHttpService by default
|
|
21
|
+
const client = new ApiReadControllerClient('/api/users');
|
|
22
|
+
|
|
23
|
+
// Or explicitly pass the default service
|
|
24
|
+
const client2 = new ApiReadControllerClient('/api/users', defaultHttpService);
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Using Angular HttpClient Implementation
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { inject } from '@angular/core';
|
|
31
|
+
import { HttpClient } from '@angular/common/http';
|
|
32
|
+
import { ApiReadControllerClient, AngularHttpService } from '@services';
|
|
33
|
+
|
|
34
|
+
const httpClient = inject<HttpClient>();
|
|
35
|
+
const angularHttpService = new AngularHttpService(httpClient);
|
|
36
|
+
|
|
37
|
+
// Set Angular HTTP service globaly
|
|
38
|
+
await apiInitializationService.initialize({ httpService: angularHttpService });
|
|
39
|
+
// Or for an explicitly chosen client
|
|
40
|
+
const apiClient = new ApiReadControllerClient('/api/users', angularHttpService);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
> **📦 For complete Angular integration guide, see [@intellegens/cornerstone-client-angular README](../../../../..//angular/README.md)**
|
|
44
|
+
|
|
45
|
+
## Creating Custom HTTP Service
|
|
46
|
+
|
|
47
|
+
You can create your own HTTP service implementation by implementing the `IHttpService` interface:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { IHttpService, HttpRequestConfig, HttpResponse } from '@services';
|
|
51
|
+
|
|
52
|
+
export class CustomHttpService implements IHttpService {
|
|
53
|
+
async request<T = any>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>> {
|
|
54
|
+
// Your custom HTTP implementation here
|
|
55
|
+
const response = await yourCustomHttpClient.request({
|
|
56
|
+
url,
|
|
57
|
+
method: config?.method || 'GET',
|
|
58
|
+
headers: config?.headers,
|
|
59
|
+
data: config?.body,
|
|
60
|
+
withCredentials: config?.credentials === 'include',
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
ok: response.status >= 200 && response.status < 300,
|
|
65
|
+
status: response.status,
|
|
66
|
+
statusText: response.statusText,
|
|
67
|
+
headers: response.headers,
|
|
68
|
+
json: async () => response.data,
|
|
69
|
+
text: async () => JSON.stringify(response.data),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## API Reference
|
|
76
|
+
|
|
77
|
+
### IHttpService Interface
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
interface IHttpService {
|
|
81
|
+
request<T = any>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### HttpRequestConfig Interface
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
interface HttpRequestConfig {
|
|
89
|
+
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
90
|
+
headers?: Record<string, string>;
|
|
91
|
+
body?: string;
|
|
92
|
+
credentials?: RequestCredentials;
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### HttpResponse Interface
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
interface HttpResponse<T = any> {
|
|
100
|
+
ok: boolean;
|
|
101
|
+
status: number;
|
|
102
|
+
statusText: string;
|
|
103
|
+
headers: Record<string, string>;
|
|
104
|
+
json(): Promise<T>;
|
|
105
|
+
text(): Promise<string>;
|
|
106
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FetchHttpService } from './FetchHttpService';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default HTTP service instance
|
|
5
|
+
*/
|
|
6
|
+
export const defaultHttpService = new FetchHttpService();
|
|
7
|
+
|
|
8
|
+
// Export additional HTTP service implementations
|
|
9
|
+
export * from './FetchHttpService';
|
|
10
|
+
export * from './HttpRequestConfig';
|
|
11
|
+
export * from './HttpResponse';
|
|
12
|
+
export * from './IHttpService';
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { ApiCrudControllerClient } from '../ApiCrudControllerClient';
|
|
2
|
+
import { apiInitializationService } from '../ApiInitializationService';
|
|
3
|
+
import { IHttpService } from '../HttpService';
|
|
4
|
+
import { ApiErrorResponseDto, ApiResponseDto, ApiSuccessResponseDto, ClaimDto, EmptyMetadataDto, ErrorCode, ReadMetadataDto, UserDto } from '@data';
|
|
5
|
+
import { fail, ok } from '@utils/result';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Client for user management operations
|
|
9
|
+
*
|
|
10
|
+
* @export
|
|
11
|
+
* @class UserManagementControllerClient
|
|
12
|
+
* @template TKey - Type of the entity key (e.g., number, string, GUID, etc.)
|
|
13
|
+
* @template TUser - Data Transfer Object representing the user entity
|
|
14
|
+
*/
|
|
15
|
+
export class UserManagementControllerClient<TKey, TUser extends UserDto<TKey>> extends ApiCrudControllerClient<TKey, TUser> {
|
|
16
|
+
/**
|
|
17
|
+
* Constructor
|
|
18
|
+
* @param baseControllerPath Base path to API controller
|
|
19
|
+
* @param httpService HTTP service implementation to use for requests
|
|
20
|
+
*/
|
|
21
|
+
constructor(baseControllerPath: string, httpService?: IHttpService) {
|
|
22
|
+
super(baseControllerPath, httpService);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Gets the roles assigned to a user
|
|
27
|
+
* @param id - The ID of the user
|
|
28
|
+
* @param {AbortSignal} [signal] - Optional cancellation signal
|
|
29
|
+
* @returns List of role names assigned to the user
|
|
30
|
+
*/
|
|
31
|
+
public async getUserRoles(id: TKey, signal?: AbortSignal): Promise<ApiResponseDto<string[], ReadMetadataDto>> {
|
|
32
|
+
try {
|
|
33
|
+
const url = await apiInitializationService.getApiUrl(this.baseControllerPath, 'GetUserRoles', encodeURIComponent(String(id)));
|
|
34
|
+
const res = await this.httpService.request(url, {
|
|
35
|
+
method: 'GET',
|
|
36
|
+
credentials: 'include',
|
|
37
|
+
signal,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (!res.ok) {
|
|
41
|
+
return fail<ApiSuccessResponseDto<string[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return ok<ApiSuccessResponseDto<string[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.error(err);
|
|
47
|
+
|
|
48
|
+
return fail<ApiSuccessResponseDto<string[], ReadMetadataDto>, ApiErrorResponseDto>({
|
|
49
|
+
error: {
|
|
50
|
+
code: ErrorCode.UnknownError,
|
|
51
|
+
message: 'Unknown error while fetching user roles',
|
|
52
|
+
metadata: {} as EmptyMetadataDto,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Gets the claims assigned to a user
|
|
60
|
+
* @param id - The ID of the user
|
|
61
|
+
* @param {AbortSignal} [signal] - Optional cancellation signal
|
|
62
|
+
* @returns List of claims assigned to the user
|
|
63
|
+
*/
|
|
64
|
+
public async getUserClaims(id: TKey, signal?: AbortSignal): Promise<ApiResponseDto<ClaimDto[], ReadMetadataDto>> {
|
|
65
|
+
try {
|
|
66
|
+
const url = await apiInitializationService.getApiUrl(this.baseControllerPath, 'GetUserClaims', encodeURIComponent(String(id)));
|
|
67
|
+
const res = await this.httpService.request(url, {
|
|
68
|
+
method: 'GET',
|
|
69
|
+
credentials: 'include',
|
|
70
|
+
signal,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (!res.ok) {
|
|
74
|
+
return fail<ApiSuccessResponseDto<ClaimDto[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return ok<ApiSuccessResponseDto<ClaimDto[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
78
|
+
} catch (err) {
|
|
79
|
+
console.error(err);
|
|
80
|
+
|
|
81
|
+
return fail<ApiSuccessResponseDto<ClaimDto[], ReadMetadataDto>, ApiErrorResponseDto>({
|
|
82
|
+
error: {
|
|
83
|
+
code: ErrorCode.UnknownError,
|
|
84
|
+
message: 'Unknown error while fetching user claims',
|
|
85
|
+
metadata: {} as EmptyMetadataDto,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Gets all available roles in the system
|
|
93
|
+
* @param {AbortSignal} [signal] - Optional cancellation signal
|
|
94
|
+
* @returns List of all role names
|
|
95
|
+
*/
|
|
96
|
+
public async getAllRoles(signal?: AbortSignal): Promise<ApiResponseDto<string[], ReadMetadataDto>> {
|
|
97
|
+
try {
|
|
98
|
+
const url = await apiInitializationService.getApiUrl(this.baseControllerPath, 'GetAllRoles');
|
|
99
|
+
const res = await this.httpService.request(url, {
|
|
100
|
+
method: 'GET',
|
|
101
|
+
credentials: 'include',
|
|
102
|
+
signal,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (!res.ok) {
|
|
106
|
+
return fail<ApiSuccessResponseDto<string[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return ok<ApiSuccessResponseDto<string[], ReadMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
110
|
+
} catch (err) {
|
|
111
|
+
console.error(err);
|
|
112
|
+
|
|
113
|
+
return fail<ApiSuccessResponseDto<string[], ReadMetadataDto>, ApiErrorResponseDto>({
|
|
114
|
+
error: {
|
|
115
|
+
code: ErrorCode.UnknownError,
|
|
116
|
+
message: 'Unknown error while fetching all roles',
|
|
117
|
+
metadata: {} as EmptyMetadataDto,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Changes the password for a user
|
|
125
|
+
* @param id - The ID of the user
|
|
126
|
+
* @param newPassword - The new password to set
|
|
127
|
+
* @param {AbortSignal} [signal] - Optional cancellation signal
|
|
128
|
+
* @returns Promise that resolves when the password is changed successfully
|
|
129
|
+
*/
|
|
130
|
+
public async changePassword(id: TKey, newPassword: string, signal?: AbortSignal): Promise<ApiResponseDto<undefined, EmptyMetadataDto>> {
|
|
131
|
+
try {
|
|
132
|
+
const url = await apiInitializationService.getApiUrl(this.baseControllerPath, 'ChangePassword', encodeURIComponent(String(id)));
|
|
133
|
+
const res = await this.httpService.request(url, {
|
|
134
|
+
method: 'POST',
|
|
135
|
+
headers: {
|
|
136
|
+
'Content-Type': 'application/json',
|
|
137
|
+
},
|
|
138
|
+
body: JSON.stringify(newPassword),
|
|
139
|
+
credentials: 'include',
|
|
140
|
+
signal,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
if (!res.ok) {
|
|
144
|
+
return fail<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return ok<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>(undefined);
|
|
148
|
+
} catch (err) {
|
|
149
|
+
console.error(err);
|
|
150
|
+
|
|
151
|
+
return fail<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>({
|
|
152
|
+
error: {
|
|
153
|
+
code: ErrorCode.UnknownError,
|
|
154
|
+
message: 'Unknown error while changing password',
|
|
155
|
+
metadata: {} as EmptyMetadataDto,
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { apiInitializationService, IHttpService } from '@services';
|
|
2
|
+
import { ApiErrorResponseDto, ApiResponseDto, ApiSuccessResponseDto, EmptyMetadataDto, ErrorCode, IPolicy, PolicyBase, UserDto, UserInfoDto } from '@data';
|
|
3
|
+
import { fail, ok } from '@utils';
|
|
4
|
+
|
|
5
|
+
export { UserDto, UserInfoDto };
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* AuthService class is responsible for managing user authentication operations.
|
|
9
|
+
* It supports login, logout, and checking the current user's details.
|
|
10
|
+
*
|
|
11
|
+
* @export
|
|
12
|
+
* @class AuthService
|
|
13
|
+
*/
|
|
14
|
+
export class AuthService<TKey, TUser extends UserDto<TKey> = UserDto<TKey>> {
|
|
15
|
+
/**
|
|
16
|
+
* Constructor
|
|
17
|
+
* @param baseControllerPath Base path to Auth API controller
|
|
18
|
+
* @param httpService HTTP service implementation to use for requests
|
|
19
|
+
*/
|
|
20
|
+
constructor(
|
|
21
|
+
protected readonly baseControllerPath: string = 'Auth',
|
|
22
|
+
httpService?: IHttpService,
|
|
23
|
+
) {
|
|
24
|
+
this._httpService = httpService;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// #region HTTP service
|
|
28
|
+
private readonly _httpService?: IHttpService = undefined;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Gets globally selected HTTP service
|
|
32
|
+
*/
|
|
33
|
+
protected get httpService(): IHttpService {
|
|
34
|
+
return this._httpService || apiInitializationService._getHttpService();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// #endregion
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Holds currently authenticated user's details
|
|
41
|
+
*/
|
|
42
|
+
public user: TUser | undefined = undefined;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Initializes the Authentication status by checking with the API if the current user is authenticated or not
|
|
46
|
+
*
|
|
47
|
+
* @async
|
|
48
|
+
* @return {Promise<void>} Resolves when initialization is complete.
|
|
49
|
+
*/
|
|
50
|
+
public async initialize(): Promise<void> {
|
|
51
|
+
// Check user's authentication status
|
|
52
|
+
await this.whoAmI();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Checks if user is authenticated and retrieves the current user's details if they are
|
|
57
|
+
*
|
|
58
|
+
* @return {Promise<UserInfoDto<TKey, TUser>>} Currently logged in user's details
|
|
59
|
+
* @throws {Error} Error if fetch fails
|
|
60
|
+
*/
|
|
61
|
+
public async whoAmI(): Promise<ApiResponseDto<UserInfoDto<TKey, TUser>, EmptyMetadataDto>> {
|
|
62
|
+
try {
|
|
63
|
+
const url = await apiInitializationService.getApiUrl(this.baseControllerPath, '/whoami');
|
|
64
|
+
const res = await this.httpService.request(url, { credentials: 'include' });
|
|
65
|
+
|
|
66
|
+
if (!res.ok) {
|
|
67
|
+
this.user = undefined;
|
|
68
|
+
return fail<ApiSuccessResponseDto<UserInfoDto<TKey, TUser>, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const response = ok<ApiSuccessResponseDto<UserInfoDto<TKey, TUser>, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
72
|
+
|
|
73
|
+
if (!response.ok) {
|
|
74
|
+
this.user = undefined;
|
|
75
|
+
return response;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
this.user = response.result.user;
|
|
79
|
+
|
|
80
|
+
return response;
|
|
81
|
+
} catch (err) {
|
|
82
|
+
console.error(err);
|
|
83
|
+
|
|
84
|
+
return fail<ApiSuccessResponseDto<UserInfoDto<TKey, TUser>, EmptyMetadataDto>, ApiErrorResponseDto>({
|
|
85
|
+
error: {
|
|
86
|
+
code: ErrorCode.UnknownError,
|
|
87
|
+
message: 'Failed checking authentication status',
|
|
88
|
+
metadata: {} as EmptyMetadataDto,
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Authenticates a user using their username and password, and retrieves user's details
|
|
96
|
+
*
|
|
97
|
+
* @param {string} username Login credentials: username
|
|
98
|
+
* @param {string} password Login credentials: password
|
|
99
|
+
* @return {Promise<TUser>} Currently logged in user's details
|
|
100
|
+
* @throws {Error} Error if fetch fails
|
|
101
|
+
*/
|
|
102
|
+
public async signIn(username: string, password: string): Promise<ApiResponseDto<TUser, EmptyMetadataDto>> {
|
|
103
|
+
try {
|
|
104
|
+
const url = await apiInitializationService.getApiUrl(this.baseControllerPath, '/signin');
|
|
105
|
+
const res = await this.httpService.request(url, {
|
|
106
|
+
method: 'POST',
|
|
107
|
+
headers: { 'Content-Type': 'application/json' },
|
|
108
|
+
body: JSON.stringify({ username, password }),
|
|
109
|
+
credentials: 'include',
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
if (!res.ok) {
|
|
113
|
+
return fail<ApiSuccessResponseDto<TUser, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// TODO: Handle tokens if not using cookies
|
|
117
|
+
|
|
118
|
+
const whoAmIRes = await this.whoAmI();
|
|
119
|
+
|
|
120
|
+
if (!whoAmIRes.ok) {
|
|
121
|
+
return whoAmIRes;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return ok<ApiSuccessResponseDto<TUser, EmptyMetadataDto>, ApiErrorResponseDto>({
|
|
125
|
+
result: whoAmIRes.result.user,
|
|
126
|
+
metadata: whoAmIRes.metadata,
|
|
127
|
+
});
|
|
128
|
+
} catch (err) {
|
|
129
|
+
console.error(err);
|
|
130
|
+
|
|
131
|
+
return fail<ApiSuccessResponseDto<TUser, EmptyMetadataDto>, ApiErrorResponseDto>({
|
|
132
|
+
error: {
|
|
133
|
+
code: ErrorCode.UnknownError,
|
|
134
|
+
message: 'Failed signing in',
|
|
135
|
+
metadata: {} as EmptyMetadataDto,
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Deauthenticates current user
|
|
143
|
+
*
|
|
144
|
+
* @return {Promise<void>}
|
|
145
|
+
* @throws {Error} Error if fetch fails
|
|
146
|
+
*/
|
|
147
|
+
public async signOut(): Promise<ApiResponseDto<undefined, EmptyMetadataDto>> {
|
|
148
|
+
try {
|
|
149
|
+
const url = await apiInitializationService.getApiUrl(this.baseControllerPath, '/signout');
|
|
150
|
+
const res = await this.httpService.request(url, { credentials: 'include' });
|
|
151
|
+
|
|
152
|
+
if (!res.ok) {
|
|
153
|
+
return fail<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
this.user = undefined;
|
|
157
|
+
return ok<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>(await res.json());
|
|
158
|
+
} catch (err) {
|
|
159
|
+
console.error(err);
|
|
160
|
+
|
|
161
|
+
return fail<ApiSuccessResponseDto<undefined, EmptyMetadataDto>, ApiErrorResponseDto>({
|
|
162
|
+
error: {
|
|
163
|
+
code: ErrorCode.UnknownError,
|
|
164
|
+
message: 'Failed signing out',
|
|
165
|
+
metadata: {} as EmptyMetadataDto,
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* If any API response returns an "Unauthenticated" response, call this method
|
|
173
|
+
* to update local authentication state to unauthenticated
|
|
174
|
+
*/
|
|
175
|
+
public handleNoAuthApiResponse(): void {
|
|
176
|
+
this.user = undefined;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// #region Client-side authorization helpers
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* True if a user is currently loaded (post whoAmI/signIn)
|
|
183
|
+
*/
|
|
184
|
+
public isAuthenticated(): boolean {
|
|
185
|
+
return !!this.user;
|
|
186
|
+
}
|
|
187
|
+
}
|