adds first implementation details and starts with login / logout
This commit is contained in:
parent
0751dbe9d3
commit
3bf56c7ee7
@ -9,6 +9,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="FluentAssertions" Version="6.7.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
@ -16,4 +17,8 @@
|
|||||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Piwigo.Client\Piwigo.Client.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
45
PiwigoDotnet/Piwigo.Client.Tests/PiwigoClientTests.cs
Normal file
45
PiwigoDotnet/Piwigo.Client.Tests/PiwigoClientTests.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using Flurl.Http.Testing;
|
||||||
|
|
||||||
|
namespace Piwigo.Client.Tests;
|
||||||
|
|
||||||
|
public class PiwigoClientTests
|
||||||
|
{
|
||||||
|
private PiwigoClient _piwigoClient = null!;
|
||||||
|
private HttpTest _httpTest = null!;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
_piwigoClient = new PiwigoClient();
|
||||||
|
_httpTest = new HttpTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public void TearDown()
|
||||||
|
{
|
||||||
|
_httpTest.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Login_should_set_cookies_and_session()
|
||||||
|
{
|
||||||
|
await LoginAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Logout_should_set_IsLoggedIn_to_false()
|
||||||
|
{
|
||||||
|
await LoginAsync();
|
||||||
|
|
||||||
|
_httpTest.RespondWith("OK");
|
||||||
|
await _piwigoClient.Logout();
|
||||||
|
_piwigoClient.IsLoggedIn.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task LoginAsync()
|
||||||
|
{
|
||||||
|
_httpTest.RespondWith("OK", 200, cookies: new { pwg_id = "pwg_id" });
|
||||||
|
await _piwigoClient.LoginAsync(new Uri("http://localhost:8080/foo/bar/ws.php?format=json"), "admin", "admin");
|
||||||
|
_piwigoClient.IsLoggedIn.Should().BeTrue();
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +0,0 @@
|
|||||||
namespace Piwigo.Client.Tests;
|
|
||||||
|
|
||||||
public class Tests
|
|
||||||
{
|
|
||||||
[SetUp]
|
|
||||||
public void Setup()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void Test1()
|
|
||||||
{
|
|
||||||
Assert.Pass();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +1,2 @@
|
|||||||
global using NUnit.Framework;
|
global using NUnit.Framework;
|
||||||
|
global using FluentAssertions;
|
@ -0,0 +1,16 @@
|
|||||||
|
using Flurl.Http.Content;
|
||||||
|
|
||||||
|
namespace Piwigo.Client;
|
||||||
|
|
||||||
|
internal static class CapturedMultipartContentExtensions
|
||||||
|
{
|
||||||
|
public static CapturedMultipartContent AddMethod(this CapturedMultipartContent part, string piwigoMethod)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(piwigoMethod))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Value cannot be null or whitespace.", nameof(piwigoMethod));
|
||||||
|
}
|
||||||
|
|
||||||
|
return part.AddString("method", piwigoMethod);
|
||||||
|
}
|
||||||
|
}
|
@ -2,5 +2,8 @@
|
|||||||
|
|
||||||
public interface IPiwigoClient
|
public interface IPiwigoClient
|
||||||
{
|
{
|
||||||
|
bool IsLoggedIn { get; }
|
||||||
|
int ChunkSize { get; set; }
|
||||||
Task LoginAsync(Uri uri, string username, string password);
|
Task LoginAsync(Uri uri, string username, string password);
|
||||||
|
Task Logout();
|
||||||
}
|
}
|
69
PiwigoDotnet/Piwigo.Client/PiwigoClient.cs
Normal file
69
PiwigoDotnet/Piwigo.Client/PiwigoClient.cs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
using System.Net;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using Flurl;
|
||||||
|
using Flurl.Http;
|
||||||
|
|
||||||
|
namespace Piwigo.Client;
|
||||||
|
|
||||||
|
public class PiwigoClient : IPiwigoClient
|
||||||
|
{
|
||||||
|
private CookieJar _cookies = new();
|
||||||
|
private string _piwigoBaseUri = null!;
|
||||||
|
public bool IsLoggedIn { get; private set; }
|
||||||
|
public int ChunkSize { get; set; } = 512;
|
||||||
|
private IFlurlRequest Request => _piwigoBaseUri.WithCookies(_cookies);
|
||||||
|
|
||||||
|
public async Task LoginAsync(Uri uri, string username, string password)
|
||||||
|
{
|
||||||
|
if (uri == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(username))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Value cannot be null or whitespace.", nameof(username));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(password))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Value cannot be null or whitespace.", nameof(password));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsLoggedIn)
|
||||||
|
{
|
||||||
|
throw new PiwigoException("The client is already logged in. Create a new instance or log out first!");
|
||||||
|
}
|
||||||
|
|
||||||
|
_piwigoBaseUri = uri.AppendPathSegment("ws.php").SetQueryParam("format", "json");
|
||||||
|
|
||||||
|
var response = await _piwigoBaseUri.WithCookies(out var cookieJar).PostMultipartAsync(c =>
|
||||||
|
c.PiwigoLogin(username, password));
|
||||||
|
|
||||||
|
if (response.StatusCode != (int)HttpStatusCode.OK)
|
||||||
|
{
|
||||||
|
throw new PiwigoException($"Could not log in to {_piwigoBaseUri} using username {username}");
|
||||||
|
}
|
||||||
|
|
||||||
|
_cookies = cookieJar;
|
||||||
|
IsLoggedIn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Logout()
|
||||||
|
{
|
||||||
|
EnsureLoggedIn();
|
||||||
|
|
||||||
|
await Request.PostMultipartAsync(c => c.PiwigoLogout());
|
||||||
|
|
||||||
|
IsLoggedIn = false;
|
||||||
|
_cookies.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnsureLoggedIn([CallerMemberName] string? callerName = null)
|
||||||
|
{
|
||||||
|
if (!IsLoggedIn)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Could not execute {callerName} as the client is not logged in.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
PiwigoDotnet/Piwigo.Client/PiwigoException.cs
Normal file
23
PiwigoDotnet/Piwigo.Client/PiwigoException.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace Piwigo.Client;
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class PiwigoException : Exception
|
||||||
|
{
|
||||||
|
public PiwigoException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PiwigoException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PiwigoException(string? message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PiwigoException(string? message, Exception? innerException) : base(message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
17
PiwigoDotnet/Piwigo.Client/PiwigoMethods.cs
Normal file
17
PiwigoDotnet/Piwigo.Client/PiwigoMethods.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Flurl.Http.Content;
|
||||||
|
|
||||||
|
namespace Piwigo.Client;
|
||||||
|
|
||||||
|
internal static class PiwigoMethods
|
||||||
|
{
|
||||||
|
public static CapturedMultipartContent PiwigoLogin(this CapturedMultipartContent part, string username,
|
||||||
|
string password)
|
||||||
|
{
|
||||||
|
return part.AddMethod("pwg.session.login").AddString("username", username).AddString("password", password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CapturedMultipartContent PiwigoLogout(this CapturedMultipartContent part)
|
||||||
|
{
|
||||||
|
return part.AddMethod("pwg.session.logout");
|
||||||
|
}
|
||||||
|
}
|
@ -1,2 +1,6 @@
|
|||||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">Required</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">Required</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_IFELSE/@EntryValue">Required</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Piwigo/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Piwigo/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
Loading…
Reference in New Issue
Block a user