You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jspwiki.apache.org by ju...@apache.org on 2020/02/24 16:53:00 UTC

[jspwiki] 18/38: Use Engine instead of WikiEngine in SecurityVerifier + Extract DummyUserDatabase to its own class

This is an automated email from the ASF dual-hosted git repository.

juanpablo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jspwiki.git

commit dbee4c25e3bbc8471737c731299a10bbded71e77
Author: juanpablo <ju...@apache.org>
AuthorDate: Fri Feb 21 12:20:07 2020 +0100

    Use Engine instead of WikiEngine in SecurityVerifier + Extract DummyUserDatabase to its own class
---
 .../org/apache/wiki/auth/DefaultUserManager.java   | 111 +--------
 .../org/apache/wiki/auth/SecurityVerifier.java     | 265 ++++++++-------------
 .../apache/wiki/auth/user/DummyUserDatabase.java   | 135 +++++++++++
 3 files changed, 230 insertions(+), 281 deletions(-)

diff --git a/jspwiki-main/src/main/java/org/apache/wiki/auth/DefaultUserManager.java b/jspwiki-main/src/main/java/org/apache/wiki/auth/DefaultUserManager.java
index c2b13af..5037db3 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/auth/DefaultUserManager.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/auth/DefaultUserManager.java
@@ -32,7 +32,7 @@ import org.apache.wiki.api.exceptions.WikiException;
 import org.apache.wiki.api.filters.PageFilter;
 import org.apache.wiki.auth.permissions.AllPermission;
 import org.apache.wiki.auth.permissions.WikiPermission;
-import org.apache.wiki.auth.user.AbstractUserDatabase;
+import org.apache.wiki.auth.user.DummyUserDatabase;
 import org.apache.wiki.auth.user.DuplicateUserException;
 import org.apache.wiki.auth.user.UserDatabase;
 import org.apache.wiki.auth.user.UserProfile;
@@ -402,115 +402,6 @@ public class DefaultUserManager implements UserManager {
         return getUserDatabase().getWikiNames();
     }
 
-    /**
-     * This is a database that gets used if nothing else is available. It does nothing of note - it just mostly throws
-     * NoSuchPrincipalExceptions if someone tries to log in.
-     */
-    public static class DummyUserDatabase extends AbstractUserDatabase {
-
-        /**
-         * No-op.
-         * @param loginName the login name to delete
-         */
-        @Override
-        public void deleteByLoginName( final String loginName ) {
-            // No operation
-        }
-
-        /**
-         * No-op; always throws <code>NoSuchPrincipalException</code>.
-         * @param index the name to search for
-         * @return the user profile
-         * @throws NoSuchPrincipalException always...
-         */
-        @Override
-        public UserProfile findByEmail(final String index) throws NoSuchPrincipalException {
-            throw new NoSuchPrincipalException("No user profiles available");
-        }
-
-        /**
-         * No-op; always throws <code>NoSuchPrincipalException</code>.
-         * @param index the name to search for
-         * @return the user profile
-         * @throws NoSuchPrincipalException always...
-         */
-        @Override
-        public UserProfile findByFullName(final String index) throws NoSuchPrincipalException {
-            throw new NoSuchPrincipalException("No user profiles available");
-        }
-
-        /**
-         * No-op; always throws <code>NoSuchPrincipalException</code>.
-         * @param index the name to search for
-         * @return the user profile
-         * @throws NoSuchPrincipalException always...
-         */
-        @Override
-        public UserProfile findByLoginName(final String index) throws NoSuchPrincipalException {
-            throw new NoSuchPrincipalException("No user profiles available");
-        }
-
-        /**
-         * No-op; always throws <code>NoSuchPrincipalException</code>.
-         * @param uid the unique identifier to search for
-         * @return the user profile
-         * @throws NoSuchPrincipalException always...
-         */
-        @Override
-        public UserProfile findByUid( final String uid ) throws NoSuchPrincipalException {
-            throw new NoSuchPrincipalException("No user profiles available");
-        }
-        /**
-         * No-op; always throws <code>NoSuchPrincipalException</code>.
-         * @param index the name to search for
-         * @return the user profile
-         * @throws NoSuchPrincipalException always...
-         */
-        @Override
-        public UserProfile findByWikiName(final String index) throws NoSuchPrincipalException {
-            throw new NoSuchPrincipalException("No user profiles available");
-        }
-
-        /**
-         * No-op.
-         * @return a zero-length array
-         */
-        @Override
-        public Principal[] getWikiNames() {
-            return new Principal[0];
-        }
-
-        /**
-         * No-op.
-         *
-         * @param engine the wiki engine
-         * @param props the properties used to initialize the wiki engine
-         */
-        @Override
-        public void initialize( final Engine engine, final Properties props ) {
-        }
-
-        /**
-         * No-op; always throws <code>NoSuchPrincipalException</code>.
-         * @param loginName the login name
-         * @param newName the proposed new login name
-         * @throws NoSuchPrincipalException always...
-         */
-        @Override
-        public void rename( final String loginName, final String newName ) throws NoSuchPrincipalException {
-            throw new NoSuchPrincipalException("No user profiles available");
-        }
-
-        /**
-         * No-op.
-         * @param profile the user profile
-         */
-        @Override
-        public void save( final UserProfile profile ) {
-        }
-
-    }
-
     // events processing .......................................................
 
     /**
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/auth/SecurityVerifier.java b/jspwiki-main/src/main/java/org/apache/wiki/auth/SecurityVerifier.java
index 6946732..fbe727d 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/auth/SecurityVerifier.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/auth/SecurityVerifier.java
@@ -20,8 +20,8 @@ package org.apache.wiki.auth;
 
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.log4j.Logger;
-import org.apache.wiki.WikiEngine;
 import org.apache.wiki.WikiSession;
+import org.apache.wiki.api.core.Engine;
 import org.apache.wiki.api.exceptions.WikiException;
 import org.apache.wiki.auth.authorize.Group;
 import org.apache.wiki.auth.authorize.GroupDatabase;
@@ -32,6 +32,7 @@ import org.apache.wiki.auth.permissions.AllPermission;
 import org.apache.wiki.auth.permissions.GroupPermission;
 import org.apache.wiki.auth.permissions.PermissionFactory;
 import org.apache.wiki.auth.permissions.WikiPermission;
+import org.apache.wiki.auth.user.DummyUserDatabase;
 import org.apache.wiki.auth.user.UserDatabase;
 import org.apache.wiki.auth.user.UserProfile;
 import org.freshcookies.security.policy.PolicyReader;
@@ -60,7 +61,7 @@ import java.util.Set;
  */
 public final class SecurityVerifier {
 
-    private WikiEngine            m_engine;
+    private Engine                m_engine;
 
     private boolean               m_isSecurityPolicyConfigured = false;
 
@@ -138,20 +139,15 @@ public final class SecurityVerifier {
      * @param engine the wiki engine
      * @param session the wiki session (typically, that of an administrator)
      */
-    public SecurityVerifier( final WikiEngine engine, final WikiSession session )
-    {
-        super();
+    public SecurityVerifier( final Engine engine, final WikiSession session ) {
         m_engine = engine;
         m_session = session;
         m_session.clearMessages();
         verifyJaas();
         verifyPolicy();
-        try
-        {
+        try {
             verifyPolicyAndContainerRoles();
-        }
-        catch ( final WikiException e )
-        {
+        } catch( final WikiException e ) {
             m_session.addMessage( ERROR_ROLES, e.getMessage() );
         }
         verifyGroupDatabase();
@@ -194,12 +190,9 @@ public final class SecurityVerifier {
 
         // Calculate column widths
         final String colWidth;
-        if ( pageActions.length > 0 && roles.length > 0 )
-        {
-            colWidth =  (67f / ( pageActions.length * roles.length )) + "%";
-        }
-        else
-        {
+        if( pageActions.length > 0 && roles.length > 0 ) {
+            colWidth = ( 67f / ( pageActions.length * roles.length ) ) + "%";
+        } else {
             colWidth = "67%";
         }
 
@@ -232,14 +225,11 @@ public final class SecurityVerifier {
         s.append( "  </tr>\n" );
 
         // Write page permission tests first
-        for( final String page : pages )
-        {
+        for( final String page : pages ) {
             s.append( "  <tr>\n" );
             s.append( "    <td>PagePermission \"" + wiki + ":" + page + "\"</td>\n" );
-            for( final Principal role : roles )
-            {
-                for( final String pageAction : pageActions )
-                {
+            for( final Principal role : roles ) {
+                for( final String pageAction : pageActions ) {
                     final Permission permission = PermissionFactory.getPagePermission( wiki + ":" + page, pageAction );
                     s.append( printPermissionTest( permission, role, 1 ) );
                 }
@@ -248,17 +238,13 @@ public final class SecurityVerifier {
         }
 
         // Now do the group tests
-        for( final String group : groups )
-        {
+        for( final String group : groups ) {
             s.append( "  <tr>\n" );
             s.append( "    <td>GroupPermission \"" + wiki + ":" + group + "\"</td>\n" );
-            for( final Principal role : roles )
-            {
-                for( final String groupAction : groupActions )
-                {
+            for( final Principal role : roles ) {
+                for( final String groupAction : groupActions ) {
                     Permission permission = null;
-                    if ( groupAction != null)
-                    {
+                    if( groupAction != null ) {
                         permission = new GroupPermission( wiki + ":" + group, groupAction );
                     }
                     s.append( printPermissionTest( permission, role, 1 ) );
@@ -269,14 +255,11 @@ public final class SecurityVerifier {
 
 
         // Now check the wiki-wide permissions
-        final String[] wikiPerms = new String[]
-        { "createGroups", "createPages", "login", "editPreferences", "editProfile" };
-        for( final String wikiPerm : wikiPerms )
-        {
+        final String[] wikiPerms = new String[] { "createGroups", "createPages", "login", "editPreferences", "editProfile" };
+        for( final String wikiPerm : wikiPerms ) {
             s.append( "  <tr>\n" );
             s.append( "    <td>WikiPermission \"" + wiki + "\",\"" + wikiPerm + "\"</td>\n" );
-            for( final Principal role : roles )
-            {
+            for( final Principal role : roles ) {
                 final Permission permission = new WikiPermission( wiki, wikiPerm );
                 s.append( printPermissionTest( permission, role, pageActions.length ) );
             }
@@ -304,16 +287,12 @@ public final class SecurityVerifier {
      * @param principal
      * @param cols
      */
-    private String printPermissionTest( final Permission permission, final Principal principal, final int cols )
-    {
+    private String printPermissionTest( final Permission permission, final Principal principal, final int cols ) {
     	final StringBuilder s = new StringBuilder();
-        if ( permission == null )
-        {
+        if( permission == null ) {
             s.append( "    <td colspan=\"" + cols + "\" align=\"center\" title=\"N/A\">" );
             s.append( "&nbsp;</td>\n" );
-        }
-        else
-        {
+        } else {
             final boolean allowed = verifyStaticPermission( principal, permission );
             s.append( "    <td colspan=\"" + cols + "\" align=\"center\" title=\"" );
             s.append( allowed ? "ALLOW: " : "DENY: " );
@@ -347,15 +326,12 @@ public final class SecurityVerifier {
      * @return the formatted HTML table containing the result of the tests
      * @throws WikiException if tests fail for unexpected reasons
      */
-    public String containerRoleTable() throws WikiException
-    {
-
-        final AuthorizationManager authorizationManager = m_engine.getAuthorizationManager();
+    public String containerRoleTable() throws WikiException {
+        final AuthorizationManager authorizationManager = m_engine.getManager( AuthorizationManager.class );
         final Authorizer authorizer = authorizationManager.getAuthorizer();
 
         // If authorizer not WebContainerAuthorizer, print error message
-        if ( !( authorizer instanceof WebContainerAuthorizer ) )
-        {
+        if ( !( authorizer instanceof WebContainerAuthorizer ) ) {
             throw new IllegalStateException( "Authorizer should be WebContainerAuthorizer" );
         }
 
@@ -373,8 +349,7 @@ public final class SecurityVerifier {
         s.append( "  </tr>\n" );
         s.append( "  <tr>\n" );
         s.append( "    <th>Anonymous</th>\n" );
-        for( final Principal role : roles )
-        {
+        for( final Principal role : roles ) {
             s.append( "    <th>" + role.getName() + "</th>\n" );
         }
         s.append( "</tr>\n" );
@@ -382,8 +357,7 @@ public final class SecurityVerifier {
         s.append( "<tbody>\n" );
 
         final WebContainerAuthorizer wca = (WebContainerAuthorizer) authorizer;
-        for( int i = 0; i < CONTAINER_ACTIONS.length; i++ )
-        {
+        for( int i = 0; i < CONTAINER_ACTIONS.length; i++ ) {
             final String action = CONTAINER_ACTIONS[i];
             final String jsp = CONTAINER_JSPS[i];
 
@@ -433,17 +407,15 @@ public final class SecurityVerifier {
     }
 
     /**
-     * If the active Authorizer is the WebContainerAuthorizer, returns the roles
-     * it knows about; otherwise, a zero-length array.
+     * If the active Authorizer is the WebContainerAuthorizer, returns the roles it knows about; otherwise, a zero-length array.
+     *
      * @return the roles parsed from <code>web.xml</code>, or a zero-length array
      * @throws WikiException if the web authorizer cannot obtain the list of roles
      */
-    public Principal[] webContainerRoles() throws WikiException
-    {
-        final Authorizer authorizer = m_engine.getAuthorizationManager().getAuthorizer();
-        if ( authorizer instanceof WebContainerAuthorizer )
-        {
-            return ( (WebContainerAuthorizer) authorizer ).getRoles();
+    public Principal[] webContainerRoles() throws WikiException {
+        final Authorizer authorizer = m_engine.getManager( AuthorizationManager.class ).getAuthorizer();
+        if ( authorizer instanceof WebContainerAuthorizer ) {
+            return authorizer.getRoles();
         }
         return new Principal[0];
     }
@@ -455,7 +427,7 @@ public final class SecurityVerifier {
      */
     protected void verifyPolicyAndContainerRoles() throws WikiException
     {
-        final Authorizer authorizer = m_engine.getAuthorizationManager().getAuthorizer();
+        final Authorizer authorizer = m_engine.getManager( AuthorizationManager.class ).getAuthorizer();
         final Principal[] containerRoles = authorizer.getRoles();
         boolean missing = false;
         for( final Principal principal : m_policyPrincipals )
@@ -483,29 +455,21 @@ public final class SecurityVerifier {
      */
     protected void verifyGroupDatabase()
     {
-        final GroupManager mgr = m_engine.getGroupManager();
+        final GroupManager mgr = m_engine.getManager( GroupManager.class );
         GroupDatabase db = null;
-        try
-        {
-            db = m_engine.getGroupManager().getGroupDatabase();
-        }
-        catch ( final WikiSecurityException e )
-        {
+        try {
+            db = m_engine.getManager( GroupManager.class ).getGroupDatabase();
+        } catch ( final WikiSecurityException e ) {
             m_session.addMessage( ERROR_GROUPS, "Could not retrieve GroupManager: " + e.getMessage() );
         }
 
         // Check for obvious error conditions
-        if ( mgr == null || db == null )
-        {
-            if ( mgr == null )
-            {
-                m_session.addMessage( ERROR_GROUPS, "GroupManager is null; JSPWiki could not " +
-                        "initialize it. Check the error logs." );
+        if ( mgr == null || db == null ) {
+            if ( mgr == null ) {
+                m_session.addMessage( ERROR_GROUPS, "GroupManager is null; JSPWiki could not initialize it. Check the error logs." );
             }
-            if ( db == null )
-            {
-                m_session.addMessage( ERROR_GROUPS, "GroupDatabase is null; JSPWiki could not " +
-                        "initialize it. Check the error logs." );
+            if ( db == null ) {
+                m_session.addMessage( ERROR_GROUPS, "GroupDatabase is null; JSPWiki could not initialize it. Check the error logs." );
             }
             return;
         }
@@ -513,61 +477,49 @@ public final class SecurityVerifier {
         // Everything initialized OK...
 
         // Tell user what class of database this is.
-        m_session.addMessage( INFO_GROUPS, "GroupDatabase is of type '" + db.getClass().getName() +
-                "'. It appears to be initialized properly." );
+        m_session.addMessage( INFO_GROUPS, "GroupDatabase is of type '" + db.getClass().getName() + "'. It appears to be initialized properly." );
 
         // Now, see how many groups we have.
-        int oldGroupCount = 0;
-        try
-        {
+        final int oldGroupCount;
+        try {
             final Group[] groups = db.groups();
             oldGroupCount = groups.length;
             m_session.addMessage( INFO_GROUPS, "The group database contains " + oldGroupCount + " groups." );
-        }
-        catch ( final WikiSecurityException e )
-        {
+        } catch( final WikiSecurityException e ) {
             m_session.addMessage( ERROR_GROUPS, "Could not obtain a list of current groups: " + e.getMessage() );
             return;
         }
 
         // Try adding a bogus group with random name
         final String name = "TestGroup" + System.currentTimeMillis();
-        Group group = null;
-        try
-        {
+        final Group group;
+        try {
             // Create dummy test group
             group = mgr.parseGroup( name, "", true );
             final Principal user = new WikiPrincipal( "TestUser" );
             group.add( user );
-            db.save( group, new WikiPrincipal("SecurityVerifier") );
+            db.save( group, new WikiPrincipal( "SecurityVerifier" ) );
 
             // Make sure the group saved successfully
-            if ( db.groups().length == oldGroupCount )
-            {
+            if( db.groups().length == oldGroupCount ) {
                 m_session.addMessage( ERROR_GROUPS, "Could not add a test group to the database." );
                 return;
             }
             m_session.addMessage( INFO_GROUPS, "The group database allows new groups to be created, as it should." );
-        }
-        catch ( final WikiSecurityException e )
-        {
+        } catch( final WikiSecurityException e ) {
             m_session.addMessage( ERROR_GROUPS, "Could not add a group to the database: " + e.getMessage() );
             return;
         }
 
         // Now delete the group; should be back to old count
-        try
-        {
+        try {
             db.delete( group );
-            if ( db.groups().length != oldGroupCount )
-            {
+            if( db.groups().length != oldGroupCount ) {
                 m_session.addMessage( ERROR_GROUPS, "Could not delete a test group from the database." );
                 return;
             }
             m_session.addMessage( INFO_GROUPS, "The group database allows groups to be deleted, as it should." );
-        }
-        catch ( final WikiSecurityException e )
-        {
+        } catch( final WikiSecurityException e ) {
             m_session.addMessage( ERROR_GROUPS, "Could not delete a test group from the database: " + e.getMessage() );
             return;
         }
@@ -581,42 +533,31 @@ public final class SecurityVerifier {
      * {@value org.apache.wiki.auth.AuthenticationManager#PROP_LOGIN_MODULE}
      * resolves to a valid class on the classpath.
      */
-    protected void verifyJaas()
-    {
+    protected void verifyJaas() {
         // Verify that the specified JAAS moduie corresponds to a class we can load successfully.
         final String jaasClass = m_engine.getWikiProperties().getProperty( AuthenticationManager.PROP_LOGIN_MODULE );
-        if ( jaasClass == null || jaasClass.length() == 0 )
-        {
-            m_session.addMessage( ERROR_JAAS, "The value of the '" + AuthenticationManager.PROP_LOGIN_MODULE +
-                    "' property was null or blank. This is a fatal error. This value should be set to a valid LoginModule implementation " +
-                    "on the classpath." );
+        if( jaasClass == null || jaasClass.length() == 0 ) {
+            m_session.addMessage( ERROR_JAAS, "The value of the '" + AuthenticationManager.PROP_LOGIN_MODULE
+                    + "' property was null or blank. This is a fatal error. This value should be set to a valid LoginModule implementation "
+                    + "on the classpath." );
             return;
         }
-        
+
         // See if we can find the LoginModule on the classpath
         Class< ? > c = null;
-        try
-        {
-            m_session.addMessage( INFO_JAAS, "The property '" + AuthenticationManager.PROP_LOGIN_MODULE +
-                                  "' specified the class '" + jaasClass + ".'" );
+        try {
+            m_session.addMessage( INFO_JAAS,
+                    "The property '" + AuthenticationManager.PROP_LOGIN_MODULE + "' specified the class '" + jaasClass + ".'" );
             c = Class.forName( jaasClass );
+        } catch( final ClassNotFoundException e ) {
+            m_session.addMessage( ERROR_JAAS, "We could not find the the class '" + jaasClass + "' on the " + "classpath. This is fatal error." );
         }
-        catch( final ClassNotFoundException e )
-        {
-            m_session.addMessage( ERROR_JAAS, "We could not find the the class '" + jaasClass + "' on the " +
-            "classpath. This is fatal error." );
-        }
-        
+
         // Is the specified class actually a LoginModule?
-        if ( LoginModule.class.isAssignableFrom( c ) )
-        {
-            m_session.addMessage( INFO_JAAS, "We found the the class '" + jaasClass + "' on the " +
-                    "classpath, and it is a LoginModule implementation. Good!" );
-        }
-        else
-        {
-            m_session.addMessage( ERROR_JAAS, "We found the the class '" + jaasClass + "' on the " +
-            "classpath, but it does not seem to be LoginModule implementation! This is fatal error." );
+        if( LoginModule.class.isAssignableFrom( c ) ) {
+            m_session.addMessage( INFO_JAAS, "We found the the class '" + jaasClass + "' on the classpath, and it is a LoginModule implementation. Good!" );
+        } else {
+            m_session.addMessage( ERROR_JAAS, "We found the the class '" + jaasClass + "' on the classpath, but it does not seem to be LoginModule implementation! This is fatal error." );
         }
     }
 
@@ -759,22 +700,15 @@ public final class SecurityVerifier {
     {
         final Subject subject = new Subject();
         subject.getPrincipals().add( principal );
-        final boolean allowedByGlobalPolicy = ((Boolean)
-            Subject.doAsPrivileged( subject, new PrivilegedAction<Object>()
-            {
-                @Override public Object run()
-                {
-                    try
-                    {
-                        AccessController.checkPermission( permission );
-                        return Boolean.TRUE;
-                    }
-                    catch ( final AccessControlException e )
-                    {
-                        return Boolean.FALSE;
-                    }
+        final boolean allowedByGlobalPolicy = (Boolean)
+            Subject.doAsPrivileged( subject, ( PrivilegedAction< Object > )() -> {
+                try {
+                    AccessController.checkPermission( permission );
+                    return Boolean.TRUE;
+                } catch( final AccessControlException e ) {
+                    return Boolean.FALSE;
                 }
-            }, null )).booleanValue();
+            }, null );
 
         if ( allowedByGlobalPolicy )
         {
@@ -783,7 +717,7 @@ public final class SecurityVerifier {
 
         // Check local policy
         final Principal[] principals = new Principal[]{ principal };
-        return m_engine.getAuthorizationManager().allowedByLocalPolicy( principals, permission );
+        return m_engine.getManager( AuthorizationManager.class ).allowedByLocalPolicy( principals, permission );
     }
 
     /**
@@ -792,7 +726,7 @@ public final class SecurityVerifier {
      */
     protected void verifyUserDatabase()
     {
-        final UserDatabase db = m_engine.getUserManager().getUserDatabase();
+        final UserDatabase db = m_engine.getManager( UserManager.class ).getUserDatabase();
 
         // Check for obvious error conditions
         if ( db == null )
@@ -802,7 +736,7 @@ public final class SecurityVerifier {
             return;
         }
 
-        if ( db instanceof UserManager.DummyUserDatabase )
+        if ( db instanceof DummyUserDatabase )
         {
             m_session.addMessage( ERROR_DB, "UserDatabase is DummyUserDatabase; JSPWiki " +
                     "may not have been able to initialize the database you supplied in " +
@@ -812,60 +746,49 @@ public final class SecurityVerifier {
 
         // Tell user what class of database this is.
         m_session.addMessage( INFO_DB, "UserDatabase is of type '" + db.getClass().getName() +
-                "'. It appears to be initialized properly." );
+                                       "'. It appears to be initialized properly." );
 
         // Now, see how many users we have.
-        int oldUserCount = 0;
-        try
-        {
+        final int oldUserCount;
+        try {
             final Principal[] users = db.getWikiNames();
             oldUserCount = users.length;
             m_session.addMessage( INFO_DB, "The user database contains " + oldUserCount + " users." );
-        }
-        catch ( final WikiSecurityException e )
-        {
+        } catch( final WikiSecurityException e ) {
             m_session.addMessage( ERROR_DB, "Could not obtain a list of current users: " + e.getMessage() );
             return;
         }
 
         // Try adding a bogus user with random name
         final String loginName = "TestUser" + System.currentTimeMillis();
-        try
-        {
+        try {
             final UserProfile profile = db.newProfile();
             profile.setEmail( "jspwiki.tests@mailinator.com" );
             profile.setLoginName( loginName );
-            profile.setFullname( "FullName"+loginName );
+            profile.setFullname( "FullName" + loginName );
             profile.setPassword( "password" );
-            db.save(profile);
+            db.save( profile );
 
             // Make sure the profile saved successfully
-            if ( db.getWikiNames().length == oldUserCount )
-            {
+            if( db.getWikiNames().length == oldUserCount ) {
                 m_session.addMessage( ERROR_DB, "Could not add a test user to the database." );
                 return;
             }
             m_session.addMessage( INFO_DB, "The user database allows new users to be created, as it should." );
-        }
-        catch ( final WikiSecurityException e )
-        {
+        } catch( final WikiSecurityException e ) {
             m_session.addMessage( ERROR_DB, "Could not add a test user to the database: " + e.getMessage() );
             return;
         }
 
         // Now delete the profile; should be back to old count
-        try
-        {
+        try {
             db.deleteByLoginName( loginName );
-            if ( db.getWikiNames().length != oldUserCount )
-            {
+            if( db.getWikiNames().length != oldUserCount ) {
                 m_session.addMessage( ERROR_DB, "Could not delete a test user from the database." );
                 return;
             }
             m_session.addMessage( INFO_DB, "The user database allows users to be deleted, as it should." );
-        }
-        catch ( final WikiSecurityException e )
-        {
+        } catch( final WikiSecurityException e ) {
             m_session.addMessage( ERROR_DB, "Could not delete a test user to the database: " + e.getMessage() );
             return;
         }
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/auth/user/DummyUserDatabase.java b/jspwiki-main/src/main/java/org/apache/wiki/auth/user/DummyUserDatabase.java
new file mode 100644
index 0000000..af4aea6
--- /dev/null
+++ b/jspwiki-main/src/main/java/org/apache/wiki/auth/user/DummyUserDatabase.java
@@ -0,0 +1,135 @@
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you 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 org.apache.wiki.auth.user;
+
+import org.apache.wiki.api.core.Engine;
+import org.apache.wiki.auth.NoSuchPrincipalException;
+
+import java.security.Principal;
+import java.util.Properties;
+
+
+/**
+ * This is a database that gets used if nothing else is available. It does nothing of note - it just mostly throws
+ * NoSuchPrincipalExceptions if someone tries to log in.
+ */
+public class DummyUserDatabase extends AbstractUserDatabase {
+
+    /**
+     * No-op.
+     * @param loginName the login name to delete
+     */
+    @Override
+    public void deleteByLoginName( final String loginName ) {
+        // No operation
+    }
+
+    /**
+     * No-op; always throws <code>NoSuchPrincipalException</code>.
+     * @param index the name to search for
+     * @return the user profile
+     * @throws NoSuchPrincipalException always...
+     */
+    @Override
+    public UserProfile findByEmail(final String index) throws NoSuchPrincipalException {
+        throw new NoSuchPrincipalException("No user profiles available");
+    }
+
+    /**
+     * No-op; always throws <code>NoSuchPrincipalException</code>.
+     * @param index the name to search for
+     * @return the user profile
+     * @throws NoSuchPrincipalException always...
+     */
+    @Override
+    public UserProfile findByFullName(final String index) throws NoSuchPrincipalException {
+        throw new NoSuchPrincipalException("No user profiles available");
+    }
+
+    /**
+     * No-op; always throws <code>NoSuchPrincipalException</code>.
+     * @param index the name to search for
+     * @return the user profile
+     * @throws NoSuchPrincipalException always...
+     */
+    @Override
+    public UserProfile findByLoginName(final String index) throws NoSuchPrincipalException {
+        throw new NoSuchPrincipalException("No user profiles available");
+    }
+
+    /**
+     * No-op; always throws <code>NoSuchPrincipalException</code>.
+     * @param uid the unique identifier to search for
+     * @return the user profile
+     * @throws NoSuchPrincipalException always...
+     */
+    @Override
+    public UserProfile findByUid( final String uid ) throws NoSuchPrincipalException {
+        throw new NoSuchPrincipalException("No user profiles available");
+    }
+    /**
+     * No-op; always throws <code>NoSuchPrincipalException</code>.
+     * @param index the name to search for
+     * @return the user profile
+     * @throws NoSuchPrincipalException always...
+     */
+    @Override
+    public UserProfile findByWikiName(final String index) throws NoSuchPrincipalException {
+        throw new NoSuchPrincipalException("No user profiles available");
+    }
+
+    /**
+     * No-op.
+     * @return a zero-length array
+     */
+    @Override
+    public Principal[] getWikiNames() {
+        return new Principal[0];
+    }
+
+    /**
+     * No-op.
+     *
+     * @param engine the wiki engine
+     * @param props the properties used to initialize the wiki engine
+     */
+    @Override
+    public void initialize( final Engine engine, final Properties props ) {
+    }
+
+    /**
+     * No-op; always throws <code>NoSuchPrincipalException</code>.
+     * @param loginName the login name
+     * @param newName the proposed new login name
+     * @throws NoSuchPrincipalException always...
+     */
+    @Override
+    public void rename( final String loginName, final String newName ) throws NoSuchPrincipalException {
+        throw new NoSuchPrincipalException("No user profiles available");
+    }
+
+    /**
+     * No-op.
+     * @param profile the user profile
+     */
+    @Override
+    public void save( final UserProfile profile ) {
+    }
+
+}