diff --git a/CHANGELOG.md b/CHANGELOG.md index 09062a82cc..cf76663a5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Changed - Fixed helm repository path for backend & frontend (wrong prefix) - Refactored dashboard response +- Updated user manual - Autocomplete endpoints changed owner String type param to Owner for input validation and sql injection prevention - Autocomplete endpoints repository uses now criteria api rather than native query - Fixed several bugs in local filtering of the parts table diff --git a/docs/src/docs/arc42/cross-cutting/architecture-design-patterns.adoc b/docs/src/docs/arc42/cross-cutting/architecture-design-patterns.adoc index f46572ffe8..005076459d 100644 --- a/docs/src/docs/arc42/cross-cutting/architecture-design-patterns.adoc +++ b/docs/src/docs/arc42/cross-cutting/architecture-design-patterns.adoc @@ -1 +1,23 @@ = Architecture and design patterns + +== Module / Package structure + +* Main domain name + +** application +*** optional: subdomain name (in case of inheritance) → following same structure as main domain +*** mapper: holds the mapper of transforming domain models to response models +*** service: holds the interface for implementation in the domain package +*** rest: holds the controller for providing the api for the domain +** domain +*** optional: subdomain name (in case of inheritance) +*** model: holds the domain model +*** service: Implementation of the interface provided in the application package +*** repository: holds the interface for accessing the infrastructure package +** infrastructure +*** optional: subdomain name (in case of inheritance) +*** model: holds the technical entities +*** repository: holds the data access layer +**** e.g. JPARepository / Impl +** All models (Request / Response) used in the API should be saved in the tx-model project. +To be reusable for cucumber testing. diff --git a/docs/src/docs/arc42/cross-cutting/development-concepts.adoc b/docs/src/docs/arc42/cross-cutting/development-concepts.adoc index 4b136078a4..0b83a6164a 100644 --- a/docs/src/docs/arc42/cross-cutting/development-concepts.adoc +++ b/docs/src/docs/arc42/cross-cutting/development-concepts.adoc @@ -1 +1,140 @@ = Development concepts + +== Build, test, deploy + +TraceX is built using Maven and utilizes all the standard concepts of it. +Test execution is part of the build process and a minimum test coverage of 80% is enforced. + +The project setup contains a multi-module Maven build. +Commonly used classes (like the TraceX data model) should be extracted into a separate submodule and reused across the project. +However, this is not a "one-size-fits-all" solution. +New submodules should be created with care and require a review by the team. + +The Maven build alone only leads up to the JAR artifact of TraceX. +Do create Docker images, the Docker build feature is used. +This copies all resources into a builder image, builds the software and creates a final Docker image at the end that can then be deployed. + +Although the Docker image can be deployed in various ways, the standard solution are the provided Helm charts, which describe the required components as well. + +== Code generation + +There are two methods of code generation in TraceX: + +=== Lombok + +The Lombok library is heavily used to generate boilerplate code (like Constructors, Getters, Setters, Builders...). +This way, code can be written faster and this boilerplate code is excluded from test coverage, which keeps the test base lean. + +=== Swagger / OpenAPI + +The API uses OpenAPI annotations to describe the endpoints with all necessary information. +The annotations are then used to automatically generate the OpenAPI specification file, which can be viewed in the Swagger UI that is deployed with the application. + +The generated OpenAPI specification file is automatically compared to a fixed, stored version of it to avoid unwanted changes of the API. + +== Migration + +There currently is no data migration mechanism for TraceX. +In case the model of the persisted data (Jobs) changes, data is dropped and Jobs will need to be recreated. + +== Configurability + +TraceX utilizes the configuration mechanism provided by Spring Boot. +Configuration properties can be defined in the file `+src/main/resources/application.yml+` + +Other profiles should be avoided. +Instead, the configuration can be overwritten using Spring's external configuration mechanism (see https://docs.spring.io/spring-boot/docs/2.1.9.RELEASE/reference/html/boot-features-external-config.html). +The operator must have total control over the configuration of TraceX. + +== Java Style Guide + +We generally follow the link:https://google.github.io/styleguide/javaguide.html[Google Java Style Guide]. + +== API Guide + +We generally follow the https://swagger.io/specification/ + +== Unit and Functional Testing + +=== General Unit testing + +* Code coverage >= 80% +* Writing methods which provide a response to be better testable (avoid void if feasible). +* Naming of unit tests are as follows: + +image::https://raw.githubusercontent.com/eclipse-tractusx/traceability-foss/main/docs/src/images/arc42/user-guide/unit_test_naming.png[] + +* Use given/when/then pattern for unit test structuring. +E.g: + +image::https://raw.githubusercontent.com/eclipse-tractusx/traceability-foss/main/docs/src/images/arc42/user-guide/given_when_then_pattern.png[] + +=== Integration Testing + +Each public api should have at least two integration tests (positive / negative). +For integration testing, the `+tx-backend/src/main/resources/application-integration.yml+` is used. +Additionally, you need to have a local Docker environment running. +For this, we recommend link:https://rancherdesktop.io/[Rancher Dektop]. + +== Clean Code + +We follow the rules and behaviour of: https://clean-code-developer.com/. + +== Secure Coding standards + +As there is no other guideline of C-X, we fix any Vulnerabilities, Exposures, Flaw detected by one of our SAST, DAST, Pentesting tools which is higher than "Very Low". + +image::https://raw.githubusercontent.com/eclipse-tractusx/traceability-foss/main/docs/src/images/arc42/user-guide/vulnerability_level.png[] + +== TRACE-X Technical class responsibilities + +=== Controllers + +* Have only one dependency to a facade or a service or a validator annotation +* Have no own logic +* Including the swagger documentation annotations +* For each controller exists and Integration Test class +* Uses a static mapper to transform a domain model into the response model +* Returns a ResponseEntity + +=== Response object + +* Should be a public version of the domain object +* It is a result of the transformation which will be done in the facade +* Is not necessary if the domain object can be fully public +* Is not allowed to be implemented in a repository or a DAO + +=== Facade + +* Should have multiple service classes injected +* Can be implemented in a controller + +=== ServiceImpl + +* Responsible for retrieving data from storage +* Performs business logic +* Can be a http client +* Returns a jpaEntity → Domain Object +* Should only be implemented in a controller through an interface + +=== Repository + +* Represents an interface to the underlying repository implementation which uses then the spring repository + +=== Domain Object + +* Mapped from an entity or external data received +* Will be used as working model until it will be finally transformed to a response object or another domain which will be later on persisted + +=== Config Object + +* Should have the suffix Config at the end of the class +* Including beans which are automatically created by app startup + +=== Constructing objects + +* Using builder pattern +** Currently we are using the constructor to create objects in our application. +Main reason is probably to provide immutable objects. +** As the handling with big loaded constructors is not easy and error prune, I would recommend using the builder pattern to have a clear understanding about what we creating at the point of implementation. +* Using lombok for annotation processing diff --git a/docs/src/docs/arc42/cross-cutting/domain-concepts.adoc b/docs/src/docs/arc42/cross-cutting/domain-concepts.adoc index 5346ca14cf..909f6457f5 100644 --- a/docs/src/docs/arc42/cross-cutting/domain-concepts.adoc +++ b/docs/src/docs/arc42/cross-cutting/domain-concepts.adoc @@ -1 +1,5 @@ = Domain concepts + +== API Model + +For detailed information about the API model, please refer to the link:https://catenax-ng.github.io/tx-traceability-foss/docs/api-specification/api-specification.html[API specification]. diff --git a/docs/src/docs/arc42/cross-cutting/operational-concepts.adoc b/docs/src/docs/arc42/cross-cutting/operational-concepts.adoc index 1370260684..8e026b9c91 100644 --- a/docs/src/docs/arc42/cross-cutting/operational-concepts.adoc +++ b/docs/src/docs/arc42/cross-cutting/operational-concepts.adoc @@ -2,3 +2,35 @@ == Administration +=== Configuration + +TraceX can be configured using two mechanisms: + +==== application.yml + +If you build TraceX yourself, you can modify the application.yml config that is shipped with TraceX. +This file contains all possible config entries for the application. +Once the Docker image has been built, these values can only be overwritten using the Spring external config mechanism (see https://docs.spring.io/spring-boot/docs/2.1.9.RELEASE/reference/html/boot-features-external-config.html), e.g. by mounting a config file in the right path or using environment variables. + +==== Helm Chart + +The most relevant config properties are exposed as environment variables and must be set in the Helm chart so the application can run at all. +Check the TraceX Helm chart in Git for all available variables. + +== Scaling + +If the number of consumers raises, TraceX can be scaled up by using more resources for the Deployment Pod. +Those resources can be used to utilize more parallel threads to handle Job execution. + +== Clustering + +TraceX can run in clustered mode, as each running job is only present in one pod at a time. +Note: as soon as a resume feature is implemented, this needs to be addressed here. + +== Logging + +Logs are being written directly to stdout and are picked up by the cluster management. + +== Monitoring + +Currently, there is on monitoring supported in TraceX. diff --git a/docs/src/docs/arc42/cross-cutting/under-the-hood.adoc b/docs/src/docs/arc42/cross-cutting/under-the-hood.adoc index 1be8138bc2..e85bdac224 100644 --- a/docs/src/docs/arc42/cross-cutting/under-the-hood.adoc +++ b/docs/src/docs/arc42/cross-cutting/under-the-hood.adoc @@ -1,2 +1,43 @@ = "Under-the-hood" concepts +== Exception and error handling + +There are two types of potential errors in TraceX: + +=== Technical errors + +Technical errors occur when there is a problem with the application itself, its configuration or directly connected infrastructure, e.g. the Postgres database. +Usually, the application cannot solve these problems by itself and requires some external support (manual work or automated recovery mechanisms, e.g. Kubernetes liveness probes). + +These errors are printed mainly to the application log and are relevant for the healthchecks. + +=== Functional errors + +Functional errors occur when there is a problem with the data that is being processed or external systems are unavailable and data cannot be sent / fetched as required for the process. +While the system might not be able to provide the required function at that moment, it may work with a different dataset or as soon as the external systems recover. + +=== Rules for exception handling + +==== Throw or log, don't do both + +When catching an exception, either log the exception and handle the problem or rethrow it, so it can be handled at a higher level of the code. +By doing both, an exception might be written to the log multiple times, which can be confusing. + +==== Write own base exceptions for (internal) interfaces + +By defining a common (checked) base exception for an interface, the caller is forced to handle potential errors, but can keep the logic simple. +On the other hand, you still have the possibility to derive various, meaningful exceptions for different error cases, which can then be thrown via the API. + +Of course, when using only RuntimeExceptions, this is not necessary - but those can be overlooked quite easily, so be careful there. + +==== Central fallback exception handler + +There will always be some exception that cannot be handled inside of the code correctly - or it may just have been unforeseen. +A central fallback exception handler is required so all problems are visible in the log and the API always returns meaningful responses. +In some cases, this is as simple as a HTTP 500. + +==== Dont expose too much exception details over API + +It's good to inform the user, why their request did not work, but only if they can do something about it (HTTP 4xx). +So in case of application problems, you should not expose details of the problem to the caller. +This way, we avoid opening potential attack vectors. diff --git a/docs/src/images/arc42/user-guide/customer-parts-list-detailed-view.png b/docs/src/images/arc42/user-guide/customer-parts-list-detailed-view.png index 85ea8f185a..a895bc0628 100644 Binary files a/docs/src/images/arc42/user-guide/customer-parts-list-detailed-view.png and b/docs/src/images/arc42/user-guide/customer-parts-list-detailed-view.png differ diff --git a/docs/src/images/arc42/user-guide/given_when_then_pattern.png b/docs/src/images/arc42/user-guide/given_when_then_pattern.png new file mode 100644 index 0000000000..001a9c4ee1 Binary files /dev/null and b/docs/src/images/arc42/user-guide/given_when_then_pattern.png differ diff --git a/docs/src/images/arc42/user-guide/parts-list-view.png b/docs/src/images/arc42/user-guide/parts-list-view.png index 1cd833faa7..a9e7f27ece 100644 Binary files a/docs/src/images/arc42/user-guide/parts-list-view.png and b/docs/src/images/arc42/user-guide/parts-list-view.png differ diff --git a/docs/src/images/arc42/user-guide/supplier-parts-list-detailed-view.png b/docs/src/images/arc42/user-guide/supplier-parts-list-detailed-view.png index fc253e7ee5..f071b4a852 100644 Binary files a/docs/src/images/arc42/user-guide/supplier-parts-list-detailed-view.png and b/docs/src/images/arc42/user-guide/supplier-parts-list-detailed-view.png differ diff --git a/docs/src/images/arc42/user-guide/unit_test_naming.png b/docs/src/images/arc42/user-guide/unit_test_naming.png new file mode 100644 index 0000000000..43f8d2552a Binary files /dev/null and b/docs/src/images/arc42/user-guide/unit_test_naming.png differ diff --git a/docs/src/images/arc42/user-guide/vulnerability_level.png b/docs/src/images/arc42/user-guide/vulnerability_level.png new file mode 100644 index 0000000000..e872bdf871 Binary files /dev/null and b/docs/src/images/arc42/user-guide/vulnerability_level.png differ diff --git a/frontend/src/app/modules/page/other-parts/presentation/supplier-parts/supplier-parts.component.html b/frontend/src/app/modules/page/other-parts/presentation/supplier-parts/supplier-parts.component.html index a480d772f2..8775fea37a 100644 --- a/frontend/src/app/modules/page/other-parts/presentation/supplier-parts/supplier-parts.component.html +++ b/frontend/src/app/modules/page/other-parts/presentation/supplier-parts/supplier-parts.component.html @@ -75,6 +75,7 @@ (configChanged)="onAsPlannedTableConfigChange($event)" (clickSelectAction)="isInvestigationOpen$.next(true)" [multiSortList]="tableSupplierAsPlannedSortList" + [mainAspectType]="MainAspectType.AS_PLANNED" [multiSelectActive]="true" (filterActivated)="filterActivated(false, $event )" [tableType]="PartTableType.AS_PLANNED_SUPPLIER" diff --git a/frontend/src/app/modules/shared/components/multi-select-autocomplete/multi-select-autocomplete.component.spec.ts b/frontend/src/app/modules/shared/components/multi-select-autocomplete/multi-select-autocomplete.component.spec.ts index d91c1091cd..814288eb9e 100644 --- a/frontend/src/app/modules/shared/components/multi-select-autocomplete/multi-select-autocomplete.component.spec.ts +++ b/frontend/src/app/modules/shared/components/multi-select-autocomplete/multi-select-autocomplete.component.spec.ts @@ -1,16 +1,12 @@ -import {DatePipe} from '@angular/common'; -import {SemanticDataModel} from '@page/parts/model/parts.model'; -import { - MultiSelectAutocompleteComponent -} from '@shared/components/multi-select-autocomplete/multi-select-autocomplete.component'; -import { - FormatPartSemanticDataModelToCamelCasePipe -} from '@shared/pipes/format-part-semantic-data-model-to-camelcase.pipe'; -import {SharedModule} from '@shared/shared.module'; -import {renderComponent} from '@tests/test-render.utils'; -import {PartTableType} from "@shared/components/table/table.model"; -import {Owner} from "@page/parts/model/owner.enum"; -import {MatDatepickerInputEvent} from "@angular/material/datepicker"; +import { DatePipe } from '@angular/common'; +import { MatDatepickerInputEvent } from '@angular/material/datepicker'; +import { Owner } from '@page/parts/model/owner.enum'; +import { SemanticDataModel } from '@page/parts/model/parts.model'; +import { MultiSelectAutocompleteComponent } from '@shared/components/multi-select-autocomplete/multi-select-autocomplete.component'; +import { PartTableType } from '@shared/components/table/table.model'; +import { FormatPartSemanticDataModelToCamelCasePipe } from '@shared/pipes/format-part-semantic-data-model-to-camelcase.pipe'; +import { SharedModule } from '@shared/shared.module'; +import { renderComponent } from '@tests/test-render.utils'; describe('MultiSelectAutocompleteComponent', () => { const renderMultiSelectAutoCompleteComponent = (multiple = true) => { @@ -414,4 +410,21 @@ describe('MultiSelectAutocompleteComponent', () => { expect(eventMock.stopPropagation).not.toHaveBeenCalled(); }); + it('should not stop event propagation for space key', async() => { + // Arrange + const {fixture} = await renderMultiSelectAutoCompleteComponent(); + const {componentInstance} = fixture; + const eventMock = { + key: ' ', + ctrlKey: false, + stopPropagation: jasmine.createSpy('stopPropagation') + }; + + // Act + componentInstance.filterKeyCommands(eventMock); + + // Assert + expect(eventMock.stopPropagation).toHaveBeenCalled(); + }); + }); diff --git a/frontend/src/app/modules/shared/components/multi-select-autocomplete/multi-select-autocomplete.component.ts b/frontend/src/app/modules/shared/components/multi-select-autocomplete/multi-select-autocomplete.component.ts index 54c20647d0..b98f26d425 100644 --- a/frontend/src/app/modules/shared/components/multi-select-autocomplete/multi-select-autocomplete.component.ts +++ b/frontend/src/app/modules/shared/components/multi-select-autocomplete/multi-select-autocomplete.component.ts @@ -17,20 +17,18 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -import {DatePipe, registerLocaleData} from '@angular/common'; +import { DatePipe, registerLocaleData } from '@angular/common'; import localeDe from '@angular/common/locales/de'; import localeDeExtra from '@angular/common/locales/extra/de'; -import {Component, EventEmitter, Inject, Input, LOCALE_ID, OnChanges, Output, ViewChild} from '@angular/core'; -import {FormControl} from '@angular/forms'; -import {DateAdapter, MAT_DATE_LOCALE} from '@angular/material/core'; -import {MatDatepickerInputEvent} from '@angular/material/datepicker'; -import {Owner} from '@page/parts/model/owner.enum'; -import {PartTableType} from '@shared/components/table/table.model'; -import { - FormatPartSemanticDataModelToCamelCasePipe -} from '@shared/pipes/format-part-semantic-data-model-to-camelcase.pipe'; -import {PartsService} from '@shared/service/parts.service'; -import {firstValueFrom} from "rxjs"; +import { Component, EventEmitter, Inject, Input, LOCALE_ID, OnChanges, Output, ViewChild } from '@angular/core'; +import { FormControl } from '@angular/forms'; +import { DateAdapter, MAT_DATE_LOCALE } from '@angular/material/core'; +import { MatDatepickerInputEvent } from '@angular/material/datepicker'; +import { Owner } from '@page/parts/model/owner.enum'; +import { PartTableType } from '@shared/components/table/table.model'; +import { FormatPartSemanticDataModelToCamelCasePipe } from '@shared/pipes/format-part-semantic-data-model-to-camelcase.pipe'; +import { PartsService } from '@shared/service/parts.service'; +import { firstValueFrom } from 'rxjs'; @Component({ selector: 'app-multiselect', @@ -256,7 +254,6 @@ export class MultiSelectAutocompleteComponent implements OnChanges { // Returns plain strings array of filtered values getFilteredOptionsValues(): string[] { - console.log("getFiltered") const filteredValues = []; this.filteredOptions.forEach(option => { if(option.length) { @@ -322,7 +319,7 @@ export class MultiSelectAutocompleteComponent implements OnChanges { } filterKeyCommands(event: any) { - if (event.key === 'Enter' || (event.ctrlKey && event.key === 'a')) { + if (event.key === 'Enter' || (event.ctrlKey && event.key === 'a' || event.key === ' ')) { event.stopPropagation(); } } diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/domain/dashboard/service/DashboardServiceImpl.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/domain/dashboard/service/DashboardServiceImpl.java index d4dcc99be1..5bb9e85235 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/domain/dashboard/service/DashboardServiceImpl.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/domain/dashboard/service/DashboardServiceImpl.java @@ -37,6 +37,7 @@ @RequiredArgsConstructor public class DashboardServiceImpl implements DashboardService { + //TODO: rework this to use Service classes instead of using the Repository directly private final AssetAsBuiltRepository assetAsBuiltRepository; private final AssetAsPlannedRepository assetAsPlannedRepository; private final InvestigationRepository investigationsRepository;