user data db
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/APIAuthentication.java b/src/main/java/de/ids_mannheim/korap/security/auth/APIAuthentication.java
index d59e503..297a36e 100644
--- a/src/main/java/de/ids_mannheim/korap/security/auth/APIAuthentication.java
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/APIAuthentication.java
@@ -58,7 +58,7 @@
     }
 
     @Override
-    public TokenContext createUserSession(User user, Map<String, String> attr)
+    public TokenContext createUserSession(User user, Map<String, Object> attr)
             throws KustvaktException {
         TokenContext c = new TokenContext();
         c.setUsername(user.getUsername());
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/BasicHttpAuth.java b/src/main/java/de/ids_mannheim/korap/security/auth/BasicHttpAuth.java
index 4470a30..e97ea53 100644
--- a/src/main/java/de/ids_mannheim/korap/security/auth/BasicHttpAuth.java
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/BasicHttpAuth.java
@@ -74,7 +74,7 @@
 
     // not supported!
     @Override
-    public TokenContext createUserSession(User user, Map<String, String> attr)
+    public TokenContext createUserSession(User user, Map<String, Object> attr)
             throws KustvaktException {
         return null;
     }
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java b/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
index 73eecd1..2eca9e0 100644
--- a/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
@@ -12,7 +12,6 @@
 import de.ids_mannheim.korap.user.*;
 import de.ids_mannheim.korap.utils.StringUtils;
 import de.ids_mannheim.korap.utils.TimeUtils;
-import de.ids_mannheim.korap.web.utils.KustvaktMap;
 import net.sf.ehcache.Cache;
 import net.sf.ehcache.CacheManager;
 import net.sf.ehcache.Element;
@@ -109,7 +108,7 @@
         AuthenticationIface provider = getProvider(context.getTokenType(),
                 null);
         if (provider == null) {
-
+            //todo:
         }
 
         try {
@@ -128,8 +127,9 @@
      * @return User
      * @throws KustvaktException
      */
+    @Override
     public User authenticate(int type, String username, String password,
-            Map<String, String> attributes) throws KustvaktException {
+            Map<String, Object> attributes) throws KustvaktException {
         User user;
         switch (type) {
             case 1:
@@ -147,8 +147,9 @@
     }
 
     // todo: dont use annotations for caching
+    @Override
     @CachePut(value = "users", key = "#user.getUsername()")
-    public TokenContext createTokenContext(User user, Map<String, String> attr,
+    public TokenContext createTokenContext(User user, Map<String, Object> attr,
             String provider_key) throws KustvaktException {
         AuthenticationIface provider = getProvider(provider_key,
                 Attributes.API_AUTHENTICATION);
@@ -159,7 +160,7 @@
         TokenContext context = provider.createUserSession(user, attr);
         if (context == null)
             throw new KustvaktException(StatusCodes.NOT_SUPPORTED);
-        context.setUserAgent(attr.get(Attributes.USER_AGENT));
+        context.setUserAgent((String) attr.get(Attributes.USER_AGENT));
         context.setHostAddress(Attributes.HOST);
         return context;
     }
@@ -175,7 +176,7 @@
         return false;
     }
 
-    private User authenticateShib(Map<String, String> attributes)
+    private User authenticateShib(Map<String, Object> attributes)
             throws KustvaktException {
         // todo use persistent id, since eppn is not unique
         String eppn = (String) attributes.get(Attributes.EPPN);
@@ -196,8 +197,8 @@
 
     //todo: what if attributes null?
     private User authenticate(String username, String password,
-            Map<String, String> attr) throws KustvaktException {
-        Map<String, String> attributes = crypto.validateMap(attr);
+            Map<String, Object> attr) throws KustvaktException {
+        Map<String, Object> attributes = crypto.validateMap(attr);
         String safeUS;
         User unknown;
         // just to make sure that the plain password does not appear anywhere in the logs!
@@ -214,8 +215,6 @@
         else {
             try {
                 unknown = entHandler.getAccount(safeUS);
-                unknown.setSettings(
-                        entHandler.getUserSettings(unknown.getId()));
             }catch (EmptyResultException e) {
                 // mask exception to disable user guessing in possible attacks
                 throw new WrappedException(new KustvaktException(username,
@@ -459,11 +458,9 @@
      * @throws KustvaktException
      */
     //fixme: remove clientinfo object (not needed), use json representation to get stuff
-    public User createUserAccount(Map attributes, boolean confirmation_required)
-            throws KustvaktException {
-        KustvaktMap kmap = new KustvaktMap(attributes);
-
-        Map<String, String> safeMap = crypto.validateMap(attributes);
+    public User createUserAccount(Map<String, Object> attributes,
+            boolean confirmation_required) throws KustvaktException {
+        Map<String, Object> safeMap = crypto.validateMap(attributes);
         if (safeMap.get(Attributes.USERNAME) == null || ((String) safeMap
                 .get(Attributes.USERNAME)).isEmpty())
             throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
@@ -474,10 +471,12 @@
                     StatusCodes.ILLEGAL_ARGUMENT, "password must be set",
                     "password");
 
-        String username = crypto.validateEntry(safeMap.get(Attributes.USERNAME),
-                Attributes.USERNAME);
-        String safePass = crypto.validateEntry(safeMap.get(Attributes.PASSWORD),
-                Attributes.PASSWORD);
+        String username = crypto
+                .validateEntry((String) safeMap.get(Attributes.USERNAME),
+                        Attributes.USERNAME);
+        String safePass = crypto
+                .validateEntry((String) safeMap.get(Attributes.PASSWORD),
+                        Attributes.PASSWORD);
         String hash;
         try {
             hash = crypto.produceSecureHash(safePass);
@@ -487,9 +486,6 @@
         }
 
         KorAPUser user = User.UserFactory.getUser(username);
-        UserDetails det = UserDetails.newDetailsIterator(safeMap);
-        user.setDetails(det);
-        user.setSettings(new UserSettings());
         if (confirmation_required) {
             user.setAccountLocked(true);
             URIParam param = new URIParam(crypto.createToken(),
@@ -499,6 +495,16 @@
         user.setPassword(hash);
         try {
             entHandler.createAccount(user);
+            Userdetails2 details = new Userdetails2(user.getId());
+            details.readDefaults(safeMap);
+            details.checkRequired();
+
+            UserSettings2 settings = new UserSettings2(user.getId());
+            settings.readDefaults(safeMap);
+            settings.checkRequired();
+
+            UserdataFactory.getDaoInstance(Userdetails2.class).store(details);
+            UserdataFactory.getDaoInstance(UserSettings2.class).store(settings);
         }catch (KustvaktException e) {
             throw new WrappedException(e, StatusCodes.CREATE_ACCOUNT_FAILED,
                     user.toString());
@@ -510,11 +516,11 @@
     }
 
     //todo:
-    private ShibUser createShibbUserAccount(Map<String, String> attributes)
+    private ShibUser createShibbUserAccount(Map<String, Object> attributes)
             throws KustvaktException {
         jlog.debug("creating shibboleth user account for user attr: {}",
                 attributes);
-        Map<String, String> safeMap = crypto.validateMap(attributes);
+        Map<String, Object> safeMap = crypto.validateMap(attributes);
 
         //todo eppn non-unique.join with idp or use persistent_id as username identifier
         ShibUser user = User.UserFactory
@@ -635,9 +641,10 @@
                     username), StatusCodes.PASSWORD_RESET_FAILED, username);
         }
 
-        this.getUserData(ident, Userdetails2.class);
+        Userdata data = this.getUserData(ident, Userdetails2.class);
         KorAPUser user = (KorAPUser) ident;
-        if (!mail.equals(user.getDetails().getEmail()))
+
+        if (!mail.equals(data.get(Attributes.EMAIL)))
             //            throw new NotAuthorizedException(StatusCodes.ILLEGAL_ARGUMENT,
             //                    "invalid parameter: email", "email");
             throw new WrappedException(new KustvaktException(user.getId(),
@@ -658,80 +665,52 @@
                 new DateTime(param.getUriExpiration()) };
     }
 
-    @Deprecated
-    public void updateUserSettings(User user, UserSettings settings)
-            throws KustvaktException {
-        if (user instanceof DemoUser)
-            return;
-        else {
-            Map map = crypto.validateMap(settings.toObjectMap());
-            settings = UserSettings.fromObjectMap(map);
-            try {
-                entHandler.updateSettings(settings);
-            }catch (KustvaktException e) {
-                jlog.error("Error ", e);
-                throw new WrappedException(e,
-                        StatusCodes.UPDATE_ACCOUNT_FAILED);
-            }
-        }
-    }
-
-    @Deprecated
-    public void updateUserDetails(User user, UserDetails details)
-            throws KustvaktException {
-        if (user instanceof DemoUser)
-            return;
-        else {
-            Map map = crypto.validateMap(details.toMap());
-
-            try {
-                entHandler
-                        .updateUserDetails(UserDetails.newDetailsIterator(map));
-            }catch (KustvaktException e) {
-                jlog.error("Error ", e);
-                throw new WrappedException(e,
-                        StatusCodes.UPDATE_ACCOUNT_FAILED);
-            }
-        }
-    }
-
     @Override
-    public <T extends Userdata> T getUserData(User user, Class<T> clazz) {
-        UserDataDbIface<T> dao = UserdataFactory.getDaoInstance(clazz);
-        return dao.get(user);
+    public <T extends Userdata> T getUserData(User user, Class<T> clazz)
+            throws WrappedException {
+
+        try {
+            UserDataDbIface<T> dao = UserdataFactory.getDaoInstance(clazz);
+            return dao.get(user);
+        }catch (KustvaktException e) {
+            jlog.error("Error ", e);
+            throw new WrappedException(e, StatusCodes.GET_ACCOUNT_FAILED);
+        }
     }
 
     //todo: cache userdata outside of the user object!
     @Override
-    public void updateUserData(Userdata data) {
-        UserDataDbIface dao = UserdataFactory.getDaoInstance(data.getClass());
-        dao.update(data);
-    }
-
-    public UserDetails getUserDetails(User user) throws KustvaktException {
+    public void updateUserData(Userdata data) throws WrappedException {
         try {
-            for (Userdata data : user.getUserdata()) {
-                if (data instanceof Userdetails2) {
-
-                }
-            }
-            if (user.getDetails() == null)
-                user.setDetails(entHandler.getUserDetails(user.getId()));
+            data.validate(this.crypto);
+            UserDataDbIface dao = UserdataFactory
+                    .getDaoInstance(data.getClass());
+            dao.update(data);
         }catch (KustvaktException e) {
-            throw new WrappedException(e, StatusCodes.GET_ACCOUNT_FAILED);
+            jlog.error("Error ", e);
+            throw new WrappedException(e, StatusCodes.UPDATE_ACCOUNT_FAILED);
         }
-        return user.getDetails();
     }
 
-    public UserSettings getUserSettings(User user) throws KustvaktException {
-        try {
-            if (user.getSettings() == null)
-                user.setSettings(entHandler.getUserSettings(user.getId()));
-        }catch (KustvaktException e) {
-            throw new WrappedException(e, StatusCodes.GET_ACCOUNT_FAILED);
-        }
-        return user.getSettings();
-    }
+    //    public UserDetails getUserDetails(User user) throws KustvaktException {
+    //        try {
+    //            if (user.getDetails() == null)
+    //                user.setDetails(entHandler.getUserDetails(user.getId()));
+    //        }catch (KustvaktException e) {
+    //            throw new WrappedException(e, StatusCodes.GET_ACCOUNT_FAILED);
+    //        }
+    //        return user.getDetails();
+    //    }
+    //
+    //    public UserSettings getUserSettings(User user) throws KustvaktException {
+    //        try {
+    //            if (user.getSettings() == null)
+    //                user.setSettings(entHandler.getUserSettings(user.getId()));
+    //        }catch (KustvaktException e) {
+    //            throw new WrappedException(e, StatusCodes.GET_ACCOUNT_FAILED);
+    //        }
+    //        return user.getSettings();
+    //    }
 
     private String cache_key(String input) throws KustvaktException {
         try {
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/OpenIDconnectAuthentication.java b/src/main/java/de/ids_mannheim/korap/security/auth/OpenIDconnectAuthentication.java
index a1871c9..3f0ebe4 100644
--- a/src/main/java/de/ids_mannheim/korap/security/auth/OpenIDconnectAuthentication.java
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/OpenIDconnectAuthentication.java
@@ -44,9 +44,9 @@
     }
 
     @Override
-    public TokenContext createUserSession(User user, Map<String, String> attr)
+    public TokenContext createUserSession(User user, Map<String, Object> attr)
             throws KustvaktException {
-        String cl_secret = attr.get(Attributes.CLIENT_SECRET);
+        String cl_secret = (String) attr.get(Attributes.CLIENT_SECRET);
         if (cl_secret == null)
             throw new KustvaktException(StatusCodes.REQUEST_INVALID);
         attr.remove(cl_secret);
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/SessionAuthentication.java b/src/main/java/de/ids_mannheim/korap/security/auth/SessionAuthentication.java
index 3a74954..68b04c8 100644
--- a/src/main/java/de/ids_mannheim/korap/security/auth/SessionAuthentication.java
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/SessionAuthentication.java
@@ -56,7 +56,7 @@
     }
 
     @Override
-    public TokenContext createUserSession(User user, Map attr)
+    public TokenContext createUserSession(User user, Map<String, Object> attr)
             throws KustvaktException {
         DateTime now = TimeUtils.getNow();
         DateTime ex = TimeUtils