Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add docs around package scanning and notify user of infected package upload. #13235

Merged
merged 3 commits into from
Aug 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.en-US.resx
Original file line number Diff line number Diff line change
Expand Up @@ -3284,4 +3284,10 @@ You can manage this in Preferences -&gt; Security.</value>
<data name="NotificationCenterButtonTooltip" xml:space="preserve">
<value>Click to view latest news from Dynamo Team.</value>
</data>
<data name="InfectedPackageMessageString" xml:space="preserve">
<value>This is an infected package. Please upload a clean version.</value>
</data>
<data name="InfectedPackageErrorString" xml:space="preserve">
<value>Upload Error</value>
</data>
</root>
6 changes: 6 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -3271,4 +3271,10 @@ You can manage this in Preferences -&gt; Security.</value>
<data name="NotificationCenterButtonTooltip" xml:space="preserve">
<value>Click to view latest news from Dynamo Team.</value>
</data>
<data name="InfectedPackageMessageString" xml:space="preserve">
<value>This is an infected package. Please upload a clean version.</value>
</data>
<data name="InfectedPackageErrorString" xml:space="preserve">
<value>Upload Error</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ <h4>Package Name:</h4>
<p>
<b>Add File:</b><br />
Select and add all the files that are related to your package; generally the bin folder, binaries and dependencies are added.
<p>
<p>
<b>Select Node Libraries:</b><br />
<p>
Specify which of the files you added to the package are the node libraries. Node libraries contain the types and methods that Dynamo will import as nodes. In general you should mark any assembly as a node library which contains types you wish to import into Dynamo. ZeroTouch, NodeModel, or NodeViewCustomization assemblies should be marked as node library.
Expand All @@ -223,4 +223,14 @@ <h4>Package Name:</h4>
When publishing locally the package will be published in the local root directory,
whereas while publishing online the package will be uploaded to the package manager.
</p>
<hr />
<h3>Anti-virus Scans</h3>
<p>
To provide a secure environment to all Dynamo Package users, we have introduced anti-virus scans for new packages.
When a user uploads a package, it will be scanned for viruses and will only be available publicly once it has been flagged as safe.
The scan will happen during the package upload process and will not add to the usual duration of 10-15 minutes for the new package to be available online.
If your package is flagged as infected, the Package Manager search window will display a notification stating that the uploaded package has
been found to be infected and won't be published online. To make the package publicly available, check the files included with the package
and upload a new version through the Package Manager.
</p>
</body>
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ public class PackageManagerClientViewModel : NotificationObject, IPackageInstall

#region Properties/Fields

private readonly string QUARANTINED = "quarantined";
public PackageManagerSearchView Owner { get; set; }

ObservableCollection<PackageUploadHandle> _uploads = new ObservableCollection<PackageUploadHandle>();
Expand All @@ -224,6 +225,7 @@ internal virtual PackageManagerExtension PackageManagerExtension
}

public List<PackageManagerSearchElement> CachedPackageList { get; private set; }
public List<PackageManagerSearchElement> InfectedPackageList { get; private set; }

public readonly DynamoViewModel DynamoViewModel;
public AuthenticationManager AuthenticationManager { get; set; }
Expand Down Expand Up @@ -471,6 +473,28 @@ public List<PackageManagerSearchElement> ListAll()
return CachedPackageList;
}

/// <summary>
/// Returns a dictionary of infected package(s) with name and version, if the last published version of package uploaded by the current user was flagged as infected.
/// </summary>
/// <returns></returns>
public List<PackageManagerSearchElement> GetInfectedPackages()
{
InfectedPackageList = new List<PackageManagerSearchElement>();
var latestPkgs = Model.GetUsersLatestPackages();
if (latestPkgs != null && latestPkgs.maintains.Count > 0)
{
foreach (var infectedVer in latestPkgs.maintains)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you remind me why do we need to look at each version here? I thought we only need to check the latest version of each package

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API will return all packages with last uploaded version, so 1 version per package only.

{
if (infectedVer.scan_status == QUARANTINED)
{
var ele = new PackageManagerSearchElement(infectedVer);
InfectedPackageList.Add(ele);
}
}
}
return InfectedPackageList;
}

/// <summary>
/// Download and install a specific package from the package manager
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ private void SetFilterHosts(object obj)
// The results of the last synchronization with the package manager server
public List<PackageManagerSearchElement> LastSync { get; set; }

/// <summary>
/// Stores a list of latest infected package versions published by the current user, if any.
/// </summary>
public ObservableCollection<PackageManagerSearchElement> InfectedPackages { get; set; }

/// <summary>
/// SortingKey property
/// </summary>
Expand Down Expand Up @@ -387,7 +392,7 @@ public PackageSearchState SearchState
/// appears at the base of the window. This command fires when the user clicks to dismiss
/// one of these toast notifications.
/// </summary>
public DelegateCommand<object> ClearDownloadToastNotificationCommand { get; set; }
public DelegateCommand<object> ClearToastNotificationCommand { get; set; }


/// <summary>
Expand All @@ -408,6 +413,7 @@ public IPreferences Preferences
internal PackageManagerSearchViewModel()
{
SearchResults = new ObservableCollection<PackageManagerSearchElementViewModel>();
InfectedPackages = new ObservableCollection<PackageManagerSearchElement>();
MaxNumSearchResults = 35;
SearchDictionary = new SearchDictionary<PackageManagerSearchElement>();
ClearCompletedCommand = new DelegateCommand(ClearCompleted, CanClearCompleted);
Expand All @@ -416,7 +422,7 @@ internal PackageManagerSearchViewModel()
SetSortingDirectionCommand = new DelegateCommand<object>(SetSortingDirection, CanSetSortingDirection);
ViewPackageDetailsCommand = new DelegateCommand<object>(ViewPackageDetails);
ClearSearchTextBoxCommand = new DelegateCommand<object>(ClearSearchTextBox);
ClearDownloadToastNotificationCommand = new DelegateCommand<object>(ClearDownloadToastNotification);
ClearToastNotificationCommand = new DelegateCommand<object>(ClearToastNotification);
SearchText = string.Empty;
SortingKey = PackageSortingKey.LastUpdate;
SortingDirection = PackageSortingDirection.Descending;
Expand Down Expand Up @@ -543,17 +549,28 @@ public void ClearSearchTextBox(object obj)
/// one of these toast notifications.
/// </summary>
/// <param name="obj"></param>
public void ClearDownloadToastNotification(object obj)
public void ClearToastNotification(object obj)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is API breaking but I guess you decided to break it intentionally?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes to make this function a bit more generic

{
if (!(obj is PackageDownloadHandle packageDownloadHandle)) return;
if (obj is PackageDownloadHandle packageDownloadHandle)
{

PackageDownloadHandle packageDownloadHandleToRemove = PackageManagerClientViewModel.Downloads
.FirstOrDefault(x => x.Id == packageDownloadHandle.Id);
PackageDownloadHandle packageDownloadHandleToRemove = PackageManagerClientViewModel.Downloads
.FirstOrDefault(x => x.Id == packageDownloadHandle.Id);

if (packageDownloadHandleToRemove == null) return;
if (packageDownloadHandleToRemove == null) return;

PackageManagerClientViewModel.Downloads.Remove(packageDownloadHandleToRemove);
RaisePropertyChanged(nameof(Downloads));
PackageManagerClientViewModel.Downloads.Remove(packageDownloadHandleToRemove);
RaisePropertyChanged(nameof(Downloads));
}
else if (obj is PackageManagerSearchElement packageSearchElement)
{
PackageManagerSearchElement packageInfectedToRemove = this.InfectedPackages
.FirstOrDefault(x => x.InfectedPackageName == packageSearchElement.InfectedPackageName);

this.InfectedPackages.Remove(packageInfectedToRemove);
RaisePropertyChanged(nameof(InfectedPackages));
}
return;
}

/// <summary>
Expand Down Expand Up @@ -671,9 +688,26 @@ public void RefreshAndSearchAsync()
}
this.SearchState = HasNoResults ? PackageSearchState.NoResults : PackageSearchState.Results;
}
RefreshInfectedPackages();
}
, TaskScheduler.FromCurrentSynchronizationContext()); // run continuation in ui thread

}

internal void RefreshInfectedPackages()
{
var infectedPkgs = PackageManagerClientViewModel.GetInfectedPackages();
infectedPkgs.Sort((e1, e2) => e1.InfectedPackageCreationDate.CompareTo(e2.InfectedPackageCreationDate));

this.InfectedPackages.Clear();
foreach (var pkg in infectedPkgs) {
this.InfectedPackages.Add(pkg);

// Limiting the infected packages list to 3. As the packages are resolved other unresolved packages will be displayed.
if (this.InfectedPackages.Count() == 3)
{
break;
}
}
}

internal void AddToSearchResults(PackageManagerSearchElementViewModel element)
Expand Down
Loading