huge work for nextcloud api

This commit is contained in:
2023-10-01 16:51:10 +02:00
parent c87c117c94
commit 16ca4ecbb6
27 changed files with 472 additions and 87 deletions

View File

@@ -2,5 +2,6 @@
<configuration>
<packageSources>
<add key="Telerik UI for WinForms 2023.1.117" value="C:\Program Files (x86)\Progress\Telerik UI for WinForms R1 2023\Bin60\NuGet" />
<add key="Telerik UI for WinForms UI.for.WinForms.AllControls.Net60.2023.2.718" value="C:\Program Files (x86)\Progress\Telerik UI for WinForms R2 2023\Bin60\NuGet" />
</packageSources>
</configuration>

View File

@@ -0,0 +1,46 @@
using Pilz.Networking.CloudProviders.Nextcloud.Model.Apps.FilesRetention;
using Pilz.Networking.CloudProviders.Nextcloud.OCS.APIs.Apps;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.Client.Apps
{
public class FilesRetentionClient : ClientBase
{
public FilesRetentionClient(NextcloudClient client) : base(client)
{
}
public Task<bool> CreateRetentionRule(RetentionRule rule)
{
var entry = rule.ToOcsData();
return Client.Ocs.GetApi<OcsApiFilesRetention>().CreateRetentionRule(entry);
}
public Task<bool> DeleteRetentionRule(int ruleID)
{
return Client.Ocs.GetApi<OcsApiFilesRetention>().DeleteRetentionRule(ruleID);
}
public async Task<RetentionRule[]?> GetRetentionRules()
{
var api = Client.Ocs.GetApi<OcsApiFilesRetention>();
var response = await api.GetRetentionRules();
if (response?.Data is not null)
{
var rules = new List<RetentionRule>();
foreach (var entry in response.Data)
rules.Add(new RetentionRule(entry));
return rules.ToArray();
}
return null;
}
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.Client
{
public abstract class ClientBase
{
public NextcloudClient Client { get; init; }
public ClientBase(NextcloudClient client)
{
Client = client;
}
}
}

View File

@@ -0,0 +1,34 @@
using Pilz.Networking.CloudProviders.Nextcloud.Model.Cloud;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.Client
{
public class CloudClient : ClientBase
{
public CloudClient(NextcloudClient client) : base(client)
{
}
public Task<UserInfo?> GetUserInfo()
{
if (!string.IsNullOrEmpty(Client.CurrentLogin?.LoginName))
return GetUserInfo(Client.CurrentLogin.LoginName);
else
return Task.FromResult<UserInfo?>(null);
}
public async Task<UserInfo?> GetUserInfo(string username)
{
var result = await Client.Ocs.Cloud.GetUserMeta(username);
if (result?.Data != null)
return new UserInfo(result.Data);
return null;
}
}
}

View File

@@ -0,0 +1,73 @@
using Pilz.Networking.CloudProviders.Nextcloud.OCS.Data.Apps.FileRetention;
using Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses.Apps.FilesRetention;
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 RetentionRule
{
/// <summary>
/// The ID for the retention rule.
/// </summary>
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>
/// Defines if a background job has been generated
/// </summary>
public bool HasJob { get; init; }
public RetentionRule(int iD, int tagID, RetentionTimeUnit timeUnit, int timeAmount, RetentionTimeAfter timeAfter, bool hasJob)
{
ID = iD;
TagID = tagID;
TimeUnit = timeUnit;
TimeAmount = timeAmount;
TimeAfter = timeAfter;
HasJob = hasJob;
}
public RetentionRule(OcsResponseDataEntryRetention data)
{
ID = data.ID ?? -1;
TagID = data.TagID ?? -1;
TimeUnit = (RetentionTimeUnit)(data.TimeUnit ?? 0);
TimeAmount = data.TimeAmount ?? -1;
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,14 @@
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 enum RetentionTimeAfter
{
CreationDate,
LastAccess
}
}

View File

@@ -0,0 +1,16 @@
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 enum RetentionTimeUnit
{
Day,
Week,
Month,
Year
}
}

View File

@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.Model
namespace Pilz.Networking.CloudProviders.Nextcloud.Model.Cloud
{
public class UserBackendCapabilities
{

View File

@@ -5,84 +5,84 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.Model
namespace Pilz.Networking.CloudProviders.Nextcloud.Model.Cloud
{
public class UserInfo
{
/// <summary>
/// Defines if the user is enabled.
/// </summary>
public bool Enabled { get; set; }
public bool Enabled { get; init; }
/// <summary>
/// The location of the user's storage directory.
/// </summary>
public string? StorageLocation { get; set; }
public string? StorageLocation { get; init; }
/// <summary>
/// The uniquie user id that infos are for.
/// </summary>
public string? ID { get; set; }
public string? ID { get; init; }
/// <summary>
/// The last time when the user has logged in to its account.
/// </summary>
public DateTime LastLogin { get; set; }
public DateTime LastLogin { get; init; }
/// <summary>
/// The backend of the user. Common values are "Database" or "LDAP".
/// </summary>
public string? Backend { get; set; }
public string? Backend { get; init; }
/// <summary>
/// The Email address of the user.
/// </summary>
public string? Email { get; set; }
public string? Email { get; init; }
/// <summary>
/// The displayname of the user.
/// </summary>
public string? Displayname { get; set; }
public string? Displayname { get; init; }
/// <summary>
/// The displayname of the user.
/// </summary>
public string? Displayname2 { get; set; }
public string? Displayname2 { get; init; }
/// <summary>
/// The phone number of the user.
/// </summary>
public string? Phone { get; set; }
public string? Phone { get; init; }
/// <summary>
/// The address of the user.
/// </summary>
public string? Address { get; set; }
public string? Address { get; init; }
/// <summary>
/// The Website of the user.
/// </summary>
public string? Website { get; set; }
public string? Website { get; init; }
/// <summary>
/// The twitter profile name of the user.
/// </summary>
public string? Twitter { get; set; }
public string? Twitter { get; init; }
/// <summary>
/// Defines the groups the user is member of.
/// </summary>
public string[] Groups { get; set; }
public string[] Groups { get; init; }
/// <summary>
/// The configured language of the user.
/// </summary>
public string? Language { get; set; }
public string? Language { get; init; }
/// <summary>
/// The configured location of the user.
/// </summary>
public string? Locale { get; set; }
public string? Locale { get; init; }
/// <summary>
/// Quota informations for the user.

View File

@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.Model
namespace Pilz.Networking.CloudProviders.Nextcloud.Model.Cloud
{
public class UserQuota
{

View File

@@ -6,39 +6,62 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Pilz.Networking.CloudProviders.Nextcloud;
using Pilz.Networking.CloudProviders.Nextcloud.Client;
using Pilz.Networking.CloudProviders.Nextcloud.Model;
using Pilz.Networking.CloudProviders.Nextcloud.Model.Cloud;
using Pilz.Networking.CloudProviders.Nextcloud.OCS;
using Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses.LoginFlowV2;
namespace ConsoleApp9
namespace Pilz.Networking.CloudProviders.Nextcloud
{
public class NextcloudClient : IDisposable
{
private readonly OcsApi ocs = new();
private readonly List<ClientBase> clients = new();
public OcsApi Ocs { get; init; } = new();
public NextcloudLogin? CurrentLogin { get; private set; }
public CloudClient Cloud => GetClient<CloudClient>();
public NextcloudClient()
{
ocs.GetOcsApiAuthCredentails += Ocs_GetOcsApiAuthCredentails;
Ocs.GetOcsApiAuthCredentails += Ocs_GetOcsApiAuthCredentails;
}
private void Ocs_GetOcsApiAuthCredentails(object sender, GetOcsApiAuthCredentailsEventArgs eventArgs)
{
if (sender == ocs)
if (sender == Ocs)
eventArgs.Credentials = CurrentLogin.ToOcsApiAuthCredentials();
}
public async Task<UserInfo?> LoginAsync(NextcloudLogin login)
public TClient GetClient<TClient>() where TClient : ClientBase
{
var instance = TryGetClient<TClient>();
return instance is null ? throw new NullReferenceException() : instance;
}
public TClient? TryGetClient<TClient>() where TClient : ClientBase
{
TClient? instance = (TClient?)clients.FirstOrDefault(n => n is TClient);
instance ??= (TClient?)Activator.CreateInstance(typeof(TClient), new object[] { this });
if (instance is not null)
clients.Add(instance);
return instance;
}
public async Task<UserInfo?> Login(NextcloudLogin login)
{
// Ensure we are logged out
await LogoutAsync();
await Logout();
// Temporary set user login
CurrentLogin = login;
// Try get user info & check if user is enabled
var userInfo = await GetUserInfoAsync();
var userInfo = await Cloud.GetUserInfo();
var isValid = userInfo != null && userInfo.Enabled;
// If invalid, reset login credentials
@@ -48,13 +71,13 @@ namespace ConsoleApp9
return userInfo;
}
public async Task<NextcloudLogin?> LoginAsync(string baseUrl, CancellationToken cancellationToken)
public async Task<NextcloudLogin?> Login(string baseUrl, CancellationToken cancellationToken)
{
// Ensure we are logged out
await LogoutAsync();
await Logout();
// Init the login process
var initResponse = await ocs.LoginFlowV2.Init(baseUrl);
var initResponse = await Ocs.LoginFlowV2.Init(baseUrl);
if (!string.IsNullOrEmpty(initResponse?.LoginUrl) && initResponse.Poll != null)
{
@@ -74,7 +97,7 @@ namespace ConsoleApp9
// Poll the credentials
if (!cancellationToken.IsCancellationRequested)
pollResponse = await ocs.LoginFlowV2.Poll(initResponse.Poll);
pollResponse = await Ocs.LoginFlowV2.Poll(initResponse.Poll);
}
// Check login credentials
@@ -85,35 +108,18 @@ namespace ConsoleApp9
return CurrentLogin;
}
public Task<UserInfo?> GetUserInfoAsync()
public Task Logout()
{
if (!string.IsNullOrEmpty(CurrentLogin?.LoginName))
return GetUserInfoAsync(CurrentLogin.LoginName);
else
return Task.FromResult<UserInfo?>(null);
return Logout(true);
}
public async Task<UserInfo?> GetUserInfoAsync(string username)
{
var result = await ocs.Cloud.GetUserMeta(username);
if (result?.Data != null)
return new UserInfo(result.Data);
return null;
}
public Task LogoutAsync()
{
return LogoutAsync(true);
}
public async Task LogoutAsync(bool logoutOnServer)
public async Task Logout(bool logoutOnServer)
{
if (CurrentLogin != null)
{
// Delete currently used app password
await ocs.Core.DeleteAppPassword();
if (logoutOnServer)
await Ocs.Core.DeleteAppPassword();
// Reset current login infos
CurrentLogin = null;
@@ -122,7 +128,7 @@ namespace ConsoleApp9
public void Dispose()
{
ocs.Dispose();
Ocs.Dispose();
GC.SuppressFinalize(this);
}
}

View File

@@ -0,0 +1,39 @@
using Pilz.Networking.CloudProviders.Nextcloud.OCS.Data.Apps.FileRetention;
using Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses;
using Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses.Apps.FilesRetention;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.APIs.Apps
{
public class OcsApiFilesRetention : OcsApiBase
{
public static readonly OcsApiUrlPath OCS_FILE_RETENTION_RULES = new("/ocs/v2.php/apps/files_retention/api/v1/retentions");
public static readonly OcsApiUrlPath OCS_FILE_RETENTION_RULE = new("/ocs/v2.php/apps/files_retention/api/v1/retentions/{0}");
public OcsApiFilesRetention(OcsApi manager) : base(manager)
{
}
public async Task<bool> CreateRetentionRule(OcsDataRetentionRule rule)
{
var response = await Manager.MakeRequest(HttpMethod.Put, OCS_FILE_RETENTION_RULES, content: rule);
return response.IsSuccessStatusCode;
}
public async Task<bool> DeleteRetentionRule(int ruleID)
{
var response = await Manager.MakeRequest(HttpMethod.Delete, OCS_FILE_RETENTION_RULE.FillParameters(ruleID));
return response.IsSuccessStatusCode;
}
public Task<OcsResponseRetention?> GetRetentionRules()
{
return Manager.MakeRequest<OcsResponseRetention>(HttpMethod.Get, OCS_FILE_RETENTION_RULES);
}
}
}

View File

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

View File

@@ -17,7 +17,7 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.APIs
public Task<OcsResponseLoginFlowV2?> Init(string url)
{
return Manager.MakeRequestJson<OcsResponseLoginFlowV2>(HttpMethod.Get, url + OCS_LOGIN_INIT);
return Manager.MakeRequest<OcsResponseLoginFlowV2>(HttpMethod.Get, url + OCS_LOGIN_INIT);
}
public Task<OcsResponseLoginFlowV2Credentials?> Poll(OcsResponseLoginFlowV2.PollData poll)
@@ -25,7 +25,7 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.APIs
ArgumentNullException.ThrowIfNull(poll?.Endpoint);
ArgumentNullException.ThrowIfNull(poll?.Token);
return Manager.MakeRequestJson<OcsResponseLoginFlowV2Credentials?>(HttpMethod.Get, poll.Endpoint,
return Manager.MakeRequest<OcsResponseLoginFlowV2Credentials?>(HttpMethod.Get, poll.Endpoint,
parameters: new Dictionary<string, string>
{
{ "token", poll.Token }

View File

@@ -0,0 +1,25 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.Data.Apps.FileRetention
{
public class OcsDataRetentionRule : OcsData
{
[JsonProperty("tagid")]
public int? TagID { get; set; }
[JsonProperty("timeunit")]
public int? TimeUnit { get; set; }
[JsonProperty("timeamount")]
public int? TimeAmount { get; set; }
[JsonProperty("timeafter")]
public int? TimeAfter { 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.Data
{
public class OcsData
{
}
}

View File

@@ -8,26 +8,42 @@ using Newtonsoft.Json;
using System.Diagnostics;
using System.Net;
using Pilz.Networking.CloudProviders.Nextcloud.OCS.APIs;
using System.Net.Sockets;
using Pilz.Networking.CloudProviders.Nextcloud.OCS.Data;
namespace Pilz.Networking.CloudProviders.Nextcloud.OCS
{
public class OcsApi : IDisposable
{
public const string CONTENT_TYPE_JSON = "application/json";
public event GetOcsApiAuthCredentailsEventHandler? GetOcsApiAuthCredentails;
private readonly HttpClient client = new();
private readonly List<OcsApiBase> apis = new();
public string BaseUrl { get; set; } = string.Empty;
public OcsApiLoginFlowV2 LoginFlowV2 { get; init; }
public OcsApiCore Core { get; init; }
public OcsApiCloud Cloud { get; init; }
public OcsApiLoginFlowV2 LoginFlowV2 => GetApi<OcsApiLoginFlowV2>();
public OcsApiCore Core => GetApi<OcsApiCore>();
public OcsApiCloud Cloud => GetApi<OcsApiCloud>();
public OcsApi()
public TApi GetApi<TApi>() where TApi : OcsApiBase
{
LoginFlowV2 = new(this);
Core = new(this);
Cloud = new(this);
var instance = TryGetApi<TApi>();
return instance is null ? throw new NullReferenceException() : instance;
}
public TApi? TryGetApi<TApi>() where TApi : OcsApiBase
{
TApi? instance = (TApi?)apis.FirstOrDefault(n => n is TApi);
instance ??= (TApi?)Activator.CreateInstance(typeof(TApi), new object[] { this });
if (instance is not null)
apis.Add(instance);
return instance;
}
public string BuildFullUrl(OcsApiUrlPath path)
@@ -35,19 +51,19 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS
return BaseUrl + path;
}
public Task<TResponse?> MakeRequestJson<TResponse>(HttpMethod httpMethod, OcsApiUrlPath url, bool useAuthentication = true, Dictionary<string, string>? parameters = null)
public Task<TResponse?> MakeRequest<TResponse>(HttpMethod httpMethod, OcsApiUrlPath url, bool useAuthentication = true, Dictionary<string, string>? parameters = null, object? content = null)
{
return MakeRequestJson<TResponse>(httpMethod, BuildFullUrl(url), useAuthentication: useAuthentication, parameters: parameters);
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)
public Task<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);
return MakeRequest(httpMethod, BuildFullUrl(url), useAuthentication: useAuthentication, parameters: parameters, content: content);
}
public async Task<TResponse?> MakeRequestJson<TResponse>(HttpMethod httpMethod, string url, bool useAuthentication = true, Dictionary<string, string>? parameters = null)
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);
using var responseInit = await MakeRequest(httpMethod, url, useAuthentication: useAuthentication, parameters: parameters, content: content);
if (responseInit != null)
{
@@ -58,10 +74,11 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS
return default;
}
public async Task<HttpResponseMessage> MakeRequest(HttpMethod httpMethod, string url, bool useAuthentication = true, Dictionary<string, string>? parameters = null)
public async Task<HttpResponseMessage> MakeRequest(HttpMethod httpMethod, string url, bool useAuthentication = true, Dictionary<string, string>? parameters = null, object? content = null)
{
OcsApiAuthCredentials? authentication;
string @params;
HttpContent? httpContent;
// Get authentication
if (useAuthentication)
@@ -79,6 +96,14 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS
else
@params = string.Empty;
// Create content
if (content is HttpContent contentHttp)
httpContent = contentHttp;
else if (content is OcsData)
httpContent = new StringContent(JsonConvert.SerializeObject(content), null, CONTENT_TYPE_JSON);
else
httpContent = null;
// Send request
var request = new HttpRequestMessage
{
@@ -86,10 +111,11 @@ namespace Pilz.Networking.CloudProviders.Nextcloud.OCS
RequestUri = new Uri(url + @params),
Headers =
{
{ "Accept", "application/json" },
{ "Accept", CONTENT_TYPE_JSON },
{ "OCS-APIREQUEST", "true" },
{ "Authorization", authentication.ToBasicAuth() }
},
Content = httpContent
};
return await client.SendAsync(request);

View File

@@ -0,0 +1,30 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses.Apps.FilesRetention
{
public class OcsResponseDataEntryRetention : OcsResponseDataEntry
{
[JsonProperty("id")]
public int? ID { get; set; }
[JsonProperty("tagid")]
public int? TagID { get; set; }
[JsonProperty("timeunit")]
public int? TimeUnit { get; set; }
[JsonProperty("timeamount")]
public int? TimeAmount { get; set; }
[JsonProperty("timeafter")]
public int? TimeAfter { get; set; }
[JsonProperty("hasJob")]
public bool? HasJob { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses.Apps.FilesRetention
{
public class OcsResponseRetention : OcsResponse<OcsResponseDataArray<OcsResponseDataEntryRetention>>
{
}
}

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 IOcsResponseData
{
}
}

View File

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

View File

@@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace Pilz.Networking.CloudProviders.Nextcloud.OCS.Responses
{
public class OcsResponseData
public class OcsResponseData : IOcsResponseData
{
}
}

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 class OcsResponseDataArray<TEntry> : List<TEntry>, IOcsResponseData where TEntry : OcsResponseDataEntry
{
}
}

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 class OcsResponseDataEntry
{
}
}

View File

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

View File

@@ -1,21 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Pilz.UI.Telerik</RootNamespace>
</PropertyGroup>
<PropertyGroup>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<IncrementVersionOnBuild>1.yyyy.Mdd.Hmm</IncrementVersionOnBuild>
<Version>1.2023.914.1955</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
<PackageReference Include="UI.for.WinForms.AllControls.Net60" Version="2023.1.117" />
<PackageReference Include="UI.for.WinForms.AllControls.Net60">
<Version>2023.2.718</Version>
</PackageReference>
</ItemGroup>
</Project>

View File

@@ -1,20 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<PropertyGroup>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<IncrementVersionOnBuild>1.yyyy.Mdd.Hmm</IncrementVersionOnBuild>
<Version>1.2023.914.856</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="UI.for.WinForms.AllControls.Net60" Version="2023.1.117" />
<PackageReference Include="UI.for.WinForms.AllControls.Net60">
<Version>2023.2.718</Version>
</PackageReference>
</ItemGroup>
</Project>