Skip to content
This repository was archived by the owner on May 16, 2023. It is now read-only.

Commit 2412501

Browse files
f11hmschulte-tsi
andauthored
Feat: UI controls for Event TeleTan (#111)
* Add UI controls for Event TeleTan * changed log to persist type Co-authored-by: m.schulte <[email protected]>
1 parent 4d097c0 commit 2412501

File tree

8 files changed

+244
-71
lines changed

8 files changed

+244
-71
lines changed

src/main/java/app/coronawarn/verification/portal/SecurityConfig.java

+14-6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.concurrent.ConcurrentHashMap;
2727
import javax.servlet.http.HttpServletRequest;
2828
import javax.servlet.http.HttpServletResponse;
29+
import lombok.RequiredArgsConstructor;
2930
import lombok.extern.slf4j.Slf4j;
3031
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
3132
import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
@@ -57,20 +58,24 @@
5758
@Configuration
5859
@EnableWebSecurity
5960
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
60-
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
61+
@RequiredArgsConstructor
62+
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
6163

62-
private static final String ROLE_C19HOTLINE = "c19hotline";
64+
public static final String ROLE_C19HOTLINE = "c19hotline";
65+
public static final String ROLE_C19HOTLINE_EVENT = "c19hotline_event";
6366
private static final String ACTUATOR_ROUTE = "/actuator/**";
6467

6568
private static final String SAMESITE_LAX = "Lax";
6669
private static final String OAUTH_TOKEN_REQUEST_STATE_COOKIE = "OAuth_Token_Request_State";
6770
private static final String SESSION_COOKIE = "SESSION";
6871

69-
@Autowired
70-
private VerificationPortalHttpFilter verificationPortalHttpFilter;
72+
private final VerificationPortalHttpFilter verificationPortalHttpFilter;
7173

74+
/**
75+
* Configures Keycloak.
76+
*/
7277
@Autowired
73-
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
78+
public void configureGlobal(AuthenticationManagerBuilder auth) {
7479
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
7580
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
7681
auth.authenticationProvider(keycloakAuthenticationProvider);
@@ -97,10 +102,13 @@ protected void configure(HttpSecurity http) throws Exception {
97102
.authorizeRequests()
98103
.mvcMatchers(HttpMethod.GET, ACTUATOR_ROUTE).permitAll()
99104
.antMatchers(VerificationPortalController.ROUTE_TELETAN)
100-
.hasRole(ROLE_C19HOTLINE)
105+
.hasAnyRole(ROLE_C19HOTLINE, ROLE_C19HOTLINE_EVENT)
101106
.anyRequest().authenticated();
102107
}
103108

109+
/**
110+
* Configures Cookie Serializer.
111+
*/
104112
@Bean
105113
public CookieSerializer defaultCookieSerializer() {
106114
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();

src/main/java/app/coronawarn/verification/portal/client/VerificationServerClient.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
configuration = VerificationServerClientConfig.class)
3232
public interface VerificationServerClient {
3333

34-
public static final String HEADER_NAME_AUTHORIZATION = "Authorization";
34+
String HEADER_NAME_AUTHORIZATION = "Authorization";
35+
String HEADER_NAME_TELETAN_TYPE = "X-CWA-TELETAN-TYPE";
3536

3637
/**
3738
* Call the verification service to get teletan from token.
@@ -43,6 +44,8 @@ public interface VerificationServerClient {
4344
produces = MediaType.APPLICATION_JSON_VALUE,
4445
consumes = MediaType.APPLICATION_JSON_VALUE
4546
)
46-
TeleTan createTeleTan(@RequestHeader(HEADER_NAME_AUTHORIZATION) String token);
47+
TeleTan createTeleTan(
48+
@RequestHeader(HEADER_NAME_AUTHORIZATION) String token,
49+
@RequestHeader(HEADER_NAME_TELETAN_TYPE) String teleTanType);
4750

4851
}

src/main/java/app/coronawarn/verification/portal/controller/VerificationPortalController.java

+35-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
package app.coronawarn.verification.portal.controller;
2323

24+
import app.coronawarn.verification.portal.SecurityConfig;
2425
import app.coronawarn.verification.portal.client.TeleTan;
2526
import app.coronawarn.verification.portal.service.TeleTanService;
2627
import feign.FeignException;
@@ -38,6 +39,7 @@
3839
import org.springframework.stereotype.Controller;
3940
import org.springframework.ui.Model;
4041
import org.springframework.web.bind.annotation.GetMapping;
42+
import org.springframework.web.bind.annotation.ModelAttribute;
4143
import org.springframework.web.bind.annotation.PostMapping;
4244
import org.springframework.web.bind.annotation.RequestMapping;
4345
import org.springframework.web.bind.annotation.RequestMethod;
@@ -92,14 +94,19 @@ public class VerificationPortalController {
9294
private static final String ATTR_TELETAN = "teleTAN";
9395
private static final String ATTR_USER = "userName";
9496
private static final String ATTR_PW_RESET_URL = "pwResetUrl";
97+
private static final String ATTR_ROLE_TEST = "role_test";
98+
private static final String ATTR_ROLE_EVENT = "role_event";
99+
100+
private static final String TELETAN_TYPE_TEST = "TEST";
101+
private static final String TELETAN_TYPE_EVENT = "EVENT";
95102

96103
/**
97104
* The Keycloak password reset URL.
98105
*/
99106
@Value("${keycloak-pw.reset-url}")
100107
private String pwResetUrl;
101108

102-
private static final Map<String, LocalDateTime> rateLimitingUserMap = new ConcurrentHashMap<String, LocalDateTime>();
109+
private static final Map<String, LocalDateTime> rateLimitingUserMap = new ConcurrentHashMap<>();
103110

104111
@Value("${rateLimiting.enabled}")
105112
private boolean rateLimitingEnabled;
@@ -142,6 +149,7 @@ public String start(HttpServletRequest request, Model model) {
142149
if (model != null) {
143150
model.addAttribute(ATTR_USER, user.replace("<", "").replace(">", ""));
144151
model.addAttribute(ATTR_PW_RESET_URL, pwResetUrl);
152+
setRoleDependentAttributes(model, principal);
145153
}
146154

147155
HttpSession session = request.getSession();
@@ -161,12 +169,19 @@ public String start(HttpServletRequest request, Model model) {
161169
* @return the name of the Thymeleaf template to be used for the HTML page
162170
*/
163171
@PostMapping(value = ROUTE_TELETAN)
164-
public String teletan(HttpServletRequest request, Model model) {
172+
public String teletan(
173+
HttpServletRequest request,
174+
Model model,
175+
@ModelAttribute("EVENT") String eventButton,
176+
@ModelAttribute("TEST") String testButton) {
177+
165178
TeleTan teleTan = new TeleTan("123456789");
166179
KeycloakAuthenticationToken principal = (KeycloakAuthenticationToken) request
167180
.getUserPrincipal();
168181
String user = ((KeycloakPrincipal) principal.getPrincipal()).getName();
169182

183+
String teleTanType = "";
184+
170185
// initially the TEMPLATE_INDEX is used (without showing the teleTAN)
171186
String template = TEMPLATE_START;
172187
HttpSession session = request.getSession();
@@ -180,7 +195,13 @@ public String teletan(HttpServletRequest request, Model model) {
180195
}
181196

182197
try {
183-
teleTan = teleTanService.createTeleTan(token);
198+
if (!eventButton.isEmpty()) {
199+
teleTan = teleTanService.createTeleTan(token, TELETAN_TYPE_EVENT);
200+
teleTanType = TELETAN_TYPE_EVENT;
201+
} else if (!testButton.isEmpty()) {
202+
teleTan = teleTanService.createTeleTan(token, TELETAN_TYPE_TEST);
203+
teleTanType = TELETAN_TYPE_TEST;
204+
}
184205
} catch (FeignException e) {
185206
if (e.status() == HttpStatus.TOO_MANY_REQUESTS.value()) {
186207
throw new ServerRateLimitationException("Too many requests. Please wait a moment.");
@@ -189,7 +210,7 @@ public String teletan(HttpServletRequest request, Model model) {
189210
}
190211
}
191212

192-
log.info("TeleTan successfully retrieved for user: {}", user);
213+
log.info("TeleTan Type {} successfully retrieved for user: {}", teleTanType,user);
193214
template = TEMPLATE_TELETAN;
194215
}
195216
session.setAttribute(SESSION_ATTR_TELETAN, "TeleTAN");
@@ -198,6 +219,7 @@ public String teletan(HttpServletRequest request, Model model) {
198219
model.addAttribute(ATTR_TELETAN, teleTan.getValue().replace("<", "").replace(">", ""));
199220
model.addAttribute(ATTR_USER, user.replace("<", "").replace(">", ""));
200221
model.addAttribute(ATTR_PW_RESET_URL, pwResetUrl);
222+
setRoleDependentAttributes(model, principal);
201223
}
202224
return template;
203225
}
@@ -230,4 +252,13 @@ public String logout(HttpServletRequest request) {
230252
}
231253
return "redirect:" + TEMPLATE_START;
232254
}
255+
256+
private void setRoleDependentAttributes(Model model, KeycloakAuthenticationToken token) {
257+
model.addAttribute(ATTR_ROLE_TEST, token.getAuthorities().stream()
258+
.anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals("ROLE_" + SecurityConfig.ROLE_C19HOTLINE)));
259+
260+
model.addAttribute(ATTR_ROLE_EVENT, token.getAuthorities().stream()
261+
.anyMatch(grantedAuthority ->
262+
grantedAuthority.getAuthority().equals("ROLE_" + SecurityConfig.ROLE_C19HOTLINE_EVENT)));
263+
}
233264
}

src/main/java/app/coronawarn/verification/portal/service/TeleTanService.java

+4-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import app.coronawarn.verification.portal.client.TeleTan;
44
import app.coronawarn.verification.portal.client.VerificationServerClient;
5-
import lombok.NonNull;
65
import lombok.RequiredArgsConstructor;
76
import lombok.extern.slf4j.Slf4j;
87
import org.springframework.stereotype.Service;
@@ -11,14 +10,13 @@
1110
@Service
1211
@RequiredArgsConstructor
1312
public class TeleTanService {
14-
15-
@NonNull
16-
private VerificationServerClient verificationServerClient;
13+
14+
private final VerificationServerClient verificationServerClient;
1715

1816
public static final String TOKEN_PREFIX = "Bearer ";
1917

20-
public TeleTan createTeleTan(String token) {
21-
return verificationServerClient.createTeleTan(TOKEN_PREFIX + token);
18+
public TeleTan createTeleTan(String token, String teleTanType) {
19+
return verificationServerClient.createTeleTan(TOKEN_PREFIX + token, teleTanType);
2220
}
2321

2422
}

src/main/resources/templates/start.html

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@
3030
<!-- BEGIN page specific content -->
3131
<div class="text-big" style="top: 210px;">TeleTAN erzeugen</div>
3232
<div class="text" style="top: 300px;">Erzeugen Sie eine neue TeleTAN für einen Patienten.</div>
33+
<div th:if="${!role_test && !role_event}" class="text-error" style="top: 360px">Sie besitzen nicht die benötigten Berechtigungen zum Erzeugen von TeleTAN.</div>
3334
<form action="/cwa/teletan" method="post">
34-
<input class="button" style="top: 360px;" type="submit" value="Eine TeleTAN erzeugen"/>
35+
<input th:if="${role_test}" class="button" style="top: 360px;" type="submit" th:name="${'TEST'}" value="Eine TeleTAN (positiver PCR Test) erzeugen" />
36+
<input th:if="${role_event}" class="button" style="top: 420px;" type="submit" th:name="${'EVENT'}" value="Eine TeleTAN (Positiver bei Event) erzeugen" />
3537
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
3638
</form>
3739

src/main/resources/templates/teletan.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
<div class="text" style="top: 300px;">Die neue TeleTAN lautet</div>
3535
<div class="text-bold" style="top: 340px;" th:text="${teleTAN}"/>
3636
<form action="/cwa/teletan" method="post">
37-
<input class="button" style="top: 410px;" type="submit" value="Eine weitere TeleTAN erzeugen"/>
37+
<input th:if="${role_test}" class="button" style="top: 410px;" type="submit" th:name="${'TEST'}" value="Eine weitere TeleTAN (positiver PCR Test) erzeugen" />
38+
<input th:if="${role_event}" class="button" style="top: 490px;" type="submit" th:name="${'EVENT'}" value="Eine weitere TeleTAN (Positiver bei Event) erzeugen" />
3839
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
3940
</form>
4041

0 commit comments

Comments
 (0)