From 6ddb7b6b224a00344a182761e42b2241a721224f Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sat, 14 Feb 2015 13:31:59 +0000 Subject: [PATCH] Move security model to CMS git-svn-id: https://svn.argeo.org/commons/trunk@7868 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- demo/log4j.properties | 14 +- org.argeo.cms/bnd.bnd | 5 +- .../org/argeo/cms/auth/ArgeoLoginContext.java | 53 ++++ .../cms/auth}/LoginCanceledException.java | 2 +- .../internal/auth/AbstractLoginModule.java | 45 ++- .../internal/auth}/AnonymousLoginModule.java | 18 +- .../auth}/ConsoleCallbackHandler.java | 2 +- .../internal/auth}/EndUserLoginModule.java | 19 +- .../auth}/GrantedAuthorityPrincipal.java | 2 +- .../auth}/OsJcrAuthenticationProvider.java | 5 +- .../RemoteJcrAuthenticationProvider.java | 4 +- .../cms/internal/auth}/SystemLoginModule.java | 16 +- .../argeo/cms/internal/kernel/Activator.java | 31 +- .../cms/internal/kernel/NodeSecurity.java | 9 +- .../org/argeo/cms/internal/kernel/jaas.cfg | 6 +- .../cms/internal/useradmin/JcrUserAdmin.java | 1 - .../useradmin}/OsJcrUserAdminService.java | 4 +- .../useradmin}/SimpleJcrSecurityModel.java | 3 +- .../jackrabbit/JackrabbitSecurityModel.java | 4 +- .../JackrabbitUserAdminService.java | 4 +- .../jackrabbit/ScopedSessionProvider.java | 2 +- .../ldap/ArgeoLdapShaPasswordEncoder.java | 2 +- .../ldap/ArgeoLdapUserDetailsManager.java | 3 +- .../ldap/ArgeoUserAdminDaoLdap.java | 2 +- .../useradmin/ldap}/JcrLdapSynchronizer.java | 5 +- .../ldap}/JcrUserDetailsContextMapper.java | 2 +- org.argeo.security.core/bnd.bnd | 3 - .../src/org/argeo/security/SecurityUtils.java | 11 - .../core/AbstractSystemExecution.java | 40 +-- .../argeo/security/jcr/JcrSecurityModel.java | 2 +- .../jcr/SecureThreadBoundSession.java | 1 + .../security/login/BundleContextCallback.java | 19 -- .../login/BundleContextCallbackHandler.java | 41 --- org.argeo.security.ui.rap/.classpath | 2 +- .../security/ui/rap/SecureEntryPoint.java | 21 +- .../argeo/security/ui/SecurityUiPlugin.java | 4 +- .../AbstractLoginDialog.java | 15 +- .../ui/auth/CompositeCallbackHandler.java | 291 ++++++++++++++++++ .../security/ui/auth/DefaultLoginDialog.java | 77 +++++ .../ui/dialogs/DefaultLoginDialog.java | 199 ------------ .../ext/test/org/argeo/jcr/MapperTest.java | 1 + .../argeo/jackrabbit/JackrabbitWrapper.java | 9 +- .../src/org/argeo/jcr/JcrUtils.java | 1 - 43 files changed, 586 insertions(+), 414 deletions(-) create mode 100644 org.argeo.cms/src/org/argeo/cms/auth/ArgeoLoginContext.java rename {org.argeo.security.core/src/org/argeo/security/login => org.argeo.cms/src/org/argeo/cms/auth}/LoginCanceledException.java (84%) rename org.argeo.security.core/src/org/argeo/security/login/AbstractSpringLoginModule.java => org.argeo.cms/src/org/argeo/cms/internal/auth/AbstractLoginModule.java (73%) rename {org.argeo.security.core/src/org/argeo/security/login => org.argeo.cms/src/org/argeo/cms/internal/auth}/AnonymousLoginModule.java (79%) rename {org.argeo.security.core/src/org/argeo/security/login => org.argeo.cms/src/org/argeo/cms/internal/auth}/ConsoleCallbackHandler.java (98%) rename {org.argeo.security.core/src/org/argeo/security/login => org.argeo.cms/src/org/argeo/cms/internal/auth}/EndUserLoginModule.java (87%) rename {org.argeo.security.core/src/org/argeo/security/login => org.argeo.cms/src/org/argeo/cms/internal/auth}/GrantedAuthorityPrincipal.java (97%) rename {org.argeo.security.core/src/org/argeo/security/jcr => org.argeo.cms/src/org/argeo/cms/internal/auth}/OsJcrAuthenticationProvider.java (95%) rename {org.argeo.security.core/src/org/argeo/security/jcr => org.argeo.cms/src/org/argeo/cms/internal/auth}/RemoteJcrAuthenticationProvider.java (97%) rename {org.argeo.security.core/src/org/argeo/security/login => org.argeo.cms/src/org/argeo/cms/internal/auth}/SystemLoginModule.java (68%) rename {org.argeo.security.core/src/org/argeo/security/jcr => org.argeo.cms/src/org/argeo/cms/internal/useradmin}/OsJcrUserAdminService.java (96%) rename {org.argeo.security.core/src/org/argeo/security/jcr => org.argeo.cms/src/org/argeo/cms/internal/useradmin}/SimpleJcrSecurityModel.java (98%) rename {org.argeo.security.core/src/org/argeo/security/jcr => org.argeo.cms/src/org/argeo/cms/internal/useradmin}/jackrabbit/JackrabbitSecurityModel.java (96%) rename {org.argeo.security.core/src/org/argeo/security/jcr => org.argeo.cms/src/org/argeo/cms/internal/useradmin}/jackrabbit/JackrabbitUserAdminService.java (99%) rename {org.argeo.security.core/src/org/argeo/security/jcr => org.argeo.cms/src/org/argeo/cms/internal/useradmin}/jackrabbit/ScopedSessionProvider.java (99%) rename {org.argeo.security.core/src/org/argeo/security => org.argeo.cms/src/org/argeo/cms/internal/useradmin}/ldap/ArgeoLdapShaPasswordEncoder.java (96%) rename {org.argeo.security.core/src/org/argeo/security => org.argeo.cms/src/org/argeo/cms/internal/useradmin}/ldap/ArgeoLdapUserDetailsManager.java (98%) rename {org.argeo.security.core/src/org/argeo/security => org.argeo.cms/src/org/argeo/cms/internal/useradmin}/ldap/ArgeoUserAdminDaoLdap.java (99%) rename {org.argeo.security.core/src/org/argeo/security/ldap/jcr => org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap}/JcrLdapSynchronizer.java (99%) rename {org.argeo.security.core/src/org/argeo/security/ldap/jcr => org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap}/JcrUserDetailsContextMapper.java (98%) delete mode 100644 org.argeo.security.core/src/org/argeo/security/login/BundleContextCallback.java delete mode 100644 org.argeo.security.core/src/org/argeo/security/login/BundleContextCallbackHandler.java rename org.argeo.security.ui/src/org/argeo/security/ui/{dialogs => auth}/AbstractLoginDialog.java (93%) create mode 100644 org.argeo.security.ui/src/org/argeo/security/ui/auth/CompositeCallbackHandler.java create mode 100644 org.argeo.security.ui/src/org/argeo/security/ui/auth/DefaultLoginDialog.java delete mode 100644 org.argeo.security.ui/src/org/argeo/security/ui/dialogs/DefaultLoginDialog.java diff --git a/demo/log4j.properties b/demo/log4j.properties index 13f949ff5..53e2c2f19 100644 --- a/demo/log4j.properties +++ b/demo/log4j.properties @@ -2,21 +2,9 @@ log4j.rootLogger=WARN, development ## Levels log4j.logger.org.argeo=DEBUG -log4j.logger.org.argeo.jackrabbit.remote.ExtendedDispatcherServlet=WARN -log4j.logger.org.argeo.server.webextender.TomcatDeployer=INFO -#log4j.logger.org.springframework.security=DEBUG -#log4j.logger.org.apache.commons.exec=DEBUG -#log4j.logger.org.apache.jackrabbit.webdav=DEBUG -#log4j.logger.org.apache.jackrabbit.remote=DEBUG -#log4j.logger.org.apache.jackrabbit.core.observation=DEBUG - -log4j.logger.org.apache.catalina=INFO -log4j.logger.org.apache.coyote=INFO - -log4j.logger.org.apache.directory=INFO -log4j.logger.org.apache.directory.server=ERROR log4j.logger.org.apache.jackrabbit.core.query.lucene=ERROR +log4j.logger.org.apache.jackrabbit.core.config.ConfigurationErrorHandler=ERROR ## Appenders # console is set to be a ConsoleAppender. diff --git a/org.argeo.cms/bnd.bnd b/org.argeo.cms/bnd.bnd index bdcfd61d0..711fe437a 100644 --- a/org.argeo.cms/bnd.bnd +++ b/org.argeo.cms/bnd.bnd @@ -9,9 +9,12 @@ org.xml.sax;version="0.0.0",\ org.eclipse.swt.widgets;version="0.0.0",\ org.argeo.jcr,\ org.springframework.context,\ +org.springframework.security.authentication.jaas,\ org.apache.jackrabbit.api,\ org.apache.jackrabbit.commons,\ -org.eclipse.rap.rwt.osgi,\ org.h2;resolution:=optional,\ org.apache.commons.vfs2.*;resolution:=optional,\ +org.apache.jackrabbit.*;resolution:=optional,\ +org.springframework.ldap.*;resolution:=optional,\ +org.springframework.security.ldap.*;resolution:=optional,\ * diff --git a/org.argeo.cms/src/org/argeo/cms/auth/ArgeoLoginContext.java b/org.argeo.cms/src/org/argeo/cms/auth/ArgeoLoginContext.java new file mode 100644 index 000000000..3a536672a --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/auth/ArgeoLoginContext.java @@ -0,0 +1,53 @@ +package org.argeo.cms.auth; + +import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; + +/** Integrates JAAS with the Argeo platform */ +public class ArgeoLoginContext extends LoginContext { + private static ThreadLocal currentContextClassLoader = new ThreadLocal() { + @Override + protected ClassLoader initialValue() { + return Thread.currentThread().getContextClassLoader(); + } + + @Override + public void set(ClassLoader value) { + throw new IllegalAccessError("Current class loader is read-only"); + } + }; + + public ArgeoLoginContext(String name, Subject subject, + CallbackHandler callbackHandler) throws LoginException { + super(setContextClassLoaderForName(name), subject, callbackHandler); + // reset current context classloader + Thread.currentThread().setContextClassLoader( + currentContextClassLoader.get()); + currentContextClassLoader.remove(); + } + + /** + * Set the context classloader + * + * @return the passed name, in order to chain calls in the constructor + */ + private static String setContextClassLoaderForName(String name) { + // store current context class loader; + currentContextClassLoader.get(); + Thread.currentThread().setContextClassLoader( + ArgeoLoginContext.class.getClassLoader()); + return name; + } + + @Override + public void login() throws LoginException { + super.login(); + } + + @Override + public void logout() throws LoginException { + super.logout(); + } +} diff --git a/org.argeo.security.core/src/org/argeo/security/login/LoginCanceledException.java b/org.argeo.cms/src/org/argeo/cms/auth/LoginCanceledException.java similarity index 84% rename from org.argeo.security.core/src/org/argeo/security/login/LoginCanceledException.java rename to org.argeo.cms/src/org/argeo/cms/auth/LoginCanceledException.java index 5629e2e25..731cdd170 100644 --- a/org.argeo.security.core/src/org/argeo/security/login/LoginCanceledException.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/LoginCanceledException.java @@ -1,4 +1,4 @@ -package org.argeo.security.login; +package org.argeo.cms.auth; import javax.security.auth.login.LoginException; diff --git a/org.argeo.security.core/src/org/argeo/security/login/AbstractSpringLoginModule.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/AbstractLoginModule.java similarity index 73% rename from org.argeo.security.core/src/org/argeo/security/login/AbstractSpringLoginModule.java rename to org.argeo.cms/src/org/argeo/cms/internal/auth/AbstractLoginModule.java index 8a09a08e0..36d5e0fef 100644 --- a/org.argeo.security.core/src/org/argeo/security/login/AbstractSpringLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/AbstractLoginModule.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.login; +package org.argeo.cms.internal.auth; import java.io.IOException; import java.util.Map; @@ -24,14 +24,16 @@ import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; +import org.argeo.ArgeoException; +import org.argeo.cms.internal.kernel.Activator; import org.osgi.framework.BundleContext; -import org.osgi.service.useradmin.UserAdmin; +import org.osgi.framework.ServiceReference; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; /** Login module which caches one subject per thread. */ -abstract class AbstractSpringLoginModule implements LoginModule { +public abstract class AbstractLoginModule implements LoginModule { // private final static Log log = LogFactory // .getLog(AbstractSpringLoginModule.class); private CallbackHandler callbackHandler; @@ -39,16 +41,22 @@ abstract class AbstractSpringLoginModule implements LoginModule { private Authentication authentication; + // state + private BundleContext bundleContext; + private ServiceReference authenticationManager; + protected abstract Authentication processLogin( CallbackHandler callbackHandler) throws LoginException, UnsupportedCallbackException, IOException, InterruptedException; - @SuppressWarnings("rawtypes") @Override public void initialize(Subject subject, CallbackHandler callbackHandler, - Map sharedState, Map options) { + Map sharedState, Map options) { this.callbackHandler = callbackHandler; this.subject = subject; + this.bundleContext = Activator.getBundleContext(); + this.authenticationManager = bundleContext + .getServiceReference(AuthenticationManager.class); } @Override @@ -115,19 +123,28 @@ abstract class AbstractSpringLoginModule implements LoginModule { return true; } - protected AuthenticationManager getAuthenticationManager( - BundleContextCallback bundleContextCallback) { - BundleContext bc = bundleContextCallback.getBundleContext(); - return bc.getService(bc - .getServiceReference(AuthenticationManager.class)); - + /** + * Return the related {@link BundleContext} (never null), or throws an + * Exception if the login module was not properly initialised. + */ + protected BundleContext getBundleContext() { + if (bundleContext == null) + throw new ArgeoException("No bundle context provided"); + return bundleContext; } - protected UserAdmin getUserAdmin(BundleContextCallback bundleContextCallback) { - BundleContext bc = bundleContextCallback.getBundleContext(); - return bc.getService(bc.getServiceReference(UserAdmin.class)); + AuthenticationManager getAuthenticationManager() { + BundleContext bc = getBundleContext(); + assert authenticationManager != null; + return bc.getService(authenticationManager); } + // protected UserAdmin getUserAdmin(BundleContextCallback + // bundleContextCallback) { + // BundleContext bc = bundleContextCallback.getBundleContext(); + // return bc.getService(bc.getServiceReference(UserAdmin.class)); + // } + protected Subject getSubject() { return subject; } diff --git a/org.argeo.security.core/src/org/argeo/security/login/AnonymousLoginModule.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/AnonymousLoginModule.java similarity index 79% rename from org.argeo.security.core/src/org/argeo/security/login/AnonymousLoginModule.java rename to org.argeo.cms/src/org/argeo/cms/internal/auth/AnonymousLoginModule.java index 0a1279cae..6078b8f2b 100644 --- a/org.argeo.security.core/src/org/argeo/security/login/AnonymousLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/AnonymousLoginModule.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.login; +package org.argeo.cms.internal.auth; import java.io.IOException; import java.util.Collections; @@ -25,7 +25,7 @@ import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.LoginException; -import org.argeo.security.SecurityUtils; +import org.argeo.cms.internal.kernel.Activator; import org.argeo.util.LocaleCallback; import org.argeo.util.LocaleUtils; import org.springframework.security.authentication.AnonymousAuthenticationToken; @@ -33,7 +33,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.SimpleGrantedAuthority; /** Login module which caches one subject per thread. */ -public class AnonymousLoginModule extends AbstractSpringLoginModule { +public class AnonymousLoginModule extends AbstractLoginModule { private String anonymousRole = "ROLE_ANONYMOUS"; /** Comma separated list of locales */ private String availableLocales = null; @@ -42,25 +42,23 @@ public class AnonymousLoginModule extends AbstractSpringLoginModule { protected Authentication processLogin(CallbackHandler callbackHandler) throws LoginException, UnsupportedCallbackException, IOException, InterruptedException { - BundleContextCallback bundleContextCallback = new BundleContextCallback(); Locale selectedLocale = null; // multi locale if (availableLocales != null && !availableLocales.trim().equals("")) { LocaleCallback localeCallback = new LocaleCallback(availableLocales); - callbackHandler.handle(new Callback[] { localeCallback, - bundleContextCallback }); + callbackHandler.handle(new Callback[] { localeCallback }); selectedLocale = localeCallback.getSelectedLocale(); } else { - callbackHandler.handle(new Callback[] { bundleContextCallback }); + callbackHandler.handle(new Callback[] {}); } List authorities = Collections .singletonList(new SimpleGrantedAuthority(anonymousRole)); AnonymousAuthenticationToken anonymousToken = new AnonymousAuthenticationToken( - SecurityUtils.getStaticKey(), null, authorities); + Activator.getSystemKey(), null, authorities); - Authentication auth = getAuthenticationManager(bundleContextCallback) - .authenticate(anonymousToken); + Authentication auth = getAuthenticationManager().authenticate( + anonymousToken); if (selectedLocale != null) LocaleUtils.threadLocale.set(selectedLocale); diff --git a/org.argeo.security.core/src/org/argeo/security/login/ConsoleCallbackHandler.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/ConsoleCallbackHandler.java similarity index 98% rename from org.argeo.security.core/src/org/argeo/security/login/ConsoleCallbackHandler.java rename to org.argeo.cms/src/org/argeo/cms/internal/auth/ConsoleCallbackHandler.java index 4c47ac637..7ea9c0737 100644 --- a/org.argeo.security.core/src/org/argeo/security/login/ConsoleCallbackHandler.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/ConsoleCallbackHandler.java @@ -1,4 +1,4 @@ -package org.argeo.security.login; +package org.argeo.cms.internal.auth; import java.io.Console; import java.io.IOException; diff --git a/org.argeo.security.core/src/org/argeo/security/login/EndUserLoginModule.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/EndUserLoginModule.java similarity index 87% rename from org.argeo.security.core/src/org/argeo/security/login/EndUserLoginModule.java rename to org.argeo.cms/src/org/argeo/cms/internal/auth/EndUserLoginModule.java index e01e714fd..de2a007de 100644 --- a/org.argeo.security.core/src/org/argeo/security/login/EndUserLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/EndUserLoginModule.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.login; +package org.argeo.cms.internal.auth; import java.io.IOException; import java.util.Locale; @@ -23,6 +23,7 @@ import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.auth.login.CredentialNotFoundException; import javax.security.auth.login.LoginException; import org.argeo.security.NodeAuthenticationToken; @@ -32,7 +33,7 @@ import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.Authentication; /** Authenticates an end user */ -public class EndUserLoginModule extends AbstractSpringLoginModule { +public class EndUserLoginModule extends AbstractLoginModule { final static String NODE_REPO_URI = "argeo.node.repo.uri"; private Long waitBetweenFailedLoginAttempts = 5 * 1000l; @@ -53,27 +54,26 @@ public class EndUserLoginModule extends AbstractSpringLoginModule { "http://localhost:7070/org.argeo.jcr.webapp/remoting/node"); NameCallback urlCallback = new NameCallback("Site URL", defaultNodeUrl); LocaleCallback localeCallback = new LocaleCallback(availableLocales); - BundleContextCallback bundleContextCallback = new BundleContextCallback(); - // handle callbacks if (remote) callbackHandler.handle(new Callback[] { nameCallback, - passwordCallback, urlCallback, localeCallback, - bundleContextCallback }); + passwordCallback, urlCallback, localeCallback }); else callbackHandler.handle(new Callback[] { nameCallback, - passwordCallback, localeCallback, bundleContextCallback }); + passwordCallback, localeCallback }); Locale selectedLocale = localeCallback.getSelectedLocale(); // create credentials final String username = nameCallback.getName(); if (username == null || username.trim().equals("")) - throw new LoginCanceledException(); + throw new CredentialNotFoundException("No credentials provided"); char[] password = {}; if (passwordCallback.getPassword() != null) password = passwordCallback.getPassword(); + else + throw new CredentialNotFoundException("No credentials provided"); NodeAuthenticationToken credentials; if (remote) { @@ -85,8 +85,7 @@ public class EndUserLoginModule extends AbstractSpringLoginModule { Authentication auth; try { - auth = getAuthenticationManager(bundleContextCallback) - .authenticate(credentials); + auth = getAuthenticationManager().authenticate(credentials); } catch (BadCredentialsException e) { // wait between failed login attempts Thread.sleep(waitBetweenFailedLoginAttempts); diff --git a/org.argeo.security.core/src/org/argeo/security/login/GrantedAuthorityPrincipal.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/GrantedAuthorityPrincipal.java similarity index 97% rename from org.argeo.security.core/src/org/argeo/security/login/GrantedAuthorityPrincipal.java rename to org.argeo.cms/src/org/argeo/cms/internal/auth/GrantedAuthorityPrincipal.java index c176c04bc..a0622da3b 100644 --- a/org.argeo.security.core/src/org/argeo/security/login/GrantedAuthorityPrincipal.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/GrantedAuthorityPrincipal.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.login; +package org.argeo.cms.internal.auth; import java.security.Principal; diff --git a/org.argeo.security.core/src/org/argeo/security/jcr/OsJcrAuthenticationProvider.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/OsJcrAuthenticationProvider.java similarity index 95% rename from org.argeo.security.core/src/org/argeo/security/jcr/OsJcrAuthenticationProvider.java rename to org.argeo.cms/src/org/argeo/cms/internal/auth/OsJcrAuthenticationProvider.java index 7125604c7..61ed7ba35 100644 --- a/org.argeo.security.core/src/org/argeo/security/jcr/OsJcrAuthenticationProvider.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/OsJcrAuthenticationProvider.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.jcr; +package org.argeo.cms.internal.auth; import java.util.Collection; @@ -23,10 +23,13 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; import org.argeo.ArgeoException; +import org.argeo.cms.internal.useradmin.SimpleJcrSecurityModel; import org.argeo.jcr.JcrUtils; import org.argeo.security.OsAuthenticationToken; import org.argeo.security.SecurityUtils; import org.argeo.security.core.OsAuthenticationProvider; +import org.argeo.security.jcr.JcrSecurityModel; +import org.argeo.security.jcr.JcrUserDetails; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; diff --git a/org.argeo.security.core/src/org/argeo/security/jcr/RemoteJcrAuthenticationProvider.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/RemoteJcrAuthenticationProvider.java similarity index 97% rename from org.argeo.security.core/src/org/argeo/security/jcr/RemoteJcrAuthenticationProvider.java rename to org.argeo.cms/src/org/argeo/cms/internal/auth/RemoteJcrAuthenticationProvider.java index 154107576..b9ebaf761 100644 --- a/org.argeo.security.core/src/org/argeo/security/jcr/RemoteJcrAuthenticationProvider.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/RemoteJcrAuthenticationProvider.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.jcr; +package org.argeo.cms.internal.auth; import java.util.ArrayList; import java.util.Dictionary; @@ -33,6 +33,8 @@ import org.argeo.jcr.ArgeoJcrConstants; import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.UserJcrUtils; import org.argeo.security.NodeAuthenticationToken; +import org.argeo.security.jcr.JcrUserDetails; +import org.argeo.security.jcr.RemoteJcrRepositoryWrapper; import org.osgi.framework.BundleContext; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.BadCredentialsException; diff --git a/org.argeo.security.core/src/org/argeo/security/login/SystemLoginModule.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/SystemLoginModule.java similarity index 68% rename from org.argeo.security.core/src/org/argeo/security/login/SystemLoginModule.java rename to org.argeo.cms/src/org/argeo/cms/internal/auth/SystemLoginModule.java index 54e80e847..5e8587d25 100644 --- a/org.argeo.security.core/src/org/argeo/security/login/SystemLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/SystemLoginModule.java @@ -13,30 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.login; +package org.argeo.cms.internal.auth; import java.io.IOException; -import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.LoginException; -import org.argeo.security.SecurityUtils; +import org.argeo.cms.internal.kernel.Activator; import org.argeo.security.core.InternalAuthentication; import org.springframework.security.core.Authentication; /** Login module which caches one subject per thread. */ -public class SystemLoginModule extends AbstractSpringLoginModule { +public class SystemLoginModule extends AbstractLoginModule { @Override protected Authentication processLogin(CallbackHandler callbackHandler) throws LoginException, UnsupportedCallbackException, IOException, InterruptedException { - BundleContextCallback bundleContextCallback = new BundleContextCallback(); - callbackHandler.handle(new Callback[] { bundleContextCallback }); - InternalAuthentication anonymousToken = new InternalAuthentication( - SecurityUtils.getStaticKey()); - return getAuthenticationManager(bundleContextCallback).authenticate( - anonymousToken); + InternalAuthentication token = new InternalAuthentication( + Activator.getSystemKey()); + return getAuthenticationManager().authenticate(token); } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java index 4d166eaf6..5ec9f5087 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java @@ -1,15 +1,27 @@ package org.argeo.cms.internal.kernel; +import java.util.UUID; + import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; +/** + * Activates the {@link Kernel} from the provided {@link BundleContext}. Gives + * access to kernel information for the rest of the bundle (and only it) + */ public class Activator implements BundleActivator { + private final static String systemKey = UUID.randomUUID().toString(); + + private static BundleContext bundleContext; private Kernel kernel; @Override public void start(BundleContext context) throws Exception { + assert bundleContext == null; assert kernel == null; - kernel = new Kernel(context); + + bundleContext = context; + kernel = new Kernel(bundleContext); kernel.init(); } @@ -17,6 +29,23 @@ public class Activator implements BundleActivator { public void stop(BundleContext context) throws Exception { kernel.destroy(); kernel = null; + bundleContext = null; + } + + /** + * Singleton interface to the {@link BundleContext} related to the calling + * thread. Can be used only within the CMS bundle. + */ + public static BundleContext getBundleContext() { + return bundleContext; + } + + /** + * @return a String which is guaranteed to be unique between and constant + * within a Java static context (typically a VM launch) + */ + public final static String getSystemKey() { + return systemKey; } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java index d0aec2023..13f48f369 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java @@ -8,12 +8,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; import org.argeo.cms.internal.useradmin.JcrUserAdmin; -import org.argeo.security.SecurityUtils; +import org.argeo.cms.internal.useradmin.SimpleJcrSecurityModel; +import org.argeo.cms.internal.useradmin.jackrabbit.JackrabbitUserAdminService; import org.argeo.security.UserAdminService; import org.argeo.security.core.InternalAuthentication; import org.argeo.security.core.InternalAuthenticationProvider; -import org.argeo.security.jcr.SimpleJcrSecurityModel; -import org.argeo.security.jcr.jackrabbit.JackrabbitUserAdminService; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import org.osgi.service.useradmin.UserAdmin; @@ -52,9 +51,9 @@ class NodeSecurity implements AuthenticationManager { this.bundleContext = bundleContext; internalAuth = new InternalAuthenticationProvider( - SecurityUtils.getStaticKey()); + Activator.getSystemKey()); anonymousAuth = new AnonymousAuthenticationProvider( - SecurityUtils.getStaticKey()); + Activator.getSystemKey()); // user admin userAdminService = new JackrabbitUserAdminService(); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg index 55194eab8..cc1a07499 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg @@ -1,15 +1,15 @@ USER { - org.argeo.security.login.EndUserLoginModule requisite; + org.argeo.cms.internal.auth.EndUserLoginModule requisite; org.springframework.security.authentication.jaas.SecurityContextLoginModule requisite; }; ANONYMOUS { - org.argeo.security.login.AnonymousLoginModule requisite; + org.argeo.cms.internal.auth.AnonymousLoginModule requisite; org.springframework.security.authentication.jaas.SecurityContextLoginModule requisite; }; SYSTEM { - org.argeo.security.login.SystemLoginModule requisite; + org.argeo.cms.internal.auth.SystemLoginModule requisite; org.springframework.security.authentication.jaas.SecurityContextLoginModule requisite; }; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrUserAdmin.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrUserAdmin.java index 94051d92e..ecaf5e0af 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrUserAdmin.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrUserAdmin.java @@ -15,7 +15,6 @@ import org.argeo.jcr.JcrUtils; import org.argeo.security.UserAdminService; import org.argeo.security.jcr.JcrSecurityModel; import org.argeo.security.jcr.JcrUserDetails; -import org.argeo.security.jcr.SimpleJcrSecurityModel; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; diff --git a/org.argeo.security.core/src/org/argeo/security/jcr/OsJcrUserAdminService.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/OsJcrUserAdminService.java similarity index 96% rename from org.argeo.security.core/src/org/argeo/security/jcr/OsJcrUserAdminService.java rename to org.argeo.cms/src/org/argeo/cms/internal/useradmin/OsJcrUserAdminService.java index 1eab37048..4ad2ad16d 100644 --- a/org.argeo.security.core/src/org/argeo/security/jcr/OsJcrUserAdminService.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/OsJcrUserAdminService.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.jcr; +package org.argeo.cms.internal.useradmin; import java.util.ArrayList; import java.util.HashSet; @@ -26,9 +26,11 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; import org.argeo.ArgeoException; +import org.argeo.cms.internal.auth.OsJcrAuthenticationProvider; import org.argeo.jcr.JcrUtils; import org.argeo.jcr.UserJcrUtils; import org.argeo.security.UserAdminService; +import org.argeo.security.jcr.JcrUserDetails; import org.springframework.dao.DataAccessException; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; diff --git a/org.argeo.security.core/src/org/argeo/security/jcr/SimpleJcrSecurityModel.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/SimpleJcrSecurityModel.java similarity index 98% rename from org.argeo.security.core/src/org/argeo/security/jcr/SimpleJcrSecurityModel.java rename to org.argeo.cms/src/org/argeo/cms/internal/useradmin/SimpleJcrSecurityModel.java index fc0158738..029719c3a 100644 --- a/org.argeo.security.core/src/org/argeo/security/jcr/SimpleJcrSecurityModel.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/SimpleJcrSecurityModel.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.jcr; +package org.argeo.cms.internal.useradmin; import java.util.List; @@ -32,6 +32,7 @@ import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.ArgeoTypes; import org.argeo.jcr.JcrUtils; import org.argeo.jcr.UserJcrUtils; +import org.argeo.security.jcr.JcrSecurityModel; /** * Manages data expected by the Argeo security model, such as user home and diff --git a/org.argeo.security.core/src/org/argeo/security/jcr/jackrabbit/JackrabbitSecurityModel.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/jackrabbit/JackrabbitSecurityModel.java similarity index 96% rename from org.argeo.security.core/src/org/argeo/security/jcr/jackrabbit/JackrabbitSecurityModel.java rename to org.argeo.cms/src/org/argeo/cms/internal/useradmin/jackrabbit/JackrabbitSecurityModel.java index e52e6c6cb..de7f72466 100644 --- a/org.argeo.security.core/src/org/argeo/security/jcr/jackrabbit/JackrabbitSecurityModel.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/jackrabbit/JackrabbitSecurityModel.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.jcr.jackrabbit; +package org.argeo.cms.internal.useradmin.jackrabbit; import java.util.ArrayList; import java.util.Iterator; @@ -30,8 +30,8 @@ import org.apache.jackrabbit.api.security.user.Group; import org.apache.jackrabbit.api.security.user.User; import org.apache.jackrabbit.api.security.user.UserManager; import org.argeo.ArgeoException; +import org.argeo.cms.internal.useradmin.SimpleJcrSecurityModel; import org.argeo.jcr.ArgeoNames; -import org.argeo.security.jcr.SimpleJcrSecurityModel; /** Make sure that user authorizable exists before syncing user directories. */ public class JackrabbitSecurityModel extends SimpleJcrSecurityModel { diff --git a/org.argeo.security.core/src/org/argeo/security/jcr/jackrabbit/JackrabbitUserAdminService.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/jackrabbit/JackrabbitUserAdminService.java similarity index 99% rename from org.argeo.security.core/src/org/argeo/security/jcr/jackrabbit/JackrabbitUserAdminService.java rename to org.argeo.cms/src/org/argeo/cms/internal/useradmin/jackrabbit/JackrabbitUserAdminService.java index aceb51612..f846e1c74 100644 --- a/org.argeo.security.core/src/org/argeo/security/jcr/jackrabbit/JackrabbitUserAdminService.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/jackrabbit/JackrabbitUserAdminService.java @@ -1,4 +1,4 @@ -package org.argeo.security.jcr.jackrabbit; +package org.argeo.cms.internal.useradmin.jackrabbit; import java.util.ArrayList; import java.util.Arrays; @@ -24,9 +24,9 @@ import org.argeo.jcr.JcrUtils; import org.argeo.jcr.UserJcrUtils; import org.argeo.security.NodeAuthenticationToken; import org.argeo.security.UserAdminService; +import org.argeo.cms.internal.auth.GrantedAuthorityPrincipal; import org.argeo.security.jcr.JcrSecurityModel; import org.argeo.security.jcr.JcrUserDetails; -import org.argeo.security.login.GrantedAuthorityPrincipal; import org.springframework.dao.DataAccessException; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.BadCredentialsException; diff --git a/org.argeo.security.core/src/org/argeo/security/jcr/jackrabbit/ScopedSessionProvider.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/jackrabbit/ScopedSessionProvider.java similarity index 99% rename from org.argeo.security.core/src/org/argeo/security/jcr/jackrabbit/ScopedSessionProvider.java rename to org.argeo.cms/src/org/argeo/cms/internal/useradmin/jackrabbit/ScopedSessionProvider.java index 635f71ee2..dcb139939 100644 --- a/org.argeo.security.core/src/org/argeo/security/jcr/jackrabbit/ScopedSessionProvider.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/jackrabbit/ScopedSessionProvider.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.jcr.jackrabbit; +package org.argeo.cms.internal.useradmin.jackrabbit; import java.io.Serializable; diff --git a/org.argeo.security.core/src/org/argeo/security/ldap/ArgeoLdapShaPasswordEncoder.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/ArgeoLdapShaPasswordEncoder.java similarity index 96% rename from org.argeo.security.core/src/org/argeo/security/ldap/ArgeoLdapShaPasswordEncoder.java rename to org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/ArgeoLdapShaPasswordEncoder.java index a2c43a589..a1d25e92c 100644 --- a/org.argeo.security.core/src/org/argeo/security/ldap/ArgeoLdapShaPasswordEncoder.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/ArgeoLdapShaPasswordEncoder.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.ldap; +package org.argeo.cms.internal.useradmin.ldap; import org.springframework.security.authentication.encoding.LdapShaPasswordEncoder; diff --git a/org.argeo.security.core/src/org/argeo/security/ldap/ArgeoLdapUserDetailsManager.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/ArgeoLdapUserDetailsManager.java similarity index 98% rename from org.argeo.security.core/src/org/argeo/security/ldap/ArgeoLdapUserDetailsManager.java rename to org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/ArgeoLdapUserDetailsManager.java index 89b5aa92d..4381fa991 100644 --- a/org.argeo.security.core/src/org/argeo/security/ldap/ArgeoLdapUserDetailsManager.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/ArgeoLdapUserDetailsManager.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.ldap; +package org.argeo.cms.internal.useradmin.ldap; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; @@ -36,6 +36,7 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.ldap.userdetails.LdapUserDetailsManager; /** Extends {@link LdapUserDetailsManager} by adding password encoding support. */ +@SuppressWarnings("deprecation") public class ArgeoLdapUserDetailsManager extends LdapUserDetailsManager implements UserAdminService { private String superUsername = "root"; diff --git a/org.argeo.security.core/src/org/argeo/security/ldap/ArgeoUserAdminDaoLdap.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/ArgeoUserAdminDaoLdap.java similarity index 99% rename from org.argeo.security.core/src/org/argeo/security/ldap/ArgeoUserAdminDaoLdap.java rename to org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/ArgeoUserAdminDaoLdap.java index 37d2a06a0..faead2e76 100644 --- a/org.argeo.security.core/src/org/argeo/security/ldap/ArgeoUserAdminDaoLdap.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/ArgeoUserAdminDaoLdap.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.ldap; +package org.argeo.cms.internal.useradmin.ldap; import java.util.Collections; import java.util.List; diff --git a/org.argeo.security.core/src/org/argeo/security/ldap/jcr/JcrLdapSynchronizer.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/JcrLdapSynchronizer.java similarity index 99% rename from org.argeo.security.core/src/org/argeo/security/ldap/jcr/JcrLdapSynchronizer.java rename to org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/JcrLdapSynchronizer.java index e0519c37c..de28c7f49 100644 --- a/org.argeo.security.core/src/org/argeo/security/ldap/jcr/JcrLdapSynchronizer.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/JcrLdapSynchronizer.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.ldap.jcr; +package org.argeo.cms.internal.useradmin.ldap; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; @@ -41,13 +41,13 @@ import javax.naming.directory.ModificationItem; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.ArgeoException; +import org.argeo.cms.internal.useradmin.SimpleJcrSecurityModel; import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.ArgeoTypes; import org.argeo.jcr.JcrUtils; import org.argeo.security.SecurityUtils; import org.argeo.security.jcr.JcrSecurityModel; import org.argeo.security.jcr.JcrUserDetails; -import org.argeo.security.jcr.SimpleJcrSecurityModel; import org.springframework.ldap.core.ContextMapper; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DirContextOperations; @@ -60,6 +60,7 @@ import org.springframework.security.ldap.LdapUsernameToDnMapper; import org.springframework.security.ldap.userdetails.UserDetailsContextMapper; /** Makes sure that LDAP and JCR are in line. */ +@SuppressWarnings("deprecation") public class JcrLdapSynchronizer implements UserDetailsContextMapper, ArgeoNames { private final static Log log = LogFactory.getLog(JcrLdapSynchronizer.class); diff --git a/org.argeo.security.core/src/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/JcrUserDetailsContextMapper.java similarity index 98% rename from org.argeo.security.core/src/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java rename to org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/JcrUserDetailsContextMapper.java index f63250c31..acfcebc11 100644 --- a/org.argeo.security.core/src/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/ldap/JcrUserDetailsContextMapper.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.ldap.jcr; +package org.argeo.cms.internal.useradmin.ldap; import java.util.Collection; import java.util.UUID; diff --git a/org.argeo.security.core/bnd.bnd b/org.argeo.security.core/bnd.bnd index fa20c3d9e..9124816cb 100644 --- a/org.argeo.security.core/bnd.bnd +++ b/org.argeo.security.core/bnd.bnd @@ -2,7 +2,4 @@ Bundle-ActivationPolicy: lazy Import-Package:org.bouncycastle.*;resolution:=optional,\ org.springframework.util,\ javax.jcr.security,\ -org.apache.jackrabbit.*;resolution:=optional,\ -org.springframework.ldap.*;resolution:=optional,\ -org.springframework.security.ldap.*;resolution:=optional,\ * diff --git a/org.argeo.security.core/src/org/argeo/security/SecurityUtils.java b/org.argeo.security.core/src/org/argeo/security/SecurityUtils.java index 8c6715446..2d453d3da 100644 --- a/org.argeo.security.core/src/org/argeo/security/SecurityUtils.java +++ b/org.argeo.security.core/src/org/argeo/security/SecurityUtils.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.UUID; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; @@ -29,19 +28,9 @@ import org.springframework.security.core.context.SecurityContextHolder; /** Static utilities */ public final class SecurityUtils { - private final static String systemKey = UUID.randomUUID().toString(); - private SecurityUtils() { } - /** - * @return a String which is guaranteed to be unique between and constant - * within a Java static context (typically a VM launch) - */ - public final static String getStaticKey() { - return systemKey; - } - /** Whether the current thread has the admin role */ public static boolean hasCurrentThreadAuthority(String authority) { SecurityContext securityContext = SecurityContextHolder.getContext(); diff --git a/org.argeo.security.core/src/org/argeo/security/core/AbstractSystemExecution.java b/org.argeo.security.core/src/org/argeo/security/core/AbstractSystemExecution.java index 0d075c3a6..bdd110da9 100644 --- a/org.argeo.security.core/src/org/argeo/security/core/AbstractSystemExecution.java +++ b/org.argeo.security.core/src/org/argeo/security/core/AbstractSystemExecution.java @@ -15,17 +15,11 @@ */ package org.argeo.security.core; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.ArgeoException; import org.argeo.security.SystemAuthentication; -import org.argeo.security.login.BundleContextCallbackHandler; -import org.osgi.framework.BundleContext; import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; @@ -45,9 +39,7 @@ public abstract class AbstractSystemExecution { private final static Log log = LogFactory .getLog(AbstractSystemExecution.class); private AuthenticationManager authenticationManager; - private BundleContext bundleContext; private String systemAuthenticationKey; - private String loginContextName = "SYSTEM"; /** Whether the current thread was authenticated by this component. */ private ThreadLocal authenticatedBySelf = new ThreadLocal() { @@ -85,24 +77,12 @@ public abstract class AbstractSystemExecution { InternalAuthentication.SYSTEM_KEY_DEFAULT); if (key == null) throw new ArgeoException("No system key defined"); - if (authenticationManager != null) { - Authentication auth = authenticationManager - .authenticate(new InternalAuthentication(key)); - securityContext.setAuthentication(auth); - } else { - try { - // TODO test this - if (bundleContext == null) - throw new ArgeoException("bundleContext must be set"); - BundleContextCallbackHandler callbackHandler = new BundleContextCallbackHandler( - bundleContext); - LoginContext loginContext = new LoginContext(loginContextName, - callbackHandler); - loginContext.login(); - } catch (LoginException e) { - throw new BadCredentialsException("Cannot authenticate"); - } - } + if (authenticationManager == null) + throw new ArgeoException("Authentication manager cannot be null."); + Authentication auth = authenticationManager + .authenticate(new InternalAuthentication(key)); + securityContext.setAuthentication(auth); + authenticatedBySelf.set(true); if (log.isTraceEnabled()) log.trace("System authenticated"); @@ -128,20 +108,12 @@ public abstract class AbstractSystemExecution { return authenticatedBySelf.get(); } - @Deprecated public void setAuthenticationManager( AuthenticationManager authenticationManager) { - // log.warn("This approach is deprecated, inject bundleContext instead"); this.authenticationManager = authenticationManager; } - @Deprecated public void setSystemAuthenticationKey(String systemAuthenticationKey) { this.systemAuthenticationKey = systemAuthenticationKey; } - - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - } diff --git a/org.argeo.security.core/src/org/argeo/security/jcr/JcrSecurityModel.java b/org.argeo.security.core/src/org/argeo/security/jcr/JcrSecurityModel.java index e9ab89c2a..a151c7f30 100644 --- a/org.argeo.security.core/src/org/argeo/security/jcr/JcrSecurityModel.java +++ b/org.argeo.security.core/src/org/argeo/security/jcr/JcrSecurityModel.java @@ -30,7 +30,7 @@ public interface JcrSecurityModel { * user has a home directory with full access and a profile with information * about him (read access) * - * @return the user profile (whose parent is the user home), never null + * @return the user profile, never null */ public Node sync(Session session, String username, List roles); } diff --git a/org.argeo.security.core/src/org/argeo/security/jcr/SecureThreadBoundSession.java b/org.argeo.security.core/src/org/argeo/security/jcr/SecureThreadBoundSession.java index 7ef15947f..e0e887a3e 100644 --- a/org.argeo.security.core/src/org/argeo/security/jcr/SecureThreadBoundSession.java +++ b/org.argeo.security.core/src/org/argeo/security/jcr/SecureThreadBoundSession.java @@ -27,6 +27,7 @@ import org.springframework.security.core.context.SecurityContextHolder; * Thread bounded JCR session factory which checks authentication and is * autoconfigured in Spring. */ +@Deprecated public class SecureThreadBoundSession extends ThreadBoundSession { private final static Log log = LogFactory .getLog(SecureThreadBoundSession.class); diff --git a/org.argeo.security.core/src/org/argeo/security/login/BundleContextCallback.java b/org.argeo.security.core/src/org/argeo/security/login/BundleContextCallback.java deleted file mode 100644 index cf32af55c..000000000 --- a/org.argeo.security.core/src/org/argeo/security/login/BundleContextCallback.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.argeo.security.login; - -import javax.security.auth.callback.Callback; - -import org.osgi.framework.BundleContext; - -/** Gives access to the OSGi {@link BundleContext} */ -public class BundleContextCallback implements Callback { - private BundleContext bundleContext; - - public BundleContext getBundleContext() { - return bundleContext; - } - - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - -} diff --git a/org.argeo.security.core/src/org/argeo/security/login/BundleContextCallbackHandler.java b/org.argeo.security.core/src/org/argeo/security/login/BundleContextCallbackHandler.java deleted file mode 100644 index 3c7f9e844..000000000 --- a/org.argeo.security.core/src/org/argeo/security/login/BundleContextCallbackHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.argeo.security.login; - -import java.io.IOException; - -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.UnsupportedCallbackException; - -import org.osgi.framework.BundleContext; - -/** - * {@link CallbackHandler} that simply wraps a {@link BundleContext} and inject - * it in provided {@link BundleContextCallback} - */ -public class BundleContextCallbackHandler implements CallbackHandler { - private BundleContext bundleContext; - - public BundleContextCallbackHandler() { - } - - public BundleContextCallbackHandler(BundleContext bundleContext) { - super(); - this.bundleContext = bundleContext; - } - - @Override - public void handle(Callback[] callbacks) throws IOException, - UnsupportedCallbackException { - for (Callback callback : callbacks) { - if (callback instanceof BundleContextCallback) - ((BundleContextCallback) callback) - .setBundleContext(bundleContext); - } - - } - - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - -} diff --git a/org.argeo.security.ui.rap/.classpath b/org.argeo.security.ui.rap/.classpath index d2953a684..f9f1a39d8 100644 --- a/org.argeo.security.ui.rap/.classpath +++ b/org.argeo.security.ui.rap/.classpath @@ -4,6 +4,6 @@ + path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7" /> diff --git a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java index 65657dc66..9b01c5525 100644 --- a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java +++ b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java @@ -18,6 +18,8 @@ package org.argeo.security.ui.rap; import java.security.PrivilegedAction; import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.login.CredentialNotFoundException; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import javax.servlet.http.HttpServletRequest; @@ -27,9 +29,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.ArgeoException; import org.argeo.cms.KernelHeader; +import org.argeo.cms.auth.ArgeoLoginContext; import org.argeo.eclipse.ui.workbench.ErrorFeedback; -import org.argeo.security.login.LoginCanceledException; -import org.argeo.security.ui.dialogs.DefaultLoginDialog; +import org.argeo.security.ui.auth.DefaultLoginDialog; import org.argeo.util.LocaleUtils; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.rap.rwt.RWT; @@ -94,12 +96,14 @@ public class SecureEntryPoint implements EntryPoint { Subject subject = new Subject(); // log in - Thread.currentThread().setContextClassLoader( - getClass().getClassLoader()); + // Thread.currentThread().setContextClassLoader( + // getClass().getClassLoader()); final LoginContext loginContext; try { - loginContext = new LoginContext(KernelHeader.LOGIN_CONTEXT_USER, - subject, new DefaultLoginDialog(display.getActiveShell())); + CallbackHandler callbackHandler = new DefaultLoginDialog( + display.getActiveShell()); + loginContext = new ArgeoLoginContext( + KernelHeader.LOGIN_CONTEXT_USER, subject, callbackHandler); } catch (LoginException e1) { throw new ArgeoException("Cannot initialize login context", e1); } @@ -119,7 +123,8 @@ public class SecureEntryPoint implements EntryPoint { httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext()); // add thread locale to RWT session - log.info("Locale " + LocaleUtils.threadLocale.get()); + if (log.isTraceEnabled()) + log.trace("Locale " + LocaleUtils.threadLocale.get()); RWT.setLocale(LocaleUtils.threadLocale.get()); // Once the user is logged in, longer session timeout @@ -201,7 +206,7 @@ public class SecureEntryPoint implements EntryPoint { if (t instanceof BadCredentialsException) return (BadCredentialsException) t; - if (t instanceof LoginCanceledException) + if (t instanceof CredentialNotFoundException) return new BadCredentialsException("Login canceled"); if (t.getCause() != null) diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/SecurityUiPlugin.java b/org.argeo.security.ui/src/org/argeo/security/ui/SecurityUiPlugin.java index ad5b36203..a4190d69a 100644 --- a/org.argeo.security.ui/src/org/argeo/security/ui/SecurityUiPlugin.java +++ b/org.argeo.security.ui/src/org/argeo/security/ui/SecurityUiPlugin.java @@ -22,7 +22,7 @@ import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import org.argeo.ArgeoException; -import org.argeo.security.ui.dialogs.DefaultLoginDialog; +import org.argeo.security.ui.auth.DefaultLoginDialog; import org.eclipse.swt.widgets.Display; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; @@ -44,7 +44,7 @@ public class SecurityUiPlugin implements BundleActivator { // The plug-in ID public final static String PLUGIN_ID = "org.argeo.security.ui"; //$NON-NLS-1$ - public final static String CONTEXT_KEYRING = "KEYRING"; + final static String CONTEXT_KEYRING = "KEYRING"; private CallbackHandler defaultCallbackHandler; private ServiceRegistration defaultCallbackHandlerReg; diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/dialogs/AbstractLoginDialog.java b/org.argeo.security.ui/src/org/argeo/security/ui/auth/AbstractLoginDialog.java similarity index 93% rename from org.argeo.security.ui/src/org/argeo/security/ui/dialogs/AbstractLoginDialog.java rename to org.argeo.security.ui/src/org/argeo/security/ui/auth/AbstractLoginDialog.java index 8a8d1f66d..107697e75 100644 --- a/org.argeo.security.ui/src/org/argeo/security/ui/dialogs/AbstractLoginDialog.java +++ b/org.argeo.security.ui/src/org/argeo/security/ui/auth/AbstractLoginDialog.java @@ -13,9 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.ui.dialogs; +package org.argeo.security.ui.auth; import java.io.IOException; +import java.util.Arrays; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; @@ -158,9 +159,15 @@ public abstract class AbstractLoginDialog extends TrayDialog implements else // clear callbacks are when cancelling for (Callback callback : callbacks) - if (callback instanceof PasswordCallback) - ((PasswordCallback) callback).setPassword(null); - else if (callback instanceof NameCallback) + if (callback instanceof PasswordCallback) { + char[] arr = ((PasswordCallback) callback) + .getPassword(); + if (arr != null) { + Arrays.fill(arr, '*'); + ((PasswordCallback) callback) + .setPassword(null); + } + } else if (callback instanceof NameCallback) ((NameCallback) callback).setName(null); } }, true, new NullProgressMonitor(), Display.getDefault()); diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/auth/CompositeCallbackHandler.java b/org.argeo.security.ui/src/org/argeo/security/ui/auth/CompositeCallbackHandler.java new file mode 100644 index 000000000..a2fc83162 --- /dev/null +++ b/org.argeo.security.ui/src/org/argeo/security/ui/auth/CompositeCallbackHandler.java @@ -0,0 +1,291 @@ +package org.argeo.security.ui.auth; + +import java.io.IOException; +import java.util.Arrays; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.TextOutputCallback; +import javax.security.auth.callback.UnsupportedCallbackException; + +import org.argeo.util.LocaleCallback; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** + * A composite that can populate itself based on {@link Callback}s. It can be + * used directly as a {@link CallbackHandler} or be used by one by calling the + * {@link #createCallbackHandlers(Callback[])}. + *

+ * Supported standard {@link Callback}s are:
+ *

    + *
  • {@link PasswordCallback}
  • + *
  • {@link NameCallback}
  • + *
  • {@link TextOutputCallback}
  • + *
+ *

+ *

+ * Supported Argeo {@link Callback}s are:
+ *

    + *
  • {@link LocaleCallback}
  • + *
+ *

+ */ +public class CompositeCallbackHandler extends Composite implements + CallbackHandler { + private static final long serialVersionUID = -928223893722723777L; + + private boolean wasUsedAlready = false; + private boolean isSubmitted = false; + private boolean isCanceled = false; + + public CompositeCallbackHandler(Composite parent, int style) { + super(parent, style); + } + + @Override + public synchronized void handle(final Callback[] callbacks) + throws IOException, UnsupportedCallbackException { + // reset + if (wasUsedAlready && !isSubmitted() && !isCanceled()) { + cancel(); + for (Control control : getChildren()) + control.dispose(); + isSubmitted = false; + isCanceled = false; + } + + for (Callback callback : callbacks) + checkCallbackSupported(callback); + // create controls synchronously in the UI thread + getDisplay().syncExec(new Runnable() { + + @Override + public void run() { + createCallbackHandlers(callbacks); + } + }); + + if (!wasUsedAlready) + wasUsedAlready = true; + + while (!isSubmitted() && !isCanceled()) { + try { + wait(1000l); + } catch (InterruptedException e) { + // silent + } + } + + cleanCallbacksAfterCancel(callbacks); + } + + public void checkCallbackSupported(Callback callback) + throws UnsupportedCallbackException { + if (callback instanceof TextOutputCallback + || callback instanceof NameCallback + || callback instanceof PasswordCallback + || callback instanceof LocaleCallback) { + return; + } else { + throw new UnsupportedCallbackException(callback); + } + } + + /** + * Set writable callbacks to null if the handle is canceled (check is done + * by the method) + */ + public void cleanCallbacksAfterCancel(Callback[] callbacks) { + if (isCanceled()) { + for (Callback callback : callbacks) { + if (callback instanceof NameCallback) { + ((NameCallback) callback).setName(null); + } else if (callback instanceof PasswordCallback) { + PasswordCallback pCallback = (PasswordCallback) callback; + char[] arr = pCallback.getPassword(); + if (arr != null) { + Arrays.fill(arr, '*'); + pCallback.setPassword(null); + } + } + } + } + } + + public void createCallbackHandlers(Callback[] callbacks) { + Composite composite = this; + for (int i = 0; i < callbacks.length; i++) { + Callback callback = callbacks[i]; + if (callback instanceof TextOutputCallback) { + createLabelTextoutputHandler(composite, + (TextOutputCallback) callback); + } else if (callback instanceof NameCallback) { + createNameHandler(composite, (NameCallback) callback); + } else if (callback instanceof PasswordCallback) { + createPasswordHandler(composite, (PasswordCallback) callback); + } else if (callback instanceof LocaleCallback) { + createLocaleHandler(composite, (LocaleCallback) callback); + } + } + } + + protected Text createNameHandler(Composite composite, + final NameCallback callback) { + Label label = new Label(composite, SWT.NONE); + label.setText(callback.getPrompt()); + final Text text = new Text(composite, SWT.SINGLE | SWT.LEAD + | SWT.BORDER); + if (callback.getDefaultName() != null) { + // set default value, if provided + text.setText(callback.getDefaultName()); + callback.setName(callback.getDefaultName()); + } + text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + text.addModifyListener(new ModifyListener() { + private static final long serialVersionUID = 7300032545287292973L; + + public void modifyText(ModifyEvent event) { + callback.setName(text.getText()); + } + }); + text.addSelectionListener(new SelectionListener() { + private static final long serialVersionUID = 1820530045857665111L; + + @Override + public void widgetSelected(SelectionEvent e) { + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + submit(); + } + }); + + text.addKeyListener(new KeyListener() { + private static final long serialVersionUID = -8698107785092095713L; + + @Override + public void keyReleased(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + } + }); + return text; + } + + protected Text createPasswordHandler(Composite composite, + final PasswordCallback callback) { + Label label = new Label(composite, SWT.NONE); + label.setText(callback.getPrompt()); + final Text passwordText = new Text(composite, SWT.SINGLE | SWT.LEAD + | SWT.PASSWORD | SWT.BORDER); + passwordText + .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + passwordText.addModifyListener(new ModifyListener() { + private static final long serialVersionUID = -7099363995047686732L; + + public void modifyText(ModifyEvent event) { + callback.setPassword(passwordText.getTextChars()); + } + }); + passwordText.addSelectionListener(new SelectionListener() { + private static final long serialVersionUID = 1820530045857665111L; + + @Override + public void widgetSelected(SelectionEvent e) { + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + submit(); + } + }); + return passwordText; + } + + protected Combo createLocaleHandler(Composite composite, + final LocaleCallback callback) { + String[] labels = callback.getSupportedLocalesLabels(); + if (labels.length == 0) + return null; + Label label = new Label(composite, SWT.NONE); + label.setText(callback.getPrompt()); + + final Combo combo = new Combo(composite, SWT.READ_ONLY); + combo.setItems(labels); + combo.select(callback.getDefaultIndex()); + combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + combo.addSelectionListener(new SelectionListener() { + private static final long serialVersionUID = 38678989091946277L; + + @Override + public void widgetSelected(SelectionEvent e) { + callback.setSelectedIndex(combo.getSelectionIndex()); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + return combo; + } + + protected Label createLabelTextoutputHandler(Composite composite, + final TextOutputCallback callback) { + Label label = new Label(composite, SWT.NONE); + label.setText(callback.getMessage()); + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.horizontalSpan = 2; + label.setLayoutData(data); + return label; + // TODO: find a way to pass this information + // int messageType = callback.getMessageType(); + // int dialogMessageType = IMessageProvider.NONE; + // switch (messageType) { + // case TextOutputCallback.INFORMATION: + // dialogMessageType = IMessageProvider.INFORMATION; + // break; + // case TextOutputCallback.WARNING: + // dialogMessageType = IMessageProvider.WARNING; + // break; + // case TextOutputCallback.ERROR: + // dialogMessageType = IMessageProvider.ERROR; + // break; + // } + // setMessage(callback.getMessage(), dialogMessageType); + } + + synchronized boolean isSubmitted() { + return isSubmitted; + } + + synchronized boolean isCanceled() { + return isCanceled; + } + + protected synchronized void submit() { + isSubmitted = true; + notifyAll(); + } + + protected synchronized void cancel() { + isCanceled = true; + notifyAll(); + } +} diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/auth/DefaultLoginDialog.java b/org.argeo.security.ui/src/org/argeo/security/ui/auth/DefaultLoginDialog.java new file mode 100644 index 000000000..85f90bd3f --- /dev/null +++ b/org.argeo.security.ui/src/org/argeo/security/ui/auth/DefaultLoginDialog.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed 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.argeo.security.ui.auth; + +import javax.security.auth.callback.CallbackHandler; + +import org.argeo.security.ui.SecurityUiPlugin; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** Default authentication dialog, to be used as {@link CallbackHandler}. */ +public class DefaultLoginDialog extends AbstractLoginDialog { + private static final long serialVersionUID = -8551827590693035734L; + + public DefaultLoginDialog() { + this(SecurityUiPlugin.display.get().getActiveShell()); + } + + public DefaultLoginDialog(Shell parentShell) { + super(parentShell); + } + + protected Point getInitialSize() { + return new Point(350, 180); + } + + @Override + protected Control createContents(Composite parent) { + Control control = super.createContents(parent); + parent.pack(); + + // Move the dialog to the center of the top level shell. + Rectangle shellBounds; + if (Display.getCurrent().getActiveShell() != null) // RCP + shellBounds = Display.getCurrent().getActiveShell().getBounds(); + else + shellBounds = Display.getCurrent().getBounds();// RAP + Point dialogSize = parent.getSize(); + int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2; + int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2; + parent.setLocation(x, y); + return control; + } + + protected Control createDialogArea(Composite parent) { + Composite dialogarea = (Composite) super.createDialogArea(parent); + CompositeCallbackHandler composite = new CompositeCallbackHandler( + dialogarea, SWT.NONE); + composite.setLayout(new GridLayout(2, false)); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + composite.createCallbackHandlers(getCallbacks()); + return composite; + } + + public void internalHandle() { + } +} diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/dialogs/DefaultLoginDialog.java b/org.argeo.security.ui/src/org/argeo/security/ui/dialogs/DefaultLoginDialog.java deleted file mode 100644 index 3dea95bf9..000000000 --- a/org.argeo.security.ui/src/org/argeo/security/ui/dialogs/DefaultLoginDialog.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed 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.argeo.security.ui.dialogs; - -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.callback.TextOutputCallback; - -import org.argeo.security.login.BundleContextCallback; -import org.argeo.security.ui.SecurityUiPlugin; -import org.argeo.util.LocaleCallback; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - -/** Default authentication dialog, to be used as {@link CallbackHandler}. */ -public class DefaultLoginDialog extends AbstractLoginDialog { - private static final long serialVersionUID = -8551827590693035734L; - - public DefaultLoginDialog() { - this(SecurityUiPlugin.display.get().getActiveShell()); - } - - public DefaultLoginDialog(Shell parentShell) { - super(parentShell); - } - - protected Point getInitialSize() { - return new Point(350, 180); - } - - @Override - protected Control createContents(Composite parent) { - Control control = super.createContents(parent); - parent.pack(); - - // Move the dialog to the center of the top level shell. - Rectangle shellBounds; - if (Display.getCurrent().getActiveShell() != null) // RCP - shellBounds = Display.getCurrent().getActiveShell().getBounds(); - else - shellBounds = Display.getCurrent().getBounds();// RAP - Point dialogSize = parent.getSize(); - int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2; - int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2; - parent.setLocation(x, y); - return control; - } - - protected Control createDialogArea(Composite parent) { - Composite dialogarea = (Composite) super.createDialogArea(parent); - Composite composite = new Composite(dialogarea, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - createCallbackHandlers(composite); - // parent.pack(); - return composite; - } - - private void createCallbackHandlers(Composite composite) { - Callback[] callbacks = getCallbacks(); - for (int i = 0; i < callbacks.length; i++) { - Callback callback = callbacks[i]; - if (callback instanceof TextOutputCallback) { - createLabelTextoutputHandler(composite, - (TextOutputCallback) callback); - } else if (callback instanceof NameCallback) { - createNameHandler(composite, (NameCallback) callback); - } else if (callback instanceof PasswordCallback) { - createPasswordHandler(composite, (PasswordCallback) callback); - } else if (callback instanceof LocaleCallback) { - createLocaleHandler(composite, (LocaleCallback) callback); - } else if (callback instanceof BundleContextCallback) { - ((BundleContextCallback) callback) - .setBundleContext(SecurityUiPlugin.getBundleContext()); - } - } - } - - private void createPasswordHandler(Composite composite, - final PasswordCallback callback) { - Label label = new Label(composite, SWT.NONE); - label.setText(callback.getPrompt()); - final Text passwordText = new Text(composite, SWT.SINGLE | SWT.LEAD - | SWT.PASSWORD | SWT.BORDER); - passwordText - .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - passwordText.addModifyListener(new ModifyListener() { - private static final long serialVersionUID = -7099363995047686732L; - - public void modifyText(ModifyEvent event) { - // FIXME use getTextChars() in Eclipse 3.7 - callback.setPassword(passwordText.getText().toCharArray()); - } - }); - } - - private void createLocaleHandler(Composite composite, - final LocaleCallback callback) { - String[] labels = callback.getSupportedLocalesLabels(); - if (labels.length == 0) - return; - Label label = new Label(composite, SWT.NONE); - label.setText(callback.getPrompt()); - - final Combo combo = new Combo(composite, SWT.READ_ONLY); - combo.setItems(labels); - combo.select(callback.getDefaultIndex()); - combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - combo.addSelectionListener(new SelectionListener() { - private static final long serialVersionUID = 38678989091946277L; - - @Override - public void widgetSelected(SelectionEvent e) { - callback.setSelectedIndex(combo.getSelectionIndex()); - } - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - } - }); - } - - private void createNameHandler(Composite composite, - final NameCallback callback) { - Label label = new Label(composite, SWT.NONE); - label.setText(callback.getPrompt()); - final Text text = new Text(composite, SWT.SINGLE | SWT.LEAD - | SWT.BORDER); - if (callback.getDefaultName() != null) { - // set default value, if provided - text.setText(callback.getDefaultName()); - callback.setName(callback.getDefaultName()); - } - text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - text.addModifyListener(new ModifyListener() { - private static final long serialVersionUID = 7300032545287292973L; - - public void modifyText(ModifyEvent event) { - callback.setName(text.getText()); - } - }); - } - - private void createLabelTextoutputHandler(Composite composite, - final TextOutputCallback callback) { - Label label = new Label(composite, SWT.NONE); - label.setText(callback.getMessage()); - GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); - data.horizontalSpan = 2; - label.setLayoutData(data); - // TODO: find a way to pass this information - // int messageType = callback.getMessageType(); - // int dialogMessageType = IMessageProvider.NONE; - // switch (messageType) { - // case TextOutputCallback.INFORMATION: - // dialogMessageType = IMessageProvider.INFORMATION; - // break; - // case TextOutputCallback.WARNING: - // dialogMessageType = IMessageProvider.WARNING; - // break; - // case TextOutputCallback.ERROR: - // dialogMessageType = IMessageProvider.ERROR; - // break; - // } - // setMessage(callback.getMessage(), dialogMessageType); - } - - public void internalHandle() { - } -} diff --git a/org.argeo.server.jcr/ext/test/org/argeo/jcr/MapperTest.java b/org.argeo.server.jcr/ext/test/org/argeo/jcr/MapperTest.java index 5486ff458..8f4599cd6 100644 --- a/org.argeo.server.jcr/ext/test/org/argeo/jcr/MapperTest.java +++ b/org.argeo.server.jcr/ext/test/org/argeo/jcr/MapperTest.java @@ -19,6 +19,7 @@ import javax.jcr.Node; import org.argeo.jcr.spring.BeanNodeMapper; +@Deprecated public class MapperTest extends AbstractInternalJackrabbitTestCase { public void testSimpleObject() throws Exception { SimpleObject mySo = new SimpleObject(); diff --git a/org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitWrapper.java b/org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitWrapper.java index 53a9ff1e2..c1addf162 100644 --- a/org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitWrapper.java +++ b/org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitWrapper.java @@ -58,6 +58,7 @@ import org.springframework.core.io.ResourceLoader; * Wrapper around a Jackrabbit repository which allows to simplify configuration * and intercept some actions. It exposes itself as a {@link Repository}. */ +@SuppressWarnings("deprecation") public class JackrabbitWrapper extends JcrRepositoryWrapper implements ResourceLoaderAware { private final static Log log = LogFactory.getLog(JackrabbitWrapper.class); @@ -170,8 +171,8 @@ public class JackrabbitWrapper extends JcrRepositoryWrapper implements String oldDigest = JcrUtils.checksumFile(dataModel, DIGEST_ALGORITHM); if (oldDigest.equals(newDigest)) { - if (log.isDebugEnabled()) - log.debug("Data model " + resUrl + if (log.isTraceEnabled()) + log.trace("Data model " + resUrl + " hasn't changed, keeping version " + currentVersion); return; @@ -313,8 +314,8 @@ public class JackrabbitWrapper extends JcrRepositoryWrapper implements resUrl = resUrl.substring(1); String pkg = resUrl.substring(0, resUrl.lastIndexOf('/')).replace('/', '.'); - ServiceReference paSr = bundleContext - .getServiceReference(PackageAdmin.class.getName()); + ServiceReference paSr = bundleContext + .getServiceReference(PackageAdmin.class); PackageAdmin packageAdmin = (PackageAdmin) bundleContext .getService(paSr); diff --git a/org.argeo.server.jcr/src/org/argeo/jcr/JcrUtils.java b/org.argeo.server.jcr/src/org/argeo/jcr/JcrUtils.java index 2176e757c..3b546684a 100644 --- a/org.argeo.server.jcr/src/org/argeo/jcr/JcrUtils.java +++ b/org.argeo.server.jcr/src/org/argeo/jcr/JcrUtils.java @@ -1415,7 +1415,6 @@ public class JcrUtils implements ArgeoJcrConstants { * files * @return how many files were copied */ - @SuppressWarnings("resource") public static Long copyFiles(Node fromNode, Node toNode, Boolean recursive, ArgeoMonitor monitor) { long count = 0l; -- 2.30.2