Index: xwiki-core/src/main/java/com/xpn/xwiki/user/impl/xwiki/XWikiAuthServiceImpl.java =================================================================== --- xwiki-core/src/main/java/com/xpn/xwiki/user/impl/xwiki/XWikiAuthServiceImpl.java (revision 18352) +++ xwiki-core/src/main/java/com/xpn/xwiki/user/impl/xwiki/XWikiAuthServiceImpl.java (working copy) @@ -381,22 +381,29 @@ // This is needed for virtual mode to work if (context != null) { String susername = cannonicalUsername; + String virtualXwikiName = null; int i = cannonicalUsername.indexOf("."); int j = cannonicalUsername.indexOf(":"); if (i != -1) { susername = cannonicalUsername.substring(i + 1); - } else if (j != -1) { + } else if (j > 0) { // The username could be in the format xwiki:Username, so strip the wiki prefix. + // read the Virtual Wiki Database Name susername = cannonicalUsername.substring(j + 1); + virtualXwikiName = cannonicalUsername.substring(0, j); } - // First we check in the local database + // Set the context database to the virtual wiki database name. + if (virtualXwikiName != null) + context.setDatabase(virtualXwikiName); + + // Check in the local database or database with virtual xwiki name. try { String user = findUser(susername, context); if (user != null) { if (checkPassword(user, password, context)) { - return new SimplePrincipal(user); + return new SimplePrincipal(virtualXwikiName != null ? context.getDatabase() + ":" + user : user); } else { context.put("message", "wrongpassword"); } Index: xwiki-core/src/test/java/com/xpn/xwiki/user/impl/xwiki/XWikiAuthServiceImplTest.java =================================================================== --- xwiki-core/src/test/java/com/xpn/xwiki/user/impl/xwiki/XWikiAuthServiceImplTest.java (revision 18352) +++ xwiki-core/src/test/java/com/xpn/xwiki/user/impl/xwiki/XWikiAuthServiceImplTest.java (working copy) @@ -123,4 +123,58 @@ assertNotNull(principal); assertEquals("XWiki.SomeUser", principal.getName()); } + + /** + * Test that user is authenticated with a global account when a local one with the same name exists. + */ + + public void testLogintoVirtualXwikiWithWikiPrefixUsername() throws Exception + { + + // Setup a simple user profile documents + XWikiDocument userDocLocal = new XWikiDocument("local", "XWiki", "Admin"); + XWikiDocument userDocVirtual = new XWikiDocument("xwiki", "XWiki", "Admin"); + + // Make a simple XWiki.XWikiUsers class that will contain a default password field + BaseClass userClass = new BaseClass(); + userClass.addPasswordField("password", "Password", 20); + userClass.setClassName("XWiki.XWikiUsers"); + + // Mock the XWikiUsers object, since a real objects requires more mocking on the XWiki object + Mock mockUserObj = mock(BaseObject.class, new Class[] {}, new Object[] {}); + mockUserObj.stubs().method("setWiki"); + mockUserObj.stubs().method("setName"); + mockUserObj.stubs().method("setNumber"); + mockUserObj.stubs().method("getStringValue").with(eq("password")).will(returnValue("admin")); + userDocLocal.addObject("XWiki.XWikiUsers", (BaseObject) mockUserObj.proxy()); + + // Prepare the XWiki mock for local + this.mockXWiki.stubs().method("getDocument").with(eq("XWiki.Admin"), eq(this.getContext())).will( + returnValue(userDocLocal)); + this.mockXWiki.stubs().method("getClass").with(eq("XWiki.XWikiUsers"), eq(this.getContext())).will( + returnValue(userClass)); + this.mockXWiki.stubs().method("exists").will(returnValue(true)); + this.mockXWiki.stubs().method("isVirtualMode").will(returnValue(false)); + + // Run the test: Using Xwiki.Admin should correctly authenticate the Admin user + Principal principalLocal = this.authService.authenticate("XWiki.Admin", "admin", this.getContext()); + assertNotNull(principalLocal); + assertEquals("XWiki.Admin", principalLocal.getName()); + + // Set the database name to local. + this.getContext().setDatabase("local"); + + // Prepare the XWiki mock for virtual + this.mockXWiki.stubs().method("getDocument").with(eq("XWiki.Admin"), eq(this.getContext())).will( + returnValue(userDocVirtual)); + this.mockXWiki.stubs().method("isVirtualMode").will(returnValue(true)); + userDocVirtual.addObject("XWiki.XWikiUsers", (BaseObject) mockUserObj.proxy()); + + // Finally run the test: Using xwiki:Xwiki.Admin should correctly authenticate the Admin user + Principal principalVirtual = this.authService.authenticate("xwiki:XWiki.Admin", "admin", this.getContext()); + assertNotNull(principalVirtual); + assertEquals("XWiki.Admin", principalVirtual.getName()); + + } + }