AbstractView.java

  1. /*
  2.  * Copyright 2010-2025 James Pether Sörling
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *   http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  *
  16.  *  $Id$
  17.  *  $HeadURL$
  18. */
  19. package com.hack23.cia.web.impl.ui.application.views.common;

  20. import java.util.Map;

  21. import javax.annotation.PostConstruct;

  22. import org.jsoup.Jsoup;
  23. import org.jsoup.safety.Safelist;
  24. import org.slf4j.Logger;
  25. import org.slf4j.LoggerFactory;
  26. import org.springframework.beans.factory.annotation.Autowired;
  27. import org.springframework.beans.factory.annotation.Value;
  28. import org.springframework.security.access.AccessDeniedException;
  29. import org.springframework.web.context.request.RequestContextHolder;

  30. import com.hack23.cia.service.api.action.application.LogoutRequest;
  31. import com.hack23.cia.web.impl.ui.application.action.PageActionEventHelper;
  32. import com.hack23.cia.web.impl.ui.application.util.UserContextUtil;
  33. import com.hack23.cia.web.impl.ui.application.views.common.labelfactory.LabelFactory;
  34. import com.hack23.cia.web.impl.ui.application.views.common.menufactory.api.ApplicationMenuItemFactory;
  35. import com.hack23.cia.web.impl.ui.application.views.common.pagelinks.api.PageLinkFactory;
  36. import com.hack23.cia.web.impl.ui.application.views.common.pagemode.PageModeContentFactory;
  37. import com.hack23.cia.web.impl.ui.application.views.common.sizing.ContentRatio;
  38. import com.hack23.cia.web.impl.ui.application.views.pageclicklistener.LogoutClickListener;
  39. import com.vaadin.icons.VaadinIcons;
  40. import com.vaadin.navigator.View;
  41. import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
  42. import com.vaadin.server.ExternalResource;
  43. import com.vaadin.server.ThemeResource;
  44. import com.vaadin.ui.Alignment;
  45. import com.vaadin.ui.Button;
  46. import com.vaadin.ui.HorizontalLayout;
  47. import com.vaadin.ui.Image;
  48. import com.vaadin.ui.Label;
  49. import com.vaadin.ui.Link;
  50. import com.vaadin.ui.MenuBar;
  51. import com.vaadin.ui.Panel;
  52. import com.vaadin.ui.VerticalLayout;

  53. /**
  54.  * The Class AbstractView.
  55.  */
  56. public abstract class AbstractView extends Panel implements View {

  57.     /** The Constant LOGGER. */
  58.     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractView.class);

  59.     /** The Constant LOGOUT. */
  60.     private static final String LOGOUT = "Logout";

  61.     /** The Constant ROLE_ADMIN. */
  62.     private static final String ROLE_ADMIN = "ROLE_ADMIN";

  63.     /** The Constant ROLE_USER. */
  64.     private static final String ROLE_USER = "ROLE_USER";

  65.     /** The Constant serialVersionUID. */
  66.     private static final long serialVersionUID = 1L;

  67.     /** The barmenu. */
  68.     private final MenuBar barmenu = new MenuBar();

  69.     /** The menu item factory. */
  70.     @Autowired
  71.     private transient ApplicationMenuItemFactory menuItemFactory;

  72.     /** The page action event helper. */
  73.     @Autowired
  74.     protected transient PageActionEventHelper pageActionEventHelper;

  75.     /** The page link factory. */
  76.     @Autowired
  77.     protected transient PageLinkFactory pageLinkFactory;

  78.     /** The page mode content factory map. */
  79.     private transient Map<String, PageModeContentFactory> pageModeContentFactoryMap;

  80.     /** The application name. */
  81.     @Value("${application.name}")
  82.     protected String applicationName;

  83.     /** The application version. */
  84.     @Value("${application.version}")
  85.     protected String applicationVersion;

  86.     /** The application url. */
  87.     @Value("${application.url}")
  88.     protected String applicationUrl;

  89.     /** The page name. */
  90.     private final String pageName;

  91.     /** The panel. */
  92.     private Panel panel;

  93.     /** The top header right panel. */
  94.     private final HorizontalLayout topHeaderRightPanel = new HorizontalLayout();


  95.     /**
  96.      * Instantiates a new abstract view.
  97.      *
  98.      * @param pageModeContentFactoryMap the page mode content factory map
  99.      * @param pageName the page name
  100.      */
  101.     protected AbstractView(final Map<String, PageModeContentFactory> pageModeContentFactoryMap, final String pageName) {
  102.         super();
  103.         this.pageModeContentFactoryMap = pageModeContentFactoryMap;
  104.         this.pageName = pageName;
  105.     }

  106.     /**
  107.      * Adds the logo to header.
  108.      *
  109.      * @param topHeader
  110.      *            the top header
  111.      */
  112.     private static void addLogoToHeader(final HorizontalLayout topHeader) {
  113.         final ThemeResource ciaLogoResource = new ThemeResource("cia-logo.png");
  114.         final Image ciaLogoImage = new Image(null,ciaLogoResource);
  115.         topHeader.addComponent(ciaLogoImage);
  116.         ciaLogoImage.setWidth("60px");
  117.         ciaLogoImage.setHeight("60px");
  118.         topHeader.setComponentAlignment(ciaLogoImage, Alignment.MIDDLE_LEFT);
  119.         topHeader.setExpandRatio(ciaLogoImage, ContentRatio.SMALL);
  120.     }


  121.     /**
  122.      * Creates the full size vertical layout.
  123.      *
  124.      * @return the vertical layout
  125.      */
  126.     private static VerticalLayout createFullSizeVerticalLayout() {
  127.         return createFullSizeVerticalLayout(true,true);
  128.     }

  129.     /**
  130.      * Creates the full size vertical layout.
  131.      *
  132.      * @param margin
  133.      *            the margin
  134.      * @param spacing
  135.      *            the spacing
  136.      * @return the vertical layout
  137.      */
  138.     private static VerticalLayout createFullSizeVerticalLayout(final boolean margin, final boolean spacing) {
  139.         final VerticalLayout layout = new VerticalLayout();
  140.         layout.setMargin(margin);
  141.         layout.setSpacing(spacing);
  142.         layout.setWidth(100, Unit.PERCENTAGE);
  143.         layout.setHeight(100, Unit.PERCENTAGE);
  144.         return layout;
  145.     }

  146.     /**
  147.      * Creates the top title header.
  148.      *
  149.      * @param topHeader
  150.      *            the top header
  151.      */
  152.     private static void createTopTitleHeader(final HorizontalLayout topHeader) {
  153.         final HorizontalLayout topTitleHeadertPanel = new HorizontalLayout();


  154.         final Label titleLabel = new Label("Citizen Intelligence Agency");
  155.         titleLabel.setStyleName("Header");
  156.         topTitleHeadertPanel.addComponent(titleLabel);
  157.         topTitleHeadertPanel.setComponentAlignment(titleLabel, Alignment.MIDDLE_LEFT);

  158.         final Label sloganLabel = new Label("// Tracking politicians like bugs!");
  159.         sloganLabel.setStyleName("HeaderSlogan");
  160.         topTitleHeadertPanel.addComponent(sloganLabel);
  161.         topTitleHeadertPanel.setComponentAlignment(sloganLabel, Alignment.MIDDLE_RIGHT);

  162.         topHeader.addComponent(topTitleHeadertPanel);
  163.         topHeader.setComponentAlignment(topTitleHeadertPanel, Alignment.MIDDLE_LEFT);
  164.         topHeader.setExpandRatio(topTitleHeadertPanel, ContentRatio.GRID);
  165.     }

  166.     /**
  167.      * Creates the basic layout with panel and footer.
  168.      *
  169.      * @param panelName
  170.      *            the panel name
  171.      */
  172.     protected final void createBasicLayoutWithPanelAndFooter(final String panelName) {
  173.         final VerticalLayout layout = createFullSizeVerticalLayout();
  174.         final VerticalLayout pageModeContent = createFullSizeVerticalLayout(false,false);
  175.         layout.addComponent(pageModeContent);

  176.         final HorizontalLayout topHeader = new HorizontalLayout();

  177.         addLogoToHeader(topHeader);
  178.         createTopTitleHeader(topHeader);

  179.         topHeaderRightPanel.removeAllComponents();
  180.         topHeader.addComponent(topHeaderRightPanel);
  181.         topHeader.setComponentAlignment(topHeaderRightPanel, Alignment.MIDDLE_RIGHT);
  182.         topHeader.setExpandRatio(topHeaderRightPanel, ContentRatio.LARGE);

  183.         createTopHeaderActionsForUserContext();

  184.         topHeaderRightPanel.setWidth("100%");
  185.         topHeaderRightPanel.setHeight("50px");

  186.         topHeader.setWidth("100%");
  187.         topHeader.setHeight("50px");

  188.         pageModeContent.addComponent(topHeader);
  189.         pageModeContent.setComponentAlignment(topHeader, Alignment.TOP_CENTER);

  190.         pageModeContent.addComponent(getBarmenu());
  191.         pageModeContent.setComponentAlignment(getBarmenu(), Alignment.TOP_CENTER);

  192.         panel = new Panel(panelName);
  193.         panel.addStyleName("v-panel-page-panel");

  194.         panel.setSizeFull();
  195.         pageModeContent.addComponent(panel);
  196.         pageModeContent.setExpandRatio(panel, ContentRatio.FULL_SIZE);

  197.         final HorizontalLayout footerTop = new HorizontalLayout();
  198.         final HorizontalLayout footerBottom = new HorizontalLayout();
  199.         final Link createMainViewPageLink = pageLinkFactory.createMainViewPageLink();
  200.         final Label appVersion = new Label(applicationName + " (" + applicationVersion +")(Apache License 2.0)");
  201.         final Link spdxLink = new Link("SBOM(spdx)", new ExternalResource("https://github.com/Hack23/cia/releases/download/" + applicationVersion +"/com.hack23.cia_citizen-intelligence-agency-" + applicationVersion +".spdx.json"));
  202.         final Link sourcCodeLink = new Link("https://github.com/Hack23/cia", new ExternalResource("https://github.com/Hack23/cia"));
  203.         final Label licenseLink = new Label("Open Source");

  204.         footerTop.addComponent(createMainViewPageLink);
  205.         footerTop.addComponent(appVersion);
  206.         footerBottom.addComponent(licenseLink);
  207.         footerBottom.addComponent(sourcCodeLink);
  208.         footerBottom.addComponent(spdxLink);
  209.         footerTop.setComponentAlignment(createMainViewPageLink, Alignment.MIDDLE_LEFT);
  210.         footerTop.setComponentAlignment(appVersion, Alignment.MIDDLE_LEFT);

  211.         footerBottom.setComponentAlignment(licenseLink, Alignment.MIDDLE_LEFT);
  212.         footerBottom.setComponentAlignment(sourcCodeLink, Alignment.MIDDLE_LEFT);
  213.         footerBottom.setComponentAlignment(spdxLink, Alignment.MIDDLE_LEFT);

  214.         footerTop.setWidth("100%");
  215.         footerTop.setHeight("25px");
  216.         footerBottom.setWidth("100%");
  217.         footerBottom.setHeight("25px");

  218.         pageModeContent.addComponent(footerTop);
  219.         pageModeContent.addComponent(footerBottom);

  220.         setContent(layout);

  221.         setWidth(100, Unit.PERCENTAGE);
  222.         setHeight(100, Unit.PERCENTAGE);
  223.         setSizeFull();

  224.     }

  225.     /**
  226.      * Creates the top header actions for user context.
  227.      */
  228.     private void createTopHeaderActionsForUserContext() {
  229.         if (UserContextUtil.allowRoleInSecurityContext(ROLE_ADMIN) || UserContextUtil.allowRoleInSecurityContext(ROLE_USER)) {
  230.             final Link userHomePageLink = pageLinkFactory.createUserHomeViewPageLink();
  231.             topHeaderRightPanel.addComponent(userHomePageLink);
  232.             topHeaderRightPanel.setComponentAlignment(userHomePageLink, Alignment.MIDDLE_RIGHT);

  233.             final Button logoutButton = new Button(LOGOUT,VaadinIcons.SIGN_OUT);

  234.             final LogoutRequest logoutRequest = new LogoutRequest();
  235.             logoutRequest.setSessionId(RequestContextHolder.currentRequestAttributes().getSessionId());
  236.             logoutButton.addClickListener(new LogoutClickListener(logoutRequest));

  237.             topHeaderRightPanel.addComponent(logoutButton);
  238.             topHeaderRightPanel.setComponentAlignment(logoutButton, Alignment.MIDDLE_RIGHT);

  239.         } else {
  240.             final Link createRegisterPageLink = pageLinkFactory.createRegisterPageLink();
  241.             topHeaderRightPanel.addComponent(createRegisterPageLink);
  242.             topHeaderRightPanel.setComponentAlignment(createRegisterPageLink, Alignment.MIDDLE_RIGHT);

  243.             final Link createLoginPageLink = pageLinkFactory.createLoginPageLink();
  244.             topHeaderRightPanel.addComponent(createLoginPageLink);
  245.             topHeaderRightPanel.setComponentAlignment(createLoginPageLink, Alignment.MIDDLE_RIGHT);
  246.         }
  247.     }

  248.     @Override
  249.     public final void enter(final ViewChangeEvent event) {
  250.         try {

  251.             final String parameters = Jsoup.clean(event.getParameters(), Safelist.basic());

  252.             for (final PageModeContentFactory pageModeContentFactory : pageModeContentFactoryMap.values()) {
  253.                 if (pageModeContentFactory.matches(pageName, parameters) && pageModeContentFactory.validReference(parameters)) {
  254.                     getPanel().setContent(pageModeContentFactory.createContent(parameters, getBarmenu(), getPanel()));
  255.                     return;
  256.                 }
  257.             }

  258.             LOGGER.warn("SECURITY:Invalid reference, content not found:{}/{}",pageName, parameters);
  259.             final VerticalLayout panelContent = createFullSizeVerticalLayout();

  260.             menuItemFactory.createMainPageMenuBar(getBarmenu());

  261.             LabelFactory.createHeader2Label(panelContent,"Invalid reference, content not found:" +pageName+ "/"+ parameters);

  262.             getPanel().setContent(panelContent);
  263.             getPanel().setCaption("Invalid Reference");
  264.         } catch (final AccessDeniedException e ) {
  265.             LOGGER.warn("Security:Authorization Failure:: {} : {}  exception : {}",e.getMessage(),pageName,e.getClass().getName());
  266.             final VerticalLayout panelContent = createFullSizeVerticalLayout();
  267.             LabelFactory.createHeader2Label(panelContent,"Access denied:" +pageName);
  268.             getPanel().setContent(panelContent);
  269.             getPanel().setCaption("Access denied");
  270.         }
  271.     }

  272.     /**
  273.      * Gets the barmenu.
  274.      *
  275.      * @return the barmenu
  276.      */
  277.     public final MenuBar getBarmenu() {
  278.         return barmenu;
  279.     }

  280.     /**
  281.      * Gets the panel.
  282.      *
  283.      * @return the panel
  284.      */
  285.     protected final Panel getPanel() {
  286.         return panel;
  287.     }

  288.     /**
  289.      * Post construct.
  290.      */
  291.     @PostConstruct
  292.     public final void postConstruct() {
  293.         setSizeFull();
  294.         createBasicLayoutWithPanelAndFooter(pageName);
  295.     }

  296. }