using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.SqlClient; using System.Linq; using DTS.Common.Classes; using DTS.Common.Interface.Tags; using DTS.Common.Storage; using DTS.Common.Utilities.Logging; using DTS.Slice.Users.UserSettings; // ReSharper disable once CheckNamespace namespace DTS.Slice.Users { public class UserCollection : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected bool SetProperty(ref T storage, T value, string propertyName = null) { if (Equals(storage, value)) return false; storage = value; OnPropertyChanged(propertyName); return true; } protected void OnPropertyChanged(string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private static readonly object MyLock = new object(); private static UserCollection _userList; public static UserCollection UsersList { get { lock (MyLock) { return _userList ?? (_userList = new UserCollection()); } } } private UserCollection() { } public static Dictionary> GetUserToTagIdLookup() { var lookup = new Dictionary>(); var hr = DbOperations.TagAssignmentsGet(TagTypes.User, out var records); if (0 == hr && null != records && records.Any()) { foreach (var record in records) { if (!lookup.ContainsKey(record.ObjectID)) { lookup.Add(record.ObjectID, new List()); } lookup[record.ObjectID].Add(record.TagID); } } return lookup; } public static User[] GetAllUsers(IUIItems[] allItems, int? uid = null) { lock (MyLock) { //keyed by user and then uiitem id var permissionLookup = new Dictionary>(); var tagsLookup = GetUserToTagIdLookup(); try { using (var cmd = DbOperations.GetSQLCommand(true)) { try { cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserUIItemSettingsGet.ToString(); #region params cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = uid }); #endregion params using (var ds = DbOperations.Connection.QueryDataSet(cmd)) { if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0) { foreach (DataRow dr in ds.Tables[0].Rows) { var userId = Convert.ToInt32(dr["UserID"]); var uiItemId = Convert.ToInt64(dr["UIItemID"]); var permission = Convert.ToInt16(dr["Permission"]); var visible = Convert.ToBoolean(dr["Visible"]); var uiItemName = Convert.ToString(dr["NAME"]); var helper = new UIItemHelper(uiItemId, permission, visible, uiItemName); if (!permissionLookup.ContainsKey(userId)) { permissionLookup.Add(userId, new Dictionary()); } permissionLookup[userId][uiItemId] = helper; } } } } finally { cmd.Connection.Dispose(); } } } catch (Exception ex) { APILogger.Log(ex); } var users = new List(); try { using (var cmd = DbOperations.GetSQLCommand(true)) { try { cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UsersGet.ToString(); #region params cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = uid }); #endregion params using (var ds = DbOperations.Connection.QueryDataSet(cmd)) { if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0) { foreach (DataRow dr in ds.Tables[0].Rows) { try { users.Add(new User(dr, allItems, permissionLookup, tagsLookup)); } catch (Exception ex) { APILogger.Log("Failed to read user", ex); } } } } } finally { cmd.Connection.Dispose(); } } } catch (Exception ex) { APILogger.Log("problem getting user", ex); } // uid is null when we are requesting all users. This function is dual purpose and can be used to request // a single user by passing a uid if (null != uid) return users.ToArray(); var roles = Enum.GetValues(typeof(User.DefaultRoles)).Cast().ToArray(); foreach (var role in roles) { var user = User.CreateDefault(role, allItems); var bFound = users.Exists(u => u.UserName == user.UserName); if (!bFound) { UsersList.Commit(user, user.UserName, allItems); } } //Now add the users that are not the default for a role var nonDefaultUser = User.CreateNonDefaultPowerUser(User.DefaultAeroUsername, allItems); var nonDefaultUserFound = users.Exists(u => u.UserName == nonDefaultUser.UserName); if (!nonDefaultUserFound) { UsersList.Commit(nonDefaultUser, nonDefaultUser.UserName, allItems); } nonDefaultUser = User.CreateNonDefaultPowerUser(User.DefaultCrashUsername, allItems); nonDefaultUserFound = users.Exists(u => u.UserName == nonDefaultUser.UserName); if (!nonDefaultUserFound) { UsersList.Commit(nonDefaultUser, nonDefaultUser.UserName, allItems); } nonDefaultUser = User.CreateNonDefaultPowerUser(User.DefaultTSRAIRUsername, allItems); nonDefaultUserFound = users.Exists(u => u.UserName == nonDefaultUser.UserName); if (!nonDefaultUserFound) { UsersList.Commit(nonDefaultUser, nonDefaultUser.UserName, allItems); } return users.ToArray(); } } public static User GetUser(int uid, IUIItems[] items) { var users = GetAllUsers(items, uid); var enumerable = users ?? users.ToArray(); return !enumerable.Any() ? null : enumerable[0]; } public static User GetUser(string username, IUIItems[] items) { try { using (var cmd = DbOperations.GetSQLCommand(true)) { try { cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UsersGetId.ToString(); #region params cmd.Parameters.Add(new SqlParameter("@UserName", SqlDbType.NVarChar, 50) { Value = username }); var newIdParam = new SqlParameter("@UserId", SqlDbType.Int) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(newIdParam); #endregion params cmd.ExecuteNonQuery(); if (DBNull.Value.Equals(newIdParam.Value)) { return null; } var id = int.Parse(newIdParam.Value.ToString()); return id != 0 ? GetUser(id, items) : null; } finally { cmd.Connection.Dispose(); } } } catch (Exception ex) { APILogger.Log(ex); } return null; } public void Commit(User user, string username, IUIItems[] items) { try { using (var cmd = DbOperations.GetSQLCommand(true)) { try { cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UsersUpdateInsert.ToString(); #region params //cmd.Parameters.Add(new SqlParameter("@Id", SqlDbType.NVarChar, 50) { Value = user.Id }); cmd.Parameters.Add( new SqlParameter("@UserName", SqlDbType.NVarChar, 50) { Value = user.UserName }); cmd.Parameters.Add( new SqlParameter("@DisplayName", SqlDbType.NVarChar, 50) { Value = user.Name }); cmd.Parameters.Add( new SqlParameter("@Password", SqlDbType.NVarChar, 2048) { Value = user.GetPasswordHash() }); cmd.Parameters.Add(new SqlParameter("@Role", SqlDbType.SmallInt) { Value = user.Role }); cmd.Parameters.Add( new SqlParameter("@LastModified", SqlDbType.DateTime) { Value = DateTime.Now }); cmd.Parameters.Add( new SqlParameter("@LastModifiedBy", SqlDbType.NVarChar, 50) { Value = username }); cmd.Parameters.Add(new SqlParameter("@LocalOnly", SqlDbType.Bit) { Value = user.LocalOnly }); var newIdParam = new SqlParameter("@new_id", SqlDbType.Int) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(newIdParam); var errorNumberParam = new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(errorNumberParam); var errorMessageParam = new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(errorMessageParam); #endregion params cmd.ExecuteNonQuery(); if (int.Parse(errorNumberParam.Value.ToString()) != 0) { //errorMessageParam.Value } var id = int.Parse(newIdParam.Value.ToString()); user.Id = id == 0 ? user.Id : id; } finally { cmd.Connection.Dispose(); } } } catch (Exception ex) { APILogger.Log(ex); } var settings = TestSetupDefaults.GetUserSettings(user.Id); var properties = settings.GetType().GetProperties(); Defaults.CreateOrUpdateUserSettingProperties(user.Id, properties); InsertPermissionsAndVisibility(user, items); InsertTags(user); OnPropertyChanged("AllUsers"); } /// /// associates tags to a user /// /// private static void InsertTags(User user) { _ = DbOperations.TagAssignmentsDelete(user.TagType, user.Id); if (!user.TagIDs.Any()) return; foreach (var tag in user.TagIDs) { using (var cmd = DbOperations.GetSQLCommand(true)) { try { cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagAssignmentsInsert.ToString(); #region params cmd.Parameters.Add(new SqlParameter("@ObjectID", SqlDbType.Int) { Value = user.Id }); cmd.Parameters.Add(new SqlParameter("@ObjectType", SqlDbType.SmallInt) { Value = user.TagType }); cmd.Parameters.Add(new SqlParameter("@TagID", SqlDbType.Int) { Value = tag }); var errorNumberParam = new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(errorNumberParam); var errorMessageParam = new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(errorMessageParam); #endregion params cmd.ExecuteNonQuery(); if (int.Parse(errorNumberParam.Value.ToString()) != 0) { //errorMessageParam.Value } } finally { cmd.Connection.Dispose(); } } } } public void Delete(User user) { lock (MyLock) { using (var cmd = DbOperations.GetSQLCommand(true)) { try { cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UsersDelete.ToString(); #region params if (user.IsADefaultUser) { cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = user.Id }); } cmd.Parameters.Add( new SqlParameter("@UserName", SqlDbType.NVarChar, 50) { Value = user.UserName }); var errorNumberParam = new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(errorNumberParam); var errorMessageParam = new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(errorMessageParam); #endregion params cmd.ExecuteNonQuery(); if (int.Parse(errorNumberParam.Value.ToString()) != 0) { //errorMessageParam.Value } } finally { cmd.Connection.Dispose(); } } OnPropertyChanged("AllUsers"); } } public void Delete(User[] users) { foreach (var user in users) { Delete(user); } } private static void InsertPermissionsAndVisibility(User user, IReadOnlyList items) { try { //all our UIItems should already be in the db, so we just have to associate them now... //but first, I guess just remove any existing associations. using (var cmd = DbOperations.GetSQLCommand(true)) { try { cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserUIItemSettingsDelete.ToString(); #region params cmd.Parameters.Add(new SqlParameter("@UserID", SqlDbType.NVarChar, 50) { Value = user.Id }); var errorNumberParam = new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(errorNumberParam); var errorMessageParam = new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(errorMessageParam); #endregion params cmd.ExecuteNonQuery(); if (int.Parse(errorNumberParam.Value.ToString()) != 0) { //errorMessageParam.Value } } finally { cmd.Connection.Dispose(); } } //now to insert them ... there could be a lot so we have to put them into a bunches foreach (var item in items) { using (var cmd = DbOperations.GetSQLCommand(true)) { try { cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserUIItemSettingsInsert.ToString(); #region params cmd.Parameters.Add(new SqlParameter("@UserID", SqlDbType.Int) { Value = user.Id }); var uiItemId = item.GetID(); var userPermission = user.GetPermission(item); var isShow = user.IsShowTabFlagSet(item); cmd.Parameters.Add(new SqlParameter("@UIItemID", SqlDbType.Int) { Value = uiItemId }); cmd.Parameters.Add( new SqlParameter("@Permission", SqlDbType.SmallInt) { Value = userPermission }); cmd.Parameters.Add(new SqlParameter("@Visible", SqlDbType.SmallInt) { Value = isShow }); var errorNumberParam = new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(errorNumberParam); var errorMessageParam = new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(errorMessageParam); #endregion params cmd.ExecuteNonQuery(); if (int.Parse(errorNumberParam.Value.ToString()) != 0) { //errorMessageParam.Value } } finally { cmd.Connection.Dispose(); } } } } catch (Exception ex) { APILogger.Log(ex); } } //private static void UpdateAll(User user, string username) //{ // try // { // using (var cmd = DbOperations.GetSQLCommand(true)) // { // try // { // cmd.CommandType = CommandType.StoredProcedure; // cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserUpdate.ToString(); // #region params // cmd.Parameters.Add(new SqlParameter("@UserName", SqlDbType.NVarChar, 50) {Value = user.Name}); // cmd.Parameters.Add( // new SqlParameter("@DisplayName", SqlDbType.NVarChar, 50) {Value = user.Name}); // cmd.Parameters.Add( // new SqlParameter("@Password", SqlDbType.NVarChar, 2048) {Value = user.GetPasswordHash()}); // cmd.Parameters.Add(new SqlParameter("@Role", SqlDbType.SmallInt) {Value = user.Role}); // cmd.Parameters.Add( // new SqlParameter("@LastModified", SqlDbType.DateTime) {Value = DateTime.Now}); // cmd.Parameters.Add( // new SqlParameter("@LastModifiedBy", SqlDbType.NVarChar, 50) {Value = username}); // cmd.Parameters.Add(new SqlParameter("@LocalOnly", SqlDbType.Bit) {Value = user.LocalOnly}); // var errorNumberParam = // new SqlParameter("@errorNumber", SqlDbType.Int) {Direction = ParameterDirection.Output}; // cmd.Parameters.Add(errorNumberParam); // var errorMessageParam = // new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250) // { // Direction = ParameterDirection.Output // }; // cmd.Parameters.Add(errorMessageParam); // #endregion params // cmd.ExecuteNonQuery(); // if (int.Parse(errorNumberParam.Value.ToString()) != 0) // { // //errorMessageParam.Value // } // } // finally // { // cmd.Connection.Dispose(); // } // } // } // catch (Exception ex) // { // APILogger.Log("Failed to update user", user.UserName, ex); // throw;// TODO: handle exception properly // } //} } }