diff --git a/vaadin-spring-tests/pom.xml b/vaadin-spring-tests/pom.xml index 3bd05397a..321fe86ae 100644 --- a/vaadin-spring-tests/pom.xml +++ b/vaadin-spring-tests/pom.xml @@ -56,6 +56,16 @@ vaadin-upload-flow ${vaadin.version} + + com.vaadin + vaadin-dialog-flow + ${vaadin.version} + + + com.vaadin + vaadin-notification-flow + ${vaadin.version} + com.vaadin vaadin-ordered-layout-flow diff --git a/vaadin-spring-tests/test-spring-security-flow/pom.xml b/vaadin-spring-tests/test-spring-security-flow/pom.xml index dda6c2210..720ab713e 100644 --- a/vaadin-spring-tests/test-spring-security-flow/pom.xml +++ b/vaadin-spring-tests/test-spring-security-flow/pom.xml @@ -36,10 +36,22 @@ com.vaadin vaadin-tabs-flow + + com.vaadin + vaadin-text-field-flow + com.vaadin vaadin-upload-flow + + com.vaadin + vaadin-dialog-flow + + + com.vaadin + vaadin-notification-flow + com.vaadin vaadin-login-flow diff --git a/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/SecurityUtils.java b/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/SecurityUtils.java index 3b4b7013f..30150f4de 100644 --- a/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/SecurityUtils.java +++ b/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/SecurityUtils.java @@ -22,6 +22,12 @@ public class SecurityUtils { public UserDetails getAuthenticatedUser() { SecurityContext context = SecurityContextHolder.getContext(); + if (context == null) { + throw new IllegalStateException("No security context available"); + } + if (context.getAuthentication() == null) { + return null; + } Object principal = context.getAuthentication().getPrincipal(); if (principal instanceof UserDetails) { UserDetails userDetails = (UserDetails) context.getAuthentication() diff --git a/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/service/BankService.java b/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/service/BankService.java index 634cc634e..9d1f7895a 100644 --- a/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/service/BankService.java +++ b/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/service/BankService.java @@ -19,13 +19,25 @@ public class BankService { private SecurityUtils utils; public void applyForLoan() { + applyForLoan(10000); + } + + public void applyForHugeLoan() { + applyForLoan(1000000); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + } + } + + private void applyForLoan(int amount) { String name = utils.getAuthenticatedUser().getUsername(); Optional acc = accountRepository.findByOwner(name); if (!acc.isPresent()) { return; } Account account = acc.get(); - account.setBalance(account.getBalance().add(new BigDecimal("10000"))); + account.setBalance(account.getBalance().add(new BigDecimal(amount))); accountRepository.save(account); } @@ -34,4 +46,5 @@ public BigDecimal getBalance() { return accountRepository.findByOwner(name).map(Account::getBalance) .orElse(null); } + } diff --git a/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/views/Broadcaster.java b/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/views/Broadcaster.java new file mode 100644 index 000000000..d94e8fc6c --- /dev/null +++ b/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/views/Broadcaster.java @@ -0,0 +1,46 @@ +/* + * Copyright 2000-2021 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.spring.flowsecurity.views; + +import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.ComponentEvent; +import com.vaadin.flow.component.ComponentEventBus; +import com.vaadin.flow.component.ComponentEventListener; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.shared.Registration; + +public class Broadcaster { + + private static Broadcaster instance = new Broadcaster(); + + private ComponentEventBus router = new ComponentEventBus(new Div()); + + public static class RefreshEvent extends ComponentEvent { + public RefreshEvent() { + super(new Div(), false); + } + } + + public static void sendMessage() { + instance.router.fireEvent(new RefreshEvent()); + } + + public static Registration addMessageListener( + ComponentEventListener listener) { + return instance.router.addListener(RefreshEvent.class, listener); + } + +} diff --git a/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/views/PrivateView.java b/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/views/PrivateView.java index a835d1927..3c5ed6f81 100644 --- a/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/views/PrivateView.java +++ b/vaadin-spring-tests/test-spring-security-flow/src/main/java/com/vaadin/flow/spring/flowsecurity/views/PrivateView.java @@ -3,23 +3,34 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.concurrent.Executor; import javax.annotation.security.PermitAll; +import com.vaadin.flow.component.AttachEvent; import com.vaadin.flow.component.ClickEvent; +import com.vaadin.flow.component.DetachEvent; +import com.vaadin.flow.component.Text; +import com.vaadin.flow.component.UI; import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.dialog.Dialog; import com.vaadin.flow.component.html.H4; import com.vaadin.flow.component.html.Image; import com.vaadin.flow.component.html.Paragraph; import com.vaadin.flow.component.html.Span; +import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.upload.Upload; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import com.vaadin.flow.server.StreamResource; +import com.vaadin.flow.shared.Registration; import com.vaadin.flow.spring.flowsecurity.SecurityUtils; import com.vaadin.flow.spring.flowsecurity.service.BankService; +import org.springframework.security.concurrent.DelegatingSecurityContextExecutor; + @Route(value = "private", layout = MainView.class) @PageTitle("Private View") @PermitAll @@ -28,15 +39,27 @@ public class PrivateView extends VerticalLayout { private BankService bankService; private Span balanceSpan = new Span(); private SecurityUtils utils; + private DelegatingSecurityContextExecutor executor; + private Registration registration; - public PrivateView(BankService bankService, SecurityUtils utils) { + public PrivateView(BankService bankService, SecurityUtils utils, + Executor executor) { this.bankService = bankService; this.utils = utils; + this.executor = new DelegatingSecurityContextExecutor(executor); updateBalanceText(); balanceSpan.setId("balanceText"); add(balanceSpan); add(new Button("Apply for a loan", this::applyForLoan)); + add(new Button("Apply for a huge loan", + this::applyForHugeLoanUsingExecutor)); + + Button globalRefresh = new Button("Send global refresh event", + e -> Broadcaster.sendMessage()); + globalRefresh.setId("sendRefresh"); + add(globalRefresh); + Upload upload = new Upload(); ByteArrayOutputStream imageStream = new ByteArrayOutputStream(); upload.setReceiver((filename, mimeType) -> { @@ -57,16 +80,57 @@ public PrivateView(BankService bankService, SecurityUtils utils) { add(upload); } + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + attachEvent.getUI().setPollInterval(1000); + registration = Broadcaster.addMessageListener(e -> { + getUI().get().access(() -> this.updateBalanceText()); + }); + } + + @Override + protected void onDetach(DetachEvent detachEvent) { + super.onDetach(detachEvent); + detachEvent.getUI().setPollInterval(-1); + registration.remove(); + } + private void updateBalanceText() { String name = utils.getAuthenticatedUserInfo().getFullName(); BigDecimal balance = bankService.getBalance(); this.balanceSpan.setText(String.format( "Hello %s, your bank account balance is $%s.", name, balance)); - } private void applyForLoan(ClickEvent