Skip to content

Commit f93b3e4

Browse files
Support "invalid" marker for applications (#362)
1 parent f5d01ed commit f93b3e4

File tree

20 files changed

+129
-73
lines changed

20 files changed

+129
-73
lines changed

src/main/java/com/hermesworld/ais/galapagos/applications/KnownApplication.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,8 @@
77
/**
88
* An application "known" to Galapagos. The list of all known applications form the basis from which the users can
99
* select "their" applications and create Application Owner Requests for. Known applications must be registered on a
10-
* Kafka Cluster using
11-
* {@link ApplicationsService#createApplicationCertificateAndPrivateKey(String, String, String, java.io.OutputStream)}
12-
* or
13-
* {@link ApplicationsService#createApplicationCertificateFromCsr(String, String, String, String, java.io.OutputStream)}
14-
* to retrieve a Client Certificate for this application.
10+
* Kafka Cluster using one of the registration methods in ApplicationService to retrieve Kafka Client Credentials for
11+
* this application.
1512
*
1613
* @author AlbrechtFlo
1714
*
@@ -60,4 +57,11 @@ public interface KnownApplication {
6057
*/
6158
List<BusinessCapability> getBusinessCapabilities();
6259

60+
/**
61+
* Returns a flag if the application should be treated as "valid". "Invalid" usually means that the system providing
62+
* the list of applications no longer would provide this application (e.g. EOL).
63+
*
64+
* @return A flag if the application should be treated as "valid" or not.
65+
*/
66+
boolean isValid();
6367
}

src/main/java/com/hermesworld/ais/galapagos/applications/controller/ApplicationsController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ private KnownApplicationDto toKnownAppDto(KnownApplication app) {
325325
}
326326
return new KnownApplicationDto(app.getId(), app.getName(),
327327
app.getInfoUrl() == null ? null : app.getInfoUrl().toString(), toCapDtos(app.getBusinessCapabilities()),
328-
new ArrayList<>(app.getAliases()));
328+
new ArrayList<>(app.getAliases()), app.isValid());
329329
}
330330

331331
private List<BusinessCapabilityDto> toCapDtos(List<? extends BusinessCapability> caps) {
Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
11
package com.hermesworld.ais.galapagos.applications.controller;
22

3-
import java.util.List;
4-
53
import lombok.Getter;
64

5+
import java.util.List;
6+
77
@Getter
88
public class KnownApplicationDto {
99

10-
private String id;
10+
private final String id;
11+
12+
private final String name;
1113

12-
private String name;
14+
private final String infoUrl;
1315

14-
private String infoUrl;
16+
private final List<BusinessCapabilityDto> businessCapabilities;
1517

16-
private List<BusinessCapabilityDto> businessCapabilities;
18+
private final List<String> aliases;
1719

18-
private List<String> aliases;
20+
private final boolean valid;
1921

2022
public KnownApplicationDto(String id, String name, String infoUrl, List<BusinessCapabilityDto> businessCapabilities,
21-
List<String> aliases) {
23+
List<String> aliases, boolean valid) {
2224
this.id = id;
2325
this.name = name;
2426
this.infoUrl = infoUrl;
2527
this.businessCapabilities = businessCapabilities;
2628
this.aliases = aliases;
29+
this.valid = valid;
2730
}
2831

2932
}

src/main/java/com/hermesworld/ais/galapagos/applications/impl/KnownApplicationImpl.java

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,42 @@
11
package com.hermesworld.ais.galapagos.applications.impl;
22

3-
import java.net.MalformedURLException;
4-
import java.net.URL;
5-
import java.util.Collections;
6-
import java.util.HashSet;
7-
import java.util.List;
8-
import java.util.Set;
9-
import java.util.stream.Collectors;
10-
113
import com.fasterxml.jackson.annotation.JsonCreator;
124
import com.fasterxml.jackson.annotation.JsonProperty;
135
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
146
import com.hermesworld.ais.galapagos.applications.BusinessCapability;
157
import com.hermesworld.ais.galapagos.applications.KnownApplication;
168
import com.hermesworld.ais.galapagos.util.HasKey;
9+
import lombok.Setter;
1710
import lombok.extern.slf4j.Slf4j;
11+
import org.springframework.lang.NonNull;
12+
13+
import java.net.MalformedURLException;
14+
import java.net.URL;
15+
import java.util.Collections;
16+
import java.util.HashSet;
17+
import java.util.List;
18+
import java.util.Set;
1819

1920
@JsonSerialize
2021
@Slf4j
2122
public class KnownApplicationImpl implements KnownApplication, HasKey, Comparable<KnownApplicationImpl> {
2223

23-
private String id;
24+
private final String id;
2425

25-
private String name;
26+
private final String name;
2627

28+
@Setter
2729
private List<String> aliases;
2830

31+
@Setter
2932
private String infoUrl;
3033

34+
@Setter
3135
private List<BusinessCapabilityImpl> businessCapabilities;
3236

37+
@Setter
38+
private boolean valid;
39+
3340
@JsonCreator
3441
public KnownApplicationImpl(@JsonProperty(value = "id", required = true) String id,
3542
@JsonProperty(value = "name", required = true) String name) {
@@ -41,6 +48,7 @@ public KnownApplicationImpl(@JsonProperty(value = "id", required = true) String
4148
}
4249
this.id = id;
4350
this.name = name;
51+
this.valid = true;
4452
}
4553

4654
@Override
@@ -63,10 +71,6 @@ public Set<String> getAliases() {
6371
return this.aliases == null ? Collections.emptySet() : new HashSet<>(this.aliases);
6472
}
6573

66-
public void setAliases(List<String> aliases) {
67-
this.aliases = aliases;
68-
}
69-
7074
@Override
7175
public URL getInfoUrl() {
7276
try {
@@ -78,25 +82,18 @@ public URL getInfoUrl() {
7882
}
7983
}
8084

81-
public void setInfoUrl(String infoUrl) {
82-
this.infoUrl = infoUrl;
83-
}
84-
8585
@Override
8686
public List<BusinessCapability> getBusinessCapabilities() {
87-
return this.businessCapabilities == null ? Collections.emptyList()
88-
: this.businessCapabilities.stream().collect(Collectors.toList());
87+
return this.businessCapabilities == null ? List.of() : List.copyOf(this.businessCapabilities);
8988
}
9089

91-
public void setBusinessCapabilities(List<BusinessCapabilityImpl> businessCapabilities) {
92-
this.businessCapabilities = businessCapabilities;
90+
@Override
91+
public boolean isValid() {
92+
return valid;
9393
}
9494

9595
@Override
96-
public int compareTo(KnownApplicationImpl o) {
97-
if (o == null) {
98-
return 1;
99-
}
96+
public int compareTo(@NonNull KnownApplicationImpl o) {
10097
return name.compareToIgnoreCase(o.name);
10198
}
10299

ui/src/app/layout/admin/admin.component.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ <h2 id="adminHeader" class="text-muted">{{ 'Administration' | translate }}</h2>
1515
id="table-complete-search"
1616
type="text"
1717
class="form-control"
18-
class="form-control"
1918
name="searchTerm"
2019
[(ngModel)]="state.searchTerm"
2120
(ngModelChange)="search()"
@@ -38,8 +37,9 @@ <h2 id="adminHeader" class="text-muted">{{ 'Administration' | translate }}</h2>
3837
<td>{{ niceTimestamp(request.createdAt) | async }}</td>
3938
<td><ngb-highlight [result]="request.userName" [term]="state.searchTerm"></ngb-highlight></td>
4039
<td>
41-
<a *ngIf="request.applicationInfoUrl" [href]="request.applicationInfoUrl" target="_blank"><ngb-highlight [result]="request.applicationName" [term]="state.searchTerm"></ngb-highlight></a>
42-
<ngb-highlight *ngIf="!request.applicationInfoUrl" [result]="request.applicationName" [term]="state.searchTerm"></ngb-highlight></td>
40+
<app-app-link *ngIf="request.appInfo" [app]="request.appInfo"
41+
[highlightText]="state.searchTerm"></app-app-link>
42+
<span *ngIf="!request.appInfo">{{ request.applicationId }}</span>
4343
<td><span [innerHTML]="request.comments"></span></td>
4444
<td style="min-width: 9em">
4545
<span

ui/src/app/layout/admin/admin.component.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { AuthService } from '../../shared/services/auth.service';
1818

1919
interface TranslatedApplicationOwnerRequest extends ApplicationOwnerRequest {
2020
applicationName?: string;
21-
applicationInfoUrl?: string;
21+
appInfo?: ApplicationInfo;
2222
}
2323

2424

@@ -37,8 +37,10 @@ const translateApps: (requests: ApplicationOwnerRequest[], apps: ApplicationInfo
3737
(requests, apps) => {
3838
const appMap = {};
3939
apps.forEach(app => appMap[app.id] = app);
40-
return requests.map(req => appMap[req.applicationId] ? { ...req, applicationName: appMap[req.applicationId].name || req.id,
41-
applicationInfoUrl: appMap[req.applicationId].infoUrl } : req);
40+
return requests.map(req => appMap[req.applicationId] ? {
41+
...req, applicationName: appMap[req.applicationId].name || req.applicationId,
42+
appInfo: appMap[req.applicationId]
43+
} : req);
4244
};
4345

4446
const entityMap = {

ui/src/app/layout/admin/admin.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import { FormsModule } from '@angular/forms';
88
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
99
import { SpinnerWhileModule } from 'src/app/shared/modules/spinner-while/spinner-while.module';
1010
import { AppSortableHeaderDirective } from './sortable.directive';
11+
import { AppLinkModule } from '../../shared/modules/app-link/app-link.module';
1112

1213
@NgModule({
13-
imports: [CommonModule, AdminRoutingModule, TranslateModule, FormsModule, NgbModule, SpinnerWhileModule],
14+
imports: [CommonModule, AdminRoutingModule, TranslateModule, FormsModule, NgbModule, SpinnerWhileModule, AppLinkModule],
1415
declarations: [AdminComponent, AppSortableHeaderDirective]
1516
})
1617
export class AdminModule {}

ui/src/app/layout/applications/applications.component.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ <h2 class="text-muted">{{ 'My Applications' | translate }}</h2>
3030
for="app_picker">{{ 'Select Application' | translate }}</label>
3131
<select class="form-select w-auto" name="appPicker" id="app_picker"
3232
[(ngModel)]="selectedApplicationForRequest">
33-
<option *ngFor="let app of availableApplications | async" [ngValue]="app">{{ app.name }}
33+
<option *ngFor="let app of availableApplications | async"
34+
[ngValue]="app">{{ app.valid ? '' : '(!) ' }}{{ app.name }}
3435
</option>
3536
</select>
3637
<span class="ms-3 text-muted" [style.display]="appListLoading ? 'inline' : 'none'"><i

ui/src/app/layout/applications/applications.component.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
ApplicationsService,
99
UserApplicationInfo
1010
} from '../../shared/services/applications.service';
11-
import { combineLatest, Observable, of } from 'rxjs';
11+
import { combineLatest, firstValueFrom, Observable, of } from 'rxjs';
1212
import { toNiceTimestamp } from '../../shared/util/time-util';
1313

1414
import { DateTime } from 'luxon';
@@ -22,6 +22,7 @@ import { HttpErrorResponse } from '@angular/common/http';
2222
import { ApiKeyService } from '../../shared/services/apikey.service';
2323
import { ApplicationCertificate, CertificateService } from '../../shared/services/certificates.service';
2424
import { copy } from '../../shared/util/copy-util';
25+
import { AuthService } from '../../shared/services/auth.service';
2526

2627
export interface UserApplicationInfoWithTopics extends UserApplicationInfo {
2728

@@ -104,24 +105,33 @@ export class ApplicationsComponent implements OnInit {
104105
private topicsService: TopicsService,
105106
private toasts: ToastService,
106107
private translateService: TranslateService,
107-
private certificateService: CertificateService
108+
private certificateService: CertificateService,
109+
private authService: AuthService
108110
) {
109111
}
110112

111-
ngOnInit() {
113+
async ngOnInit() {
112114
const now = DateTime.now();
113115

114116
this.currentLang = this.translateService.onLangChange.pipe(map(evt => evt.lang))
115117
.pipe(startWith(this.translateService.currentLang)).pipe(shareReplay(1));
116118

117119
const relevant = (req: ApplicationOwnerRequest) => DateTime.fromISO(req.lastStatusChangeAt)
118120
.minus(30, 'days') < now;
119-
this.availableApplications = this.applicationsService.getAvailableApplications(true).pipe(
120-
map(val => {
121+
122+
const admin = await firstValueFrom(this.authService.admin);
123+
124+
const filterInvalidApps = (ls: ApplicationInfo[]) => {
125+
return admin ? ls : ls.filter(app => app.valid);
126+
}
127+
128+
this.availableApplications = this.applicationsService.getAvailableApplications(true)
129+
.pipe(map(ls => filterInvalidApps(ls)))
130+
.pipe(map(val => {
121131
this.appListLoading = false;
122132
return val;
123133
})
124-
);
134+
);
125135
this.userRequests = this.applicationsService
126136
.getUserApplicationOwnerRequests()
127137
.pipe(map(requests => requests.filter(req => relevant(req))));
@@ -148,7 +158,7 @@ export class ApplicationsComponent implements OnInit {
148158

149159
this.currentEnv = this.environmentsService.getCurrentEnvironment();
150160

151-
this.applicationsService.refresh().then();
161+
await this.applicationsService.refresh();
152162
}
153163

154164
submitRequest(): Promise<any> {

ui/src/app/layout/topics/schemasection/schema-section.component.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ describe('SchemaSectionComponent', () => {
7373

7474
name: 'app1',
7575

76-
aliases: ['a1']
76+
aliases: ['a1'],
77+
78+
valid: true
7779
},
7880

7981
createdTimestamp: 'string',

0 commit comments

Comments
 (0)