Various S3 is WIP
This commit is contained in:
parent
44836b0bca
commit
6f4c1122f7
|
@ -1,3 +1,5 @@
|
||||||
|
using System.Runtime.InteropServices.ComTypes;
|
||||||
|
using System.Text.Json.Nodes;
|
||||||
using InnovEnergy.App.Backend.Database;
|
using InnovEnergy.App.Backend.Database;
|
||||||
using InnovEnergy.App.Backend.DataTypes;
|
using InnovEnergy.App.Backend.DataTypes;
|
||||||
using InnovEnergy.App.Backend.DataTypes.Methods;
|
using InnovEnergy.App.Backend.DataTypes.Methods;
|
||||||
|
@ -399,6 +401,19 @@ public class Controller : ControllerBase
|
||||||
: Unauthorized();
|
: Unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpPost(nameof(EditInstallationConfig))]
|
||||||
|
public async Task<ActionResult<IEnumerable<Object>>> EditInstallationConfig([FromBody] String config, Int64 installationId, Token authToken)
|
||||||
|
{
|
||||||
|
var session = Db.GetSession(authToken);
|
||||||
|
|
||||||
|
// var installationToUpdate = Db.GetInstallationById(installationId);
|
||||||
|
|
||||||
|
return await session.SendInstallationConfig(installationId, config)
|
||||||
|
? Ok()
|
||||||
|
: Unauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPut(nameof(MoveFolder))]
|
[HttpPut(nameof(MoveFolder))]
|
||||||
public ActionResult MoveFolder(Int64 folderId,Int64 parentId, Token authToken)
|
public ActionResult MoveFolder(Int64 folderId,Int64 parentId, Token authToken)
|
||||||
{
|
{
|
||||||
|
@ -458,8 +473,9 @@ public class Controller : ControllerBase
|
||||||
: Unauthorized();
|
: Unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpGet(nameof(ResetPassword))]
|
[HttpGet(nameof(ResetPassword))]
|
||||||
public ActionResult<IEnumerable<Object>> ResetPassword(Token token)
|
public ActionResult<Object> ResetPassword(Token token)
|
||||||
{
|
{
|
||||||
var user = Db.GetSession(token)?.User;
|
var user = Db.GetSession(token)?.User;
|
||||||
|
|
||||||
|
@ -467,9 +483,13 @@ public class Controller : ControllerBase
|
||||||
return Unauthorized();
|
return Unauthorized();
|
||||||
|
|
||||||
//todo dont hardcode url
|
//todo dont hardcode url
|
||||||
return Db.DeleteUserPassword(user)
|
if (!Db.DeleteUserPassword(user))
|
||||||
? RedirectToRoute("https://monitor.innov.energy")
|
{
|
||||||
: Unauthorized();
|
return Unauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Db.Sessions.Delete(s => s.Token == token);
|
||||||
|
return Redirect($"https://monitor.innov.energy/?username={user.Email}");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,11 @@ public class Installation : TreeNode
|
||||||
public String Location { get; set; } = "";
|
public String Location { get; set; } = "";
|
||||||
public String Region { get; set; } = "";
|
public String Region { get; set; } = "";
|
||||||
public String Country { get; set; } = "";
|
public String Country { get; set; } = "";
|
||||||
|
public String InstallationName { get; set; } = "";
|
||||||
|
|
||||||
// TODO: make relation
|
// TODO: make relation
|
||||||
//public IReadOnlyList<String> OrderNumbers { get; set; } = Array.Empty<String>();
|
//public IReadOnlyList<String> OrderNumbers { get; set; } = Array.Empty<String>();
|
||||||
public String? OrderNumbers { get; set; } = "";
|
// public String? OrderNumbers { get; set; } = "";
|
||||||
|
|
||||||
public Double Lat { get; set; }
|
public Double Lat { get; set; }
|
||||||
public Double Long { get; set; }
|
public Double Long { get; set; }
|
||||||
|
@ -21,4 +22,7 @@ public class Installation : TreeNode
|
||||||
public String S3Key { get; set; } = "";
|
public String S3Key { get; set; } = "";
|
||||||
public String S3WriteSecret { get; set; } = "";
|
public String S3WriteSecret { get; set; } = "";
|
||||||
public String S3Secret { get; set; } = "";
|
public String S3Secret { get; set; } = "";
|
||||||
|
|
||||||
|
[Ignore]
|
||||||
|
public IReadOnlyList<String>? OrderNumbers { get; set; }
|
||||||
}
|
}
|
|
@ -8,17 +8,36 @@ namespace InnovEnergy.App.Backend.DataTypes.Methods;
|
||||||
public static class ExoCmd
|
public static class ExoCmd
|
||||||
{
|
{
|
||||||
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
|
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
|
||||||
private static readonly S3Credentials? S3Creds = JsonSerializer.Deserialize<S3Credentials>("./exoscaleS3.json");
|
public static readonly S3Credentials? S3Creds = JsonSerializer.Deserialize<S3Credentials>(File.OpenRead("./Resources/exoscaleS3.json"));
|
||||||
|
|
||||||
public static async Task<(String key, String secret)> CreateReadKey(this Installation installation)
|
public static async Task<(String key, String secret)> CreateReadKey(this Installation installation)
|
||||||
{
|
{
|
||||||
var iamService = new S3Region(installation.Region, S3Creds!).GetIamClient();
|
var iamService = new S3Region($"https://{installation.S3Region}.{installation.S3Provider}", S3Creds!).GetIamClient();
|
||||||
if (!await Iam.UserExists(iamService, $"READ{installation.BucketName()}"))
|
if (!await Iam.RoleExists(iamService, $"READ{installation.BucketName()}"))
|
||||||
{
|
{
|
||||||
|
|
||||||
var readOnlyPolicy = $"{installation.BucketName()}"; // TODO make me
|
var readOnlyPolicy =@"{
|
||||||
await Iam.CreateUserAsync(iamService, $"READ{installation.BucketName()}");
|
""default-service-strategy"": ""deny"",
|
||||||
await Iam.PutUserPolicyAsync(iamService, $"READ{installation.BucketName()}", $"READ{installation.BucketName()}",readOnlyPolicy);
|
""services"": {
|
||||||
|
""sos"": {
|
||||||
|
""type"": ""rules"",
|
||||||
|
""rules"": [
|
||||||
|
{
|
||||||
|
""expression"": ""operation == 'list-objects'"",
|
||||||
|
""action"": ""allow""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""expression"": ""operation == 'get-object'"",
|
||||||
|
""action"": ""allow""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
""resource"": " + $@"{installation.BucketName()}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
}}";
|
||||||
|
|
||||||
|
await Iam.CreateRoleAsync(iamService, $"READ{installation.BucketName()}");
|
||||||
|
await Iam.PutRolePolicyAsync(iamService, $"READ{installation.BucketName()}", $"READ{installation.BucketName()}",readOnlyPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
var keySecret = await Iam.CreateAccessKeyAsync(iamService, $"READ{installation.BucketName()}");
|
var keySecret = await Iam.CreateAccessKeyAsync(iamService, $"READ{installation.BucketName()}");
|
||||||
|
@ -29,8 +48,8 @@ public static class ExoCmd
|
||||||
|
|
||||||
public static async Task<Boolean> RevokeReadKey(this Installation installation)
|
public static async Task<Boolean> RevokeReadKey(this Installation installation)
|
||||||
{
|
{
|
||||||
var iamService = new S3Region(installation.Region, S3Creds!).GetIamClient();
|
var iamService = new S3Region($"https://{installation.S3Region}.{installation.S3Provider}", S3Creds!).GetIamClient();
|
||||||
if (!await Iam.UserExists(iamService, $"READ{installation.BucketName()}"))
|
if (!await Iam.RoleExists(iamService, $"READ{installation.BucketName()}"))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -40,12 +59,20 @@ public static class ExoCmd
|
||||||
|
|
||||||
public static async Task<(String key, String secret)> CreateWriteKey(this Installation installation)
|
public static async Task<(String key, String secret)> CreateWriteKey(this Installation installation)
|
||||||
{
|
{
|
||||||
var iamService = new S3Region(installation.Region, S3Creds!).GetIamClient();
|
var iamService = new S3Region($"https://{installation.S3Region}.{installation.S3Provider}", S3Creds!).GetIamClient();
|
||||||
if (!await Iam.UserExists(iamService, $"READWRITE{installation.BucketName()}"))
|
if (!await Iam.RoleExists(iamService, $"READWRITE{installation.BucketName()}"))
|
||||||
{
|
{
|
||||||
var readWritePolicy = $"{installation.BucketName()}"; // TODO make me
|
var readWritePolicy = @"{
|
||||||
await Iam.CreateUserAsync(iamService, $"READWRITE{installation.BucketName()}");
|
""default-service-strategy"": ""deny"",
|
||||||
await Iam.PutUserPolicyAsync(iamService, $"READWRITE{installation.BucketName()}", $"READWRITE{installation.BucketName()}",readWritePolicy);
|
""services"": {
|
||||||
|
""sos"": {
|
||||||
|
""type"": ""allow"",
|
||||||
|
""resource"": " + $@"{installation.BucketName()}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
}}";
|
||||||
|
await Iam.CreateRoleAsync(iamService, $"READWRITE{installation.BucketName()}");
|
||||||
|
await Iam.PutRolePolicyAsync(iamService, $"READWRITE{installation.BucketName()}", $"READWRITE{installation.BucketName()}",readWritePolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
var keySecret = await Iam.CreateAccessKeyAsync(iamService, $"READWRITE{installation.BucketName()}");
|
var keySecret = await Iam.CreateAccessKeyAsync(iamService, $"READWRITE{installation.BucketName()}");
|
||||||
|
@ -55,9 +82,11 @@ public static class ExoCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static async Task<Boolean> CreateBucket(this Installation installation)
|
public static async Task<Boolean> CreateBucket(this Installation installation)
|
||||||
{
|
{
|
||||||
var s3Region = new S3Region(installation.Region, S3Creds!);
|
var s3Region = new S3Region($"https://{installation.S3Region}.{installation.S3Provider}", S3Creds!);
|
||||||
return await s3Region.PutBucket(installation.BucketName()) != null;
|
return await s3Region.PutBucket(installation.BucketName()) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,4 +1,8 @@
|
||||||
|
using System.Net;
|
||||||
|
using System.Text.Json.Nodes;
|
||||||
|
using CliWrap;
|
||||||
using InnovEnergy.App.Backend.Database;
|
using InnovEnergy.App.Backend.Database;
|
||||||
|
using InnovEnergy.App.Backend.Relations;
|
||||||
using InnovEnergy.Lib.S3Utils;
|
using InnovEnergy.Lib.S3Utils;
|
||||||
using InnovEnergy.Lib.Utils;
|
using InnovEnergy.Lib.Utils;
|
||||||
|
|
||||||
|
@ -40,6 +44,29 @@ public static class InstallationMethods
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<Boolean> SendConfig(this Installation installation, String config)
|
||||||
|
{
|
||||||
|
|
||||||
|
// This looks hacky but here we grab the vpn-Ip of the installation by its installation Name (e.g. Salimax0001)
|
||||||
|
// From the vpn server (here salidomo, but we use the vpn home ip for future-proofing)
|
||||||
|
using var client = new HttpClient();
|
||||||
|
var webRequest = client.GetAsync("10.2.0.1/vpnstatus.txt");
|
||||||
|
var text = webRequest.ToString();
|
||||||
|
var lines = text!.Split(new [] { Environment.NewLine }, StringSplitOptions.None);
|
||||||
|
var vpnIp = lines.First(l => l.Contains(installation.InstallationName)).Split(",")[1];
|
||||||
|
|
||||||
|
// Writing the config to a file and then sending that file with rsync sounds inefficient
|
||||||
|
// We should find a better solution...
|
||||||
|
// TODO The VPN server should do this not the backend!!!
|
||||||
|
await File.WriteAllTextAsync("./config.json", config);
|
||||||
|
var result = await Cli.Wrap("rsync")
|
||||||
|
.WithArguments("./config.json")
|
||||||
|
.AppendArgument($@"root@{vpnIp}:/salimax")
|
||||||
|
.ExecuteAsync();
|
||||||
|
|
||||||
|
return result.ExitCode == 200;
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<User> UsersWithAccess(this Installation installation)
|
public static IEnumerable<User> UsersWithAccess(this Installation installation)
|
||||||
{
|
{
|
||||||
return installation
|
return installation
|
||||||
|
@ -114,7 +141,7 @@ public static class InstallationMethods
|
||||||
return Db.Installations.Any(i => i.Id == installation.Id);
|
return Db.Installations.Any(i => i.Id == installation.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IReadOnlyList<String> GetOrderNumbers(this Installation installation)
|
public static IReadOnlyList<String>? GetOrderNumbers(this Installation installation)
|
||||||
{
|
{
|
||||||
return Db.OrderNumber2Installation
|
return Db.OrderNumber2Installation
|
||||||
.Where(i => i.InstallationId == installation.Id)
|
.Where(i => i.InstallationId == installation.Id)
|
||||||
|
@ -124,7 +151,7 @@ public static class InstallationMethods
|
||||||
|
|
||||||
public static Installation FillOrderNumbers(this Installation installation)
|
public static Installation FillOrderNumbers(this Installation installation)
|
||||||
{
|
{
|
||||||
installation.OrderNumbers = installation.GetOrderNumbers().ToString();
|
installation.OrderNumbers = installation.GetOrderNumbers();
|
||||||
return installation;
|
return installation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Text.Json.Nodes;
|
||||||
using InnovEnergy.App.Backend.Database;
|
using InnovEnergy.App.Backend.Database;
|
||||||
using InnovEnergy.App.Backend.Relations;
|
using InnovEnergy.App.Backend.Relations;
|
||||||
using InnovEnergy.Lib.Utils;
|
using InnovEnergy.Lib.Utils;
|
||||||
|
@ -66,6 +67,18 @@ public static class SessionMethods
|
||||||
.Apply(Db.Update);
|
.Apply(Db.Update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<Boolean> SendInstallationConfig(this Session? session, Int64 installationId, String configuration)
|
||||||
|
{
|
||||||
|
var user = session?.User;
|
||||||
|
var installation = Db.GetInstallationById(installationId);
|
||||||
|
|
||||||
|
return user is not null
|
||||||
|
&& installation is not null
|
||||||
|
&& user.HasWriteAccess
|
||||||
|
&& user.HasAccessTo(installation)
|
||||||
|
&& await installation.SendConfig(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
public static Boolean Delete(this Session? session, Folder? folder)
|
public static Boolean Delete(this Session? session, Folder? folder)
|
||||||
{
|
{
|
||||||
var user = session?.User;
|
var user = session?.User;
|
||||||
|
@ -101,13 +114,13 @@ public static class SessionMethods
|
||||||
var user = session?.User;
|
var user = session?.User;
|
||||||
|
|
||||||
var original = Db.GetInstallationById(installation?.Id);
|
var original = Db.GetInstallationById(installation?.Id);
|
||||||
var originalOrderNumbers = original.OrderNumbers;
|
var originalOrderNumbers = original!.GetOrderNumbers();
|
||||||
|
|
||||||
if (!Equals(originalOrderNumbers, installation?.OrderNumbers))
|
if (!Equals(originalOrderNumbers, installation?.OrderNumbers))
|
||||||
{
|
{
|
||||||
foreach (var orderNumber in installation!.OrderNumbers.Split(','))
|
foreach (var orderNumber in installation!.OrderNumbers!)
|
||||||
{
|
{
|
||||||
if (originalOrderNumbers.Contains(orderNumber)) continue;
|
if (originalOrderNumbers!.Contains(orderNumber)) continue;
|
||||||
var o2I = new OrderNumber2Installation
|
var o2I = new OrderNumber2Installation
|
||||||
{
|
{
|
||||||
OrderNumber = orderNumber,
|
OrderNumber = orderNumber,
|
||||||
|
@ -116,9 +129,9 @@ public static class SessionMethods
|
||||||
Db.Create(o2I);
|
Db.Create(o2I);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var orderNumberOld in originalOrderNumbers.Split(','))
|
foreach (var orderNumberOld in originalOrderNumbers!)
|
||||||
{
|
{
|
||||||
if (!installation!.OrderNumbers.Contains(orderNumberOld))
|
if (!installation.OrderNumbers.Contains(orderNumberOld))
|
||||||
{
|
{
|
||||||
Db.OrderNumber2Installation.Delete(i =>
|
Db.OrderNumber2Installation.Delete(i =>
|
||||||
i.InstallationId == installation.Id && i.OrderNumber == orderNumberOld);
|
i.InstallationId == installation.Id && i.OrderNumber == orderNumberOld);
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"Key": "EXOf67c5b528282988503ddab12",
|
|
||||||
"Secret": "KBFh5HvoSQcTtGYcWSm4Qn4m-WFutKe89UqsOdOL-ts"
|
|
||||||
}
|
|
|
@ -5,6 +5,8 @@ using CliWrap.Buffered;
|
||||||
using InnovEnergy.App.Backend.DataTypes;
|
using InnovEnergy.App.Backend.DataTypes;
|
||||||
using InnovEnergy.App.Backend.DataTypes.Methods;
|
using InnovEnergy.App.Backend.DataTypes.Methods;
|
||||||
using InnovEnergy.App.Backend.Relations;
|
using InnovEnergy.App.Backend.Relations;
|
||||||
|
using InnovEnergy.Lib.S3Utils;
|
||||||
|
using InnovEnergy.Lib.S3Utils.DataTypes;
|
||||||
using SQLite;
|
using SQLite;
|
||||||
using SQLiteConnection = SQLite.SQLiteConnection;
|
using SQLiteConnection = SQLite.SQLiteConnection;
|
||||||
|
|
||||||
|
@ -149,20 +151,26 @@ public static partial class Db
|
||||||
|
|
||||||
private static async Task UpdateS3Urls()
|
private static async Task UpdateS3Urls()
|
||||||
{
|
{
|
||||||
var bucketList = await Cli.Wrap("exo")
|
var regions = Installations
|
||||||
.WithArguments("storage list -O json")
|
.Select(i => i.S3Region)
|
||||||
.ExecuteBufferedAsync();
|
.Distinct().ToList();
|
||||||
|
const String provider = "exo.io";
|
||||||
|
foreach (var region in regions)
|
||||||
|
{
|
||||||
|
var bucketList = await new S3Region($"https://{region}.{provider}", ExoCmd.S3Creds!).ListAllBuckets();
|
||||||
|
|
||||||
|
foreach (var bucket in bucketList.Buckets)
|
||||||
var installationsToUpdate = Installations
|
{
|
||||||
.Select(i => i)
|
foreach (var installation in Installations)
|
||||||
.Where(i => bucketList.StandardOutput.Contains("\"" + i.BucketName() + "\"")).ToList();
|
{
|
||||||
|
if (installation.BucketName() == bucket.BucketName)
|
||||||
foreach (var installation in installationsToUpdate)
|
|
||||||
{
|
{
|
||||||
await installation.RenewS3Credentials();
|
await installation.RenewS3Credentials();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Boolean SendPasswordResetEmail(User user, String sessionToken)
|
public static Boolean SendPasswordResetEmail(User user, String sessionToken)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
"dotnetRunMessages": true,
|
"dotnetRunMessages": true,
|
||||||
|
|
||||||
"launchUrl": "swagger",
|
"launchUrl": "swagger",
|
||||||
"applicationUrl": "https://localhost:7087",
|
"applicationUrl": "http://localhost:7087",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||||
"HOME":"~/backend"
|
"HOME":"~/backend"
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"Key": "EXOea18f5a82bd358896154c783",
|
||||||
|
"Secret": "lYtzU7R5e0L6XKOgBaLVPFr41nEBDxDdXU47zBAEI6M"
|
||||||
|
}
|
|
@ -123,7 +123,7 @@ th { /* header cell */
|
||||||
<td>{{Serial}}</td>
|
<td>{{Serial}}</td>
|
||||||
<td>{{NumBatteries}}</td>
|
<td>{{NumBatteries}}</td>
|
||||||
<td>{{BatteryVersion}}</td>
|
<td>{{BatteryVersion}}</td>
|
||||||
<td><a target='_blank' href=http://{{ServerIp}}/UpdateBatteryFirmware/{{Ip}}/{{NumBatteries}}>⬆️{{FirmwareVersion}}</a></td>
|
<td><a target='_blank' href=http://{{ServerIp}}/UpdateBatteryFirmware/{{Ip}}>⬆️{{FirmwareVersion}}</a></td>
|
||||||
<td>{{BatteryUpdateStatus}}</td>
|
<td>{{BatteryUpdateStatus}}</td>
|
||||||
</tr>";
|
</tr>";
|
||||||
|
|
||||||
|
@ -189,21 +189,22 @@ th { /* header cell */
|
||||||
installation.BatteryUpdateStatus = "Running";
|
installation.BatteryUpdateStatus = "Running";
|
||||||
Db.Update(installation: installation);
|
Db.Update(installation: installation);
|
||||||
var batteryIdsResult = await Db.ExecuteBufferedAsyncCommandOnIp(installationIp, $"dbus-send --system --dest=com.victronenergy.battery.{batteryTtyName} --type=method_call --print-reply / com.victronenergy.BusItem.GetText | grep -E -o '_Battery/[0-9]+/' | grep -E -o '[0-9]+'| sort -u");
|
var batteryIdsResult = await Db.ExecuteBufferedAsyncCommandOnIp(installationIp, $"dbus-send --system --dest=com.victronenergy.battery.{batteryTtyName} --type=method_call --print-reply / com.victronenergy.BusItem.GetText | grep -E -o '_Battery/[0-9]+/' | grep -E -o '[0-9]+'| sort -u");
|
||||||
|
|
||||||
var batteryIds = batteryIdsResult.Split("\n").ToList();
|
var batteryIds = batteryIdsResult.Split("\n").ToList();
|
||||||
batteryIds.Pop();
|
batteryIds.Pop();
|
||||||
|
|
||||||
foreach (var batteryId in batteryIds)
|
foreach (var batteryId in batteryIds)
|
||||||
{
|
{
|
||||||
localCommand = localCommand.Append(
|
localCommand = localCommand.Append(
|
||||||
$" && /opt/innovenergy/scripts/upload-bms-firmware {batteryTtyName} {batteryId} /opt/innovenergy/bms-firmware/{FirmwareVersion}.bin");
|
$" && /opt/innovenergy/scripts/upload-bms-firmware {batteryTtyName} {batteryId} /opt/innovenergy/bms-firmware/{FirmwareVersion}.bin");
|
||||||
}
|
}
|
||||||
#pragma warning disable CS4014
|
#pragma warning disable CS4014
|
||||||
Console.WriteLine(localCommand);
|
// Console.WriteLine(localCommand);
|
||||||
Db.ExecuteBufferedAsyncCommandOnIp(installationIp, localCommand)
|
Db.ExecuteBufferedAsyncCommandOnIp(installationIp, localCommand)
|
||||||
.ContinueWith(async t =>
|
.ContinueWith(async t =>
|
||||||
{
|
{
|
||||||
Console.WriteLine(t.Result);
|
Console.WriteLine(t.Result);
|
||||||
installation.BatteryUpdateStatus = "Complete";
|
installation.BatteryUpdateStatus = "Complete";
|
||||||
|
// installation.BatteryFirmwareVersion = FirmwareVersion;
|
||||||
Db.Update(installation: installation);
|
Db.Update(installation: installation);
|
||||||
var vrmInst = await FindVrmInstallationByIp(installation.Ip!);
|
var vrmInst = await FindVrmInstallationByIp(installation.Ip!);
|
||||||
await UpdateVrmTagsToNewFirmware(installationIp);
|
await UpdateVrmTagsToNewFirmware(installationIp);
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using Amazon.CognitoIdentityProvider;
|
||||||
using Amazon.IdentityManagement;
|
using Amazon.IdentityManagement;
|
||||||
using Amazon.IdentityManagement.Model;
|
using Amazon.IdentityManagement.Model;
|
||||||
using Amazon.Runtime;
|
using Amazon.Runtime;
|
||||||
using InnovEnergy.Lib.S3Utils.DataTypes;
|
using InnovEnergy.Lib.S3Utils.DataTypes;
|
||||||
using InnovEnergy.Lib.Utils;
|
using InnovEnergy.Lib.Utils;
|
||||||
|
using S3Region = InnovEnergy.Lib.S3Utils.DataTypes.S3Region;
|
||||||
|
|
||||||
namespace InnovEnergy.Lib.S3Utils;
|
namespace InnovEnergy.Lib.S3Utils;
|
||||||
|
|
||||||
|
@ -13,8 +15,6 @@ public static class Iam
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static readonly ConcurrentDictionary<S3Region, AmazonIdentityManagementServiceClient> AimClientCache = new();
|
private static readonly ConcurrentDictionary<S3Region, AmazonIdentityManagementServiceClient> AimClientCache = new();
|
||||||
|
|
||||||
public static AmazonIdentityManagementServiceClient GetIamClient(this S3Url url ) => url.Bucket.GetIamClient();
|
public static AmazonIdentityManagementServiceClient GetIamClient(this S3Url url ) => url.Bucket.GetIamClient();
|
||||||
|
@ -30,27 +30,28 @@ public static class Iam
|
||||||
clientConfig: new() { ServiceURL = region.Name.EnsureStartsWith("https://") }
|
clientConfig: new() { ServiceURL = region.Name.EnsureStartsWith("https://") }
|
||||||
);
|
);
|
||||||
|
|
||||||
public static async Task<User> CreateUserAsync(AmazonIdentityManagementServiceClient iamService,String userName)
|
public static async Task<Role> CreateRoleAsync(AmazonIdentityManagementServiceClient iamService,String userName)
|
||||||
{
|
{
|
||||||
var response = await iamService.CreateUserAsync(new CreateUserRequest { UserName = userName });
|
var response = await iamService.CreateRoleAsync(new CreateRoleRequest() { RoleName = userName });
|
||||||
return response.User;
|
return response.Role;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<Boolean> PutUserPolicyAsync(AmazonIdentityManagementServiceClient iamService, String userName, String policyName, String policyDocument)
|
public static async Task<Boolean> PutRolePolicyAsync(AmazonIdentityManagementServiceClient iamService, String userName, String policyName, String policyDocument)
|
||||||
{
|
{
|
||||||
var request = new PutUserPolicyRequest()
|
var request = new PutRolePolicyRequest()
|
||||||
{
|
{
|
||||||
UserName = userName,
|
RoleName = userName,
|
||||||
PolicyName = policyName,
|
PolicyName = policyName,
|
||||||
PolicyDocument = policyDocument
|
PolicyDocument = policyDocument
|
||||||
};
|
};
|
||||||
|
|
||||||
var response = await iamService.PutUserPolicyAsync(request);
|
var response = await iamService.PutRolePolicyAsync(request);
|
||||||
return response.HttpStatusCode == System.Net.HttpStatusCode.OK;
|
return response.HttpStatusCode == System.Net.HttpStatusCode.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<AccessKey> CreateAccessKeyAsync(AmazonIdentityManagementServiceClient iamService, String userName)
|
public static async Task<AccessKey> CreateAccessKeyAsync(AmazonIdentityManagementServiceClient iamService, String userName)
|
||||||
{
|
{
|
||||||
|
// iamService.Role
|
||||||
var response = await iamService.CreateAccessKeyAsync(new CreateAccessKeyRequest
|
var response = await iamService.CreateAccessKeyAsync(new CreateAccessKeyRequest
|
||||||
{
|
{
|
||||||
UserName= userName,
|
UserName= userName,
|
||||||
|
@ -60,9 +61,9 @@ public static class Iam
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<Boolean> UserExists(AmazonIdentityManagementServiceClient iamService, String userName)
|
public static async Task<Boolean> RoleExists(AmazonIdentityManagementServiceClient iamService, String roleName)
|
||||||
{
|
{
|
||||||
var response = await iamService.GetUserAsync(new GetUserRequest { UserName = userName });
|
var response = await iamService.GetRoleAsync(new GetRoleRequest{RoleName = roleName});
|
||||||
return response.HttpStatusCode == HttpStatusCode.OK;
|
return response.HttpStatusCode == HttpStatusCode.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,13 @@ public static class S3
|
||||||
.Select(o => new S3Url(o.Key, bucket));
|
.Select(o => new S3Url(o.Key, bucket));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<ListBucketsResponse> ListAllBuckets(this S3Region region)
|
||||||
|
{
|
||||||
|
return await region
|
||||||
|
.GetS3Client()
|
||||||
|
.ListBucketsAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public static Task<Boolean> PutObject(this S3Url path, String data, Encoding encoding) => path.PutObject(encoding.GetBytes(data));
|
public static Task<Boolean> PutObject(this S3Url path, String data, Encoding encoding) => path.PutObject(encoding.GetBytes(data));
|
||||||
public static Task<Boolean> PutObject(this S3Url path, String data) => path.PutObject(data, Encoding.UTF8);
|
public static Task<Boolean> PutObject(this S3Url path, String data) => path.PutObject(data, Encoding.UTF8);
|
||||||
public static Task<Boolean> PutObject(this S3Url path, Byte[] data) => path.PutObject(new MemoryStream(data));
|
public static Task<Boolean> PutObject(this S3Url path, Byte[] data) => path.PutObject(new MemoryStream(data));
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AWSSDK.CognitoIdentityProvider" Version="3.7.203.6" />
|
||||||
<PackageReference Include="AWSSDK.IdentityManagement" Version="3.7.200.39" />
|
<PackageReference Include="AWSSDK.IdentityManagement" Version="3.7.200.39" />
|
||||||
<PackageReference Include="AWSSDK.S3" Version="3.7.203.12" />
|
<PackageReference Include="AWSSDK.S3" Version="3.7.203.12" />
|
||||||
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
|
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
|
||||||
|
|
Loading…
Reference in New Issue