-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d72c187
commit f0b0f6c
Showing
32 changed files
with
2,536 additions
and
108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -351,3 +351,4 @@ MigrationBackup/ | |
|
||
build/dev/ | ||
!build/dev/.gitkeep | ||
dist/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
[CmdletBinding()] | ||
param ( | ||
[Parameter(Mandatory = $True)] | ||
[string] | ||
$Cert, | ||
[Parameter(Mandatory = $True)] | ||
[string] | ||
$Pass | ||
) | ||
|
||
$flag = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable | ||
$collection = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection | ||
$collection.Import($Cert, $Pass, $flag) | ||
$pkcs12ContentType = [System.Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12 | ||
$clearBytes = $collection.Export($pkcs12ContentType) | ||
$fileContentEncoded = [System.Convert]::ToBase64String($clearBytes) | ||
$secret = ConvertTo-SecureString -String $fileContentEncoded -AsPlainText –Force | ||
|
||
Write-Host $fileContentEncoded |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
[CmdletBinding()] | ||
param ( | ||
[Parameter(Mandatory = $True)] | ||
[string] | ||
$ZipFile, | ||
[Parameter(Mandatory = $True)] | ||
[string] | ||
$Cert, | ||
[Parameter(Mandatory = $True)] | ||
[string] | ||
$Pass | ||
) | ||
|
||
$Location = Get-Location | ||
Write-Host "Signing logic-node project at ``${ZipFile}``" -ForegroundColor Blue | ||
$RepositoryRoot = Resolve-Path (Join-Path $PSScriptRoot '../') | ||
$ZipFile = Resolve-Path $ZipFile | ||
$Cert = Resolve-Path $Cert | ||
$SdkDir = Join-path $PSScriptRoot 'tools/gira' | ||
$DistDir = Resolve-Path (Join-Path $PSScriptRoot '../dist') | ||
|
||
Write-Host "Repository: ``${RepositoryRoot}``" | ||
Write-Host "SDK-Tools: ``${SdkDir}``" | ||
Write-Host "Output: ``${DistDir}``" | ||
|
||
$SignToolPath = Join-Path -Path $SdkDir -ChildPath 'SignLogicNodes.exe' | ||
|
||
Set-Location $SdkDir | ||
|
||
try { | ||
$SignNodeArgs = @( | ||
"${Cert}" | ||
"${Pass}" | ||
"${ZipFile}" | ||
) | ||
|
||
Write-Host "${SignToolPath} ${SignNodeArgs}" -ForegroundColor Magenta | ||
. $SignToolPath $SignNodeArgs | ||
} | ||
finally { | ||
Set-Location $Location | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
dotnet/src/NecatiMeral.Logic.ComfortOnline/ComfortOnlineConsts.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
namespace Necati_Meral_Yahoo_De.Logic.ComfortOnline; | ||
public static class ComfortOnlineConsts | ||
{ | ||
public const string ComfortOnlineBaseAddress = "https://www.comfort-online.com/"; | ||
|
||
public static class ErrorCodes | ||
{ | ||
public const string Ok = "Ok"; | ||
public const string InitialRequestFailed = "InitialRequestFailed"; | ||
public const string MissingRequestVerificationToken = "MissingRequestVerificationToken"; | ||
public const string InvalidCredentials = "InvalidCredentials"; | ||
public const string LoginFailed = "LoginFailed"; | ||
public const string UnexpectedError = "UnexpectedError: "; | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
dotnet/src/NecatiMeral.Logic.ComfortOnline/ComfortOnlinePageParser.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
using System.Text.RegularExpressions; | ||
|
||
namespace Necati_Meral_Yahoo_De.Logic.ComfortOnline; | ||
public class ComfortOnlinePageParser | ||
{ | ||
readonly Regex _spanRegex = new Regex("<span.*?(?:id=\\\"val_([\\d_]*)\\\")>(.*)<\\/span>", RegexOptions.Compiled | RegexOptions.IgnoreCase); | ||
readonly Regex _inputRegex = new Regex("<input.*?(?:id=\\\"slider_([\\d_]*)\\\".*?value=\\\"([^\\\"]+)|value=\\\"([^\\\"]+).*?id=\\\"slider_([\\d_]*)\\\")[^>]*>", RegexOptions.Compiled | RegexOptions.IgnoreCase); | ||
|
||
public ComfortOnlinePlantSectionInfo Parse(string body) | ||
{ | ||
var info = new ComfortOnlinePlantSectionInfo(); | ||
|
||
var spanMatches = _spanRegex.Matches(body); | ||
foreach (Match match in spanMatches) | ||
{ | ||
if(match.Groups.Count == 3) | ||
{ | ||
info[match.Groups[1].Value] = match.Groups[2].Value; | ||
} | ||
} | ||
|
||
var inputMatches = _inputRegex.Matches(body); | ||
foreach (Match match in inputMatches) | ||
{ | ||
if (match.Groups.Count == 5) | ||
{ | ||
if (string.IsNullOrEmpty(match.Groups[1].Value)) | ||
{ | ||
info[match.Groups[3].Value] = match.Groups[4].Value; | ||
} | ||
else | ||
{ | ||
info[match.Groups[1].Value] = match.Groups[2].Value; | ||
} | ||
} | ||
} | ||
|
||
return info; | ||
} | ||
|
||
public class ComfortOnlinePlantSectionInfo | ||
{ | ||
Dictionary<string, string> _dict; | ||
|
||
public IReadOnlyDictionary<string, string> Values => _dict; | ||
|
||
public string this[string key] | ||
{ | ||
get => _dict[key]; | ||
set => _dict[key] = value; | ||
} | ||
|
||
public ComfortOnlinePlantSectionInfo() | ||
{ | ||
_dict = new Dictionary<string, string>(); | ||
} | ||
} | ||
} |
153 changes: 153 additions & 0 deletions
153
dotnet/src/NecatiMeral.Logic.ComfortOnline/ComfortOnlineRequestNode.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
using System.CodeDom; | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Text.RegularExpressions; | ||
using LogicModule.ObjectModel.TypeSystem; | ||
using Necati_Meral_Yahoo_De.Helpers; | ||
using Necati_Meral_Yahoo_De.Http; | ||
using Necati_Meral_Yahoo_De.LogicNodes; | ||
|
||
namespace Necati_Meral_Yahoo_De.Logic.ComfortOnline; | ||
public class ComfortOnlineRequestNode : LocalizablePrefixLogicNodeBase | ||
{ | ||
protected ITypeService TypeService { get; } | ||
protected ComfortOnlinePageParser Parser { get; } | ||
protected IHttpClient HttpClient { get; } | ||
|
||
[Input(DisplayOrder = 1, IsRequired = true)] | ||
public BoolValueObject Trigger { get; private set; } | ||
|
||
[Input(IsDefaultShown = true, DisplayOrder = 2)] | ||
public StringValueObject PlantId { get; } | ||
|
||
[Input(IsDefaultShown = true, DisplayOrder = 3)] | ||
public StringValueObject PlantSection { get; } | ||
|
||
[Input(IsDefaultShown = false, DisplayOrder = 4)] | ||
public StringValueObject UserName { get; } | ||
|
||
[Input(IsDefaultShown = false, DisplayOrder = 5)] | ||
public StringValueObject Password { get; } | ||
|
||
[Output(IsDefaultShown = true, DisplayOrder = 1)] | ||
public StringValueObject Data { get; private set; } | ||
|
||
[Output(IsDefaultShown = false, DisplayOrder = 99)] | ||
public StringValueObject Diagnostics { get; private set; } | ||
|
||
public ComfortOnlineRequestNode(INodeContext context) | ||
: base(context, LogicNodeConsts.InputPrefix) | ||
{ | ||
context.ThrowIfNull("context"); | ||
|
||
TypeService = context.GetService<ITypeService>(); | ||
Parser = new ComfortOnlinePageParser(); | ||
|
||
Trigger = TypeService.CreateBool("BINARY", "Trigger", false); | ||
PlantId = TypeService.CreateString("STRING", "PlantId", string.Empty); | ||
PlantSection = TypeService.CreateString("STRING", "PlantSection", string.Empty); | ||
UserName = TypeService.CreateString("STRING", "UserName", string.Empty); | ||
Password = TypeService.CreateString("STRING", "Password", string.Empty); | ||
Data = TypeService.CreateString("STRING", "Data", string.Empty); | ||
Diagnostics = TypeService.CreateString("STRING", "Diagnostics", string.Empty); | ||
|
||
HttpClient = CreateHttpClient(); | ||
} | ||
|
||
public override void Execute() | ||
{ | ||
if(Trigger.HasValue && Trigger.WasSet) | ||
{ | ||
try | ||
{ | ||
AsyncHelper.RunSync(ExecuteAsync); | ||
} | ||
catch (AggregateException ex) | ||
{ | ||
Diagnostics.Value = $"{ComfortOnlineConsts.ErrorCodes.UnexpectedError} {ex.Message}"; | ||
throw ex.InnerException; | ||
} | ||
} | ||
} | ||
|
||
protected virtual async Task ExecuteAsync() | ||
{ | ||
var loginSucceeded = await LoginAsync(); | ||
if (loginSucceeded) | ||
{ | ||
var plantSectionResponse = await HttpClient.GetStringAsync($"/Measurand/Values?plant={PlantId.Value}&name={PlantSection.Value}"); | ||
var parsed = Parser.Parse(plantSectionResponse); | ||
|
||
var entries = parsed.Values.Select(p => string.Format("\"{0}\": \"{1}\"", p.Key, string.Join(",", p.Value))); | ||
|
||
Data.Value = $"{{{string.Join(", ", entries)}}}"; | ||
Diagnostics.Value = ComfortOnlineConsts.ErrorCodes.Ok; | ||
} | ||
} | ||
|
||
protected virtual async Task<bool> LoginAsync() | ||
{ | ||
string initialRequestBody; | ||
try | ||
{ | ||
initialRequestBody = await HttpClient.GetStringAsync("/Account/Login"); | ||
} | ||
catch (Exception) | ||
{ | ||
Diagnostics.Value = ComfortOnlineConsts.ErrorCodes.InitialRequestFailed; | ||
return false; | ||
} | ||
|
||
var requestVerificationToken = GetRequestVerificationToken(initialRequestBody); | ||
if (string.IsNullOrEmpty(requestVerificationToken)) | ||
{ | ||
Diagnostics.Value = ComfortOnlineConsts.ErrorCodes.MissingRequestVerificationToken; | ||
return false; | ||
} | ||
|
||
try | ||
{ | ||
var loginPage = await HttpClient.PostAsync("/Account/Login", new Dictionary<string, string> | ||
{ | ||
{ "UserName", UserName.Value }, | ||
{ "Password", Password.Value }, | ||
{ "__RequestVerificationToken", requestVerificationToken } | ||
}); | ||
|
||
// Basic detection if we got redirected to login page = login failed | ||
if (loginPage.Contains("<form action=\"/account/login\"")) | ||
{ | ||
Diagnostics.Value = ComfortOnlineConsts.ErrorCodes.InvalidCredentials; | ||
return false; | ||
} | ||
} | ||
catch (Exception) | ||
{ | ||
Diagnostics.Value = ComfortOnlineConsts.ErrorCodes.LoginFailed; | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
protected virtual IHttpClient CreateHttpClient() | ||
{ | ||
var cookies = new CookieContainer(); | ||
var httpClient = new HttpClient(new HttpClientHandler { CookieContainer = cookies }) | ||
{ | ||
BaseAddress = new Uri(ComfortOnlineConsts.ComfortOnlineBaseAddress) | ||
}; | ||
|
||
return new NetHttpClient(httpClient); | ||
} | ||
|
||
protected virtual string GetRequestVerificationToken(string body) | ||
{ | ||
var matches = Regex.Match(body, "<input.*?(?:name=\\\"__RequestVerificationToken\\\".*?value=\\\"([^\"]+)|value=\\\"([^\"]+).*?name=\\\"__RequestVerificationToken\\\")[^>]*>"); | ||
if (matches.Success) | ||
{ | ||
return matches.Groups[1].Value; | ||
} | ||
return string.Empty; | ||
} | ||
} |
Oops, something went wrong.