Skip to content

Commit

Permalink
Merge branch 'release/4.1.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
tznind committed Jun 15, 2020
2 parents 95b1a09 + 2271830 commit 60d6436
Show file tree
Hide file tree
Showing 79 changed files with 1,016 additions and 239 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Rdmp.Core.Icons.IconProvision;
using Rdmp.UI.Icons.IconProvision;
using Rdmp.UI.ItemActivation;
using Rdmp.UI.Menus;
using ResearchDataManagementPlatform.WindowManagement.ContentWindowTracking.Persistence;

namespace ResearchDataManagementPlatform.WindowManagement.TabPageContextMenus
Expand All @@ -28,6 +29,13 @@ public RDMPSingleControlTabMenu(IActivateItems activator, RDMPSingleControlTab t
Items.Add("Close All But This", null, (s, e) => windowManager.CloseAllButThis(tab));

Items.Add("Show", null, (s, e) => tab.HandleUserRequestingEmphasis(activator));

if (tab is PersistableSingleDatabaseObjectDockContent single)
{
var builder = new GoToMenuBuilder(activator);
Items.Add(builder.GetMenu(single.DatabaseObject));
}

Items.Add("Refresh", FamFamFamIcons.arrow_refresh, (s, e) => _tab.HandleUserRequestingTabRefresh(activator));

var help = new ToolStripMenuItem("Help", FamFamFamIcons.help, (s, e) => _tab.ShowHelp(activator));
Expand Down
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

...

## [4.1.3] - 2020-06-15

### Added

- Added `-f` option to CLI (`rdmp.exe -f somefile.yaml`) to run all commands in a file
- Added "Go To" to tab right click context menu (previously only available in collections).
- Private key encryption file location can now be customized per user by setting an environment variable `RDMP_KEY_LOCATION`. This will override any key file location specified in the RDMP platform database.

### Changed

- Frozen Extraction Configurations folder always appears at the bottom of the branch under Projects
- Improved layout of query building errors in QueryBuilder SQL viewing user interfaces

### Fixed

- Fixed bug in tree ordering when comparing a fixed order node to a non fixed order node.

## [4.1.2] - 2020-06-03

### Added
Expand Down Expand Up @@ -422,7 +439,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed Culture (e.g. en-us) not being passed correctly in DelimitedFlatFileAttacher
- Fixed bug where Updater would show older versions of RDMP as installable 'updates'

[Unreleased]: https://github.com/HicServices/RDMP/compare/v4.1.2...develop
[Unreleased]: https://github.com/HicServices/RDMP/compare/v4.1.3...develop
[4.1.3]: https://github.com/HicServices/RDMP/compare/v4.1.2...v4.1.3
[4.1.2]: https://github.com/HicServices/RDMP/compare/v4.1.1...v4.1.2
[4.1.1]: https://github.com/HicServices/RDMP/compare/v4.1.0...v4.1.1
[4.1.0]: https://github.com/HicServices/RDMP/compare/v4.0.3...v4.1.0
Expand Down
10 changes: 10 additions & 0 deletions Documentation/CodeTutorials/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
1. [RDMP is not listing my table as importable](#notlistingtable)
1. User Interface
1. [I cannot resize a column in a listbox/tree view](#resize)
1. [Where does RDMP store user settings](#user-settings)
1. Anonymisation
1. [Does RDMP support data anonymisation?](#does-rdmp-support-data-anonymisation)
1. Curation
Expand Down Expand Up @@ -358,6 +359,15 @@ Some columns in RDMP are set to fill the available space (in the dialog). For e

[![How to resize a column](Images/FAQ/ResizeColumnFillsSpace.png)](https://youtu.be/OcbG-FDEq30)

<a name="user-settings"></a>
## Where does RDMP store user settings?

RDMP stores user settings in IsolatedStorage. In Windows you can reach this by entering the following in Windows Explorer:

```
%LocalAppData%\IsolatedStorage
```

## Anonymisation

### Does RDMP Support Data Anonymisation?
Expand Down
104 changes: 104 additions & 0 deletions Rdmp.Core.Tests/CommandLine/RdmpScriptTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright (c) The University of Dundee 2018-2019
// This file is part of the Research Data Management Platform (RDMP).
// RDMP 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.
// RDMP 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 RDMP. If not, see <https://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Rdmp.Core.CommandLine.Options;
using Rdmp.Core.CommandLine.Runners;
using Rdmp.Core.Curation.Data;
using Rdmp.Core.DataFlowPipeline;
using ReusableLibraryCode.Checks;
using ReusableLibraryCode.Progress;
using Tests.Common;

namespace Rdmp.Core.Tests.CommandLine
{
class RdmpScriptTests : UnitTests
{
[TestCase("NewObject Catalogue 'trog dor'","trog dor")]
[TestCase("NewObject Catalogue \"trog dor\"","trog dor")]
[TestCase("NewObject Catalogue \"'trog dor'\"","'trog dor'")]
[TestCase("NewObject Catalogue '\"trog dor\"'","\"trog dor\"")]

public void RdmpScript_NewObject_Catalogue(string command, string expectedName)
{
foreach(var c in RepositoryLocator.CatalogueRepository.GetAllObjects<Catalogue>())
c.DeleteInDatabase();

var runner = new ExecuteCommandRunner(new ExecuteCommandOptions()
{
Script = new RdmpScript()
{
Commands = new[] {command}
}
});

SetupMEF();

var exitCode = runner.Run(RepositoryLocator, new ThrowImmediatelyDataLoadEventListener(), new ThrowImmediatelyCheckNotifier(), new GracefulCancellationToken());

Assert.AreEqual(0,exitCode);
Assert.AreEqual(1,RepositoryLocator.CatalogueRepository.GetAllObjects<Catalogue>().Length);

Assert.AreEqual(expectedName,RepositoryLocator.CatalogueRepository.GetAllObjects<Catalogue>().Single().Name);
}

[TestCase("NewObject Catalogue 'fffff'","NewObject CatalogueItem Catalogue:*fff* 'bbbb'","bbbb")]
[TestCase("NewObject Catalogue '\"fff\"'","NewObject CatalogueItem 'Catalogue:\"fff\"' 'bbbb'","bbbb")]
[TestCase("NewObject Catalogue '\"ff ff\"'","NewObject CatalogueItem 'Catalogue:\"ff ff\"' 'bb bb'","bb bb")]
[TestCase("NewObject Catalogue '\"ff ff\"'","NewObject CatalogueItem 'Catalogue:\"ff ff\"' bb'bb","bb'bb")]
[TestCase("NewObject Catalogue '\"ff ff\"'","NewObject CatalogueItem 'Catalogue:\"ff ff\"' b\"b'bb'","b\"b'bb'")]
public void RdmpScript_NewObject_CatalogueItem(string cataCommand,string cataItemCommand, string expectedCataItemName)
{
foreach(var c in RepositoryLocator.CatalogueRepository.GetAllObjects<Catalogue>())
c.DeleteInDatabase();

var runner = new ExecuteCommandRunner(new ExecuteCommandOptions()
{
Script = new RdmpScript()
{
Commands = new[]
{
cataCommand,
cataItemCommand
}
}
});

SetupMEF();

var exitCode = runner.Run(RepositoryLocator, new ThrowImmediatelyDataLoadEventListener(), new ThrowImmediatelyCheckNotifier(), new GracefulCancellationToken());

Assert.AreEqual(0,exitCode);
Assert.AreEqual(1,RepositoryLocator.CatalogueRepository.GetAllObjects<Catalogue>().Length);
var ci = RepositoryLocator.CatalogueRepository.GetAllObjects<Catalogue>().Single().CatalogueItems.Single();

Assert.AreEqual(expectedCataItemName,ci.Name);

}

[Test]
public void Test_SplitCommandLine()
{
var vals = ExecuteCommandRunner.SplitCommandLine("NewObject CatalogueItem 'Catalogue:\"fff\"' 'bbbb'").ToArray();
Assert.AreEqual("NewObject",vals[0]);
Assert.AreEqual("CatalogueItem",vals[1]);
Assert.AreEqual("Catalogue:\"fff\"",vals[2]);
Assert.AreEqual("bbbb",vals[3]);
}
[Test]
public void Test_SplitCommandLine_QuotesInStrings()
{
var vals = ExecuteCommandRunner.SplitCommandLine("NewObject CatalogueItem bb\"'bb'").ToArray();
Assert.AreEqual("NewObject",vals[0]);
Assert.AreEqual("CatalogueItem",vals[1]);
Assert.AreEqual("bb\"'bb'",vals[2]);
}
}
}
4 changes: 4 additions & 0 deletions Rdmp.Core.Tests/Curation/Integration/EncryptionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Linq;
using NUnit.Framework;
using Rdmp.Core.Curation.Data;
using Rdmp.Core.Repositories.Managers;
using ReusableLibraryCode;
using Tests.Common;

Expand Down Expand Up @@ -204,6 +205,9 @@ public void MigrationOfOldPasswordsTest()
[Test]
public void PasswordTooLong()
{
if(RepositoryLocator.CatalogueRepository.EncryptionManager is PasswordEncryptionKeyLocation em && !string.IsNullOrWhiteSpace(em.GetKeyFileLocation()))
Assert.Inconclusive("Could not run test because there is already an encryption key set up. Likely one that handles very long passwords");

string password = "a";
for (int i = 0; i < 200; i++)
password += "a";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ protected override void SetUp()
base.SetUp();

var keyLocation = new PasswordEncryptionKeyLocation(CatalogueRepository);

if(keyLocation.GetKeyFileLocation() != null)
keyLocation.DeleteKey();
Assert.Inconclusive();
}

[Test]
Expand Down
103 changes: 103 additions & 0 deletions Rdmp.Core.Tests/Curation/Unit/IMightBeReadOnlyTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright (c) The University of Dundee 2018-2019
// This file is part of the Research Data Management Platform (RDMP).
// RDMP 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.
// RDMP 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 RDMP. If not, see <https://www.gnu.org/licenses/>.

using NUnit.Framework;
using Rdmp.Core.Curation.Data;
using Rdmp.Core.Curation.Data.Aggregation;
using Rdmp.Core.Curation.Data.Cohort;
using Rdmp.Core.Curation.Data.Spontaneous;
using Rdmp.Core.DataExport.Data;
using Rdmp.Core.Repositories;
using Tests.Common;

namespace Rdmp.Core.Tests.Curation.Unit
{
class IMightBeReadOnlyTests : UnitTests
{
[Test]
public void IsReadonly_AggregateFilterContainer()
{
//im probably an orphan
var c = WhenIHaveA<AggregateFilterContainer>();
Assert.IsFalse(c.ShouldBeReadOnly(out _));

//now I am in a cic
var cic = WhenIHaveA<CohortIdentificationConfiguration>();
cic.Name = "fff";
cic.CreateRootContainerIfNotExists();
cic.RootCohortAggregateContainer.AddChild(c.GetAggregate(),0);

Assert.IsFalse(c.ShouldBeReadOnly(out _));

cic.Frozen = true;
Assert.IsTrue(c.ShouldBeReadOnly(out string reason));

Assert.AreEqual("fff is Frozen",reason);
}

[Test]
public void IsReadonly_ExtractionFilterContainer()
{
var c = WhenIHaveA<FilterContainer>();
Assert.IsFalse(c.ShouldBeReadOnly(out _));

var ec = c.GetSelectedDataSetIfAny().ExtractionConfiguration;

Assert.IsFalse(c.ShouldBeReadOnly(out _));

ec.Name = "lll";
ec.IsReleased = true;
Assert.IsTrue(c.ShouldBeReadOnly(out string reason));

Assert.AreEqual("lll has already been released",reason);
}

[Test]
public void IsReadonly_SpontaneousContainer()
{
var memoryrepo = new MemoryCatalogueRepository();
var c = new SpontaneouslyInventedFilterContainer(memoryrepo,null,null,FilterContainerOperation.AND);
Assert.IsFalse(c.ShouldBeReadOnly(out _),"Spont containers should never be in UI but lets not tell the programmer they shouldn't be edited");
}



[Test]
public void IsReadonly_AggregateFilter()
{
//im probably an orphan
var f = WhenIHaveA<AggregateFilter>();
Assert.IsFalse(f.ShouldBeReadOnly(out _));

//now I am in a cic
var cic = WhenIHaveA<CohortIdentificationConfiguration>();
cic.Name = "fff";
cic.CreateRootContainerIfNotExists();
cic.RootCohortAggregateContainer.AddChild(f.GetAggregate(),0);

Assert.IsFalse(f.ShouldBeReadOnly(out _));

cic.Frozen = true;
Assert.IsTrue(f.ShouldBeReadOnly(out string reason));

Assert.AreEqual("fff is Frozen",reason);
}

[Test]
public void IsReadonly_DeployedExtractionFilter()
{
var f = WhenIHaveA<DeployedExtractionFilter>();
Assert.IsFalse(f.ShouldBeReadOnly(out _));

var ec = ((FilterContainer) f.FilterContainer).GetSelectedDataSetIfAny().ExtractionConfiguration;
ec.Name = "lll";
ec.IsReleased = true;
Assert.IsTrue(f.ShouldBeReadOnly(out string reason));

Assert.AreEqual("lll has already been released",reason);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ public ExecuteCommandAddAggregateConfigurationToCohortIdentificationSetContainer
{
_aggregateConfigurationCombineable = aggregateConfigurationCommand;
_targetCohortAggregateContainer = targetCohortAggregateContainer;

if(targetCohortAggregateContainer.ShouldBeReadOnly(out string reason))
SetImpossible(reason);
}

public override void Execute()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public ExecuteCommandAddCatalogueToCohortIdentificationSetContainer(IBasicActiva

if(!catalogueCombineable.ContainsAtLeastOneExtractionIdentifier)
SetImpossible("Catalogue " + catalogueCombineable.Catalogue + " does not contain any IsExtractionIdentifier columns");

if(targetCohortAggregateContainer.ShouldBeReadOnly(out string reason))
SetImpossible(reason);
}

public override void Execute()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ public ExecuteCommandConvertAggregateConfigurationToPatientIndexTable(IBasicActi
if(sourceAggregateConfigurationCommand.JoinableDeclarationIfAny != null)
SetImpossible("Aggregate is already a Patient Index Table");

if(_sourceAggregateConfigurationCombineable.CohortIdentificationConfigurationIfAny != null &&
_sourceAggregateConfigurationCombineable.CohortIdentificationConfigurationIfAny.ID != _cohortIdentificationConfiguration.ID)
SetImpossible("Aggregate '" + _sourceAggregateConfigurationCombineable.Aggregate + "' belongs to a different Cohort Identification Configuration");
var cic = _sourceAggregateConfigurationCombineable.CohortIdentificationConfigurationIfAny;

if( cic != null && cic.ID != _cohortIdentificationConfiguration.ID)
SetImpossible("Aggregate '" + _sourceAggregateConfigurationCombineable.Aggregate + "' belongs to a different Cohort Identification Configuration");

if(cic != null && cic.ShouldBeReadOnly(out string reason))
SetImpossible(reason);
}

public override void Execute()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) The University of Dundee 2018-2019
// This file is part of the Research Data Management Platform (RDMP).
// RDMP 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.
// RDMP 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 RDMP. If not, see <https://www.gnu.org/licenses/>.

using System.IO;
using Rdmp.Core.Repositories.Managers;

namespace Rdmp.Core.CommandExecution.AtomicCommands
{
/// <summary>
/// Creates a new private key for encrypting credentials in RDMP. Old passwords will not decrypt using the new key and will be lost (unless you have the original key)
/// </summary>
public class ExecuteCommandCreatePrivateKey : BasicCommandExecution
{
private readonly FileInfo _keyFileToCreate;
private PasswordEncryptionKeyLocation _encryption;

public ExecuteCommandCreatePrivateKey(IBasicActivateItems activator, FileInfo keyFileToCreate) : base(activator)
{
_keyFileToCreate = keyFileToCreate;
_encryption = activator.RepositoryLocator.CatalogueRepository.EncryptionManager as PasswordEncryptionKeyLocation;

if (_encryption == null)
{
SetImpossible("Current Encryption manager is not based on key files");
return;
}

var existing = _encryption.GetKeyFileLocation();
if (existing != null)
SetImpossible($"There is already a key file at '{existing}'");
}

public override void Execute()
{
base.Execute();

_encryption.CreateNewKeyFile(_keyFileToCreate.FullName);
}
}
}
Loading

0 comments on commit 60d6436

Please sign in to comment.