added injection support for authentication, group, repository and user listeners

This commit is contained in:
Sebastian Sdorra
2011-08-16 19:10:36 +02:00
parent de97f9a91b
commit a60f04e083
10 changed files with 133 additions and 86 deletions

View File

@@ -109,6 +109,16 @@ public class BindingExtensionProcessor implements ExtensionProcessor
Multibinder<ChangesetPreProcessorFactory> changesetPreProcessorFactoryBinder = Multibinder<ChangesetPreProcessorFactory> changesetPreProcessorFactoryBinder =
Multibinder.newSetBinder(binder, ChangesetPreProcessorFactory.class); Multibinder.newSetBinder(binder, ChangesetPreProcessorFactory.class);
// listeners
Multibinder<RepositoryListener> repositoryListenerBinder =
Multibinder.newSetBinder(binder, RepositoryListener.class);
Multibinder<UserListener> userListenerBinder =
Multibinder.newSetBinder(binder, UserListener.class);
Multibinder<GroupListener> groupListenerBinder =
Multibinder.newSetBinder(binder, GroupListener.class);
Multibinder<AuthenticationListener> authenticationListenerBinder =
Multibinder.newSetBinder(binder, AuthenticationListener.class);
authenticators.addBinding().to(XmlAuthenticationHandler.class); authenticators.addBinding().to(XmlAuthenticationHandler.class);
for (Class extensionClass : extensions) for (Class extensionClass : extensions)
@@ -147,9 +157,8 @@ public class BindingExtensionProcessor implements ExtensionProcessor
logger.info("bind GroupListener {}", extensionClass.getName()); logger.info("bind GroupListener {}", extensionClass.getName());
} }
GroupListener listener = (GroupListener) extensionClass.newInstance(); binder.bind(extensionClass);
groupListenerBinder.addBinding().to(extensionClass);
groupListeners.add(listener);
} }
else if (UserListener.class.isAssignableFrom(extensionClass)) else if (UserListener.class.isAssignableFrom(extensionClass))
{ {
@@ -158,9 +167,8 @@ public class BindingExtensionProcessor implements ExtensionProcessor
logger.info("bind UserListener {}", extensionClass.getName()); logger.info("bind UserListener {}", extensionClass.getName());
} }
UserListener listener = (UserListener) extensionClass.newInstance(); binder.bind(extensionClass);
userListenerBinder.addBinding().to(extensionClass);
userListeners.add(listener);
} }
else if (RepositoryListener.class.isAssignableFrom(extensionClass)) else if (RepositoryListener.class.isAssignableFrom(extensionClass))
{ {
@@ -169,10 +177,8 @@ public class BindingExtensionProcessor implements ExtensionProcessor
logger.info("bind RepositoryListener {}", extensionClass.getName()); logger.info("bind RepositoryListener {}", extensionClass.getName());
} }
RepositoryListener listener = binder.bind(extensionClass);
(RepositoryListener) extensionClass.newInstance(); repositoryListenerBinder.addBinding().to(extensionClass);
repositoryListeners.add(listener);
} }
else if (AuthenticationListener.class.isAssignableFrom(extensionClass)) else if (AuthenticationListener.class.isAssignableFrom(extensionClass))
{ {
@@ -182,10 +188,8 @@ public class BindingExtensionProcessor implements ExtensionProcessor
extensionClass.getName()); extensionClass.getName());
} }
AuthenticationListener listener = binder.bind(extensionClass);
(AuthenticationListener) extensionClass.newInstance(); authenticationListenerBinder.addBinding().to(extensionClass);
authenticationListeners.add(listener);
} }
else if (ResourceHandler.class.isAssignableFrom(extensionClass)) else if (ResourceHandler.class.isAssignableFrom(extensionClass))
{ {
@@ -285,17 +289,6 @@ public class BindingExtensionProcessor implements ExtensionProcessor
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
public Set<AuthenticationListener> getAuthenticationListeners()
{
return authenticationListeners;
}
/** /**
* Method description * Method description
* *
@@ -307,17 +300,6 @@ public class BindingExtensionProcessor implements ExtensionProcessor
return fileSystemClass; return fileSystemClass;
} }
/**
* Method description
*
*
* @return
*/
public Set<GroupListener> getGroupListeners()
{
return groupListeners;
}
/** /**
* Method description * Method description
* *
@@ -340,28 +322,6 @@ public class BindingExtensionProcessor implements ExtensionProcessor
return moduleSet; return moduleSet;
} }
/**
* Method description
*
*
* @return
*/
public Set<RepositoryListener> getRepositoryListeners()
{
return repositoryListeners;
}
/**
* Method description
*
*
* @return
*/
public Set<UserListener> getUserListeners()
{
return userListeners;
}
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
/** /**
@@ -420,18 +380,4 @@ public class BindingExtensionProcessor implements ExtensionProcessor
/** Field description */ /** Field description */
private Set<Module> moduleSet; private Set<Module> moduleSet;
/** Field description */
private Set<RepositoryListener> repositoryListeners =
new HashSet<RepositoryListener>();
/** Field description */
private Set<AuthenticationListener> authenticationListeners =
new HashSet<AuthenticationListener>();
/** Field description */
private Set<UserListener> userListeners = new HashSet<UserListener>();
/** Field description */
private Set<GroupListener> groupListeners = new HashSet<GroupListener>();
} }

View File

@@ -151,20 +151,17 @@ public class ScmContextListener extends GuiceServletContextListener
RepositoryManager repositoryManager = RepositoryManager repositoryManager =
injector.getInstance(RepositoryManager.class); injector.getInstance(RepositoryManager.class);
repositoryManager.addListeners(bindExtProcessor.getRepositoryListeners());
repositoryManager.addHooks(bindExtProcessor.getHooks()); repositoryManager.addHooks(bindExtProcessor.getHooks());
repositoryManager.init(context); repositoryManager.init(context);
// init UserManager // init UserManager
UserManager userManager = injector.getInstance(UserManager.class); UserManager userManager = injector.getInstance(UserManager.class);
userManager.addListeners(bindExtProcessor.getUserListeners());
userManager.init(context); userManager.init(context);
// init GroupManager // init GroupManager
GroupManager groupManager = injector.getInstance(GroupManager.class); GroupManager groupManager = injector.getInstance(GroupManager.class);
groupManager.addListeners(bindExtProcessor.getGroupListeners());
groupManager.init(context); groupManager.init(context);
// init Authenticator // init Authenticator
@@ -172,8 +169,6 @@ public class ScmContextListener extends GuiceServletContextListener
injector.getInstance(AuthenticationManager.class); injector.getInstance(AuthenticationManager.class);
authenticationManager.init(context); authenticationManager.init(context);
authenticationManager.addListeners(
bindExtProcessor.getAuthenticationListeners());
return injector; return injector;
} }

View File

@@ -49,6 +49,7 @@ import sonia.scm.group.AbstractGroupManager;
import sonia.scm.group.Group; import sonia.scm.group.Group;
import sonia.scm.group.GroupAllreadyExistExeption; import sonia.scm.group.GroupAllreadyExistExeption;
import sonia.scm.group.GroupException; import sonia.scm.group.GroupException;
import sonia.scm.group.GroupListener;
import sonia.scm.search.SearchRequest; import sonia.scm.search.SearchRequest;
import sonia.scm.search.SearchUtil; import sonia.scm.search.SearchUtil;
import sonia.scm.security.SecurityContext; import sonia.scm.security.SecurityContext;
@@ -68,6 +69,7 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set;
/** /**
* *
@@ -95,13 +97,16 @@ public class XmlGroupManager extends AbstractGroupManager
* *
* @param securityContextProvider * @param securityContextProvider
* @param storeFactory * @param storeFactory
* @param groupListenerProvider
*/ */
@Inject @Inject
public XmlGroupManager(Provider<SecurityContext> securityContextProvider, public XmlGroupManager(Provider<SecurityContext> securityContextProvider,
StoreFactory storeFactory) StoreFactory storeFactory,
Provider<Set<GroupListener>> groupListenerProvider)
{ {
this.securityContextProvider = securityContextProvider; this.securityContextProvider = securityContextProvider;
this.store = storeFactory.getStore(XmlGroupDatabase.class, STORE_NAME); this.store = storeFactory.getStore(XmlGroupDatabase.class, STORE_NAME);
this.groupListenerProvider = groupListenerProvider;
} }
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
@@ -215,6 +220,13 @@ public class XmlGroupManager extends AbstractGroupManager
{ {
groupDB = new XmlGroupDatabase(); groupDB = new XmlGroupDatabase();
} }
Set<GroupListener> listeners = groupListenerProvider.get();
if (Util.isNotEmpty(listeners))
{
addListeners(listeners);
}
} }
/** /**
@@ -482,6 +494,9 @@ public class XmlGroupManager extends AbstractGroupManager
/** Field description */ /** Field description */
private XmlGroupDatabase groupDB; private XmlGroupDatabase groupDB;
/** Field description */
private Provider<Set<GroupListener>> groupListenerProvider;
/** Field description */ /** Field description */
private Provider<SecurityContext> securityContextProvider; private Provider<SecurityContext> securityContextProvider;

View File

@@ -58,6 +58,7 @@ import sonia.scm.repository.RepositoryHandler;
import sonia.scm.repository.RepositoryHandlerNotFoundException; import sonia.scm.repository.RepositoryHandlerNotFoundException;
import sonia.scm.repository.RepositoryHook; import sonia.scm.repository.RepositoryHook;
import sonia.scm.repository.RepositoryHookEvent; import sonia.scm.repository.RepositoryHookEvent;
import sonia.scm.repository.RepositoryListener;
import sonia.scm.repository.RepositoryNotFoundException; import sonia.scm.repository.RepositoryNotFoundException;
import sonia.scm.security.ScmSecurityException; import sonia.scm.security.ScmSecurityException;
import sonia.scm.store.Store; import sonia.scm.store.Store;
@@ -111,15 +112,18 @@ public class XmlRepositoryManager extends AbstractRepositoryManager
* @param securityContextProvider * @param securityContextProvider
* @param storeFactory * @param storeFactory
* @param handlerSet * @param handlerSet
* @param repositoryListenersProvider
*/ */
@Inject @Inject
public XmlRepositoryManager( public XmlRepositoryManager(
SCMContextProvider contextProvider, SCMContextProvider contextProvider,
Provider<WebSecurityContext> securityContextProvider, Provider<WebSecurityContext> securityContextProvider,
StoreFactory storeFactory, Set<RepositoryHandler> handlerSet) StoreFactory storeFactory, Set<RepositoryHandler> handlerSet,
Provider<Set<RepositoryListener>> repositoryListenersProvider)
{ {
this.securityContextProvider = securityContextProvider; this.securityContextProvider = securityContextProvider;
this.store = storeFactory.getStore(XmlRepositoryDatabase.class, STORE_NAME); this.store = storeFactory.getStore(XmlRepositoryDatabase.class, STORE_NAME);
this.repositoryListenersProvider = repositoryListenersProvider;
handlerMap = new HashMap<String, RepositoryHandler>(); handlerMap = new HashMap<String, RepositoryHandler>();
types = new HashSet<Type>(); types = new HashSet<Type>();
@@ -288,6 +292,13 @@ public class XmlRepositoryManager extends AbstractRepositoryManager
{ {
repositoryDB = new XmlRepositoryDatabase(); repositoryDB = new XmlRepositoryDatabase();
} }
Set<RepositoryListener> listeners = repositoryListenersProvider.get();
if (Util.isNotEmpty(listeners))
{
addListeners(listeners);
}
} }
/** /**
@@ -764,6 +775,9 @@ public class XmlRepositoryManager extends AbstractRepositoryManager
/** Field description */ /** Field description */
private XmlRepositoryDatabase repositoryDB; private XmlRepositoryDatabase repositoryDB;
/** Field description */
private Provider<Set<RepositoryListener>> repositoryListenersProvider;
/** Field description */ /** Field description */
private Provider<WebSecurityContext> securityContextProvider; private Provider<WebSecurityContext> securityContextProvider;

View File

@@ -54,6 +54,7 @@ import sonia.scm.user.AbstractUserManager;
import sonia.scm.user.User; import sonia.scm.user.User;
import sonia.scm.user.UserAllreadyExistException; import sonia.scm.user.UserAllreadyExistException;
import sonia.scm.user.UserException; import sonia.scm.user.UserException;
import sonia.scm.user.UserListener;
import sonia.scm.util.AssertUtil; import sonia.scm.util.AssertUtil;
import sonia.scm.util.CollectionAppender; import sonia.scm.util.CollectionAppender;
import sonia.scm.util.IOUtil; import sonia.scm.util.IOUtil;
@@ -71,6 +72,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Set;
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException; import javax.xml.bind.JAXBException;
@@ -109,13 +111,16 @@ public class XmlUserManager extends AbstractUserManager
* *
* @param scurityContextProvider * @param scurityContextProvider
* @param storeFactory * @param storeFactory
* @param userListenerProvider
*/ */
@Inject @Inject
public XmlUserManager(Provider<WebSecurityContext> scurityContextProvider, public XmlUserManager(Provider<WebSecurityContext> scurityContextProvider,
StoreFactory storeFactory) StoreFactory storeFactory,
Provider<Set<UserListener>> userListenerProvider)
{ {
this.scurityContextProvider = scurityContextProvider; this.scurityContextProvider = scurityContextProvider;
this.store = storeFactory.getStore(XmlUserDatabase.class, STORE_NAME); this.store = storeFactory.getStore(XmlUserDatabase.class, STORE_NAME);
this.userListenerProvider = userListenerProvider;
} }
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
@@ -248,6 +253,13 @@ public class XmlUserManager extends AbstractUserManager
userDB = new XmlUserDatabase(); userDB = new XmlUserDatabase();
createDefaultAccounts(); createDefaultAccounts();
} }
Set<UserListener> listeners = userListenerProvider.get();
if (Util.isNotEmpty(listeners))
{
addListeners(listeners);
}
} }
/** /**
@@ -551,4 +563,7 @@ public class XmlUserManager extends AbstractUserManager
/** Field description */ /** Field description */
private XmlUserDatabase userDB; private XmlUserDatabase userDB;
/** Field description */
private Provider<Set<UserListener>> userListenerProvider;
} }

View File

@@ -36,6 +36,7 @@ package sonia.scm.web.security;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -48,6 +49,7 @@ import sonia.scm.security.EncryptionHandler;
import sonia.scm.user.User; import sonia.scm.user.User;
import sonia.scm.util.AssertUtil; import sonia.scm.util.AssertUtil;
import sonia.scm.util.IOUtil; import sonia.scm.util.IOUtil;
import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
@@ -82,19 +84,24 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
* @param authenticationHandlerSet * @param authenticationHandlerSet
* @param encryptionHandler * @param encryptionHandler
* @param cacheManager * @param cacheManager
* @param authenticationListenerProvider
*/ */
@Inject @Inject
public ChainAuthenticatonManager( public ChainAuthenticatonManager(
Set<AuthenticationHandler> authenticationHandlerSet, Set<AuthenticationHandler> authenticationHandlerSet,
EncryptionHandler encryptionHandler, CacheManager cacheManager) EncryptionHandler encryptionHandler, CacheManager cacheManager,
Provider<Set<AuthenticationListener>> authenticationListenerProvider)
{ {
AssertUtil.assertIsNotEmpty(authenticationHandlerSet); AssertUtil.assertIsNotEmpty(authenticationHandlerSet);
AssertUtil.assertIsNotNull(cacheManager); AssertUtil.assertIsNotNull(cacheManager);
this.authenticationHandlerSet = authenticationHandlerSet; this.authenticationHandlerSet = authenticationHandlerSet;
this.encryptionHandler = encryptionHandler; this.encryptionHandler = encryptionHandler;
this.authenticationListenerProvider = authenticationListenerProvider;
this.cache = cacheManager.getCache(String.class, this.cache = cacheManager.getCache(String.class,
AuthenticationCacheValue.class, AuthenticationCacheValue.class,
CACHE_NAME); CACHE_NAME);
// addListeners(authenticationListeners);
} }
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
@@ -166,6 +173,14 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
{ {
authenticator.init(context); authenticator.init(context);
} }
Set<AuthenticationListener> listeners =
authenticationListenerProvider.get();
if (Util.isNotEmpty(listeners))
{
addListeners(listeners);
}
} }
/** /**
@@ -297,6 +312,9 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
/** Field description */ /** Field description */
private Set<AuthenticationHandler> authenticationHandlerSet; private Set<AuthenticationHandler> authenticationHandlerSet;
/** Field description */
private Provider<Set<AuthenticationListener>> authenticationListenerProvider;
/** Field description */ /** Field description */
private Cache<String, AuthenticationCacheValue> cache; private Cache<String, AuthenticationCacheValue> cache;

View File

@@ -35,12 +35,16 @@ package sonia.scm.repository;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Provider;
import sonia.scm.Manager; import sonia.scm.Manager;
import sonia.scm.repository.xml.XmlRepositoryManager; import sonia.scm.repository.xml.XmlRepositoryManager;
import sonia.scm.store.JAXBStoreFactory; import sonia.scm.store.JAXBStoreFactory;
import sonia.scm.store.StoreFactory; import sonia.scm.store.StoreFactory;
import sonia.scm.util.MockUtil; import sonia.scm.util.MockUtil;
import static org.mockito.Mockito.*;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import java.util.HashSet; import java.util.HashSet;
@@ -68,8 +72,12 @@ public class XmlRepositoryManagerTest extends RepositoryManagerTestBase
factory.init(contextProvider); factory.init(contextProvider);
handlerSet.add(new DummyRepositoryHandler(factory)); handlerSet.add(new DummyRepositoryHandler(factory));
Provider<Set<RepositoryListener>> listenerProvider = mock(Provider.class);
when(listenerProvider.get()).thenReturn(new HashSet<RepositoryListener>());
return new XmlRepositoryManager(contextProvider, return new XmlRepositoryManager(contextProvider,
MockUtil.getAdminSecurityContextProvider(), MockUtil.getAdminSecurityContextProvider(),
factory, handlerSet); factory, handlerSet, listenerProvider);
} }
} }

View File

@@ -35,10 +35,19 @@ package sonia.scm.user;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import sonia.scm.util.MockUtil; import com.google.inject.Provider;
import sonia.scm.store.JAXBStoreFactory; import sonia.scm.store.JAXBStoreFactory;
import sonia.scm.store.StoreFactory; import sonia.scm.store.StoreFactory;
import sonia.scm.user.xml.XmlUserManager; import sonia.scm.user.xml.XmlUserManager;
import sonia.scm.util.MockUtil;
import static org.mockito.Mockito.*;
//~--- JDK imports ------------------------------------------------------------
import java.util.HashSet;
import java.util.Set;
/** /**
* *
@@ -60,7 +69,11 @@ public class XmlUserManagerTest extends UserManagerTestBase
factory.init(contextProvider); factory.init(contextProvider);
Provider<Set<UserListener>> listenerProvider = mock(Provider.class);
when(listenerProvider.get()).thenReturn(new HashSet<UserListener>());
return new XmlUserManager(MockUtil.getAdminSecurityContextProvider(), return new XmlUserManager(MockUtil.getAdminSecurityContextProvider(),
factory); factory, listenerProvider);
} }
} }

View File

@@ -35,6 +35,8 @@ package sonia.scm.web.security;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Provider;
import org.junit.Test; import org.junit.Test;
import sonia.scm.AbstractTestBase; import sonia.scm.AbstractTestBase;
@@ -48,6 +50,8 @@ import sonia.scm.util.MockUtil;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import java.io.IOException; import java.io.IOException;
@@ -130,8 +134,15 @@ public class ChainAuthenticationManagerTest extends AbstractTestBase
trillian.setPassword("trillian123"); trillian.setPassword("trillian123");
handlerSet.add(new SingleUserAuthenticaionHandler("trilliansType", handlerSet.add(new SingleUserAuthenticaionHandler("trilliansType",
trillian)); trillian));
Provider<Set<AuthenticationListener>> listenerProvider =
mock(Provider.class);
when(listenerProvider.get()).thenReturn(
new HashSet<AuthenticationListener>());
manager = new ChainAuthenticatonManager(handlerSet, manager = new ChainAuthenticatonManager(handlerSet,
new MessageDigestEncryptionHandler(), cacheManager); new MessageDigestEncryptionHandler(), cacheManager,
listenerProvider);
manager.init(contextProvider); manager.init(contextProvider);
request = MockUtil.getHttpServletRequest(); request = MockUtil.getHttpServletRequest();
response = MockUtil.getHttpServletResponse(); response = MockUtil.getHttpServletResponse();

View File

@@ -35,6 +35,8 @@ package sonia.scm.web.security;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Provider;
import org.junit.Test; import org.junit.Test;
import sonia.scm.AbstractTestBase; import sonia.scm.AbstractTestBase;
@@ -43,14 +45,20 @@ import sonia.scm.security.MessageDigestEncryptionHandler;
import sonia.scm.store.JAXBStoreFactory; import sonia.scm.store.JAXBStoreFactory;
import sonia.scm.store.StoreFactory; import sonia.scm.store.StoreFactory;
import sonia.scm.user.User; import sonia.scm.user.User;
import sonia.scm.user.UserListener;
import sonia.scm.user.UserTestData; import sonia.scm.user.UserTestData;
import sonia.scm.user.xml.XmlUserManager; import sonia.scm.user.xml.XmlUserManager;
import sonia.scm.util.MockUtil; import sonia.scm.util.MockUtil;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import java.util.HashSet;
import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@@ -127,9 +135,13 @@ public class XmlAuthenticationHandlerTest extends AbstractTestBase
storeFactory.init(contextProvider); storeFactory.init(contextProvider);
Provider<Set<UserListener>> listenerProvider = mock(Provider.class);
when(listenerProvider.get()).thenReturn(new HashSet<UserListener>());
XmlUserManager userManager = XmlUserManager userManager =
new XmlUserManager(MockUtil.getAdminSecurityContextProvider(), new XmlUserManager(MockUtil.getAdminSecurityContextProvider(),
storeFactory); storeFactory, listenerProvider);
userManager.init(contextProvider); userManager.init(contextProvider);
userManager.create(slarti); userManager.create(slarti);