Wiring in image ownership

Spring WebFlux's ServerWebExchange comes prepared for security by providing a getPrincipal() API that returns Mono<Principal>. While the default version, straight out of Spring Framework, supplies Mono.empty(), Spring Security automatically hooks in a filter to supply a real value via WebSessionSecurityContextRepository.

With Spring Security and Spring Session hooked into all our web calls, we can leverage this information every time a new image is uploaded.

First of all, we can adjust our Image domain object as follows:

    @Data 
    @AllArgsConstructor 
    public class Image { 
 
      @Id private String id; 
      private String name; 
      private String owner; 
    } 

This last code is the same POJO that we've used throughout this book with one change:

  • It now has a String owner property. This lets us associate an image with whoever uploaded it (which we'll see shortly).

Spring Security makes it possible to inject any Spring WebFlux controller with an authentication object as follows:

    @PostMapping(value = BASE_PATH) 
    public Mono<String> createFile( 
      @RequestPart("file") Flux<FilePart> files, 
       @AuthenticationPrincipal Principal principal) { 
         return imageService.createImage(files, principal) 
          .then(Mono.just("redirect:/")); 
    } 

This change to our image service's UploadController.createFile, as shown in the preceding code, can be described as follows:

  • Using Spring Security's @AuthenticationPrincipal annotation, the second parameter allows us to find out the security context of the caller.
  • The actual type can be flexible, whether we want a Java Principal, a Spring Security subinterface Authentication, or a concrete instance (UsernamePasswordAuthenticationToken by default). This parameter can also be wrapped as a Mono<T> of this type.
  • For simplicity, we grab it unwrapped and pass it along to ImageService as a new argument.

So, let's go update ImageService.createImage(), where Image objects are actually created:

    public Mono<Void> createImage(Flux<FilePart> files, 
     Principal auth) { 
       return files 
        .log("createImage-files") 
        .flatMap(file -> { 
          Mono<Image> saveDatabaseImage = imageRepository.save( 
            new Image( 
              UUID.randomUUID().toString(), 
               file.filename(), 
               auth.getName())) 
               .log("createImage-save"); 
 
          ...the rest that hasn't changed... 
        }
}

The parts that have changed in the preceding code can be described as follows:

  • This method now accepts a second argument, Principal. This is a Java standard token.
  • The code where we actually create a new Image is populated in the same as done earlier for the first two fields, with a random ID and the name of the file.
  • The owner field is now populated with auth.getName(), supplied to us by Spring Security's context-enabling advice.

The last link in the chain of ownership is to display it on the page. To do this, we can update the model fed to that HTML fragment in HomeController, as follows:

    model.addAttribute("images", 
     imageService 
      .findAllImages() 
      .map(image -> new HashMap<String, Object>() {{ 
        put("id", image.getId()); 
        put("name", image.getName()); 
        put("owner", image.getOwner()); 
        put("comments", 
         commentHelper.getComments(image, 
            webSession.getId())); 
      }}) 
    ); 

This preceding fragment from public String index() has been updated to include the new owner attribute.

With that added to the template's model, we can display it by adding the following bit of HTML to our Thymeleaf template, like this:

    <td th:text="${image.owner}" /> 

This attribute can now be seen when we log in and check things out, as seen in this screenshot:

In the preceding screenshot, we see one image loaded by greg and one image loaded by phil.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.27.72