Skip to content

Commit 58947f0

Browse files
authored
Merge branch 'develop' into backport/pr-2161
2 parents cd84d80 + 941e774 commit 58947f0

File tree

56 files changed

+771
-307
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+771
-307
lines changed

.github/workflows/_build-image.yml

+6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ jobs:
3333
run: |
3434
DOCKER_IMAGE=ghcr.io/${{ steps.lowercase_repo_owner.outputs.lowercase }}/${{ inputs.image-name }}
3535
TAGS="${DOCKER_IMAGE}:${{ github.sha }},${DOCKER_IMAGE}:latest"
36+
37+
# Add dev-latest tag for develop branch
38+
if [ "${{ github.ref }}" = "refs/heads/develop" ]; then
39+
TAGS="${TAGS},${DOCKER_IMAGE}:latest-dev"
40+
fi
41+
3642
echo "tags=${TAGS}" >> $GITHUB_OUTPUT
3743
echo "created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
3844

.github/workflows/cd.yml

+7-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,15 @@ jobs:
1212
with:
1313
environment: test
1414
secrets: inherit
15+
concurrency:
16+
group: deploy-test
17+
cancel-in-progress: true
1518
deploy-prod:
1619
needs: deploy-test
1720
uses: ./.github/workflows/deploy.yml
1821
with:
1922
environment: prod
20-
secrets: inherit
23+
secrets: inherit
24+
concurrency:
25+
group: deploy-prod
26+
cancel-in-progress: true

.github/workflows/trivy-scan.yml

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Weekly Trivy DEV Image Scans
2+
3+
on:
4+
schedule:
5+
# Runs every week at 02:00 Sunday Morning.
6+
- cron: '0 2 * * 0'
7+
workflow_dispatch:
8+
9+
permissions:
10+
packages: read
11+
security-events: write
12+
13+
jobs:
14+
image-scan-api:
15+
name: Scan latest-dev API Image
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Run Trivy vulnerability scanner
19+
uses: aquasecurity/[email protected]
20+
env:
21+
TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2
22+
with:
23+
image-ref: 'ghcr.io/bcgov/alcs-api:latest-dev'
24+
format: 'sarif'
25+
output: 'trivy-results.sarif'
26+
ignore-unfixed: true
27+
vuln-type: 'os,library'
28+
severity: 'CRITICAL,HIGH'
29+
limit-severities-for-sarif: true
30+
31+
- name: Upload Trivy scan results to GitHub Security tab
32+
uses: github/codeql-action/upload-sarif@v3
33+
with:
34+
sarif_file: 'trivy-results.sarif'
35+
36+
image-scan-portal:
37+
name: Scan latest-dev Portal Image
38+
runs-on: ubuntu-latest
39+
steps:
40+
- name: Run Trivy vulnerability scanner
41+
uses: aquasecurity/[email protected]
42+
env:
43+
TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2
44+
with:
45+
image-ref: 'ghcr.io/bcgov/alcs-portal-frontend:latest-dev'
46+
format: 'sarif'
47+
output: 'trivy-results.sarif'
48+
ignore-unfixed: true
49+
vuln-type: 'os,library'
50+
severity: 'CRITICAL,HIGH'
51+
limit-severities-for-sarif: true
52+
53+
- name: Upload Trivy scan results to GitHub Security tab
54+
uses: github/codeql-action/upload-sarif@v3
55+
with:
56+
sarif_file: 'trivy-results.sarif'
57+
58+
image-scan-frontend:
59+
name: Scan latest-dev Frontend Image
60+
runs-on: ubuntu-latest
61+
steps:
62+
- name: Run Trivy vulnerability scanner
63+
uses: aquasecurity/[email protected]
64+
env:
65+
TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2
66+
with:
67+
image-ref: 'ghcr.io/bcgov/alcs-frontend:latest-dev'
68+
format: 'sarif'
69+
output: 'trivy-results.sarif'
70+
ignore-unfixed: true
71+
vuln-type: 'os,library'
72+
severity: 'CRITICAL,HIGH'
73+
limit-severities-for-sarif: true
74+
75+
- name: Upload Trivy scan results to GitHub Security tab
76+
uses: github/codeql-action/upload-sarif@v3
77+
with:
78+
sarif_file: 'trivy-results.sarif'

.github/workflows/zap-scan.yml

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: Weekly OWASP ZAP Baseline Scan on DEV Site
2+
3+
on:
4+
schedule:
5+
# Runs every week at 01:00 Sunday Morning.
6+
- cron: '0 1 * * 0'
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
issues: write
12+
13+
jobs:
14+
zap-scan-api:
15+
name: OWASP ZAP API Scan
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: API Scan
19+
uses: zaproxy/[email protected]
20+
with:
21+
target: 'https://alcs-dev-api.apps.silver.devops.gov.bc.ca/docs'
22+
issue_title: OWASP ZAP API Scan Results
23+
artifact_name: zap-api-scan-report
24+
25+
zap-scan-frontend:
26+
name: OWASP ZAP Frontend Scan
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Checkout Repository
30+
uses: actions/checkout@v4
31+
32+
- name: Frontend Scan
33+
uses: zaproxy/[email protected]
34+
with:
35+
target: "https://alcs-dev.apps.silver.devops.gov.bc.ca"
36+
issue_title: OWASP ZAP Frontend Scan Results
37+
rules_file_name: .zap/frontend.tsv
38+
artifact_name: zap-frontend-scan-report
39+
40+
zap-scan-portal:
41+
name: OWASP ZAP Portal Scan
42+
runs-on: ubuntu-latest
43+
steps:
44+
- name: Checkout Repository
45+
uses: actions/checkout@v4
46+
47+
- name: Portal Scan
48+
uses: zaproxy/[email protected]
49+
with:
50+
target: "https://alcs-dev-portal.apps.silver.devops.gov.bc.ca"
51+
issue_title: OWASP ZAP Portal Scan Results
52+
rules_file_name: .zap/portal.tsv
53+
artifact_name: zap-portal-scan-report

.github/workflows/zap_api.yml

-13
This file was deleted.

.github/workflows/zap_frontend.yml

-15
This file was deleted.

.zap/portal.tsv

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
10055 IGNORE (CSP: style-src unsafe-inline)
2+
10015 IGNORE (Incomplete or No Cache-control and Pragma HTTP Header Set)
3+
10110 IGNORE (Dangerous JS Functions)

alcs-frontend/src/app/features/application/decision/conditions/condition-card-dialog/condition-card-dialog.component.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ <h3>Create New Condition Card</h3>
3434
</ng-container>
3535

3636
<ng-container matColumnDef="index">
37-
<th mat-header-cell *matHeaderCellDef class="column-index">#</th>
38-
<td mat-cell *matCellDef="let element" class="column-index">{{ element.index }}</td>
37+
<th mat-header-cell *matHeaderCellDef class="column-index"></th>
38+
<td mat-cell *matCellDef="let element" class="column-index">{{ !isOrderNull ? alphaIndex(element.condition.order + 1) : '' }}</td>
3939
</ng-container>
4040

4141
<ng-container matColumnDef="type">

alcs-frontend/src/app/features/application/decision/conditions/condition-card-dialog/condition-card-dialog.component.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import {
66
ApplicationDecisionConditionDto,
77
CreateApplicationDecisionConditionCardDto,
88
} from '../../../../../services/application/decision/application-decision-v2/application-decision-v2.dto';
9-
import { ApplicationDecisionConditionDto as OriginalApplicationDecisionConditionDto } from '../../../../../services/application/decision/application-decision-v2/application-decision-v2.dto';
109
import { ApplicationDecisionConditionCardService } from '../../../../../services/application/decision/application-decision-v2/application-decision-condition/application-decision-condition-card/application-decision-condition-card.service';
1110
import { BOARD_TYPE_CODES, BoardService } from '../../../../../services/board/board.service';
1211
import { BoardDto, BoardStatusDto } from '../../../../../services/board/board.dto';
1312
import { ToastService } from '../../../../../services/toast/toast.service';
1413
import { CardType } from '../../../../../shared/card/card.component';
14+
import { countToString } from '../../../../../shared/utils/count-to-string';
1515

1616
@Component({
1717
selector: 'app-condition-card-dialog',
@@ -22,6 +22,7 @@ export class ConditionCardDialogComponent implements OnInit {
2222
displayColumns: string[] = ['select', 'index', 'type', 'description'];
2323
conditionBoard: BoardDto | undefined;
2424
selectedStatus = '';
25+
isOrderNull = false;
2526

2627
@ViewChild(MatSort) sort!: MatSort;
2728
dataSource: MatTableDataSource<{ condition: ApplicationDecisionConditionDto; index: number; selected: boolean }> =
@@ -37,6 +38,8 @@ export class ConditionCardDialogComponent implements OnInit {
3738
) {}
3839

3940
async ngOnInit() {
41+
const orderIndexes = this.data.conditions.map((c) => c.condition.order);
42+
this.isOrderNull = this.data.conditions.length > 1 && orderIndexes.every((val, i, arr) => val === arr[0] && arr[0] === 0);
4043
this.dataSource.data = this.data.conditions.map((item) => ({
4144
condition: item.condition,
4245
selected: false,
@@ -87,4 +90,8 @@ export class ConditionCardDialogComponent implements OnInit {
8790
this.dialogRef.close({ action: 'save', result: false });
8891
}
8992
}
93+
94+
alphaIndex(index: number) {
95+
return countToString(index);
96+
}
9097
}

alcs-frontend/src/app/features/application/decision/conditions/condition/condition.component.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ <h4 *ngIf="condition.type">{{ alphaIndex(index) }}. {{ condition.type.label }}</
1919

2020
<div *ngIf="showSecurityAmountField">
2121
<div class="subheading2">Security Amount</div>
22-
{{ condition.securityAmount }}
22+
{{ condition.securityAmount | number }}
2323
<app-no-data *ngIf="condition.securityAmount === null || condition.securityAmount === undefined"></app-no-data>
2424
</div>
2525

alcs-frontend/src/app/features/application/decision/conditions/condition/condition.component.ts

+23-15
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { countToString } from '../../../../../shared/utils/count-to-string';
2828
import { ApplicationDecisionV2Service } from '../../../../../services/application/decision/application-decision-v2/application-decision-v2.service';
2929
import { MatTableDataSource } from '@angular/material/table';
3030
import { MatSort } from '@angular/material/sort';
31+
import { ConfirmationDialogService } from '../../../../../shared/confirmation-dialog/confirmation-dialog.service';
3132

3233
type Condition = ApplicationDecisionConditionWithStatus & {
3334
componentLabelsStr?: string;
@@ -86,6 +87,7 @@ export class ConditionComponent implements OnInit, AfterViewInit {
8687
private conditionService: ApplicationDecisionConditionService,
8788
private conditionLotService: ApplicationDecisionComponentToConditionLotService,
8889
private decisionService: ApplicationDecisionV2Service,
90+
private confirmationDialogService: ConfirmationDialogService,
8991
) {}
9092

9193
async ngOnInit() {
@@ -314,21 +316,27 @@ export class ConditionComponent implements OnInit, AfterViewInit {
314316
}
315317

316318
async onDeleteDate(dateUuid: string) {
317-
const result = await this.conditionService.deleteDate(dateUuid);
318-
if (result) {
319-
const index = this.dates.findIndex((date) => date.uuid === dateUuid);
320-
321-
if (index !== -1) {
322-
this.dates.splice(index, 1);
323-
this.dataSource = new MatTableDataSource<ApplicationDecisionConditionDateWithIndex>(
324-
this.addIndex(this.sortDates(this.dates)),
325-
);
326-
const conditionNewStatus = await this.decisionService.getStatus(this.condition.uuid);
327-
this.condition.status = conditionNewStatus.status;
328-
this.statusChange.emit(this.condition.status);
329-
this.setPillLabel(this.condition.status);
330-
}
331-
}
319+
this.confirmationDialogService
320+
.openDialog({ body: 'Are you sure you want to delete this date?' })
321+
.subscribe(async (confirmed) => {
322+
if (confirmed) {
323+
const result = await this.conditionService.deleteDate(dateUuid);
324+
if (result) {
325+
const index = this.dates.findIndex((date) => date.uuid === dateUuid);
326+
327+
if (index !== -1) {
328+
this.dates.splice(index, 1);
329+
this.dataSource = new MatTableDataSource<ApplicationDecisionConditionDateWithIndex>(
330+
this.addIndex(this.sortDates(this.dates)),
331+
);
332+
const conditionNewStatus = await this.decisionService.getStatus(this.condition.uuid);
333+
this.condition.status = conditionNewStatus.status;
334+
this.statusChange.emit(this.condition.status);
335+
this.setPillLabel(this.condition.status);
336+
}
337+
}
338+
}
339+
});
332340
}
333341

334342
alphaIndex(index: number) {

0 commit comments

Comments
 (0)