public AddEditClientDialog(ClientRecord clientToEdit) { InitializeComponent(); this.ClientRecord = new ClientRecord() { Name = clientToEdit.Name, ClientId = clientToEdit.ClientId }; clientRecordBindingSource.DataSource = this.ClientRecord; this.Text = "Rename Client"; commitButton.Text = "Save"; }
public PurgeClientDialog(ClientRecord client) { InitializeComponent(); mainInstructionLabel.Text = String.Format(mainInstructionLabel.Text, client.Name); }
public ClientRecordEventArgs(ClientRecord client) { this.ClientRecords = new[] { client }; }
private void DisplayClient(ClientRecord currentClient) { if (_editMode) EndEditMode(); //stop listening to the old client if (_activeClient != null) { _activeClient.EntriesAdded -= ClientRecord_EntryAdded; _activeClient.EntriesRemoved -= ClientRecord_EntryRemoved; foreach (var e in _activeClient.Entries) { e.PropertyChanged -= ClientEntry_PropertyChanged; } } entryListView.Items.Clear(); _currentClientFields.Clear(); _entryNotes.Clear(); entryListView.Enabled = (currentClient != null); clientNameLabel.Enabled = (currentClient != null); _activeClient = currentClient; if (currentClient != null) { activeClientBindingSource.DataSource = currentClient; _activeClient.EntriesAdded += new EventHandler<ClientEntryEventArgs>(ClientRecord_EntryAdded); _activeClient.EntriesRemoved += new EventHandler<ClientEntryEventArgs>(ClientRecord_EntryRemoved); //since the listview doesn't support databinding, we need to simulate it by populating it and listening //for changes for both the entry list and each entry foreach (var entry in currentClient.Entries) { AddEntryToListView(entry); } entryListView.SelectedItems.Clear(); if (entryListView.Items.Count > 0) entryListView.Items[0].Selected = true; else DisplaySelectedEntry(); bool editAllowed = currentClient.Security.CheckIsAllowedEdit(this.CurrentDatabase.CurrentUser); renameClientToolStripMenuItem.Enabled = editAllowed; editButton.Enabled = editAllowed; purgeClientToolStripMenuItem.Enabled = editAllowed; editModeToolStripMenuItem.Enabled = editAllowed; addEntryToolStripMenuItem.Enabled = editAllowed; addEntryButton.Enabled = editAllowed; deleteEntryToolStripMenuItem.Enabled = editAllowed; renameEntryToolStripMenuItem.Enabled = editAllowed; securityToolStripMenuItem.Enabled = this.CurrentDatabase.CurrentUser.IsAdmin; securityToolStripMenuItem1.Enabled = this.CurrentDatabase.CurrentUser.IsAdmin; } else { activeClientBindingSource.DataSource = typeof(ClientRecord); renameClientToolStripMenuItem.Enabled = false; editButton.Enabled = false; purgeClientToolStripMenuItem.Enabled = false; editModeToolStripMenuItem.Enabled = false; addEntryButton.Enabled = false; addEntryToolStripMenuItem.Enabled = false; deleteEntryToolStripMenuItem.Enabled = false; renameEntryToolStripMenuItem.Enabled = false; securityToolStripMenuItem.Enabled = false; securityToolStripMenuItem1.Enabled = false; } }
private void RecordCurrentClientOnHeaderMouseDown(object sender, DataGridViewCellMouseEventArgs e) { if (e.RowIndex != -1) return; _presortClient = clientListBindingSource.Current as ClientRecord; }
/// <summary> /// Populates a ClientRecord's Security and ClientEntries list from the database. /// </summary> /// <param name="client"></param> /// <remarks> /// This method is horrifically long and is due for refactoring. /// </remarks> public void Refresh(ClientRecord client) { //preconditions if (!this.Connected) throw new InvalidOperationException("Cannot get the list of entries for this client because the database is not connected."); if (!this.Authenticated) throw new InvalidOperationException("Cannot get the list of entries for this client because the current user is not authenticated with the Database."); RefreshDefaultSecurity(); RefreshClientSecurityInternal(client); if ((client.Security.Count == 0 && this.DefaultSecurity.CheckIsAllowedView(this.CurrentUser)) || client.Security.CheckIsAllowedView(this.CurrentUser)) { RefreshClientEntriesInternal(client); } else { client.RemoveEntries(client.Entries); } }
/// <summary> /// Refreshes the list of clients from the database. /// </summary> public void RefreshClientList() { if (!this.Connected) throw new InvalidOperationException("Cannot get the list of clients because the database is not connected."); if (!this.Authenticated) throw new InvalidOperationException("Cannot get the list of clients because the current user is not authenticated with the Database."); var getListCommand = new SqlCommand("sp_GetClientList", _connection) { CommandType = System.Data.CommandType.StoredProcedure }; getListCommand.Parameters.Add(new SqlParameter("token", "null_token")); //TODO: token will go here var newClients = new List<ClientRecord>(); var prevClientIds = _clients.Keys.ToList(); using (var reader = getListCommand.ExecuteReader()) { while (reader.Read()) { ClientRecord client; int clientDbId = (int)reader[0]; if (!_clients.TryGetItem(clientDbId, out client)) { client = new ClientRecord(); client.Security.Parent = this.DefaultSecurity; _clients.Add(clientDbId, client); newClients.Add(client); } //update the properties of the client, regardless if it existed before client.Name = (string)reader[1]; client.ClientId = reader[2] as string; } } //clean up the internal list, and raise events for the UI var deletedClientIds = prevClientIds.Except(_clients.Keys); if (deletedClientIds.Any()) { var deletedClients = new List<ClientRecord>(); foreach (var id in deletedClientIds) { deletedClients.Add(_clients[id]); _clients.Remove(id); } OnClientsRemoved(new ClientRecordEventArgs(deletedClients)); } if (newClients.Any()) OnClientsAdded(new ClientRecordEventArgs(newClients)); }
public void CommitClientSecurity(ClientRecord clientRecord) { if (clientRecord == null) throw new ArgumentNullException("clientRecord"); int clientId; if (!_clients.TryGetKey(clientRecord, out clientId)) throw new ArgumentException("The client specified does not exist in this database."); if (!this.Connected) throw new InvalidOperationException("Cannot commit the security settings because the database is not connected."); if (!this.Authenticated) throw new InvalidOperationException("Cannot commit the security settings because the current user is not authenticated with the Database."); //prepare the query in a format understood by sp_UpdateEntryValues var query = new XElement("Security"); foreach (var descriptor in clientRecord.Security) { XElement descriptorElement = new XElement("Descriptor", new XAttribute("view", descriptor.ViewAllowed), new XAttribute("edit", descriptor.EditingAllowed)); if (descriptor.SecurityPrincipal is UserPrincipal) { int userId; if (!_users.TryGetKey((UserPrincipal)descriptor.SecurityPrincipal, out userId)) throw new ArgumentException(String.Format("The user '{0}' does not have a valid user ID.", descriptor.SecurityPrincipal.Name)); descriptorElement.Add(new XAttribute("userId", userId)); } else if (descriptor.SecurityPrincipal is GroupPrincipal) { if (descriptor.SecurityPrincipal != GroupPrincipal.Everyone) { int groupId; if (!_groups.TryGetKey((GroupPrincipal)descriptor.SecurityPrincipal, out groupId)) throw new ArgumentException(String.Format("The group '{0}' does not have a valid user ID.", descriptor.SecurityPrincipal.Name)); descriptorElement.Add(new XAttribute("groupId", groupId)); } } else { throw new NotSupportedException(String.Format("Security Principals of type '{0}' are not supported by PogsDatabase.", descriptor.SecurityPrincipal.GetType().Name)); } query.Add(descriptorElement); } //Query the Database var updateCommand = new SqlCommand("sp_UpdateClientSecurity", _connection) { CommandType = CommandType.StoredProcedure }; updateCommand.Parameters.Add(new SqlParameter("token", "null_token")); //TODO: token will go here updateCommand.Parameters.Add(new SqlParameter("clientId", clientId)); updateCommand.Parameters.Add(new SqlParameter("updateXml", query.ToString())); updateCommand.ExecuteNonQuery(); AddLogEntryInternal(UserLogEntryType.Edit, clientRecord, "Changed Security Settings"); }
public void PurgeClient(ClientRecord clientRecord) { if (!this.Connected) throw new InvalidOperationException("Cannot purge the client because the database is not connected."); if (!this.Authenticated) throw new InvalidOperationException("Cannot purge the client because the current user is not authenticated with the Database."); if (clientRecord == null) throw new ArgumentNullException("clientRecord"); int id; if (!_clients.TryGetKey(clientRecord, out id)) throw new ArgumentException("Cannot purge this client because it does not exist in this database."); //delete entries and associated values (takes care of both memory and DB) clientRecord.RemoveEntries(clientRecord.Entries.ToList()); CommitClient(clientRecord); //delete client in DB var purgeCommand = new SqlCommand("sp_PurgeClient", _connection) { CommandType = System.Data.CommandType.StoredProcedure }; purgeCommand.Parameters.Add(new SqlParameter("token", "null_token")); //TODO: token will go here purgeCommand.Parameters.Add(new SqlParameter("client_id", id)); purgeCommand.ExecuteNonQuery(); //delete client in memory _clients.Remove(clientRecord); OnClientsRemoved(new ClientRecordEventArgs(clientRecord)); AddLogEntryInternal(UserLogEntryType.Delete, null, String.Format("Purged client: {0}", clientRecord.Name)); }
/// <summary> /// Updates the Database with any changed client name, id, or entry additions or deletions. /// </summary> /// <param name="clientRecord"></param> public void CommitClient(ClientRecord clientRecord) { if (clientRecord == null) throw new ArgumentNullException("clientRecord"); int clientId; if (!_clients.TryGetKey(clientRecord, out clientId)) throw new ArgumentException("Cannot commit this client because it does not exist in this database."); //update general information about the client var renameCommand = new SqlCommand("sp_UpdateClientName", _connection) { CommandType = System.Data.CommandType.StoredProcedure }; renameCommand.Parameters.Add(new SqlParameter("token", "null_token")); //TODO: token will go here renameCommand.Parameters.Add(new SqlParameter("clientId", clientId)); renameCommand.Parameters.Add(new SqlParameter("clientName", clientRecord.Name)); renameCommand.Parameters.Add(new SqlParameter("clientNumber", clientRecord.ClientId)); renameCommand.ExecuteNonQuery(); //add new entries var newEntries = clientRecord.Entries.Where(e => !_entries.ContainsItem(e)).ToList(); if (newEntries.Any()) { var query = new XElement("Entries", from e in newEntries select new XElement("Entry", new XAttribute("client_id", clientId), new XAttribute("template_id", e.Template == null ? 0 : _templates[e.Template]), new XAttribute("icon_id", e.IconIndex), new XAttribute("name", e.Name))); var updateCommand = new SqlCommand("sp_AddEntries", _connection) { CommandType = System.Data.CommandType.StoredProcedure }; updateCommand.Parameters.Add(new SqlParameter("token", "null_token")); //TODO: token will go here updateCommand.Parameters.Add(new SqlParameter("addXml", query.ToString())); //assign ids to the new entries using (var reader = updateCommand.ExecuteReader()) { int i = 0; while (reader.Read()) { if (i >= newEntries.Count) throw new InvalidOperationException("The database returned more new entires than expected."); int entryId = (int)reader[0]; _entries.Add(entryId, newEntries[i]); i++; } if (i < newEntries.Count) throw new InvalidOperationException("The database returned less new entries than expected."); } foreach (var e in newEntries) AddLogEntry(e, UserLogEntryType.Add); } //delete var deletedEntries = _entries.Items.Where(e => e.Client == clientRecord).Except(clientRecord.Entries).ToList(); if (deletedEntries.Any()) { var query = new XElement("Entries", from e in deletedEntries select new XElement("Entry", new XAttribute("id", _entries[e]))); var deleteCommand = new SqlCommand("sp_DeleteEntries", _connection) { CommandType = System.Data.CommandType.StoredProcedure }; deleteCommand.Parameters.Add(new SqlParameter("token", "null_token")); //TODO: token will go here deleteCommand.Parameters.Add(new SqlParameter("deleteXml", query.ToString())); deleteCommand.ExecuteNonQuery(); //TODO: check count foreach (var entry in deletedEntries) { //remove the custom field values from memory foreach (var field in entry.CustomFields) { _customFields.Remove(field); } //remove the template field values from memory if (entry.Template != null) { var values = _templateValues .Where(kvp => kvp.Value.ClientEntry == entry) .ToList(); foreach (var v in values) { _templateValues.Remove(v.Key); } } //remove the IDs from memory _entries.Remove(entry); } foreach (var e in deletedEntries) AddLogEntry(e, UserLogEntryType.Delete); } }
private void RefreshClientSecurityInternal(ClientRecord client) { var getDefaultSecurityCommand = new SqlCommand("sp_GetClientSecurity", _connection) { CommandType = System.Data.CommandType.StoredProcedure }; getDefaultSecurityCommand.Parameters.Add(new SqlParameter("token", "null_token")); //TODO: token will go here getDefaultSecurityCommand.Parameters.Add(new SqlParameter("clientId", _clients[client])); using (var reader = getDefaultSecurityCommand.ExecuteReader()) { client.Security.Clear(); while (reader.Read()) { int userId = reader.IsDBNull(0) ? -1 : (int)reader[0]; int groupId = reader.IsDBNull(1) ? -1 : (int)reader[1]; if (userId != -1 && groupId != -1) throw new InvalidOperationException("An invalid default security record was received from the Database."); SecurityPrincipal target; bool createdNew = false; if (userId != -1) target = CreateOrUpdateUser(reader, 0, -1, -1, out createdNew); else if (groupId != -1) target = CreateOrUpdateGroup(reader, 1, -1, -1, out createdNew); else target = GroupPrincipal.Everyone; //both null means everyone if (createdNew) OnPrincipalsAdded(new SecurityPrincipalsEventArgs(target)); client.Security.Add(new SecurityDescriptor(target, (bool)reader[3], (bool)reader[2])); } } }
public void AddNewClient(ClientRecord clientRecord) { if (!this.Connected) throw new InvalidOperationException("Cannot add the client because the database is not connected."); if (!this.Authenticated) throw new InvalidOperationException("Cannot add the client because the current user is not authenticated with the Database."); if (clientRecord == null) throw new ArgumentNullException("clientRecord"); if (_clients.ContainsItem(clientRecord)) throw new ArgumentException("Cannot add this client because it already exists in this database."); //execute the stored procedure var addCommand = new SqlCommand("sp_AddClient", _connection) { CommandType = System.Data.CommandType.StoredProcedure }; addCommand.Parameters.Add(new SqlParameter("token", "null_token")); //TODO: token will go here addCommand.Parameters.Add(new SqlParameter("client_name", clientRecord.Name)); addCommand.Parameters.Add(new SqlParameter("client_id", clientRecord.ClientId)); //assign the IDs int newId = (int)addCommand.ExecuteScalar(); _clients.Add(newId, clientRecord); clientRecord.Security.Parent = this.DefaultSecurity; //raise events OnClientsAdded(new ClientRecordEventArgs(clientRecord)); AddLogEntryInternal(UserLogEntryType.Add, clientRecord, String.Format("Added new client: {0}", clientRecord.Name)); }
private void RefreshClientEntriesInternal(ClientRecord client) { //preparation int clientId = _clients[client]; if (!_clients.TryGetKey(client, out clientId)) throw new ArgumentException("The specified client is not in this database."); var newEntries = new List<ClientEntry>(); var prevEntryIds = client.Entries.Select(e => _entries[e]).ToList(); //Query the Database var getListCommand = new SqlCommand("sp_GetClientEntries", _connection) { CommandType = System.Data.CommandType.StoredProcedure }; getListCommand.Parameters.Add(new SqlParameter("token", "null_token")); //TODO: token will go here getListCommand.Parameters.Add(new SqlParameter("client_id", clientId)); using (var reader = getListCommand.ExecuteReader()) { //result set 1: entry list for the specified client while (reader.Read()) { ClientEntry entry; int clientEntryDbId = (int)reader[0]; //index the entry if it is new if (!_entries.TryGetItem(clientEntryDbId, out entry)) { entry = new ClientEntry(); _entries.Add(clientEntryDbId, entry); newEntries.Add(entry); } //update the properties of the entry, regardless if it existed before entry.Name = (string)reader[2]; entry.IconIndex = (int)reader[3]; entry.Notes = WebUtility.HtmlDecode((reader[5] as string ?? String.Empty).Replace("<br>", Environment.NewLine)); //set the template, it will get updated later if it doesn't exist yet //we index the new template right away EntryTemplate template; int templateId = (reader[4] == DBNull.Value) ? -1 : (int)reader[4]; if (templateId == -1) { template = null; //orphaned record } else if (!_templates.TryGetItem(templateId, out template)) { template = new EntryTemplate(); _templates.Add(templateId, template); } entry.Template = template; } //result set 2: template definition reader.NextResult(); while (reader.Read()) { EntryTemplate template; int templateDbId = (int)reader[0]; if (!_templates.TryGetItem(templateDbId, out template)) throw new InvalidOperationException("A template was returned that was not part of the first result set."); //update the properties template.Name = reader[1] as string; template.IconIndex = (int)reader[2]; template.AllowCustomFields = (bool)reader[3]; } //result set 3: fields for the previous templates reader.NextResult(); while (reader.Read()) { EntryField templateField; EntryTemplate template; int templateFieldId = (int)reader[0]; int templateId = (int)reader[1]; if (!_templates.TryGetItem(templateId, out template)) throw new InvalidOperationException("A template field was returned that belongs to a template that was not returned in the previous result set."); if (!_templateFields.TryGetItem(templateFieldId, out templateField)) { templateField = new EntryField(); _templateFields.Add(templateFieldId, templateField); } if (!template.Fields.Contains(templateField)) template.AddField(templateField); //update the properties templateField.Name = reader[2] as string; templateField.EntryType = (EntryFieldType)reader[3]; templateField.DefaultValue = reader[4] as string; } //TODO: remove any fields that were not returned //result set 4: field values reader.NextResult(); while (reader.Read()) { int fieldValueId = (int)reader[0]; int entryId = (int)reader[1]; ClientEntry entry; if (!_entries.TryGetItem(entryId, out entry)) throw new InvalidOperationException("A ClientEntry was returned that was not defined in a previous result set."); int templateFieldId = (reader[2] == DBNull.Value) ? -1 : (int)reader[2]; string entryValue = reader[4] as string; //indexing of fields values: // template field values are indexed by TFVR objects in the _templateFieldsById dictionary // custom field values are indexed by just the EntryField object in the _customFieldsById dictionary if (templateFieldId == -1) { //custom field string fieldName = reader[3] as string; EntryField customField; if (!_customFields.TryGetItem(fieldValueId, out customField)) { customField = new EntryField() { Name = fieldName }; //todo: type entry.AddCustomField(customField); _customFields.Add(fieldValueId, customField); } //update the name and value customField.Name = fieldName; entry.SetValue(customField, DataSecurity.DecryptStringAES(entryValue)); } else { //find the template EntryField by ID EntryField templateField; if (_templateFields.TryGetItem(templateFieldId, out templateField)) { //save the ID of the field value for saving later if (!_templateValues.Values.Any(tfvr => tfvr.ClientEntry == entry && tfvr.TemplateField == templateField)) _templateValues.Add(fieldValueId, new TemplateFieldValueRelation() { ClientEntry = entry, TemplateField = templateField }); entry.SetValue(templateField, DataSecurity.DecryptStringAES(entryValue)); } else { throw new InvalidOperationException("A template field was returned that cannot be matched to an existing template."); } } } //TODO: remove any fields that were not returned } //clean up the internal list, and raise events for the UI var deletedEntryIds = prevEntryIds.Except(_entries.Keys).ToList(); if (deletedEntryIds.Any()) { var deletedEntries = new List<ClientEntry>(); foreach (var id in deletedEntryIds) { var entry = _entries[id]; deletedEntries.Add(entry); _entries.Remove(entry); } client.RemoveEntries(deletedEntries); } if (newEntries.Any()) client.AddEntries(newEntries); }
private void AddLogEntryInternal(UserLogEntryType entryType, ClientRecord client, string description) { //send the command var addLogEntryCommand = new SqlCommand("sp_AddLogEntry", _connection) { CommandType = System.Data.CommandType.StoredProcedure }; addLogEntryCommand.Parameters.Add(new SqlParameter("username", this.CurrentUser.Name)); addLogEntryCommand.Parameters.Add(new SqlParameter("actiontype", (int)entryType)); addLogEntryCommand.Parameters.Add(new SqlParameter("clientid", client == null ? -1 : _clients[client])); addLogEntryCommand.Parameters.Add(new SqlParameter("description", description)); addLogEntryCommand.ExecuteNonQuery(); }