dhulipudi / webextest

test
0 stars 0 forks source link

login form issue #4

Open dhulipudi opened 3 months ago

dhulipudi commented 3 months ago
Login Form
dhulipudi commented 3 months ago

2 floating text

Login Form
dhulipudi commented 3 months ago

import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.commons.lang.StringUtils; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.injectorspecific.RequestAttribute; import org.apache.sling.models.annotations.injectorspecific.SlingObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory;

import com.day.cq.wcm.api.Page; import com.day.cq.wcm.api.PageManager; import com.drew.lang.annotations.NotNull; import com.drew.lang.annotations.Nullable;

/**

@Model(adaptables = { SlingHttpServletRequest.class, Resource.class}) public class NavigationModel { private final Logger LOG = LoggerFactory.getLogger(NavigationModel.class);

            protected static final String RESOURCE_TYPE = "wellsfargobc/components/navigation";

private List<NavigationItem> items;

@SlingObject
private Resource currentResource;
@SlingObject
private ResourceResolver resourceResolver;

private String currentPagePath;

@RequestAttribute
@org.apache.sling.models.annotations.Optional
private String path;

@PostConstruct
protected void init() {
            LOG.debug("NavigationModel:Path:{}", path);
            if ( path != null ) {
                                            String[] rootPathArray = path.split("/");                 

                                            List<String> pathList = Arrays.asList(rootPathArray).subList(0, 7);                         
                                            if ( path.contains("brand-standards")) {
                                                            pathList = Arrays.asList(rootPathArray).subList(0, 8);
                                            }
                                            String rootPath = StringUtils.join(pathList,"/");
                            LOG.debug("rootPath:{}", rootPath);

                            PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
                    Page currentPage = pageManager.getContainingPage(rootPath);
                    if (currentPage != null) {
                        LOG.debug("NavigationModel:currentPage:{} Name:{}", currentPage, currentPage.getName());
                        items = buildNavigation(currentPage);
                        if ( !currentPage.getName().equalsIgnoreCase("brand-standards"))
                            items.add(0, new NavigationItem(currentPage, false));
                        LOG.debug("Items:{} Size: {}", items, items.size());
                    }
            }
}

            @Nullable
public List<NavigationItem> getItems() {
    return items;
}

/**
 * Build the Navigation for the current resource 
 * @param currentPage
 * @return
 */
private List<NavigationItem> buildNavigation(@NotNull final Page currentPage) {
    List<NavigationItem> navigationItems = new ArrayList<>();

    Iterator<Page> siblings = currentPage.listChildren();
    while (siblings.hasNext()) {
        Page sibling = siblings.next();
        if (!sibling.isHideInNav()) {
            navigationItems.add(new NavigationItem(sibling));
        }
    }
    return navigationItems;
}

public class NavigationItem {
    private String title;
    private String url;
    private boolean isActive;
    private List<NavigationItem> children;

    public NavigationItem(@NotNull final Page page, @NotNull final boolean includeChild) {
        this.title = page.getTitle();
        this.url = page.getPath() + ".html";
        this.isActive = page.getPath().equalsIgnoreCase(currentPagePath);            
        if (includeChild && page.listChildren().hasNext()) {
            this.children = buildNavigation(page);
        }
    }

    public NavigationItem(@NotNull final Page page) {
        this.title = page.getTitle();
        this.url = page.getPath() + ".html";
        this.isActive = page.getPath().equalsIgnoreCase(currentPagePath);
        if (page.listChildren().hasNext()) {
            this.children = buildNavigation(page);
        }
    }

            public boolean isActive() {
                            return isActive;
            }

            public List<NavigationItem> getChildren() {
                            return children;
            }

            public String getUrl() {
                            return url;
            }

            public String getTitle() {
                            return title;
            }
}

}

${item.title}

  • ${child.title @ context='html'}
    • ${child2.title @ context='html'}
dhulipudi commented 3 months ago

import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.Optional; import org.apache.sling.models.annotations.injectorspecific.RequestAttribute; import org.apache.sling.models.annotations.injectorspecific.SlingObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory;

import com.day.cq.wcm.api.Page; import com.day.cq.wcm.api.PageManager;

/**

dhulipudi commented 3 months ago

============= 333===

import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.Optional; import org.apache.sling.models.annotations.injectorspecific.RequestAttribute; import org.apache.sling.models.annotations.injectorspecific.SlingObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory;

import com.day.cq.wcm.api.Page; import com.day.cq.wcm.api.PageManager;

/**

===================== import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.*;

import com.day.cq.wcm.api.Page; import com.bsc.ewp.slingmodels.NavigationModel; import com.bsc.ewp.slingmodels.NavigationModel.NavigationItem; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.SlingHttpServletRequest; import org.junit.Before; import org.junit.Test;

import java.util.Iterator;

public class NavigationModelTest { private NavigationModel navigationModel; private Page mockPage; private ResourceResolver mockResolver; private SlingHttpServletRequest mockRequest; private Resource mockResource;

@Before
public void setUp() {
    // Create mock objects
    mockPage = mock(Page.class);
    mockResolver = mock(ResourceResolver.class);
    mockRequest = mock(SlingHttpServletRequest.class);
    mockResource = mock(Resource.class);

    // Set up mock behavior
    when(mockPage.getTitle()).thenReturn("Test Title");
    when(mockPage.getPath()).thenReturn("/content/test");
    when(mockPage.listChildren()).thenReturn(mock(Iterator.class));
    when(mockResolver.adaptTo(Page.class)).thenReturn(mockPage);
    when(mockResource.adaptTo(Page.class)).thenReturn(mockPage);
    when(mockRequest.getResource()).thenReturn(mockResource);

    // Create NavigationModel object
    navigationModel = new NavigationModel();
    navigationModel.resourceResolver = mockResolver;
    navigationModel.currentResource = mockResource;
    navigationModel.init();
}

@Test
public void testGetItems() {
    assertEquals(1, navigationModel.getItems().size());
}

@Test
public void testNavigationItemGetUrl() {
    NavigationItem item = navigationModel.getItems().get(0);
    assertEquals("/content/test.html", item.getUrl());
}

@Test
public void testNavigationItemGetTitle() {
    NavigationItem item = navigationModel.getItems().get(0);
    assertEquals("Test Title", item.getTitle());
}

}

dhulipudi commented 3 months ago

import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.*;

import com.day.cq.wcm.api.Page; import com.day.cq.wcm.api.PageManager; import com.bsc.ewp.slingmodels.NavigationModel; import com.bsc.ewp.slingmodels.NavigationModel.NavigationItem; import io.wcm.testing.mock.aem.junit5.AemContext; import io.wcm.testing.mock.aem.junit5.AemContextExtension; import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith;

@ExtendWith(AemContextExtension.class) public class NavigationModelTest { private final AemContext context = new AemContext();

@BeforeEach
public void setUp() {
    // Create a Page object
    Page page = context.create().page("/content/test", "test-template", "Test Title");

    // Set up the request
    MockSlingHttpServletRequest request = context.request();
    request.setResource(page.adaptTo(Resource.class));

    // Set up the PageManager
    PageManager pageManager = context.pageManager();
    when(pageManager.getContainingPage(anyString())).thenReturn(page);

    // Set up the NavigationModel
    NavigationModel navigationModel = request.adaptTo(NavigationModel.class);
    navigationModel.resourceResolver = context.resourceResolver();
    navigationModel.currentResource = request.getResource();
    navigationModel.path = "/content/test";
    navigationModel.init();
}

@Test
public void testGetItems() {
    NavigationModel navigationModel = context.request().adaptTo(NavigationModel.class);
    assertEquals(1, navigationModel.getItems().size());
}

@Test
public void testNavigationItemGetUrl() {
    NavigationModel navigationModel = context.request().adaptTo(NavigationModel.class);
    NavigationItem item = navigationModel.getItems().get(0);
    assertEquals("/content/test.html", item.getUrl());
}

@Test
public void testNavigationItemGetTitle() {
    NavigationModel navigationModel = context.request().adaptTo(NavigationModel.class);
    NavigationItem item = navigationModel.getItems().get(0);
    assertEquals("Test Title", item.getTitle());
}

}

dhulipudi commented 3 months ago
                <truncateText
                    jcr:primaryType="nt:unstructured"
                    sling:resourceType="granite/ui/components/coral/foundation/form/radiogroup"
                    fieldLabel="trunc_text"
                    name="./truncateText"
                    required="{Boolean}true">
                    <items jcr:primaryType="nt:unstructured">
                        <no_trunc
                            jcr:primaryType="nt:unstructured"
                            text="no_trunc"
                            value="no-truncate"/>
                        <lines3
                            jcr:primaryType="nt:unstructured"
                            checked="{Boolean}true"
                            text="three_lines"
                            value="truncate-lines-to-3"/>
                        <lines4
                            jcr:primaryType="nt:unstructured"
                            text="four_lines"
                            value="truncate-lines-to-4"/>
                    </items>
                </truncateText>
dhulipudi commented 3 months ago

@Model(adaptables = {Resource.class}, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) public class TextCTAModelLinkItem {

private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

@Self
@Via("resource")
private Resource resource;

@ValueMapValue
@Optional
private String path;

@ValueMapValue
@Optional
private String text;

@ValueMapValue
@Optional
private Boolean openInNewWindow;

public String getPath() {
    return path;
}

public String getText() {
    return text;
}

public String getTarget(){
    return openInNewWindow ? "_blank" : null;
}

@PostConstruct
private void activate(){
    // we will treat this as a link to a page - path, with no extension
    if(path != null && path.startsWith("/content") && !path.startsWith("/content/dam") && !path.contains(".html")){
        path = path + ".html";
    }
}

}

=========

dialog

<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="nt:unstructured" jcr:title="What's New Header" sling:resourceType="cq/gui/components/authoring/dialog"> <content jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/container">

</content>

</jcr:root>

dhulipudi commented 3 months ago

====

import org.apache.sling.api.resource.Resource; import org.apache.sling.models.annotations.Default; import org.apache.sling.models.annotations.DefaultInjectionStrategy; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.Optional; import org.apache.sling.models.annotations.injectorspecific.ChildResource; import org.apache.sling.models.annotations.injectorspecific.Self; import org.apache.sling.models.annotations.injectorspecific.ValueMapValue; import org.slf4j.Logger; import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct; import java.lang.invoke.MethodHandles; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport;

/**

}

dhulipudi commented 3 months ago

.cmp-page-header--breadcrumbs-title { // NOTE: This applies to an alternative page header style in EWP Left Navigation Template - Breadcrumb Container Policy

h1 { margin: space(md) 0.625rem space(3x); // NOTE: The l/r is a one-off size to align the h1 with the full-width primary nav } }

// Background Colors

.cmp-container { &:first-child { background: transparent; } }

.cmp-container--accent {

.cmp-container { &:first-child { background: $accent-primary-20; } } }

.cmp-container--action {

.cmp-container { &:first-child { background: $action-primary-97; } } }

.cmp-container--assertive {

.cmp-container { &:first-child { background: $neutral-00; } } }

.cmp-container--ghost {

.cmp-container { &:first-child { background: $neutral-100; } } }

.cmp-container--gradient-assertive {

.cmp-container { &:first-child { background: $gradient-assertive; } } }

.cmp-container--gradient-subtle {

.cmp-container { &:first-child { background: $gradient-subtle; } } }

.cmp-container--subtle {

.cmp-container { &:first-child { background: $neutral-95; } } }

// Background Patterns

.cmp-container--pattern-arrow {

.cmp-container { &:first-child { position: relative;

  &::after {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    width: 100%;
    height: 100%;
    background-image: url('/etc.clientlibs/ewp/clientlibs/clientlib-default/resources/images/pattern-arrow.svg');
    background-position-x: left;
    background-position-y: top;
    background-repeat: repeat-y;
    background-size: cover;
    content: '';
  }

  > * {
    position: relative;
    z-index: 2;
  }
}

}

&.cmp-container--accent {

.cmp-container { &:first-child { &::after { background-image: url('/etc.clientlibs/ewp/clientlibs/clientlib-default/resources/images/pattern-arrow-accent.svg'); } } } }

&.cmp-container--action {

.cmp-container { &:first-child { &::after { background-image: url('/etc.clientlibs/ewp/clientlibs/clientlib-default/resources/images/pattern-arrow-action.svg'); } } } }

&.cmp-container--assertive {

.cmp-container { &:first-child { &::after { background-image: url('/etc.clientlibs/ewp/clientlibs/clientlib-default/resources/images/pattern-arrow-assertive.svg'); } } } }

&.cmp-container--gradient-assertive {

.cmp-container { &:first-child { &::after { background-image: url('/etc.clientlibs/ewp/clientlibs/clientlib-default/resources/images/pattern-arrow-assertive-gradient.svg'); } } } } }

// Decorative Treatments

.cmp-container--border-accent {

.cmp-container { &:first-child { @include border-gradient-accent; } }

&.cmp-container--assertive, &.cmp-container--gradient-assertive {

.cmp-container { &:first-child { border: space(sm) solid $accent-secondary-60; } } }

&.cmp-container--accent {

.cmp-container { &:first-child { border: space(sm) solid $accent-primary-60; } } } }

.cmp-container--shadow {

.cmp-container { &:first-child { box-shadow: $box-shadow-tertiary; } } }

.cmp-container--split {

.cmp-container { &:first-child { position: relative; background: transparent;

  &::before {
    // NOTE: this is the background color
    position: absolute;
    top: 0;
    right: 0;
    bottom: 25%;
    left: 0;
    z-index: -1;
    content: '';
  }

  &::after {
    // NOTE: this is the arrow pattern
    height: 75%;
  }
}

}

&.cmp-container--accent {

.cmp-container { &:first-child { &::before { background: $accent-primary-20; } } } }

&.cmp-container--action {

.cmp-container { &:first-child { &::before { background: $action-primary-97; } } } }

&.cmp-container--assertive {

.cmp-container { &:first-child { &::before { background: $neutral-00; } } } }

&.cmp-container--ghost {

.cmp-container { &:first-child { &::before { background: $neutral-100; } } } }

&.cmp-container--gradient-assertive {

.cmp-container { &:first-child { &::before { background: $gradient-assertive; } } } }

&.cmp-container--gradient-subtle {

.cmp-container { &:first-child { &::before { background: $gradient-subtle; } } } }

&.cmp-container--subtle {

.cmp-container { &:first-child { &::before { background: $neutral-95; } } } }

@media (min-width: 992px) {

.cmp-container { &:first-child { &::before { // NOTE: this is the background color bottom: 50%; }

    &::after {
      // NOTE: this is the arrow pattern
      height: 50%;
    }
  }
}

} }

// Padding // NOTE: The naming convention is slightly different here since the default is truly 0/remove // We set default to 6x since that would be the default inset padding, in the event that the author adds padding

.cmp-container--padding-increase {

.cmp-container { &:first-child { padding: space(8x); } } }

.cmp-container--padding-default {

.cmp-container { &:first-child { padding: space(6x); } } }

.cmp-container--padding-decrease {

.cmp-container { &:first-child { padding: space(4x); } } }

// Margin Top

.cmp-container--margin-top-increase-2 {

.cmp-container { &:first-child { margin-top: space(12x); } } }

.cmp-container--margin-top-increase-1 {

.cmp-container { &:first-child { margin-top: space(8x); } } }

.cmp-container--margin-top-default {

.cmp-container { &:first-child { margin-top: space(6x); } } }

.cmp-container--margin-top-decrease-1 {

.cmp-container { &:first-child { margin-top: space(4x); } } }

.cmp-container--margin-top-decrease-2 {

.cmp-container { &:first-child { margin-top: space(3x); } } }

dhulipudi commented 3 months ago

/ ----Teaser Component JS---- / var comp = window.comp || {}; comp.teaser = {}; comp.teaser = { insertTargetDiv: function () { $('.cmp-teaser--brand-element .cmp-teaser__content').prepend( '

' ); },

initArrowsTracking: function () { window.dataLayer = window.dataLayer || []; var $targetDiv = $('#iconAdvancingArrows');

$targetDiv.on('click', function () {
  window.dataLayer.push({
    event: 'teaserArrowsClicked'
  });
});

} };

comp.teaser.insertTargetDiv(); comp.teaser.initArrowsTracking();

dhulipudi commented 3 months ago

.cmp-teaser--hero { &.cmp-teaser--brand-element { &:not(.cmp-teaser--interactive) { .cmp-teaser__content { position: relative; border-bottom: space(sm) solid transparent; padding-top: calc(space(4x) + space(3x)); // NOTE: This is the regular padding + half the height of the arrows

    &::before {
      position: absolute;
      top: - space(3x);
      left: space(4x);
      z-index: 2;
      display: block;
      width: space(8x);
      height: space(6x);
      background: url('/etc.clientlibs/ewp/clientlibs/clientlib-default/resources/images/bsc-advancing-arrows.svg');
      background-size: 100%;
      content: '';
    }

    .icon-advancing-arrows {
      position: absolute;
      top: - space(3x);
      left: space(4x);
      z-index: 3;
      display: block;
      width: space(8x);
      height: space(6x);
    }

    &::after {
      bottom: - space(sm);
      @include decorative-bar;
      @include animated-gradient-brand;
      z-index: 1;
      content: '';
    }

    @media (min-width: 768px) {
      margin-top: calc(space(6x) + space(3x)); // NOTE: This is the regular margin + half the height of the arrows
    }

    &:first-child {
      padding-top: space(4x);

      &::before {
        position: relative;
        top: 0;
        left: 0;
        margin-bottom: space(4x);
      }

      .icon-advancing-arrows {
        top: space(4x);
      }

      &::after {
        bottom: - space(sm);
        @include animated-gradient-brand;
      }

      @media (min-width: 768px) {
        margin-top: unset;
      }
    }
  }

  &.cmp-teaser--hero-center {
    .cmp-teaser__content {
      &::before,
      .icon-advancing-arrows {
        left: calc(50% - space(4x));
      }
    }
  }

  &.cmp-teaser--hero-overlap {
    .cmp-teaser__content {
      margin: - space(8x) space(6x) 0;
    }

    @media (min-width: 992px) {
      .cmp-teaser__content {
        margin: 0;
      }
    }
  }
}

} }

dhulipudi commented 3 months ago

Teaser 1

Teaser 1

WF Brandcentral

dhulipudi commented 3 months ago
  |   -- | --   |   |   |   |   | en   |     |     |   |   |     |     |     |     |   |     |     |     |     |     |   |     |     |     |     |     |     |     |     |     |     |     |     |     |     |   |     |     |     |   |   |     |     |     |     |   |     |     |     |     |     |   |   |   |     |     |     |     |     |     |     |     |
  |     |     |
  |     |     |     |
  |     |
  |
  |     |     |     |     |     |
  |     |   |
  |   |     |     |     |
  |   |     |     |
  |     |     |
  |     |     |
  |
  |     |     |
  |     |     |     |
  |     |
  |
  |

WF Brandcentral

  |
  |     |     |     |
  |
  |     |     |
  |     |     |     |
  |     |
  |
  |     |
  |     |     |     |     |

  | Epic Journey   |

  |     |     |

Don't stop half way, go for the top!

  |
  |     |     |     |     |
  |     |     |     |     |
  |     |     |     |
  |
  |
  |     |
  |     |     |     |     |

  | Epic Journey   |

  |     |     |

Don't stop half way, go for the top!

  |
  |     |     |     |     |
  |     |     |     |     |
  |     |     |     |
  |
  |
  |     |
  |     |     |     |     |

  | Epic Journey   |

  |     |     |

Don't stop half way, go for the top!

  |
  |     |     |     |     |
  |     |     |     |     |
  |     |     |     |
  |
  |
  |

Hello World Component

  |
  |

Text property:

  |
lalala :)
  |
  |
  |

Model message:

  |
Hello World!
  | Resource type is: brandcentral/components/helloworld
  | Current page is:  /content/brandcentral/us/en
  | 
  |
  |
  |
  |
  |
  |     |
  |     |     |     |     |

  | Do This   |

  |     |     |

Headlines 24pt and above, set in Wells Fargo Display.

  |
  |     |     |     |     |
  |     |
  |
  |     | Do this   |     |     |     |
  |     |     |     |
  |     |     |
  |     |     |     |
  |
  |     |     |     |     |
  |     |
  |
  |     |
  |     |

Teaser 1

  |     |     |

  | Teaser 1   |

  |     |     |     |     |     |     |     |
  |     |     |     |     |
  |     |     |     |
  |
  |
  |     |
  |     |     |     |     |

  | WF Brandcentral   |

  |     |     |     |     |     |     |     |
  |     |     |     |     |
  |     |     |     |
  |     |     |
  |     |     |
  |     |     |
  |     |
  |     |     |     |
  |     |     |
  |     |
  |     |     |     |
  |
  |   |     |     |
  |     |     |
  |     |
  |     |     |     |
  |     |     |     |     |   |     |     |     |     |     |   |   |     |     |     |     |     |     |     |     |     |     |     |     |     |   |

  |  

<!DOCTYPE HTML>

en

WF Brandcentral

Epic Journey

Don't stop half way, go for the top!

Epic Journey

Don't stop half way, go for the top!

Epic Journey

Don't stop half way, go for the top!

Hello World Component

Text property:

lalala :)

Model message:

Hello World!
Resource type is: brandcentral/components/helloworld
Current page is:  /content/brandcentral/us/en

Do This

Headlines 24pt and above, set in Wells Fargo Display.

Do this

Teaser 1

Teaser 1

WF Brandcentral

dhulipudi commented 3 months ago

Test Page

test 2

dhulipudi commented 3 months ago

container-e70f86c747 > .aem-GridColumn {

display: flex; flex-wrap: wrap; }

container-e70f86c747 > .aem-GridColumn > div {

flex: 1 0 50%; / This makes the items take up 50% of the container's width, allowing two items per row / }

@media (max-width: 768px) { / Adjust this value as needed /

container-e70f86c747 > .aem-GridColumn {

flex-direction: column;

} }

dhulipudi commented 2 months ago

package com.wellsfargo.bc.core.services.auth;

import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.stream.Stream;

import javax.jcr.LoginException; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.SimpleCredentials; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils; import org.apache.jackrabbit.api.security.authentication.token.TokenCredentials; import org.apache.sling.auth.core.spi.AuthenticationFeedbackHandler; import org.apache.sling.auth.core.spi.AuthenticationHandler; import org.apache.sling.auth.core.spi.AuthenticationInfo; import org.apache.sling.auth.core.spi.DefaultAuthenticationFeedbackHandler; import org.apache.sling.jcr.api.SlingRepository; import org.apache.sling.auth.core.AuthUtil; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.osgi.service.metatype.annotations.AttributeDefinition; import org.osgi.service.metatype.annotations.Designate; import org.osgi.service.metatype.annotations.ObjectClassDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory;

import com.day.crx.security.token.TokenCookie;

import static org.apache.sling.auth.core.spi.AuthenticationHandler.TYPE_PROPERTY; import static org.apache.sling.auth.core.spi.AuthenticationHandler.PATH_PROPERTY; import static org.osgi.framework.Constants.SERVICE_DESCRIPTION; import static org.osgi.framework.Constants.SERVICE_RANKING; import static org.osgi.service.component.annotations.ReferenceCardinality.MULTIPLE; import static org.osgi.service.component.annotations.ReferencePolicy.DYNAMIC; import static org.apache.commons.lang3.StringUtils.EMPTY;

/**

@Component(service = { AuthenticationHandler.class, AuthenticationFeedbackHandler.class }, // configurationPolicy = REQUIRE, property = { PATH_PROPERTY + "=/content", TYPE_PROPERTY + "= WF_OAUTH", SERVICE_DESCRIPTION + "= WellsFargo Federated Authenticator", SERVICE_RANKING + ":Integer=80000" }) public class WFAuthenticationHandler extends DefaultAuthenticationFeedbackHandler implements AuthenticationHandler {

private static final Logger LOGGER = LoggerFactory.getLogger(WFAuthenticationHandler.class);

@ObjectClassDefinition(name = "CWA AuthenticationHandler Configuration", description = "Configuration for CWA AuthenticationHandler.")
public @interface Config {

    @AttributeDefinition(name = "WF AuthenticationHandler Paths")
    String[] path() default { "/content/brandcentral" };

    @AttributeDefinition(name = "Auth Request Url")
    String cwaAuthRequestUrl() default "";

    @AttributeDefinition(name = "Callback Url")
    String cwaCallbackUrl() default "";

    @AttributeDefinition(name = "SessionManager Callback Url")
    String sessionManagerCallbackUrl() default "";

    @AttributeDefinition(name = "SessionManager Logout Url")
    String sessionManagerLogoutUrl() default "";

    @AttributeDefinition(name = "SessionManager UserInfo Url")
    String sessionManagerUserInfoUrl() default "";
}

private Config config;

private final String REQUEST_METHOD = "GET";
private final String USER_NAME = "j_username";
private final String PASSWORD = "j_password";
private static final String TOKEN_ID = ".token";
private final ConcurrentMap<String, WFLoginCallback> callbacks = new ConcurrentHashMap<>();

@Reference
private SlingRepository repository;

@Override
public AuthenticationInfo extractCredentials(HttpServletRequest request, HttpServletResponse response) {
    LOGGER.info("extractCredentials");
    AuthenticationInfo authenticationInfo = null;
    String j_username = request.getParameter(USER_NAME);
    String j_password = request.getParameter(PASSWORD);
    if ((request.getRequestURI().contains("j_security_check"))) {
        try {
            authenticationInfo = basicAuth(request, response, j_username, j_password);
        } catch (LoginException ex) {
            LOGGER.error(ex.getMessage());
            return null;
        }
    }

    return authenticationInfo;
}

private AuthenticationInfo basicAuth(HttpServletRequest request, HttpServletResponse response,
        String userName, String password) throws LoginException {
    AuthenticationInfo authInfo = null;
    if ((userName != null && password != null)) {
        authInfo = new AuthenticationInfo("TOKEN", userName);
        SimpleCredentials creds = new SimpleCredentials(userName,
                password.toCharArray());
        Session session = null;
        try {
            session = this.repository.login(creds);
            this.repository.login(creds);
            if (session != null) {
                // create a new AuthenticationInfo object that makes use of the standard
                // AEM token authentication
                authInfo = new AuthenticationInfo("TOKEN",
                        userName);
                // and we set a dummy token which will be updated
                creds.setAttribute(TOKEN_ID, "");

                // log in using the credentials to record the log in event
                repository.login(creds);

                // use the associated session to create TokenCredentials
                TokenCredentials tc = new TokenCredentials((String) creds.getAttribute(TOKEN_ID));
                // and set the token-credentials in authenticationInfo object
                authInfo.put("user.jcr.credentials", tc);

                // set or update login token cookie
                String repoId = repository.getDescriptor("crx.cluster.id");
                TokenCookie.update(request, response, repoId, tc.getToken(),
                        repository.getDefaultWorkspace(), true);
                if (session.isLive()) {
                    session.logout();
                }
                LOGGER.info("authInfo:{}", authInfo);
                return authInfo;
            }
        } catch (LoginException e) {
            LOGGER.error(
                    this.getClass().getName() + " extractCredentials(..) Failed to log user in" + e.getMessage(),
                    e);
            e.printStackTrace();
        } catch (RepositoryException e) {
            LOGGER.error(
                    this.getClass().getName() + " extractCredentials(..) Failed to log user in" + e.getMessage(),
                    e);
            e.printStackTrace();
        }
    }
    return authInfo;
}

@Override
public boolean requestCredentials(HttpServletRequest request, HttpServletResponse response) throws IOException {
    return false;
}

@Override
public void dropCredentials(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String appId = request.getParameter("appId");
    LOGGER.info("dropCredentials for appId: [{}]", appId);
    if (StringUtils.isNotEmpty(appId)) {
        if (Boolean.parseBoolean(request.getParameter("sm"))) {
            LOGGER.info("Sending AppId: [{}] to SessionManager for logout.", appId);
            this.redirect(response, this.config.sessionManagerLogoutUrl() + "?appId=" + appId, true);
        } else {
            this.redirect(response, "/bin/public/servlets/cwa/logout?appId=" + appId, true);
        }
    }
}

// <<----------------------------------- AuthenticationFeedbackHandler
// ----------------------------------->>

@Override
public void authenticationFailed(HttpServletRequest request, HttpServletResponse response,
        AuthenticationInfo authInfo) {
    LOGGER.info("authenticationFailed");
    this.callbacks.forEach((name, callback) -> {
        try {
            if (callback.canHandle(request)) {
                callback.onLoginFailure(request);
            }
        } catch (Exception ex) {
            LOGGER.error(ex.getMessage(), ex);
        }
    });
}

@Override
public boolean authenticationSucceeded(HttpServletRequest request, HttpServletResponse response,
        AuthenticationInfo authInfo) {
    LOGGER.info("authenticationSucceeded");
    this.callbacks.forEach((name, callback) -> {
        try {
            LOGGER.info("Name:{}", name);
            if (callback.canHandle(request)) {
                callback.onLoginSuccess(request);
            }
        } catch (Exception ex) { // NOSONAR
            LOGGER.error(ex.getMessage(), ex);
        }
    });
    // return true so that SlingAuthenticator stops further request processing and
    // redirect to the given url instead.
    return redirectQuietly(response, AuthUtil.getLoginResource(request, EMPTY), false);
}

@Reference(service = WFLoginCallback.class, cardinality = MULTIPLE, policy = DYNAMIC)
protected void bindCWALoginCallback(WFLoginCallback callback) {
    this.callbacks.put(callback.getTenantName(), callback);
    LOGGER.info("Added [{}] WFLoginCallback!", callback.getTenantName());
}

protected void unbindCWALoginCallback(WFLoginCallback callback) {
    if (this.callbacks.remove(callback.getTenantName()) != null) {
        LOGGER.info("Removed [{}] WFLoginCallback!", callback.getTenantName());
    }
}

private boolean redirectQuietly(HttpServletResponse resp, String url, boolean encodeUrl) {
    boolean outcome = false;
    try {
        if (resp.isCommitted()) {
            LOGGER.error("Response already committed!!");
        } else {
            LOGGER.debug("Redirecting to url: [{}]", url);
            resp.sendRedirect(encodeUrl ? resp.encodeRedirectURL(url) : url);
            outcome = true;
        }
    } catch (IOException ex) {
        LOGGER.error(ex.getMessage(), ex);// NOSONAR
    }
    return outcome;
}

private void redirect(HttpServletResponse resp, String url, boolean encodeUrl) throws IOException {
    LOGGER.debug("Redirecting to: [{}]", url);
    resp.sendRedirect(encodeUrl ? resp.encodeRedirectURL(url) : url);
}

@Activate
protected void start(Config config) {
    this.config = config;
    Stream.of(config.path())
            .forEach(path -> LOGGER.info("WFAuthenticationHandler listening at path: [{}]", path));
}

}