CCM NG: ccm-shortcuts:

- ShortcutFilter migrated from trunk
    - Some minor adjustments to the repository


git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4150 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2016-06-10 11:42:44 +00:00
parent fea14a860e
commit 7691377674
6 changed files with 215 additions and 25 deletions

View File

@ -0,0 +1,122 @@
/*
* Copyright (C) 2016 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.shortcuts;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.util.Optional;
import javax.inject.Inject;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ShortcutFilter implements Filter {
private final static Logger LOGGER = LogManager.getLogger(
ShortcutFilter.class);
@Inject
private ShortcutRepository shortcutRepository;
@Override
public void init(final FilterConfig filterConfig) throws ServletException {
//Nothing
}
@Override
public void doFilter(final ServletRequest request,
final ServletResponse response,
final FilterChain chain)
throws IOException, ServletException {
if (request instanceof HttpServletRequest
&& response instanceof HttpServletResponse) {
final HttpServletRequest httpRequest = (HttpServletRequest) request;
final String path = httpRequest.getRequestURI();
LOGGER.debug(
"Request path into: '{}', path translated: '{}', URI: '{}'",
httpRequest.getPathInfo(),
httpRequest.getPathTranslated(),
httpRequest.getRequestURI());
if (path == null || path.isEmpty()) {
LOGGER.debug("No path, passing off to next filter.");
chain.doFilter(request, response);
return;
}
final Optional<Shortcut> shortcut = shortcutRepository.findByUrlKey(
path);
if (shortcut.isPresent()) {
LOGGER.debug("Found Shortcut for path {}: {}",
path,
shortcut.toString());
final StringBuffer targetBuffer = new StringBuffer(shortcut
.get()
.getRedirect());
final String queryString = httpRequest.getQueryString();
if (queryString != null && !queryString.isEmpty()) {
LOGGER.debug("Request URL has query parameters. Appending "
+ "then to target URL.");
targetBuffer.append('?');
targetBuffer.append(queryString);
}
final String target = targetBuffer.toString();
LOGGER.debug("Redirecting to {}...", target);
((HttpServletResponse) response).sendRedirect(target);
} else {
LOGGER.debug(
"No Shortcut for {} found. Passing off to next filter.",
path);
chain.doFilter(request, response);
}
} else {
LOGGER.debug("Request is not a HttpServletRequest. Passing off "
+ "to next filter.");
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
//Nothing
}
}

View File

@ -18,7 +18,6 @@
*/ */
package org.libreccm.shortcuts; package org.libreccm.shortcuts;
import org.libreccm.security.AuthorizationRequired; import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege; import org.libreccm.security.RequiresPrivilege;
@ -41,10 +40,12 @@ public class ShortcutManager {
private ShortcutRepository shortcutRepository; private ShortcutRepository shortcutRepository;
/** /**
* Creates a Shortcut * Creates a new Shortcut. The Shortcut is automatically saved to the
* database.
* *
* @param url The URL of the Shortcut. Can't be null. * @param url The URL of the Shortcut. Can't be null.
* @param redirect The URL to which the Shortcut redirects. Can't be null. * @param redirect The URL to which the Shortcut redirects. Can't be null.
*
* @return the new Shortcut * @return the new Shortcut
*/ */
@AuthorizationRequired @AuthorizationRequired
@ -52,25 +53,29 @@ public class ShortcutManager {
public Shortcut createShortcut(final String url, final String redirect) { public Shortcut createShortcut(final String url, final String redirect) {
if (url == null || url.trim().isEmpty()) { if (url == null || url.trim().isEmpty()) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The URL key of a Shortcut can't be empty"); "The URL key of a Shortcut can't be empty");
} }
if (redirect == null || redirect.trim().isEmpty()) { if (redirect == null || redirect.trim().isEmpty()) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The redirect target of a Shortcut can't be empty"); "The redirect target of a Shortcut can't be empty");
} }
Shortcut shortcut = new Shortcut(); Shortcut shortcut = new Shortcut();
shortcut.setUrlKey(url); shortcut.setUrlKey(url);
shortcut.setRedirect(redirect); shortcut.setRedirect(redirect);
shortcutRepository.save(shortcut);
return shortcut; return shortcut;
} }
/** /**
* Creates a Shortcut * Creates a Shortcut
* *
* @param url The URL of the Shortcut. Can't be null. * @param url The URL of the Shortcut. Can't be null.
* @param redirect The URL to which the Shortcut redirects. Can't be null. * @param redirect The URL to which the Shortcut redirects. Can't be null.
*
* @return the new Shortcut * @return the new Shortcut
*/ */
// public Shortcut createShortcut(final URL url, final URL redirect) { // public Shortcut createShortcut(final URL url, final URL redirect) {
@ -89,12 +94,12 @@ public class ShortcutManager {
// shortcut.setRedirect(redirect.toString()); // shortcut.setRedirect(redirect.toString());
// return shortcut; // return shortcut;
// } // }
/** /**
* Creates a Shortcut * Creates a Shortcut
* *
* @param uri The URI of the Shortcut. Can't be null. * @param uri The URI of the Shortcut. Can't be null.
* @param redirect The URI to which the Shortcut redirects. Can't be null. * @param redirect The URI to which the Shortcut redirects. Can't be null.
*
* @return the new Shortcut * @return the new Shortcut
*/ */
// public Shortcut createShortcut(final URI uri, final URI redirect) { // public Shortcut createShortcut(final URI uri, final URI redirect) {
@ -113,7 +118,6 @@ public class ShortcutManager {
// shortcut.setRedirect(redirect.toString()); // shortcut.setRedirect(redirect.toString());
// return shortcut; // return shortcut;
// } // }
/** /**
* checks if the Shortcut exists. * checks if the Shortcut exists.
* *
@ -128,8 +132,9 @@ public class ShortcutManager {
* checks if the given URL is valid * checks if the given URL is valid
* *
* @param url the URL you want to validate * @param url the URL you want to validate
*
* @return true if you can successfully connect to the url, therefore is * @return true if you can successfully connect to the url, therefore is
* valid. * valid.
*/ */
private boolean validateURL(final String url) { private boolean validateURL(final String url) {
//TODO //TODO

View File

@ -18,6 +18,8 @@
*/ */
package org.libreccm.shortcuts; package org.libreccm.shortcuts;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.core.AbstractEntityRepository; import org.libreccm.core.AbstractEntityRepository;
import org.libreccm.security.AuthorizationRequired; import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege; import org.libreccm.security.RequiresPrivilege;
@ -36,6 +38,9 @@ import javax.persistence.TypedQuery;
@RequestScoped @RequestScoped
public class ShortcutRepository extends AbstractEntityRepository<Long, Shortcut> { public class ShortcutRepository extends AbstractEntityRepository<Long, Shortcut> {
private static final Logger LOGGER = LogManager.getLogger(
ShortcutRepository.class);
@Override @Override
public Class<Shortcut> getEntityClass() { public Class<Shortcut> getEntityClass() {
return Shortcut.class; return Shortcut.class;
@ -54,9 +59,11 @@ public class ShortcutRepository extends AbstractEntityRepository<Long, Shortcut>
* @return The shortcut with the specified {@code urlKey} if there is any. * @return The shortcut with the specified {@code urlKey} if there is any.
*/ */
public Optional<Shortcut> findByUrlKey(final String urlKey) { public Optional<Shortcut> findByUrlKey(final String urlKey) {
LOGGER.debug("Trying to find Shortcut for urlKey {}",
cleanUrlKey(urlKey));
final TypedQuery<Shortcut> query = getEntityManager().createNamedQuery( final TypedQuery<Shortcut> query = getEntityManager().createNamedQuery(
"Shortcut.findByUrlKey", Shortcut.class); "Shortcut.findByUrlKey", Shortcut.class);
query.setParameter("urlKey", urlKey); query.setParameter("urlKey", cleanUrlKey(urlKey));
try { try {
final Shortcut result = query.getSingleResult(); final Shortcut result = query.getSingleResult();
@ -65,18 +72,19 @@ public class ShortcutRepository extends AbstractEntityRepository<Long, Shortcut>
return Optional.empty(); return Optional.empty();
} }
} }
/** /**
* Finds all shortcuts which redirect to the provided target. * Finds all shortcuts which redirect to the provided target.
* *
* @param redirect the wanted redirect * @param redirect the wanted redirect
*
* @return a List of Shortcuts with the specified {@code redirect} * @return a List of Shortcuts with the specified {@code redirect}
*/ */
public List<Shortcut> findByRedirect(final String redirect) { public List<Shortcut> findByRedirect(final String redirect) {
final TypedQuery<Shortcut> query = getEntityManager().createNamedQuery( final TypedQuery<Shortcut> query = getEntityManager().createNamedQuery(
"Shortcut.findByRedirect", Shortcut.class); "Shortcut.findByRedirect", Shortcut.class);
query.setParameter("redirect", redirect); query.setParameter("redirect", redirect);
return query.getResultList(); return query.getResultList();
} }
@ -84,13 +92,33 @@ public class ShortcutRepository extends AbstractEntityRepository<Long, Shortcut>
@AuthorizationRequired @AuthorizationRequired
@RequiresPrivilege(ShortcutsConstants.SHORTSCUT_MANAGE_PRIVILEGE) @RequiresPrivilege(ShortcutsConstants.SHORTSCUT_MANAGE_PRIVILEGE)
public void save(final Shortcut shortcut) { public void save(final Shortcut shortcut) {
//Cleanup the URL key
shortcut.setUrlKey(cleanUrlKey(shortcut.getUrlKey()));
super.save(shortcut); super.save(shortcut);
} }
@Override @Override
@AuthorizationRequired @AuthorizationRequired
@RequiresPrivilege(ShortcutsConstants.SHORTSCUT_MANAGE_PRIVILEGE) @RequiresPrivilege(ShortcutsConstants.SHORTSCUT_MANAGE_PRIVILEGE)
public void delete(final Shortcut shortcut) { public void delete(final Shortcut shortcut) {
super.delete(shortcut); super.delete(shortcut);
} }
private String cleanUrlKey(final String urlKey) {
final StringBuffer result = new StringBuffer(urlKey.length());
if (!urlKey.startsWith("/")) {
result.append('/');
}
result.append(urlKey);
if (!urlKey.endsWith("/")) {
result.append('/');
}
return result.toString();
}
} }

View File

@ -177,7 +177,7 @@ public class ShortcutManagerTest {
@UsingDataSet( @UsingDataSet(
"datasets/org/libreccm/shortcuts/ShortcutManagerTest/data.xml") "datasets/org/libreccm/shortcuts/ShortcutManagerTest/data.xml")
@ShouldMatchDataSet( @ShouldMatchDataSet(
value = "datasets/org/libreccm/shortcuts/ShortcutManagerTest/data.xml", value = "datasets/org/libreccm/shortcuts/ShortcutManagerTest/after-create.xml",
excludeColumns = {"shortcut_id"}) excludeColumns = {"shortcut_id"})
@InSequence(100) @InSequence(100)
public void createShortcutBySystemUser() { public void createShortcutBySystemUser() {
@ -195,7 +195,7 @@ public class ShortcutManagerTest {
@UsingDataSet( @UsingDataSet(
"datasets/org/libreccm/shortcuts/ShortcutManagerTest/data.xml") "datasets/org/libreccm/shortcuts/ShortcutManagerTest/data.xml")
@ShouldMatchDataSet( @ShouldMatchDataSet(
value = "datasets/org/libreccm/shortcuts/ShortcutManagerTest/data.xml", value = "datasets/org/libreccm/shortcuts/ShortcutManagerTest/after-create.xml",
excludeColumns = {"shortcut_id"}) excludeColumns = {"shortcut_id"})
@InSequence(110) @InSequence(110)
public void createShortcutByAuthorizedUser() { public void createShortcutByAuthorizedUser() {

View File

@ -1,19 +1,54 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<dataset> <dataset>
<ccm_core.parties party_id="-100"
name="public-user" />
<ccm_core.parties party_id="-110"
name="jdoe" />
<ccm_core.users party_id="-100"
given_name="public"
family_name="user"
email_address="public-user@localhost"
banned="false"
bouncing="false"
verified="true"
password_reset_required="false" />
<!-- Password is foo123 -->
<ccm_core.users party_id="-110"
given_name="John"
family_name="Doe"
email_address="john.doe@example.org"
password="$shiro1$SHA-512$500000$Y7CnccN1h25sR7KCElMOXg==$CVLWBhetodaEzzhDfGjRcCFZtSW02xOnjH7xhBx0lbxO66grKIt6LWmXoUhLEydce1JZ7cbzNLYOxIwwTeqi5Q=="
banned="false"
bouncing="false"
verified="true"
password_reset_required="false" />
<ccm_core.ccm_roles role_id="-200"
name="shortcuts-manager"/>
<ccm_core.role_memberships membership_id="-300"
role_id="-200"
member_id="-110" />
<ccm_core.permissions permission_id="-400"
granted_privilege="manage_shortcuts"
grantee_id="-200" />
<ccm_shortcuts.shortcuts shortcut_id="-10" <ccm_shortcuts.shortcuts shortcut_id="-10"
url_key="mitglieder" url_key="/mitglieder/"
redirect="/ccm/navigation/members" /> redirect="/ccm/navigation/members" />
<ccm_shortcuts.shortcuts shortcut_id="-20" <ccm_shortcuts.shortcuts shortcut_id="-20"
url_key="members" url_key="/members/"
redirect="/ccm/navigation/members" /> redirect="/ccm/navigation/members" />
<ccm_shortcuts.shortcuts shortcut_id="-30" <ccm_shortcuts.shortcuts shortcut_id="-30"
url_key="privacy" url_key="/privacy/"
redirect="/ccm/navigation/privacy" /> redirect="/ccm/navigation/privacy" />
<ccm_shortcuts.shortcuts shortcut_id="-40" <ccm_shortcuts.shortcuts shortcut_id="-40"
url_key="shop" url_key="/shop/"
redirect="http://www.example.com" /> redirect="http://www.example.com" />
<ccm_shortcuts.shortcuts shortcut_id="-50" <ccm_shortcuts.shortcuts shortcut_id="-50"
url_key="datenschutz" url_key="/datenschutz/"
redirect="/ccm/navigation/privacy" /> redirect="/ccm/navigation/privacy" />
</dataset> </dataset>

View File

@ -36,15 +36,15 @@
grantee_id="-200" /> grantee_id="-200" />
<ccm_shortcuts.shortcuts shortcut_id="-10" <ccm_shortcuts.shortcuts shortcut_id="-10"
url_key="mitglieder" url_key="/mitglieder/"
redirect="/ccm/navigation/members" /> redirect="/ccm/navigation/members" />
<ccm_shortcuts.shortcuts shortcut_id="-20" <ccm_shortcuts.shortcuts shortcut_id="-20"
url_key="members" url_key="/members/"
redirect="/ccm/navigation/members" /> redirect="/ccm/navigation/members" />
<ccm_shortcuts.shortcuts shortcut_id="-30" <ccm_shortcuts.shortcuts shortcut_id="-30"
url_key="privacy" url_key="/privacy/"
redirect="/ccm/navigation/privacy" /> redirect="/ccm/navigation/privacy" />
<ccm_shortcuts.shortcuts shortcut_id="-40" <ccm_shortcuts.shortcuts shortcut_id="-40"
url_key="shop" url_key="/shop/"
redirect="http://www.example.com" /> redirect="http://www.example.com" />
</dataset> </dataset>