fixes for Nextcloud

This commit is contained in:
2023-10-02 15:25:16 +02:00
parent c7f5de4974
commit b2ef1e5cce
21 changed files with 233 additions and 101 deletions

View File

@@ -14,21 +14,21 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.Client.Apps
{ {
} }
public Task<bool> CreateRetentionRule(RetentionRule rule) public bool CreateRetentionRule(RetentionRuleInfo rule)
{ {
var entry = rule.ToOcsData(); var entry = rule.ToOcsData();
return Client.Ocs.GetApi<OcsApiFilesRetention>().CreateRetentionRule(entry); return Client.Ocs.GetApi<OcsApiFilesRetention>().CreateRetentionRule(entry);
} }
public Task<bool> DeleteRetentionRule(int ruleID) public bool DeleteRetentionRule(int ruleID)
{ {
return Client.Ocs.GetApi<OcsApiFilesRetention>().DeleteRetentionRule(ruleID); return Client.Ocs.GetApi<OcsApiFilesRetention>().DeleteRetentionRule(ruleID);
} }
public async Task<RetentionRule[]?> GetRetentionRules() public RetentionRule[]? GetRetentionRules()
{ {
var api = Client.Ocs.GetApi<OcsApiFilesRetention>(); var api = Client.Ocs.GetApi<OcsApiFilesRetention>();
var response = await api.GetRetentionRules(); var response = api.GetRetentionRules();
if (response?.Data is not null) if (response?.Data is not null)
{ {

View File

@@ -8,7 +8,7 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.Client
{ {
public abstract class ClientBase public abstract class ClientBase
{ {
public NextcloudClient Client { get; init; } protected NextcloudClient Client { get; init; }
public ClientBase(NextcloudClient client) public ClientBase(NextcloudClient client)
{ {

View File

@@ -13,17 +13,17 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.Client
{ {
} }
public Task<UserInfo?> GetUserInfo() public UserInfo? GetUserInfo()
{ {
if (!string.IsNullOrEmpty(Client.CurrentLogin?.LoginName)) if (!string.IsNullOrEmpty(Client.CurrentLogin?.LoginName))
return GetUserInfo(Client.CurrentLogin.LoginName); return GetUserInfo(Client.CurrentLogin.LoginName);
else else
return Task.FromResult<UserInfo?>(null); return null;
} }
public async Task<UserInfo?> GetUserInfo(string username) public UserInfo? GetUserInfo(string username)
{ {
var result = await Client.Ocs.Cloud.GetUserMeta(username); var result = Client.Ocs.Cloud.GetUserMeta(username);
if (result?.Data != null) if (result?.Data != null)
return new UserInfo(result.Data); return new UserInfo(result.Data);

View File

@@ -8,46 +8,20 @@ using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.Model.Apps.FilesRetention namespace Pilz.Networking.CloudProviders.Nextcloud.Model.Apps.FilesRetention
{ {
public class RetentionRule public class RetentionRule : RetentionRuleInfo
{ {
/// <summary> /// <summary>
/// The ID for the retention rule. /// The ID for the retention rule.
/// </summary> /// </summary>
public int ID { get; init; } public int ID { get; init; }
/// <summary>
/// The ID for the tag that is used for this rule.
/// </summary>
public int TagID { get; init; }
/// <summary>
/// The unit used for the time.
/// </summary>
public RetentionTimeUnit TimeUnit { get; init; }
/// <summary>
/// Represents numer of days/weeks/months/years.
/// </summary>
public int TimeAmount { get; init; }
/// <summary>
/// The time used for the rule.
/// </summary>
public RetentionTimeAfter TimeAfter { get; init; }
/// <summary> /// <summary>
/// Defines if a background job has been generated /// Defines if a background job has been generated
/// </summary> /// </summary>
public bool HasJob { get; init; } public bool HasJob { get; init; }
public RetentionRule(int iD, int tagID, RetentionTimeUnit timeUnit, int timeAmount, RetentionTimeAfter timeAfter, bool hasJob) public RetentionRule()
{ {
ID = iD;
TagID = tagID;
TimeUnit = timeUnit;
TimeAmount = timeAmount;
TimeAfter = timeAfter;
HasJob = hasJob;
} }
public RetentionRule(OcsResponseDataEntryRetention data) public RetentionRule(OcsResponseDataEntryRetention data)
@@ -58,16 +32,5 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.Model.Apps.FilesRetention
TimeAmount = data.TimeAmount ?? -1; TimeAmount = data.TimeAmount ?? -1;
TimeAfter = (RetentionTimeAfter)(data.TimeAfter ?? 0); TimeAfter = (RetentionTimeAfter)(data.TimeAfter ?? 0);
} }
public OcsDataRetentionRule ToOcsData()
{
return new OcsDataRetentionRule
{
TagID = TagID,
TimeUnit = (int)TimeUnit,
TimeAmount = TimeAmount,
TimeAfter = (int)TimeAfter
};
}
} }
} }

View File

@@ -0,0 +1,43 @@
using Pilz.Networking.CloudProviders.Nextcloud.OCS.Data.Apps.FileRetention;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.Model.Apps.FilesRetention
{
public class RetentionRuleInfo
{
/// <summary>
/// The ID for the tag that is used for this rule.
/// </summary>
public int TagID { get; init; }
/// <summary>
/// The unit used for the time.
/// </summary>
public RetentionTimeUnit TimeUnit { get; init; }
/// <summary>
/// Represents numer of days/weeks/months/years.
/// </summary>
public int TimeAmount { get; init; }
/// <summary>
/// The time used for the rule.
/// </summary>
public RetentionTimeAfter TimeAfter { get; init; }
public OcsDataRetentionRule ToOcsData()
{
return new OcsDataRetentionRule
{
TagID = TagID,
TimeUnit = (int)TimeUnit,
TimeAmount = TimeAmount,
TimeAfter = (int)TimeAfter
};
}
}
}

View File

@@ -99,7 +99,7 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.Model.Cloud
Enabled = Convert.ToBoolean(responseData.Enabled); Enabled = Convert.ToBoolean(responseData.Enabled);
StorageLocation = responseData.StorageLocation; StorageLocation = responseData.StorageLocation;
ID = responseData.ID; ID = responseData.ID;
LastLogin = Convert.ToDateTime(responseData.LastLogin); LastLogin = DateTimeOffset.FromUnixTimeMilliseconds(responseData.LastLogin ?? 0).LocalDateTime;
Backend = responseData.Backend; Backend = responseData.Backend;
Email = responseData.Email; Email = responseData.Email;
Displayname = responseData.Displayname; Displayname = responseData.Displayname;

View File

@@ -12,17 +12,17 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.Model.Cloud
/// <summary> /// <summary>
/// Amount of free bytes left. /// Amount of free bytes left.
/// </summary> /// </summary>
public ulong Free { get; set; } public long Free { get; set; }
/// <summary> /// <summary>
/// Amount of already used bytes. /// Amount of already used bytes.
/// </summary> /// </summary>
public ulong Used { get; set; } public long Used { get; set; }
/// <summary> /// <summary>
/// Total amount of all bytes (free + used). /// Total amount of all bytes (free + used).
/// </summary> /// </summary>
public ulong Total { get; set; } public long Total { get; set; }
/// <summary> /// <summary>
/// Relative amount of used quota in percent. /// Relative amount of used quota in percent.
@@ -32,6 +32,6 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.Model.Cloud
/// <summary> /// <summary>
/// Total amount of bytes available. /// Total amount of bytes available.
/// </summary> /// </summary>
public ulong Quota { get; set; } public long Quota { get; set; }
} }
} }

View File

@@ -17,9 +17,19 @@ namespace Pilz.Networking.CloudProviders.Nextcloud
public class NextcloudClient : IDisposable public class NextcloudClient : IDisposable
{ {
private readonly List<ClientBase> clients = new(); private readonly List<ClientBase> clients = new();
private NextcloudLogin? currentLogin;
public OcsApi Ocs { get; init; } = new(); public OcsApi Ocs { get; init; } = new();
public NextcloudLogin? CurrentLogin { get; private set; }
public NextcloudLogin? CurrentLogin
{
get => currentLogin;
private set
{
currentLogin = value;
Ocs.BaseUrl = value?.Server ?? string.Empty;
}
}
public CloudClient Cloud => GetClient<CloudClient>(); public CloudClient Cloud => GetClient<CloudClient>();
@@ -52,16 +62,16 @@ namespace Pilz.Networking.CloudProviders.Nextcloud
return instance; return instance;
} }
public async Task<UserInfo?> Login(NextcloudLogin login) public UserInfo? Login(NextcloudLogin login)
{ {
// Ensure we are logged out // Ensure we are logged out
await Logout(); Logout(false);
// Temporary set user login // Temporary set user login
CurrentLogin = login; CurrentLogin = login;
// Try get user info & check if user is enabled // Try get user info & check if user is enabled
var userInfo = await Cloud.GetUserInfo(); var userInfo = Cloud.GetUserInfo();
var isValid = userInfo != null && userInfo.Enabled; var isValid = userInfo != null && userInfo.Enabled;
// If invalid, reset login credentials // If invalid, reset login credentials
@@ -71,13 +81,13 @@ namespace Pilz.Networking.CloudProviders.Nextcloud
return userInfo; return userInfo;
} }
public async Task<NextcloudLogin?> Login(string baseUrl, CancellationToken cancellationToken) public NextcloudLogin? Login(string baseUrl, CancellationToken cancellationToken)
{ {
// Ensure we are logged out // Ensure we are logged out
await Logout(); Logout(false);
// Init the login process // Init the login process
var initResponse = await Ocs.LoginFlowV2.Init(baseUrl); var initResponse = Ocs.LoginFlowV2.Init(baseUrl);
if (!string.IsNullOrEmpty(initResponse?.LoginUrl) && initResponse.Poll != null) if (!string.IsNullOrEmpty(initResponse?.LoginUrl) && initResponse.Poll != null)
{ {
@@ -97,7 +107,7 @@ namespace Pilz.Networking.CloudProviders.Nextcloud
// Poll the credentials // Poll the credentials
if (!cancellationToken.IsCancellationRequested) if (!cancellationToken.IsCancellationRequested)
pollResponse = await Ocs.LoginFlowV2.Poll(initResponse.Poll); pollResponse = Ocs.LoginFlowV2.Poll(initResponse.Poll);
} }
// Check login credentials // Check login credentials
@@ -108,18 +118,18 @@ namespace Pilz.Networking.CloudProviders.Nextcloud
return CurrentLogin; return CurrentLogin;
} }
public Task Logout() public void Logout()
{ {
return Logout(true); Logout(true);
} }
public async Task Logout(bool logoutOnServer) public void Logout(bool logoutOnServer)
{ {
if (CurrentLogin != null) if (CurrentLogin != null)
{ {
// Delete currently used app password // Delete currently used app password
if (logoutOnServer) if (logoutOnServer)
await Ocs.Core.DeleteAppPassword(); Ocs.Core.DeleteAppPassword();
// Reset current login infos // Reset current login infos
CurrentLogin = null; CurrentLogin = null;

View File

@@ -19,21 +19,21 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.APIs.Apps
{ {
} }
public async Task<bool> CreateRetentionRule(OcsDataRetentionRule rule) public bool CreateRetentionRule(OcsDataRetentionRule rule)
{ {
var response = await Manager.MakeRequest(HttpMethod.Post, OCS_FILE_RETENTION_RULES, content: rule); var response = Manager.MakeRequest(HttpMethod.Post, OCS_FILE_RETENTION_RULES, content: rule);
return response.IsSuccessStatusCode; return response.IsSuccessStatusCode;
} }
public async Task<bool> DeleteRetentionRule(int ruleID) public bool DeleteRetentionRule(int ruleID)
{ {
var response = await Manager.MakeRequest(HttpMethod.Delete, OCS_FILE_RETENTION_RULE.FillParameters(ruleID)); var response = Manager.MakeRequest(HttpMethod.Delete, OCS_FILE_RETENTION_RULE.FillParameters(ruleID));
return response.IsSuccessStatusCode; return response.IsSuccessStatusCode;
} }
public Task<OcsResponseRetention?> GetRetentionRules() public OcsResponseRetention? GetRetentionRules()
{ {
return Manager.MakeRequest<OcsResponseRetention>(HttpMethod.Get, OCS_FILE_RETENTION_RULES); return Manager.MakeRequestOcs<OcsResponseRetention>(HttpMethod.Get, OCS_FILE_RETENTION_RULES);
} }
} }
} }

View File

@@ -8,7 +8,7 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.APIs
{ {
public abstract class OcsApiBase public abstract class OcsApiBase
{ {
public OcsApi Manager { get; init; } protected OcsApi Manager { get; init; }
protected OcsApiBase(OcsApi manager) protected OcsApiBase(OcsApi manager)
{ {

View File

@@ -15,9 +15,9 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.APIs
{ {
} }
public Task<OcsResponseUser?> GetUserMeta(string username) public OcsResponseUser? GetUserMeta(string username)
{ {
return Manager.MakeRequest<OcsResponseUser>(HttpMethod.Get, OCS_CLOUD_USER_METADATA.FillParameters(username)); return Manager.MakeRequestOcs<OcsResponseUser>(HttpMethod.Get, OCS_CLOUD_USER_METADATA.FillParameters(username));
} }
} }
} }

View File

@@ -14,9 +14,9 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.APIs
{ {
} }
public async Task<bool> DeleteAppPassword() public bool DeleteAppPassword()
{ {
using var msg = await Manager.MakeRequest(HttpMethod.Delete, OCS_CORE_APPPASSWORD); using var msg = Manager.MakeRequest(HttpMethod.Delete, OCS_CORE_APPPASSWORD);
return msg != null && msg.IsSuccessStatusCode; return msg != null && msg.IsSuccessStatusCode;
} }
} }

View File

@@ -15,12 +15,12 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.APIs
{ {
} }
public Task<OcsResponseLoginFlowV2?> Init(string url) public OcsResponseLoginFlowV2? Init(string url)
{ {
return Manager.MakeRequest<OcsResponseLoginFlowV2>(HttpMethod.Get, url + OCS_LOGIN_INIT); return Manager.MakeRequest<OcsResponseLoginFlowV2>(HttpMethod.Get, url + OCS_LOGIN_INIT);
} }
public Task<OcsResponseLoginFlowV2Credentials?> Poll(OcsResponseLoginFlowV2.PollData poll) public OcsResponseLoginFlowV2Credentials? Poll(OcsResponseLoginFlowV2.PollData poll)
{ {
ArgumentNullException.ThrowIfNull(poll?.Endpoint); ArgumentNullException.ThrowIfNull(poll?.Endpoint);
ArgumentNullException.ThrowIfNull(poll?.Token); ArgumentNullException.ThrowIfNull(poll?.Token);

View File

@@ -10,6 +10,8 @@ using System.Net;
using Pilz.Networking.CloudProviders.Nextcloud.OCS.APIs; using Pilz.Networking.CloudProviders.Nextcloud.OCS.APIs;
using System.Net.Sockets; using System.Net.Sockets;
using Pilz.Networking.CloudProviders.Nextcloud.OCS.Data; using Pilz.Networking.CloudProviders.Nextcloud.OCS.Data;
using Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses;
using System.Xml.Linq;
namespace Pilz.Networking.CloudProviders.Nextcloud.OCS namespace Pilz.Networking.CloudProviders.Nextcloud.OCS
{ {
@@ -51,30 +53,103 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS
return BaseUrl + path; return BaseUrl + path;
} }
public Task<TResponse?> MakeRequest<TResponse>(HttpMethod httpMethod, OcsApiUrlPath url, bool useAuthentication = true, Dictionary<string, string>? parameters = null, object? content = null) /// <summary>
/// Makes an request with the given arguments and deserialize it to the given type.
/// </summary>
/// <typeparam name="TResponse"></typeparam>
/// <param name="httpMethod"></param>
/// <param name="url"></param>
/// <param name="useAuthentication"></param>
/// <param name="parameters"></param>
/// <param name="content"></param>
/// <returns>Returns the given OcsResponse type from the deserialized OcsApiResponse content.</returns>
public TResponse? MakeRequestOcs<TResponse>(HttpMethod httpMethod, OcsApiUrlPath url, bool useAuthentication = true, Dictionary<string, string>? parameters = null, object? content = null) where TResponse : IOcsResponse
{
return MakeRequestOcs<TResponse>(httpMethod, BuildFullUrl(url), useAuthentication: useAuthentication, parameters: parameters, content: content);
}
/// <summary>
/// Makes an request with the given arguments and deserialize it to the given type.
/// </summary>
/// <typeparam name="TResponse"></typeparam>
/// <param name="httpMethod"></param>
/// <param name="url"></param>
/// <param name="useAuthentication"></param>
/// <param name="parameters"></param>
/// <param name="content"></param>
/// <returns>Returns the given OcsResponse type from the deserialized OcsApiResponse content.</returns>
public TResponse? MakeRequestOcs<TResponse>(HttpMethod httpMethod, string url, bool useAuthentication = true, Dictionary<string, string>? parameters = null, object? content = null) where TResponse : IOcsResponse
{
var response = MakeRequest<OcsApiResponse<TResponse>?>(httpMethod, url, useAuthentication: useAuthentication, parameters: parameters, content: content);
if (response != null)
return response.Ocs;
return default;
}
/// <summary>
/// Makes an request with the given arguments and deserialize it to the given type.
/// </summary>
/// <typeparam name="TResponse"></typeparam>
/// <param name="httpMethod"></param>
/// <param name="url"></param>
/// <param name="useAuthentication"></param>
/// <param name="parameters"></param>
/// <param name="content"></param>
/// <returns>Returns the deserialized content of type given type.</returns>
public TResponse? MakeRequest<TResponse>(HttpMethod httpMethod, OcsApiUrlPath url, bool useAuthentication = true, Dictionary<string, string>? parameters = null, object? content = null)
{ {
return MakeRequest<TResponse>(httpMethod, BuildFullUrl(url), useAuthentication: useAuthentication, parameters: parameters, content: content); return MakeRequest<TResponse>(httpMethod, BuildFullUrl(url), useAuthentication: useAuthentication, parameters: parameters, content: content);
} }
public Task<HttpResponseMessage> MakeRequest(HttpMethod httpMethod, OcsApiUrlPath url, bool useAuthentication = true, Dictionary<string, string>? parameters = null, object? content = null) /// <summary>
/// Makes an request with the given arguments and deserialize it to the given type.
/// </summary>
/// <typeparam name="TResponse"></typeparam>
/// <param name="httpMethod"></param>
/// <param name="url"></param>
/// <param name="useAuthentication"></param>
/// <param name="parameters"></param>
/// <param name="content"></param>
/// <returns>Returns the deserialized content of type given type.</returns>
public TResponse? MakeRequest<TResponse>(HttpMethod httpMethod, string url, bool useAuthentication = true, Dictionary<string, string>? parameters = null, object? content = null)
{ {
return MakeRequest(httpMethod, BuildFullUrl(url), useAuthentication: useAuthentication, parameters: parameters, content: content); using var responseInit = MakeRequest(httpMethod, url, useAuthentication: useAuthentication, parameters: parameters, content: content);
}
public async Task<TResponse?> MakeRequest<TResponse>(HttpMethod httpMethod, string url, bool useAuthentication = true, Dictionary<string, string>? parameters = null, object? content = null)
{
using var responseInit = await MakeRequest(httpMethod, url, useAuthentication: useAuthentication, parameters: parameters, content: content);
if (responseInit != null) if (responseInit != null)
{ {
var bodyInit = await responseInit.Content.ReadAsStringAsync(); var bodyInit = responseInit.Content.ReadAsStringAsync().Result;
return JsonConvert.DeserializeObject<TResponse>(bodyInit); return JsonConvert.DeserializeObject<TResponse>(bodyInit);
} }
return default; return default;
} }
public async Task<HttpResponseMessage> MakeRequest(HttpMethod httpMethod, string url, bool useAuthentication = true, Dictionary<string, string>? parameters = null, object? content = null) /// <summary>
/// Makes an request with the given arguments.
/// </summary>
/// <param name="httpMethod"></param>
/// <param name="url"></param>
/// <param name="useAuthentication"></param>
/// <param name="parameters"></param>
/// <param name="content"></param>
/// <returns>Returns a HttpResponseMessage as result.</returns>
public HttpResponseMessage MakeRequest(HttpMethod httpMethod, OcsApiUrlPath url, bool useAuthentication = true, Dictionary<string, string>? parameters = null, object? content = null)
{
return MakeRequest(httpMethod, BuildFullUrl(url), useAuthentication: useAuthentication, parameters: parameters, content: content);
}
/// <summary>
/// Makes an request with the given arguments.
/// </summary>
/// <param name="httpMethod"></param>
/// <param name="url"></param>
/// <param name="useAuthentication"></param>
/// <param name="parameters"></param>
/// <param name="content"></param>
/// <returns>Returns a HttpResponseMessage as result.</returns>
public HttpResponseMessage MakeRequest(HttpMethod httpMethod, string url, bool useAuthentication = true, Dictionary<string, string>? parameters = null, object? content = null)
{ {
OcsApiAuthCredentials? authentication; OcsApiAuthCredentials? authentication;
string @params; string @params;
@@ -118,7 +193,7 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS
Content = httpContent Content = httpContent
}; };
return await client.SendAsync(request); return client.Send(request);
} }
public void Dispose() public void Dispose()

View File

@@ -0,0 +1,17 @@
using Newtonsoft.Json;
using Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Pilz.Networking.CloudProviders.Nextcloud.OCS
{
public class OcsApiResponse<TOcsResponse> where TOcsResponse : IOcsResponse
{
[JsonProperty("ocs")]
public TOcsResponse? Ocs { get; set; }
}
}

View File

@@ -12,32 +12,32 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses.Cloud
public class ResponseQuota public class ResponseQuota
{ {
[JsonProperty("free")] [JsonProperty("free")]
public ulong? Free { get; set; } public long? Free { get; set; }
[JsonProperty("used")] [JsonProperty("used")]
public ulong? Used { get; set; } public long? Used { get; set; }
[JsonProperty("total")] [JsonProperty("total")]
public ulong? Total { get; set; } public long? Total { get; set; }
[JsonProperty("relative")] [JsonProperty("relative")]
public float? Relative { get; set; } public float? Relative { get; set; }
[JsonProperty("quota")] [JsonProperty("quota")]
public ulong? Quota { get; set; } public long? Quota { get; set; }
} }
public class ResponseBackendCapabilities public class ResponseBackendCapabilities
{ {
[JsonProperty("setDisplayName")] [JsonProperty("setDisplayName")]
public int? SetDisplayName { get; set; } public bool? SetDisplayName { get; set; }
[JsonProperty("setPassword")] [JsonProperty("setPassword")]
public int? SetPassword { get; set; } public bool? SetPassword { get; set; }
} }
[JsonProperty("enabled")] [JsonProperty("enabled")]
public int? Enabled { get; set; } public bool? Enabled { get; set; }
[JsonProperty("storageLocation")] [JsonProperty("storageLocation")]
public string? StorageLocation { get; set; } public string? StorageLocation { get; set; }
@@ -46,7 +46,7 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses.Cloud
public string? ID { get; set; } public string? ID { get; set; }
[JsonProperty("lastLogin")] [JsonProperty("lastLogin")]
public ulong? LastLogin { get; set; } public long? LastLogin { get; set; }
[JsonProperty("backend")] [JsonProperty("backend")]
public string? Backend { get; set; } public string? Backend { get; set; }

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses
{
public interface IOcsResponse
{
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses
{
public interface IOcsResponseMeta
{
}
}

View File

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses
{ {
public class OcsResponse<TMeta, TData> where TMeta : OcsResponseMeta where TData : IOcsResponseData public class OcsResponse<TMeta, TData> : IOcsResponse where TMeta : IOcsResponseMeta where TData : IOcsResponseData
{ {
[JsonProperty("meta")] [JsonProperty("meta")]
public TMeta? Meta { get; set; } public TMeta? Meta { get; set; }
@@ -20,7 +20,7 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses
{ {
} }
public class OcsResponse : OcsResponse<OcsResponseMeta, IOcsResponseData> public class OcsResponse : OcsResponse<OcsResponseMeta, OcsResponseData>
{ {
} }
} }

View File

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses
{ {
public class OcsResponseMeta public class OcsResponseMeta : IOcsResponseMeta
{ {
[JsonProperty("status")] [JsonProperty("status")]
public string? Status { get; set; } public string? Status { get; set; }

View File

@@ -9,7 +9,7 @@
<PropertyGroup> <PropertyGroup>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<IncrementVersionOnBuild>1.yyyy.Mdd.Hmm</IncrementVersionOnBuild> <IncrementVersionOnBuild>1.yyyy.Mdd.Hmm</IncrementVersionOnBuild>
<Version>1.2023.1001.1650</Version> <Version>1.2023.1002.1520</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>