Skip to content

Commit

Permalink
Kirc max/back comp login (#96)
Browse files Browse the repository at this point in the history
* backward compatible login

* adjust factory login methods

* bump version

* remove commented code
  • Loading branch information
KircMax authored Jan 7, 2025
1 parent f30df25 commit 4fe55ea
Show file tree
Hide file tree
Showing 8 changed files with 441 additions and 142 deletions.
227 changes: 157 additions & 70 deletions src/Webserver.API/Services/ApiStandardServiceFactory.cs

Large diffs are not rendered by default.

116 changes: 116 additions & 0 deletions src/Webserver.API/Services/IApiServiceFactory.cs

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -180,21 +180,24 @@ public virtual IApiRequest GetApiGetCertificateUrlRequest(string jsonRpc = null,
/// <returns>ApiLoginRequest with the given "user":userName, "password": password, "include_web_application_cookie" : include_web_application_cookie (might be null)</returns>
/// <param name="id">Request Id</param>
/// <param name="jsonRpc">JsonRpc to be used</param>
public virtual IApiRequest GetApiLoginRequest(ApiAuthenticationMode mode, string userName, string password, bool? include_web_application_cookie = null,
public virtual IApiRequest GetApiLoginRequest(string userName, string password, bool? include_web_application_cookie = null, ApiAuthenticationMode? mode = null,
string jsonRpc = null, string id = null)
{
string jsonRpcReq = jsonRpc ?? JsonRpcVersion;
string idReq = id ?? RequestIdGenerator.Generate();
Dictionary<string, object> requestParams = new Dictionary<string, object>()
{
{ "mode", mode.ToString().ToLower() },
{ "user", userName },
{ "password", password }
};
if (include_web_application_cookie == true)
{
requestParams.Add("include_web_application_cookie", include_web_application_cookie);
}
if(mode != null)
{
requestParams.Add("mode", mode.ToString().ToLower());
}
return new ApiRequest("Api.Login", jsonRpcReq, idReq, requestParams);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ public interface IApiRequestFactory
/// <returns>ApiLoginRequest with the given "user":userName, "password": password, "include_web_application_cookie" : include_web_application_cookie (might be null)</returns>
/// <param name="id">Request Id</param>
/// <param name="jsonRpc">JsonRpc to be used</param>
IApiRequest GetApiLoginRequest(ApiAuthenticationMode mode, string userName, string password, bool? include_web_application_cookie = null,
string jsonRpc = null, string id = null);
IApiRequest GetApiLoginRequest(string userName, string password, bool? include_web_application_cookie = null,
ApiAuthenticationMode? mode = null, string jsonRpc = null, string id = null);
/// <summary>
/// get an Api.Logout Request without parameters
/// </summary>
Expand Down
41 changes: 35 additions & 6 deletions src/Webserver.API/Services/RequestHandling/IApiRequestHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,27 @@ public interface IApiRequestHandler
/// <param name="username">The user account for which the password shall be changed</param>
/// <param name="currentPassword">The current password for the user</param>
/// <param name="newPassword">The new password for the user</param>
/// <param name="cancellationToken">Enables the method to terminate its operation if a cancellation is requested from it's CancellationTokenSource.</param>
/// <returns>True if changing password for the user was successful</returns>
Task<ApiTrueOnSuccessResponse> ApiChangePasswordAsync(string username, string currentPassword, string newPassword, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Send an Api.ChangePassword request
/// </summary>
/// <param name="username">The user account for which the password shall be changed</param>
/// <param name="currentPassword">The current password for the user</param>
/// <param name="newPassword">The new password for the user</param>
/// <param name="mode">The mode defines where the password change shall be performed on. If null, the PLC will treat it as local.</param>
/// <param name="cancellationToken">Enables the method to terminate its operation if a cancellation is requested from it's CancellationTokenSource.</param>
/// <returns>True if changing password for the user was successful</returns>
Task<ApiTrueOnSuccessResponse> ApiChangePasswordAsync(string username, string currentPassword, string newPassword, ApiAuthenticationMode? mode = null, CancellationToken cancellationToken = default(CancellationToken));
Task<ApiTrueOnSuccessResponse> ApiChangePasswordAsync(string username, string currentPassword, string newPassword, ApiAuthenticationMode mode, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Send an Api.ChangePassword request
/// </summary>
/// <param name="username">The user account for which the password shall be changed</param>
/// <param name="currentPassword">The current password for the user</param>
/// <param name="newPassword">The new password for the user</param>
/// <returns>True if changing password for the user was successful</returns>
ApiTrueOnSuccessResponse ApiChangePassword(string username, string currentPassword, string newPassword);
/// <summary>
/// Send an Api.ChangePassword request
/// </summary>
Expand All @@ -113,7 +130,7 @@ public interface IApiRequestHandler
/// <param name="newPassword">The new password for the user</param>
/// <param name="mode">The mode defines where the password change shall be performed on. If null, the PLC will treat it as local.</param>
/// <returns>True if changing password for the user was successful</returns>
ApiTrueOnSuccessResponse ApiChangePassword(string username, string currentPassword, string newPassword, ApiAuthenticationMode? mode = null);
ApiTrueOnSuccessResponse ApiChangePassword(string username, string currentPassword, string newPassword, ApiAuthenticationMode mode);
/// <summary>
/// Send an Api.GetCertificateUrl Request
/// </summary>
Expand All @@ -135,6 +152,7 @@ public interface IApiRequestHandler
/// </summary>
/// <returns>A QuantityStructure object</returns>
ApiGetQuantityStructuresResponse ApiGetQuantityStructures();

/// <summary>
/// Send a Api.Login Request
/// </summary>
Expand All @@ -148,13 +166,13 @@ public interface IApiRequestHandler
/// <summary>
/// Send a Api.Login Request
/// </summary>
/// <param name="mode">The mode defines where the login shall be performed. All available modes supported by API method Api.GetAuthenticationMode can be passed. </param>
/// <param name="userName">Username to login with</param>
/// <param name="password">Password for the user to login with</param>
/// <param name="loginMode">The mode defines where the login shall be performed. All available modes supported by API method Api.GetAuthenticationMode can be passed. </param>
/// <param name="includeWebApplicationCookie">Used to determine wether or not a WebApplicationCookie should be included in the Response (Result)</param>
/// <param name="cancellationToken">Enables the method to terminate its operation if a cancellation is requested from it's CancellationTokenSource.</param>
/// <returns>ApiLoginResponse: contains ApiTokenResult: Token(auth token string) and if requested Web_application_cookie</returns>
Task<ApiLoginResponse> ApiLoginAsync(ApiAuthenticationMode mode, string userName, string password, bool? includeWebApplicationCookie = null, CancellationToken cancellationToken = default(CancellationToken));
Task<ApiLoginResponse> ApiLoginAsync(string userName, string password, ApiAuthenticationMode loginMode, bool? includeWebApplicationCookie = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Send an Api.Logout Request
/// </summary>
Expand Down Expand Up @@ -1064,12 +1082,12 @@ public interface IApiRequestHandler
/// <summary>
/// Send a Api.Login Request
/// </summary>
/// <param name="mode">The mode defines where the login shall be performed. All available modes supported by API method Api.GetAuthenticationMode can be passed. </param>
/// <param name="userName">Username to login with</param>
/// <param name="password">Password for the user to login with</param>
/// <param name="loginMode">The mode defines where the login shall be performed. All available modes supported by API method Api.GetAuthenticationMode can be passed.</param>
/// <param name="includeWebApplicationCookie">Used to determine wether or not a WebApplicationCookie should be included in the Response (Result)</param>
/// <returns>ApiLoginResponse: contains ApiTokenResult: Token(auth token string) and if requested Web_application_cookie</returns>
ApiLoginResponse ApiLogin(ApiAuthenticationMode mode, string userName, string password, bool? includeWebApplicationCookie = null);
ApiLoginResponse ApiLogin(string userName, string password, ApiAuthenticationMode loginMode, bool? includeWebApplicationCookie = null);
/// <summary>
/// Send an Api.Logout Request
/// </summary>
Expand Down Expand Up @@ -2155,11 +2173,22 @@ public interface IApiRequestHandler
/// </summary>
Task<ApiLoginResponse> ReLoginAsync(string userName, string password, bool? includeWebApplicationCookie = null, CancellationToken cancellationToken = default(CancellationToken));

/// <summary>
/// Re-login to the plc, set the header again in the connected service (e.g.HttpClient)!
/// </summary>
Task<ApiLoginResponse> ReLoginAsync(string userName, string password, ApiAuthenticationMode loginMode, bool? includeWebApplicationCookie = null, CancellationToken cancellationToken = default(CancellationToken));

/// <summary>
/// Re-login to the plc, set the header again in the connected service (e.g.HttpClient)!
/// </summary>
ApiLoginResponse ReLogin(string userName, string password, bool? includeWebApplicationCookie = null);

/// <summary>
/// Re-login to the plc, set the header again in the connected service (e.g.HttpClient)!
/// </summary>
ApiLoginResponse ReLogin(string userName, string password, ApiAuthenticationMode loginMode, bool? includeWebApplicationCookie = null);


/// <summary>
/// Send a Failsafe.ReadParameters request
/// </summary>
Expand Down
16 changes: 8 additions & 8 deletions tests/Webserver.API.UnitTests/ApiRequestTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ public void T007_01_ApiLogin_InvalidLogin_UnauthorizedExc()
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);
var req = ApiRequestFactory.GetApiLoginRequest(ApiAuthenticationMode.Local, "Everybody", "wrong");
var req = ApiRequestFactory.GetApiLoginRequest("Everybody", "wrong", null, ApiAuthenticationMode.Local);
Assert.ThrowsAsync<UnauthorizedAccessException>(async () => await TestHandler.SendPostRequestAsync(req));
}

Expand All @@ -487,7 +487,7 @@ public void T007_02_ApiLogin_AlreadyLoggedIn_UnauthorizedExc()
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);
var req = ApiRequestFactory.GetApiLoginRequest(ApiAuthenticationMode.Local, "Everybody", "");
var req = ApiRequestFactory.GetApiLoginRequest("Everybody", "", null, ApiAuthenticationMode.Local);
Assert.ThrowsAsync<ApiAlreadyAuthenticatedException>(async () => await TestHandler.SendPostRequestAsync(req));
}

Expand All @@ -506,7 +506,7 @@ public void T007_03_ApiLogin_NoResources_NoResourcesExc()
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);
var req = ApiRequestFactory.GetApiLoginRequest(ApiAuthenticationMode.Local, "Everybody", "");
var req = ApiRequestFactory.GetApiLoginRequest("Everybody", "", null, ApiAuthenticationMode.Local);
Assert.ThrowsAsync<ApiNoResourcesException>(async () => await TestHandler.SendPostRequestAsync(req));
}

Expand All @@ -525,7 +525,7 @@ public async Task T007_04_ApiLogin_ValidToken_TokenReturnedNoCookie()
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);
var req = ApiRequestFactory.GetApiLoginRequest(ApiAuthenticationMode.Local, "Everybody", "");
var req = ApiRequestFactory.GetApiLoginRequest("Everybody", "", null, ApiAuthenticationMode.Local);
var res = JsonConvert.DeserializeObject<ApiLoginResponse>(await TestHandler.SendPostRequestAsync(req));
if (string.IsNullOrEmpty(res.Result.Token))
Assert.Fail("token is empty or null altough server returned with!");
Expand All @@ -548,7 +548,7 @@ public async Task T007_05_ApiLogin_ValidToken_TokenReturnedAndCookie()
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);
var req = ApiRequestFactory.GetApiLoginRequest(ApiAuthenticationMode.Local, "Everybody", "", true);
var req = ApiRequestFactory.GetApiLoginRequest("Everybody", "", true, ApiAuthenticationMode.Local);
var res = JsonConvert.DeserializeObject<ApiLoginResponse>(await TestHandler.SendPostRequestAsync(req));
if (string.IsNullOrEmpty(res.Result.Token))
Assert.Fail("token is empty or null altough server returned with!");
Expand All @@ -571,7 +571,7 @@ public async Task T007_06_ApiLogin_ValidToken_WithEverything()
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);
var req = ApiRequestFactory.GetApiLoginRequest(ApiAuthenticationMode.Local, "Anonymous", "", true);
var req = ApiRequestFactory.GetApiLoginRequest("Anonymous", "", true, ApiAuthenticationMode.Local);
var res = JsonConvert.DeserializeObject<ApiLoginResponse>(await TestHandler.SendPostRequestAsync(req));
if (string.IsNullOrEmpty(res.Result.Token))
Assert.Fail("token is empty or null altough server returned with!");
Expand Down Expand Up @@ -601,7 +601,7 @@ public async Task T007_07_ApiLogin_ValidToken_Works()
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);
var result = (await TestHandler.ApiLoginAsync(ApiAuthenticationMode.Local, "Admin", "Siemens_1")).Result;
var result = (await TestHandler.ApiLoginAsync("Admin", "Siemens_1", ApiAuthenticationMode.Local)).Result;
Assert.That(result.Token, Is.EqualTo("G8ejtdxTZ6fz8AIuwDG.tWf+6Cou"));
}

Expand All @@ -620,7 +620,7 @@ public void T007_08_ApiLogin_ValidToken_InfrastructureErrorExc()
var client = new HttpClient(mockHttp);
client.BaseAddress = new Uri($"https://{Ip.ToString()}");
TestHandler = new ApiHttpClientRequestHandler(client, ApiRequestFactory, ApiResponseChecker);
Assert.ThrowsAsync<ApiInfrastructureErrorException>(async () => await TestHandler.ApiLoginAsync(ApiAuthenticationMode.Umc, "Admin", "Siemens_1"));
Assert.ThrowsAsync<ApiInfrastructureErrorException>(async () => await TestHandler.ApiLoginAsync("Admin", "Siemens_1", ApiAuthenticationMode.Umc));
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion version.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
"version": "3.0",
"version": "3.1",
"publicReleaseRefSpec": [
"^refs/heads/main$"
],
Expand Down

0 comments on commit 4fe55ea

Please sign in to comment.