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 new UserClient implementation #503

Merged
merged 1 commit into from
Feb 27, 2024
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
20 changes: 9 additions & 11 deletions Source/v2/Meadow.Cli/Commands/Current/BaseCloudCommand.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using CliFx.Attributes;
using Meadow.Cloud.Client;
using Meadow.Cloud.Client.Identity;
using Meadow.Cloud.Client.Users;
using Microsoft.Extensions.Logging;
using System.Linq;

namespace Meadow.CLI.Commands.DeviceManagement;

Expand All @@ -15,17 +17,13 @@ public abstract class BaseCloudCommand<T> : BaseCommand<T>
protected bool RequiresAuthentication { get; set; } = true;

protected IMeadowCloudClient MeadowCloudClient { get; }
protected UserService UserService { get; }


public BaseCloudCommand(
IMeadowCloudClient meadowCloudClient,
UserService userService,
ILoggerFactory loggerFactory)
: base(loggerFactory)
{
MeadowCloudClient = meadowCloudClient;
UserService = userService;
}

protected virtual ValueTask PreAuthenticatedValidation()
Expand All @@ -48,7 +46,7 @@ protected sealed override async ValueTask ExecuteCommand()
}

// If the user does not yet exist in Meadow.Cloud, this creates them and sets up their initial org
var _ = await UserService.GetMe(Host, CancellationToken)
var _ = await MeadowCloudClient.User.GetUser(CancellationToken)
?? throw new CommandException("There was a problem retrieving your account information.");
}

Expand All @@ -62,22 +60,22 @@ protected sealed override async ValueTask ExecuteCommand()
}
}

protected async Task<UserOrg?> GetOrg(string host, string? orgNameOrId = null, CancellationToken? cancellationToken = null)
protected async Task<GetOrganizationResponse?> GetOrganization(string? orgNameOrId = null, CancellationToken cancellationToken = default)
{
Logger.LogInformation("Retrieving your user and organization information...");

var userOrgs = await UserService.GetUserOrgs(host, cancellationToken).ConfigureAwait(false);
if (userOrgs.Count > 1 && string.IsNullOrEmpty(orgNameOrId))
var orgs = await MeadowCloudClient.User.GetOrganizations(cancellationToken).ConfigureAwait(false);
if (orgs.Count() > 1 && string.IsNullOrEmpty(orgNameOrId))
{
Logger.LogInformation($"You are a member of more than 1 organization. Please specify the desired orgId for this device provisioning.");
return null;
}
else if (userOrgs.Count == 1 && string.IsNullOrEmpty(orgNameOrId))
else if (orgs.Count() == 1 && string.IsNullOrEmpty(orgNameOrId))
{
orgNameOrId = userOrgs[0].Id;
orgNameOrId = orgs.Single().Id;
}

var org = userOrgs.FirstOrDefault(o => o.Id == orgNameOrId || o.Name == orgNameOrId);
var org = orgs.FirstOrDefault(o => o.Id == orgNameOrId || string.Equals(o.Name, orgNameOrId, StringComparison.OrdinalIgnoreCase));
if (org == null)
{
Logger.LogInformation($"Unable to find an organization with a Name or ID matching '{orgNameOrId}'");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ public class CloudApiKeyCreateCommand : BaseCloudCommand<CloudApiKeyCreateComman
public CloudApiKeyCreateCommand(
IMeadowCloudClient meadowCloudClient,
ApiTokenService apiTokenService,
UserService userService,
ILoggerFactory loggerFactory)
: base(meadowCloudClient, userService, loggerFactory)
: base(meadowCloudClient, loggerFactory)
{
ApiTokenService = apiTokenService;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ public class CloudApiKeyDeleteCommand : BaseCloudCommand<CloudApiKeyDeleteComman
public CloudApiKeyDeleteCommand(
IMeadowCloudClient meadowCloudClient,
ApiTokenService apiTokenService,
UserService userService,
ILoggerFactory loggerFactory)
: base(meadowCloudClient, userService, loggerFactory)
: base(meadowCloudClient, loggerFactory)
{
ApiTokenService = apiTokenService;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ public class CloudApiKeyListCommand : BaseCloudCommand<CloudApiKeyListCommand>
public CloudApiKeyListCommand(
IMeadowCloudClient meadowCloudClient,
ApiTokenService apiTokenService,
UserService userService,
ILoggerFactory loggerFactory)
: base(meadowCloudClient, userService, loggerFactory)
: base(meadowCloudClient, loggerFactory)
{
ApiTokenService = apiTokenService;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,15 @@ public class CloudApiKeyUpdateCommand : BaseCloudCommand<CloudApiKeyUpdateComman
public CloudApiKeyUpdateCommand(
IMeadowCloudClient meadowCloudClient,
ApiTokenService apiTokenService,
UserService userService,
ILoggerFactory loggerFactory)
: base(meadowCloudClient, userService, loggerFactory)
: base(meadowCloudClient, loggerFactory)
{
ApiTokenService = apiTokenService;
}

protected override ValueTask PreAuthenticatedValidation()
{
Logger?.LogInformation($"Updating API key `{NameOrId}` on Meadow.Cloud{(Host != DefaultHost ? $" ({Host.ToLowerInvariant()})" : string.Empty)}...");
Logger.LogInformation($"Updating API key `{NameOrId}` on Meadow.Cloud{(Host != DefaultHost ? $" ({Host.ToLowerInvariant()})" : string.Empty)}...");
return ValueTask.CompletedTask;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,31 @@ public class CloudCollectionListCommand : BaseCloudCommand<CloudCollectionListCo

public CloudCollectionListCommand(
IMeadowCloudClient meadowCloudClient,
UserService userService,
CollectionService collectionService,
ILoggerFactory loggerFactory)
: base(meadowCloudClient, userService, loggerFactory)
: base(meadowCloudClient, loggerFactory)
{
_collectionService = collectionService;
}

protected override async ValueTask ExecuteCloudCommand()
{
var org = await GetOrg(Host, OrgId, CancellationToken);
var org = await GetOrganization(OrgId, CancellationToken);

if (org == null) return;

var collections = await _collectionService.GetOrgCollections(org.Id, Host, CancellationToken);

if (collections == null || collections.Count == 0)
{
Logger?.LogInformation("No collections found.");
Logger.LogInformation("No collections found.");
}
else
{
Logger?.LogInformation("Collections:");
Logger.LogInformation("Collections:");
foreach (var collection in collections)
{
Logger?.LogInformation($" {collection.Id} | {collection.Name}");
Logger.LogInformation($" {collection.Id} | {collection.Name}");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,9 @@ public class CloudCommandPublishCommand : BaseCloudCommand<CloudCommandPublishCo

public CloudCommandPublishCommand(
IMeadowCloudClient meadowCloudClient,
UserService userService,
CommandService commandService,
ILoggerFactory loggerFactory)
: base(meadowCloudClient, userService, loggerFactory)
: base(meadowCloudClient, loggerFactory)
{
CommandService = commandService;
}
Expand Down Expand Up @@ -67,7 +66,7 @@ protected override async ValueTask ExecuteCloudCommand()
{
throw new CommandException("Cannot specify both a collection ID (-c|--collectionId) and list of device IDs (-d|--deviceIds). Only one is allowed.");
}
Logger?.LogInformation("Publish command successful.");
Logger.LogInformation("Publish command successful.");
}
catch (MeadowCloudException ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ protected override async ValueTask ExecuteCommand()
}

// build
Logger?.LogInformation(string.Format(Strings.BuildingSpecifiedConfiguration, Configuration));
Logger.LogInformation(string.Format(Strings.BuildingSpecifiedConfiguration, Configuration));
if (!_packageManager.BuildApplication(ProjectPath, Configuration, true, CancellationToken))
{
throw new CommandException(Strings.BuildFailed);
Expand All @@ -68,20 +68,20 @@ protected override async ValueTask ExecuteCommand()

var file = candidates.OrderByDescending(c => c.LastWriteTime).First();
// trim
Logger?.LogInformation(string.Format(Strings.TrimmingApplicationForSpecifiedVersion, osVersion));
Logger.LogInformation(string.Format(Strings.TrimmingApplicationForSpecifiedVersion, osVersion));
await _packageManager.TrimApplication(file, cancellationToken: CancellationToken);

// package
var packageDir = Path.Combine(file.Directory?.FullName ?? string.Empty, PackageManager.PackageOutputDirectoryName);
//TODO - properly manage shared paths
var postlinkDir = Path.Combine(file.Directory?.FullName ?? string.Empty, PackageManager.PostLinkDirectoryName);

Logger?.LogInformation(Strings.AssemblingCloudPackage);
Logger.LogInformation(Strings.AssemblingCloudPackage);
var packagePath = await _packageManager.AssemblePackage(postlinkDir, packageDir, osVersion, MpakName, Filter, true, CancellationToken);

if (packagePath != null)
{
Logger?.LogInformation(string.Format(Strings.PackageAvailableAtSpecifiedPath, packagePath));
Logger.LogInformation(string.Format(Strings.PackageAvailableAtSpecifiedPath, packagePath));
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,31 @@ public class CloudPackageListCommand : BaseCloudCommand<CloudPackageListCommand>

public CloudPackageListCommand(
IMeadowCloudClient meadowCloudClient,
UserService userService,
PackageService packageService,
ILoggerFactory loggerFactory)
: base(meadowCloudClient, userService, loggerFactory)
: base(meadowCloudClient, loggerFactory)
{
_packageService = packageService;
}

protected override async ValueTask ExecuteCloudCommand()
{
var org = await GetOrg(Host, OrgId, CancellationToken);
var org = await GetOrganization(OrgId, CancellationToken);

if (org == null) { return; }

var packages = await _packageService.GetOrgPackages(org.Id, Host, CancellationToken);

if (packages == null || packages.Count == 0)
{
Logger?.LogInformation("No packages found");
Logger.LogInformation("No packages found");
}
else
{
Logger?.LogInformation("packages:");
Logger.LogInformation("packages:");
foreach (var package in packages)
{
Logger?.LogInformation($" {package.Id} | {package.Name}");
Logger.LogInformation($" {package.Id} | {package.Name}");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ public class CloudPackagePublishCommand : BaseCloudCommand<CloudPackagePublishCo

public CloudPackagePublishCommand(
IMeadowCloudClient meadowCloudClient,
UserService userService,
PackageService packageService,
ILoggerFactory loggerFactory)
: base(meadowCloudClient, userService, loggerFactory)
: base(meadowCloudClient, loggerFactory)
{
_packageService = packageService;
}
Expand All @@ -33,14 +32,14 @@ protected override async ValueTask ExecuteCloudCommand()
{
try
{
Logger?.LogInformation($"Publishing package {PackageId} to collection {CollectionId}...");
Logger.LogInformation($"Publishing package {PackageId} to collection {CollectionId}...");

await _packageService.PublishPackage(PackageId, CollectionId, Metadata ?? string.Empty, Host, CancellationToken);
Logger?.LogInformation("Publish successful.");
Logger.LogInformation("Publish successful.");
}
catch (MeadowCloudException mex)
{
Logger?.LogError($"Publish failed: {mex.Message}");
Logger.LogError($"Publish failed: {mex.Message}");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ public class CloudPackageUploadCommand : BaseCloudCommand<CloudPackageUploadComm

public CloudPackageUploadCommand(
IMeadowCloudClient meadowCloudClient,
UserService userService,
PackageService packageService,
ILoggerFactory loggerFactory)
: base(meadowCloudClient, userService, loggerFactory)
: base(meadowCloudClient, loggerFactory)
{
_packageService = packageService;
}
Expand All @@ -40,20 +39,20 @@ protected override ValueTask PreAuthenticatedValidation()

protected override async ValueTask ExecuteCloudCommand()
{
var org = await GetOrg(Host, OrgId, CancellationToken);
var org = await GetOrganization(OrgId, CancellationToken);

if (org == null) { return; }

try
{
Logger?.LogInformation($"Uploading package {Path.GetFileName(MpakPath)}...");
Logger.LogInformation($"Uploading package {Path.GetFileName(MpakPath)}...");

var package = await _packageService.UploadPackage(MpakPath, org.Id, Description ?? string.Empty, Host, CancellationToken);
Logger?.LogInformation($"Upload complete. Package Id: {package.Id}");
Logger.LogInformation($"Upload complete. Package Id: {package.Id}");
}
catch (MeadowCloudException mex)
{
Logger?.LogError($"Upload failed: {mex.Message}");
Logger.LogError($"Upload failed: {mex.Message}");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ public class FirmwareDownloadCommand : BaseCloudCommand<FirmwareDownloadCommand>
public FirmwareDownloadCommand(
FileManager fileManager,
IMeadowCloudClient meadowCloudClient,
UserService userService,
ILoggerFactory loggerFactory)
: base(meadowCloudClient, userService, loggerFactory)
: base(meadowCloudClient, loggerFactory)
{
_fileManager = fileManager;
}
Expand Down Expand Up @@ -48,26 +47,26 @@ protected override async ValueTask ExecuteCloudCommand()
return;
}

Logger?.LogInformation($"Latest available version is '{latest}'...");
Logger.LogInformation($"Latest available version is '{latest}'...");
Version = latest;
}
else
{
explicitVersion = true;
Logger?.LogInformation($"Checking for firmware package '{Version}'...");
Logger.LogInformation($"Checking for firmware package '{Version}'...");
}

var isAvailable = await collection.IsVersionAvailableForDownload(Version);

if (!isAvailable)
{
Logger?.LogError($"Requested package version '{Version}' is not available");
Logger.LogError($"Requested package version '{Version}' is not available");
return;
}

if (collection[Version] != null && Force == false)
{
Logger?.LogInformation($"Firmware package '{Version}' already exists locally");
Logger.LogInformation($"Firmware package '{Version}' already exists locally");

if (explicitVersion == false)
{
Expand All @@ -76,7 +75,7 @@ protected override async ValueTask ExecuteCloudCommand()
return;
}

Logger?.LogInformation($"Downloading firmware package '{Version}'...");
Logger.LogInformation($"Downloading firmware package '{Version}'...");

try
{
Expand All @@ -86,11 +85,11 @@ protected override async ValueTask ExecuteCloudCommand()

if (!result)
{
Logger?.LogError($"Unable to download package '{Version}'");
Logger.LogError($"Unable to download package '{Version}'");
}
else
{
Logger?.LogInformation($"Firmware package '{Version}' downloaded");
Logger.LogInformation($"Firmware package '{Version}' downloaded");

if (explicitVersion == false)
{
Expand All @@ -100,13 +99,13 @@ protected override async ValueTask ExecuteCloudCommand()
}
catch (Exception ex)
{
Logger?.LogError($"Unable to download package '{Version}': {ex.Message}");
Logger.LogError($"Unable to download package '{Version}': {ex.Message}");
}
}

private void OnDownloadProgress(object? sender, long e)
{
// use Console so we can Write instead of Logger which only supports WriteLine
Console?.Output.Write($"Retrieved {e} bytes... \r");
Console.Output.Write($"Retrieved {e} bytes... \r");
}
}
Loading
Loading