#region License Information /* HeuristicLab * Copyright (C) 2002-2015 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 . */ #endregion using System; using HeuristicLab.Clients.Common; using HeuristicLab.Common; using HeuristicLab.Core; using System.ServiceModel; using HeuristicLab.Clients.Hive.WebJobManager.ViewModels; using System.Collections.Generic; using System.ServiceModel.Security; using HeuristicLab.Clients.Access; namespace HeuristicLab.Clients.Hive.WebJobManager.Services.Imports { /// /// Controls everything User/Group/Role related /// [Item("AccessAdministrationClient", "AccessAdministration client.")] public class AccessAdministrationClient : IContent { private WebLoginService weblog; private AccessServiceClient client; public Guid userId { get; set; } #region Properties private ItemList users; public ItemList Users { get { return users; } } public ItemList Groups { get; set; } public ItemList Roles { get; set; } #endregion public AccessAdministrationClient(Guid u) { weblog = WebLoginService.Instance; userId = u; } public bool checkAuthorised() { if (client != null) { try { client.GetAllUsers(); return true; } catch (Exception e) { if (e is MessageSecurityException || e is InvalidOperationException) { return false; } throw; } } return false; } #region Refresh public void RefreshUsers() { users = new ItemList(); users.AddRange(CallAccessService>(s => new ItemList(s.GetAllUsers()))); } public void RefreshUsersAsync(Action exceptionCallback) { ExecuteActionAsync(RefreshUsers, exceptionCallback); } public void RefreshUserGroups() { Groups = new ItemList(); Groups.AddRange(CallAccessService>(s => new ItemList(s.GetAllUserGroups()))); } public void RefreshUserGroupsAsync(Action exceptionCallback) { ExecuteActionAsync(RefreshUserGroups, exceptionCallback); } public void RefreshRoles() { Roles = new ItemList(); Roles.AddRange(CallAccessService>(s => new ItemList(s.GetRoles()))); } public void RefreshRolesAsync(Action exceptionCallback) { ExecuteActionAsync(RefreshRoles, exceptionCallback); } #endregion #region Store public void StoreUsers() { foreach (User u in users) { if (u.Modified) { if (u.Id == Guid.Empty) { CallAccessService(s => u.Id = s.AddUser(u).Id); } else { CallAccessService(s => s.UpdateUser(u)); } u.SetUnmodified(); } } } public void StoreUsersAsync(Action exceptionCallback) { ExecuteActionAsync(StoreUsers, exceptionCallback); } public void StoreUserGroups() { foreach (UserGroup g in Groups) { if (g.Modified) { if (g.Id == Guid.Empty) { CallAccessService(s => g.Id = s.AddUserGroup(g)); } else { CallAccessService(s => s.UpdateUserGroup(g)); } g.SetUnmodified(); } } } public void StoreUserGroupsAsync(Action exceptionCallback) { ExecuteActionAsync(StoreUserGroups, exceptionCallback); } public void StoreRoles() { foreach (Role g in Roles) { if (g.Modified) { CallAccessService(s => s.AddRole(g)); g.SetUnmodified(); } } } public void StoreRolesAsync(Action exceptionCallback) { ExecuteActionAsync(StoreRoles, exceptionCallback); } #endregion #region Delete public void DeleteUser(User u) { CallAccessService(s => s.DeleteUser(u)); } public void DeleteUserAsync(User u, Action exceptionCallback) { Action deleteUserAction = new Action(delegate { DeleteUser(u); }); ExecuteActionAsync(deleteUserAction, exceptionCallback); } /* BROKEN public void DeleteUserGroup(UserGroup u) { CallAccessService(s => s.DeleteUserGroup(u)); } public void DeleteUserGroupAsync(UserGroup u, Action exceptionCallback) { Action deleteUserGroupAction = new Action(delegate { DeleteUserGroup(u); }); ExecuteActionAsync(deleteUserGroupAction, exceptionCallback); } */ public void DeleteRole(Role u) { CallAccessService(s => s.DeleteRole(u)); } public void DeleteRoleAsync(Role u, Action exceptionCallback) { Action deleteRoleAction = new Action(delegate { DeleteRole(u); }); ExecuteActionAsync(deleteRoleAction, exceptionCallback); } #endregion public void ExecuteActionAsync(Action action, Action exceptionCallback) { var call = new Func(delegate () { try { OnRefreshing(); action(); } catch (Exception ex) { return ex; } finally { OnRefreshed(); } return null; }); call.BeginInvoke(delegate (IAsyncResult result) { Exception ex = call.EndInvoke(result); if (ex != null) exceptionCallback(ex); }, null); } #region Events public event EventHandler Refreshing; private void OnRefreshing() { EventHandler handler = Refreshing; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler Refreshed; private void OnRefreshed() { EventHandler handler = Refreshed; if (handler != null) handler(this, EventArgs.Empty); } #endregion #region User public string resetPassword(Guid id) { return CallAccessService(s => s.ResetPassword(id)); } public Guid addUser(Access.User u) { return CallAccessService(s => s.AddUser(u).Id); } public void updateUser(Access.User u) { CallAccessService(s => s.UpdateUser(u)); } public List getRoles(User u) { return CallAccessService(s => s.GetUserRoles(u)); } public void addRoleToUser(User u, Role r) { CallAccessService(s => s.AddUserToRole(r, u)); } public void deleteUserRole(User u, Role r) { CallAccessService(s => s.RemoveUserFromRole(r, u)); } #endregion #region Group public Guid addGroup(Access.UserGroup g) { return CallAccessService(s => s.AddUserGroup(g)); } public void updateGroup(UserGroup g) { CallAccessService(s => s.UpdateUserGroup(g)); } public List getSubscribedGroups(Guid id) { var maps = CallAccessService(s => s.GetUserGroupMapping()); maps = maps.FindAll(x => x.Child == id); RefreshUserGroups(); RefreshUsers(); List members = new List(); foreach (var map in maps) { UserGroup g = Groups.Find(x => x.Id == map.Parent); if (g != null) { members.Add( g); } } return members; } public List getGroupMembers(Guid id) { var maps = CallAccessService(s => s.GetUserGroupMapping()); maps = maps.FindAll(x => x.Parent == id); RefreshUserGroups(); RefreshUsers(); List members = new List(); foreach (var map in maps) { User t = users.Find(x => x.Id == map.Child); if (t == null) { UserGroup g = Groups.Find(x => x.Id == map.Child); if (g != null) { members.Insert(0,g);//Groups always in the front } } else { members.Add(t);//members in the back } } return members; } public void deleteUserGroup(UserGroup group) { deleteAllMembers(group); CallAccessService(s => s.DeleteUserGroup(group)); } private void deleteAllMembers(UserGroup group) { var list = getGroupMembers(group.Id); foreach (var member in list) {//Empties all member connections CallAccessService(s => s.RemoveUserGroupBaseFromGroup(member, group)); } } public void addMember(UserGroupBase member, UserGroup group) { CallAccessService(s => s.AddUserGroupBaseToGroup(member, group)); } public void deleteMember(UserGroupBase member,UserGroup group) { CallAccessService(s => s.RemoveUserGroupBaseFromGroup(member, group)); } #endregion #region Roles public Role addRole(Access.Role r) { return CallAccessService(s => s.AddRole(r)); } public void deleteRole(string name) { Role r = Roles.Find(x => x.Name == name); CallAccessService(s => s.DeleteRole(r)); } public List getEnrolled(Role r) { var enroll = new List(); RefreshUsers(); foreach(var us in users) { var temp = CallAccessService(s => s.GetUserRoles(us)); if (temp.Contains(r)) enroll.Add(us); } return enroll; } #endregion #region Helpers private void getAccessClient() { //build config by code WSHttpBinding binding = new WSHttpBinding(); binding.Name = "WSHttpBinding_IAccessService"; binding.CloseTimeout = TimeSpan.FromMinutes(1); binding.OpenTimeout = TimeSpan.FromMinutes(1); binding.ReceiveTimeout = TimeSpan.FromMinutes(10); binding.SendTimeout = TimeSpan.FromMinutes(1); binding.BypassProxyOnLocal = false; binding.TransactionFlow = false; binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard; binding.MaxBufferPoolSize = 524288; binding.MaxReceivedMessageSize = 65536; binding.MessageEncoding = WSMessageEncoding.Text; binding.TextEncoding = System.Text.Encoding.UTF8; binding.UseDefaultWebProxy = true; binding.AllowCookies = false; binding.ReaderQuotas.MaxDepth = 32; binding.ReaderQuotas.MaxStringContentLength = 8192; binding.ReaderQuotas.MaxArrayLength = 16384; binding.ReaderQuotas.MaxBytesPerRead = 4096; binding.ReaderQuotas.MaxNameTableCharCount = 16384; binding.ReliableSession.Ordered = true; binding.ReliableSession.InactivityTimeout = TimeSpan.Parse("00:10:00"); binding.ReliableSession.Enabled = false; binding.Security.Mode = SecurityMode.Message; binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName; binding.Security.Message.NegotiateServiceCredential = true; binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Default; binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows; binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None; binding.Security.Transport.Realm = ""; var end = new EndpointAddress("http://services.heuristiclab.com/AccessService-3.3/AccessService.svc"); client = new AccessServiceClient(binding, end); client.ClientCredentials.UserName.UserName = weblog.getLoginViewModel(userId).loginName; //PASSWORD CANNOT BE ENCRYPTED client.ClientCredentials.UserName.Password = weblog.getServiceLocator(userId).Password; client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None; } public void CallAccessService(Action call) { getAccessClient(); try { call(client); } finally { try { client.Close(); } catch (Exception) { client.Abort(); } } } public T CallAccessService(Func call) { getAccessClient(); try { return call(client); } finally { try { client.Close(); } catch (Exception) { client.Abort(); } } } #endregion internal bool CheckLogin() { try { this.RefreshUsers(); return true; } catch (SecurityAccessDeniedException e) { return false; } catch (MessageSecurityException e) { return false; } } } }