Index: branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/AccessService.cs
===================================================================
--- branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/AccessService.cs	(revision 6840)
+++ branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/AccessService.cs	(revision 6852)
@@ -24,4 +24,5 @@
 using System.Linq;
 using System.ServiceModel;
+using System.Web.Security;
 using DA = HeuristicLab.Services.Access.DataAccess;
 using DT = HeuristicLab.Services.Access.DataTransfer;
@@ -30,4 +31,11 @@
   [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
   public class AccessService : IAccessService {
+    private IUserManager userManager;
+    private IUserManager UserManager {
+      get {
+        if (userManager == null) userManager = new UserManager();
+        return userManager;
+      }
+    }
 
     #region Client Members
@@ -83,6 +91,12 @@
     public void DeleteClient(DT.Client client) {
       using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
-        context.Resources.DeleteOnSubmit(Convert.ToEntity(client));
-        context.SubmitChanges();
+        //load client because we could get a detached object
+        var query = from c in context.GetTable<DA.Resource>().OfType<DA.Client>()
+                    where c.Id == client.Id
+                    select c;
+        if (query.Count() > 0) {
+          context.Resources.DeleteOnSubmit(query.First());
+          context.SubmitChanges();
+        }
       }
     }
@@ -120,12 +134,18 @@
     }
 
-    public void DeleteClientGroup(DT.ClientGroup group) {
-      using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
-        context.Resources.DeleteOnSubmit(Convert.ToEntity(group));
-        context.SubmitChanges();
-      }
-    }
-
-    public void AddResourceToGroup(DT.Resource resource, DT.UserGroup group) {
+    public void DeleteClientGroup(DT.ClientGroup clientGroup) {
+      using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+        //load clientGroup because we could get a detached object
+        var query = from c in context.GetTable<DA.Resource>().OfType<DA.ClientGroup>()
+                    where c.Id == clientGroup.Id
+                    select c;
+        if (query.Count() > 0) {
+          context.Resources.DeleteOnSubmit(query.First());
+          context.SubmitChanges();
+        }
+      }
+    }
+
+    public void AddResourceToGroup(DT.Resource resource, DT.ClientGroup group) {
       using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
         DA.ResourceResourceGroup rrg = new DA.ResourceResourceGroup() {
@@ -139,5 +159,5 @@
     }
 
-    public void RemoveResourceFromGroup(DT.Resource resource, DT.UserGroup group) {
+    public void RemoveResourceFromGroup(DT.Resource resource, DT.ClientGroup group) {
       using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
         var query = context.ResourceResourceGroups.Where(x => x.ResourceId == resource.Id && x.ResourceGroupId == group.Id);
@@ -214,77 +234,233 @@
 
     #region User
+    private DT.User BuildUserDto(Guid userId) {
+      DA.aspnet_User aspUser = null;
+      DA.aspnet_Membership aspMembership = null;
+      DA.User accessUser = null;
+
+      using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+        var query = from u in context.UserGroupBases.OfType<DA.User>()
+                    where u.Id == userId
+                    select u;
+        if (query.Count() == 1) {
+          accessUser = query.First();
+        }
+      }
+
+      using (DA.ASPNETAuthenticationDataContext context = new DA.ASPNETAuthenticationDataContext()) {
+        var userQuery = from u in context.aspnet_Users
+                        where u.UserId == userId
+                        select u;
+        if (userQuery.Count() == 1) {
+          aspUser = userQuery.First();
+        }
+
+        var memQuery = from u in context.aspnet_Memberships
+                       where u.UserId == userId
+                       select u;
+        if (memQuery.Count() == 1) {
+          aspMembership = memQuery.First();
+        }
+      }
+
+      if (aspUser == null || aspMembership == null || accessUser == null) {
+        //TODO: error handling
+        return null;
+      } else {
+        return Convert.ToDto(accessUser, aspUser, aspMembership);
+      }
+    }
+
     public DT.User Login() {
-      throw new System.NotImplementedException();
+      Guid userId = UserManager.CurrentUserId;
+      return BuildUserDto(userId);
     }
 
     public IEnumerable<DT.User> GetAllUsers() {
-      throw new System.NotImplementedException();
-    }
-
-    public IEnumerable<DT.User> GetUsers(IEnumerable<DT.User> ids) {
-      throw new System.NotImplementedException();
+      List<Guid> accessUserGuids = null;
+
+      using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+        var query = from u in context.UserGroupBases.OfType<DA.User>()
+                    select u.Id;
+        accessUserGuids = query.ToList();
+      }
+
+      return accessUserGuids.Select(x => BuildUserDto(x));
+    }
+
+    public IEnumerable<DT.User> GetUsers(IEnumerable<Guid> ids) {
+      List<Guid> accessUserGuids = null;
+
+      using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+        var query = from u in context.UserGroupBases.OfType<DA.User>()
+                    where ids.Contains(u.Id)
+                    select u.Id;
+        accessUserGuids = query.ToList();
+      }
+
+      return accessUserGuids.Select(x => BuildUserDto(x));
     }
 
     public DT.User AddUser(DT.User user) {
-      throw new System.NotImplementedException();
+      DA.User accessUser;
+      DA.aspnet_User aspUser;
+      DA.aspnet_Membership aspMembership;
+      bool userExistsInASP;
+
+      Convert.ToEntity(user, out accessUser, out aspUser, out aspMembership, out userExistsInASP);
+
+      if (userExistsInASP) {
+        if (accessUser.Id == null || accessUser.Id == Guid.Empty) {
+          accessUser.Id = aspMembership.UserId;
+        }
+        using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+          context.UserGroupBases.InsertOnSubmit(accessUser);
+          context.SubmitChanges();
+        }
+        MembershipUser membershipUser = Membership.GetUser((object)accessUser.Id);
+        if (membershipUser != null) {
+          membershipUser.Email = aspMembership.Email;
+          membershipUser.IsApproved = aspMembership.IsApproved;
+          membershipUser.Comment = aspMembership.Comment;
+          Membership.UpdateUser(membershipUser);
+        }
+      } else {
+        MembershipUser membershipUser = Membership.CreateUser(aspUser.UserName, aspUser.UserName, aspMembership.Email);
+        membershipUser.IsApproved = aspMembership.IsApproved;
+        membershipUser.Comment = aspMembership.Comment;
+        Membership.UpdateUser(membershipUser);
+
+        Guid userId = (Guid)membershipUser.ProviderUserKey;
+        accessUser.Id = userId;
+
+        using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+          context.UserGroupBases.InsertOnSubmit(accessUser);
+          context.SubmitChanges();
+        }
+      }
+
+      using (DA.ASPNETAuthenticationDataContext context = new DA.ASPNETAuthenticationDataContext()) {
+        var newAspUser = context.aspnet_Users.Where(x => x.UserId == accessUser.Id).FirstOrDefault();
+        var newAspMembership = context.aspnet_Memberships.Where(x => x.UserId == accessUser.Id).FirstOrDefault();
+        return Convert.ToDto(accessUser, newAspUser, newAspMembership);
+      }
     }
 
     public void DeleteUser(DT.User user) {
-      throw new System.NotImplementedException();
+      if (user.Id != null && user.Id != Guid.Empty) {
+        Membership.DeleteUser(user.UserName);
+        using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+          context.UserGroupBases.DeleteOnSubmit(Convert.ToEntity(user));
+          context.SubmitChanges();
+        }
+      }
     }
 
     public void UpdateUser(DT.User user) {
-      throw new System.NotImplementedException();
+      AddUser(user);
     }
 
     public void AddUserToRole(DT.Role role, DT.User user) {
-      throw new System.NotImplementedException();
+      //TODO: usernames and rolenames have to be unique!
+      MembershipUser msUser = Membership.GetUser((object)user.Id);
+      if (msUser != null) {
+        Roles.AddUserToRole(msUser.UserName, role.Name);
+      }
     }
 
     public void RemoveUserFromRole(DT.Role role, DT.User user) {
-      throw new System.NotImplementedException();
-    }
-
-    public void ResetPassword(DT.User user, string password) {
-      throw new System.NotImplementedException();
-    }
-    #endregion
-
+      MembershipUser msUser = Membership.GetUser((object)user.Id);
+      if (msUser != null) {
+        Roles.RemoveUserFromRole(msUser.UserName, role.Name);
+      }
+    }
+
+    public bool ResetPassword(DT.User user, string oldPassword, string newPassword) {
+      MembershipUser msUser = Membership.GetUser((object)user.Id);
+      if (msUser != null) {
+        return msUser.ChangePassword(oldPassword, newPassword);
+      }
+      return false;
+    }
+    #endregion
+
+    #region UserGroup
     public IEnumerable<DT.UserGroup> GetAllUserGroups() {
-      throw new System.NotImplementedException();
+      using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+        var query = from u in context.UserGroupBases.OfType<DA.UserGroup>()
+                    select Convert.ToDto(u);
+        return query.ToList();
+      }
     }
 
     public IEnumerable<DT.UserGroup> GetUserGroups(IEnumerable<Guid> ids) {
-      throw new System.NotImplementedException();
-    }
-
-    public DT.UserGroup AddUserGroup(DT.UserGroup group) {
-      throw new System.NotImplementedException();
+      using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+        var query = from u in context.UserGroupBases.OfType<DA.UserGroup>()
+                    where ids.Contains(u.Id)
+                    select Convert.ToDto(u);
+        return query.ToList();
+      }
+    }
+
+    public Guid AddUserGroup(DT.UserGroup group) {
+      using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+        context.UserGroupBases.InsertOnSubmit(Convert.ToEntity(group));
+        context.SubmitChanges();
+        return group.Id;
+      }
     }
 
     public void UpdateUserGroup(DT.UserGroup group) {
-      throw new System.NotImplementedException();
+      AddUserGroup(group);
     }
 
     public void DeleteUserGroup(DT.UserGroup group) {
-      throw new System.NotImplementedException();
+      using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+        context.UserGroupBases.DeleteOnSubmit(Convert.ToEntity(group));
+        context.SubmitChanges();
+      }
     }
 
     public void AddUserGroupBaseToGroup(DT.UserGroupBase resource, DT.UserGroup group) {
-      throw new System.NotImplementedException();
-    }
-
-    public void RemoveUserGroupBaseFromGroup(DT.UserGroupBase resource, DT.UserGroup group) {
-      throw new System.NotImplementedException();
+      using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+        DA.UserGroupUserGroup ugug = new DA.UserGroupUserGroup();
+        ugug.UserGroupId = resource.Id;
+        ugug.UserGroupUserGroupId = group.Id;
+        context.UserGroupUserGroups.InsertOnSubmit(ugug);
+        context.SubmitChanges();
+      }
+    }
+
+    public void RemoveUserGroupBaseFromGroup(DT.UserGroupBase resource, DT.UserGroup userGroup) {
+      using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+        var query = from u in context.UserGroupUserGroups
+                    where u.UserGroupId == resource.Id && u.UserGroupUserGroupId == userGroup.Id
+                    select u;
+
+        if (query.Count() == 1) {
+          context.UserGroupUserGroups.DeleteOnSubmit(query.First());
+          context.SubmitChanges();
+        }
+      }
     }
 
     public IEnumerable<DT.UserGroupBase> GetUsersAndGroups() {
-      throw new System.NotImplementedException();
+      using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+        var query = from u in context.UserGroupBases
+                    select Convert.ToDto(u);
+        return query.ToList();
+      }
     }
 
     public IEnumerable<DT.UserGroupMapping> GetUserGroupMapping() {
-      throw new System.NotImplementedException();
-    }
-
+      using (DA.ClientManagementDataContext context = new DA.ClientManagementDataContext()) {
+        var query = from u in context.UserGroupUserGroups
+                    select Convert.ToDto(u);
+        return query.ToList();
+      }
+    }
+    #endregion
+
+    #region Roles
     public IEnumerable<DT.Role> GetRoles() {
       throw new System.NotImplementedException();
@@ -306,5 +482,7 @@
       throw new System.NotImplementedException();
     }
-
+    #endregion
+
+    #region Error Reporting
     public void ReportError(DT.ClientError error) {
       throw new System.NotImplementedException();
@@ -322,4 +500,5 @@
       throw new System.NotImplementedException();
     }
+    #endregion
   }
 }
Index: branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/Convert.cs
===================================================================
--- branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/Convert.cs	(revision 6840)
+++ branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/Convert.cs	(revision 6852)
@@ -68,16 +68,24 @@
     #region Country
     public static DT.Country ToDto(DA.Country source) {
-      return new DT.Country() {
-        Id = source.Id,
-        Name = source.Name
-      };
+      if (source == null) {
+        return null;
+      } else {
+        return new DT.Country() {
+          Id = source.Id,
+          Name = source.Name
+        };
+      }
     }
 
     public static DA.Country ToEntity(DT.Country source) {
-      return new DA.Country() {
-        Id = source.Id,
-        Name = source.Name,
-
-      };
+      if (source == null) {
+        return null;
+      } else {
+        return new DA.Country() {
+          Id = source.Id,
+          Name = source.Name,
+
+        };
+      }
     }
     #endregion
@@ -85,15 +93,23 @@
     #region OperatingSystem
     public static DT.OperatingSystem ToDto(DA.OperatingSystem source) {
-      return new DT.OperatingSystem() {
-        Id = source.Id,
-        Name = source.Name
-      };
+      if (source == null) {
+        return null;
+      } else {
+        return new DT.OperatingSystem() {
+          Id = source.Id,
+          Name = source.Name
+        };
+      }
     }
 
     public static DA.OperatingSystem ToEntity(DT.OperatingSystem source) {
-      return new DA.OperatingSystem() {
-        Id = source.Id,
-        Name = source.Name,
-      };
+      if (source == null) {
+        return null;
+      } else {
+        return new DA.OperatingSystem() {
+          Id = source.Id,
+          Name = source.Name,
+        };
+      }
     }
     #endregion
@@ -101,16 +117,24 @@
     #region ClientType
     public static DT.ClientType ToDto(DA.ClientType source) {
-      return new DT.ClientType() {
-        Id = source.Id,
-        Name = source.Name
-      };
+      if (source == null) {
+        return null;
+      } else {
+        return new DT.ClientType() {
+          Id = source.Id,
+          Name = source.Name
+        };
+      }
     }
 
     public static DA.ClientType ToEntity(DT.ClientType source) {
-      return new DA.ClientType() {
-        Id = source.Id,
-        Name = source.Name,
-
-      };
+      if (source == null) {
+        return null;
+      } else {
+        return new DA.ClientType() {
+          Id = source.Id,
+          Name = source.Name,
+
+        };
+      }
     }
     #endregion
@@ -118,17 +142,25 @@
     #region ClientConfiguration
     public static DT.ClientConfiguration ToDto(DA.ClientConfiguration source) {
-      return new DT.ClientConfiguration() {
-        Id = source.Id,
-        Hash = source.Hash,
-        Description = source.Description
-      };
+      if (source == null) {
+        return null;
+      } else {
+        return new DT.ClientConfiguration() {
+          Id = source.Id,
+          Hash = source.Hash,
+          Description = source.Description
+        };
+      }
     }
 
     public static DA.ClientConfiguration ToEntity(DT.ClientConfiguration source) {
-      return new DA.ClientConfiguration() {
-        Id = source.Id,
-        Hash = source.Hash,
-        Description = source.Description
-      };
+      if (source == null) {
+        return null;
+      } else {
+        return new DA.ClientConfiguration() {
+          Id = source.Id,
+          Hash = source.Hash,
+          Description = source.Description
+        };
+      }
     }
     #endregion
@@ -264,4 +296,8 @@
         UserName = aspUserSource.UserName
       };
+    }
+
+    public static DA.User ToEntity(DT.User source) {
+      return new DA.User() { Id = source.Id, FullName = source.FullName };
     }
 
@@ -302,12 +338,26 @@
 
     #region ClientGroupMapping
-    public static DT.ClientGroupMapping ToDto(DA.ResourceResourceGroup c) {
+    public static DT.ClientGroupMapping ToDto(DA.ResourceResourceGroup source) {
       return new DT.ClientGroupMapping() {
-        Child = c.ResourceId, Parent = c.ResourceGroupId
-      };
-    }
-    #endregion
-
-
+        Child = source.ResourceId, Parent = source.ResourceGroupId
+      };
+    }
+    #endregion
+
+    #region UserGroupBase
+    public static DT.UserGroupBase ToDto(DA.UserGroupBase source) {
+      return new DT.UserGroupBase() {
+        Id = source.Id
+      };
+    }
+    #endregion
+
+    #region UserGroupMapping
+    public static DT.UserGroupMapping ToDto(DA.UserGroupUserGroup source) {
+      return new DT.UserGroupMapping() {
+        Child = source.UserGroupId, Parent = source.UserGroupUserGroupId
+      };
+    }
+    #endregion
   }
 }
Index: branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/HeuristicLab.Services.Access-3.3.csproj
===================================================================
--- branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/HeuristicLab.Services.Access-3.3.csproj	(revision 6840)
+++ branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/HeuristicLab.Services.Access-3.3.csproj	(revision 6852)
@@ -48,4 +48,6 @@
     <Reference Include="System.Runtime.Serialization" />
     <Reference Include="System.ServiceModel" />
+    <Reference Include="System.Web" />
+    <Reference Include="System.Web.ApplicationServices" />
     <Reference Include="System.Xml" />
     <Reference Include="System.Xml.Linq" />
@@ -71,6 +73,8 @@
     <Compile Include="DataTransfer\UserGroupMapping.cs" />
     <Compile Include="IAccessService.cs" />
+    <Compile Include="Interfaces\IUserManager.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="AccessService.cs" />
+    <Compile Include="UserManager.cs" />
   </ItemGroup>
   <ItemGroup>
Index: branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/IAccessService.cs
===================================================================
--- branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/IAccessService.cs	(revision 6840)
+++ branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/IAccessService.cs	(revision 6852)
@@ -70,8 +70,8 @@
 
     [OperationContract]
-    void AddResourceToGroup(Resource resource, UserGroup group);
+    void AddResourceToGroup(Resource resource, ClientGroup group);
 
     [OperationContract]
-    void RemoveResourceFromGroup(Resource resource, UserGroup group);
+    void RemoveResourceFromGroup(Resource resource, ClientGroup group);
     #endregion
 
@@ -111,5 +111,5 @@
 
     [OperationContract]
-    IEnumerable<User> GetUsers(IEnumerable<User> ids);
+    IEnumerable<User> GetUsers(IEnumerable<Guid> ids);
 
     [OperationContract]
@@ -129,5 +129,5 @@
 
     [OperationContract]
-    void ResetPassword(User user, string password);
+    bool ResetPassword(User user, string oldPassword, string newPassword);
     #endregion
 
@@ -140,5 +140,5 @@
 
     [OperationContract]
-    UserGroup AddUserGroup(UserGroup group);
+    Guid AddUserGroup(UserGroup group);
 
     [OperationContract]
Index: branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/Interfaces/IUserManager.cs
===================================================================
--- branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/Interfaces/IUserManager.cs	(revision 6852)
+++ branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/Interfaces/IUserManager.cs	(revision 6852)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Web.Security;
+
+namespace HeuristicLab.Services.Access {
+  public interface IUserManager {
+    MembershipUser CurrentUser { get; }
+    Guid CurrentUserId { get; }
+    MembershipUser GetUserByName(string username);
+    MembershipUser GetUserById(Guid userId);
+  }
+}
Index: branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/UserManager.cs
===================================================================
--- branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/UserManager.cs	(revision 6852)
+++ branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/UserManager.cs	(revision 6852)
@@ -0,0 +1,43 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Web.Security;
+
+namespace HeuristicLab.Services.Access {
+  public class UserManager : IUserManager {
+    public MembershipUser CurrentUser {
+      get { return Membership.GetUser(); }
+    }
+
+    public Guid CurrentUserId {
+      get { return (Guid)CurrentUser.ProviderUserKey; }
+    }
+
+    public MembershipUser GetUserByName(string username) {
+      return Membership.GetUser(username);
+    }
+
+    public MembershipUser GetUserById(Guid userId) {
+      return Membership.GetUser(userId);
+    }
+  }
+}
