chore: initial commit
This commit is contained in:
14
src/Exceptions/PaymoApiException.cs
Normal file
14
src/Exceptions/PaymoApiException.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace Novaloop.PaymoApi.Exceptions
|
||||
{
|
||||
public class PaymoApiException : Exception
|
||||
{
|
||||
public PaymoApiException(int statusCode, string message) : base($"[{statusCode}]: {message})")
|
||||
{
|
||||
StatusCode = statusCode;
|
||||
}
|
||||
|
||||
public int StatusCode { get; }
|
||||
}
|
||||
}
|
||||
37
src/Extensions/HttpClientExtensions.cs
Normal file
37
src/Extensions/HttpClientExtensions.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Novaloop.PaymoApi.Extensions
|
||||
{
|
||||
internal static class HttpClientExtensions
|
||||
{
|
||||
internal static void SetApiKeyHeader(this HttpClient client, string apiKey)
|
||||
{
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Base64Encode($"{apiKey}:random"));
|
||||
}
|
||||
|
||||
internal static async Task<HttpResponseMessage> PatchAsync(this HttpClient client, string uri, HttpContent content)
|
||||
{
|
||||
var method = new HttpMethod("PATCH");
|
||||
if (client.BaseAddress is null)
|
||||
{
|
||||
throw new ArgumentException("Can not handle 'BaseAddress' null value configuration.");
|
||||
}
|
||||
|
||||
var request = new HttpRequestMessage(method, new Uri(CombineBaseUrlWithSegment(client.BaseAddress.ToString(), uri))) {Content = content};
|
||||
return await client.SendAsync(request);
|
||||
}
|
||||
|
||||
private static string CombineBaseUrlWithSegment(string uri1, string uri2)
|
||||
{
|
||||
return $"{uri1.TrimEnd('/')}/{uri2.TrimStart('/')}";
|
||||
}
|
||||
|
||||
private static string Base64Encode(string plainText)
|
||||
{
|
||||
return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(plainText));
|
||||
}
|
||||
}
|
||||
}
|
||||
17
src/Extensions/HttpResponseMessageExtensions.cs
Normal file
17
src/Extensions/HttpResponseMessageExtensions.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Novaloop.PaymoApi.Exceptions;
|
||||
|
||||
namespace Novaloop.PaymoApi.Extensions
|
||||
{
|
||||
internal static class HttpResponseMessageExtensions
|
||||
{
|
||||
internal static async Task ThrowExceptionWithDetailsIfUnsuccessful(this HttpResponseMessage response)
|
||||
{
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
throw new PaymoApiException((int) response.StatusCode, await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/Extensions/PaymoApiExtensions.cs
Normal file
20
src/Extensions/PaymoApiExtensions.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Novaloop.PaymoApi.Shared;
|
||||
using Novaloop.PaymoApi.Tasks;
|
||||
|
||||
namespace Novaloop.PaymoApi.Extensions
|
||||
{
|
||||
public static class PaymoApiExtensions
|
||||
{
|
||||
public static IServiceCollection AddPaymoApi(this IServiceCollection services, Action<PaymoApiOptions> options)
|
||||
{
|
||||
services.Configure(options);
|
||||
var resolvedOptions = (IOptions<PaymoApiOptions>) services.BuildServiceProvider().GetService(typeof(IOptions<PaymoApiOptions>));
|
||||
services.AddHttpClient<PaymoApiClient>(client => { client.BaseAddress = new Uri(resolvedOptions.Value.BaseUrl); });
|
||||
services.AddTransient<IPaymoTasksApiService, PaymoTasksApiService>();
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
8
src/Extensions/PaymoApiOptions.cs
Normal file
8
src/Extensions/PaymoApiOptions.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Novaloop.PaymoApi.Extensions
|
||||
{
|
||||
public class PaymoApiOptions
|
||||
{
|
||||
public string BaseUrl { get; set; } = "https://app.paymoapp.com/api";
|
||||
public string ApiToken { get; set; }
|
||||
}
|
||||
}
|
||||
19
src/Novaloop.PaymoApi.csproj
Normal file
19
src/Novaloop.PaymoApi.csproj
Normal file
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<PackageId>Novaloop.PaymoApi</PackageId>
|
||||
<title>Access your paymo instance for asp.net core</title>
|
||||
<PackageTags>api;paymo;asp.net core;</PackageTags>
|
||||
<Version>0.1.0</Version>
|
||||
<Authors>Matthias Langhard</Authors>
|
||||
<Company>Novaloop AG</Company>
|
||||
<PackageProjectUrl>https://gitlab.com/novaloop-oss/novaloop.paymoapi</PackageProjectUrl>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
14
src/Shared/PaymoApiClient.cs
Normal file
14
src/Shared/PaymoApiClient.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Novaloop.PaymoApi.Shared
|
||||
{
|
||||
public class PaymoApiClient
|
||||
{
|
||||
public PaymoApiClient(HttpClient client)
|
||||
{
|
||||
Client = client;
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
}
|
||||
}
|
||||
11
src/Tasks/IPaymoTasksApiService.cs
Normal file
11
src/Tasks/IPaymoTasksApiService.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.Threading.Tasks;
|
||||
using Novaloop.PaymoApi.Tasks.Models;
|
||||
|
||||
namespace Novaloop.PaymoApi.Tasks
|
||||
{
|
||||
public interface IPaymoTasksApiService
|
||||
{
|
||||
Task<GetTasksResponse> GetTask(int taskId);
|
||||
Task<CreateTaskResponse> CreateTask(CreateTaskRequest createTask);
|
||||
}
|
||||
}
|
||||
12
src/Tasks/Models/CreateTaskRequest.cs
Normal file
12
src/Tasks/Models/CreateTaskRequest.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Novaloop.PaymoApi.Tasks.Models
|
||||
{
|
||||
public class CreateTaskRequest
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public int TasklistId { get; set; }
|
||||
public List<int> Users { get; set; }
|
||||
}
|
||||
}
|
||||
7
src/Tasks/Models/CreateTaskResponse.cs
Normal file
7
src/Tasks/Models/CreateTaskResponse.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Novaloop.PaymoApi.Tasks.Models
|
||||
{
|
||||
public class CreateTaskResponse : PaymoTask
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
9
src/Tasks/Models/GetTasksResponse.cs
Normal file
9
src/Tasks/Models/GetTasksResponse.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Novaloop.PaymoApi.Tasks.Models
|
||||
{
|
||||
public class GetTasksResponse
|
||||
{
|
||||
public IEnumerable<PaymoTask> Tasks { get; set; }
|
||||
}
|
||||
}
|
||||
25
src/Tasks/Models/PaymoTask.cs
Normal file
25
src/Tasks/Models/PaymoTask.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Novaloop.PaymoApi.Tasks.Models
|
||||
{
|
||||
public class PaymoTask
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Code { get; set; }
|
||||
public int ProjectId { get; set; }
|
||||
public int TasklistId { get; set; }
|
||||
public int UserId { get; set; }
|
||||
public bool Complete { get; set; }
|
||||
public bool Billable { get; set; }
|
||||
public int Seq { get; set; }
|
||||
public string Description { get; set; }
|
||||
public object PricePerHour { get; set; }
|
||||
public object DueDate { get; set; }
|
||||
public object BudgetHours { get; set; }
|
||||
public List<int> Users { get; set; }
|
||||
public DateTime CreatedOn { get; set; }
|
||||
public DateTime UpdatedOn { get; set; }
|
||||
}
|
||||
}
|
||||
44
src/Tasks/PaymoTasksApiService.cs
Normal file
44
src/Tasks/PaymoTasksApiService.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Novaloop.PaymoApi.Extensions;
|
||||
using Novaloop.PaymoApi.Shared;
|
||||
using Novaloop.PaymoApi.Tasks.Models;
|
||||
|
||||
namespace Novaloop.PaymoApi.Tasks
|
||||
{
|
||||
public class PaymoTasksApiService : IPaymoTasksApiService
|
||||
{
|
||||
private readonly PaymoApiOptions _options;
|
||||
private readonly HttpClient _client;
|
||||
|
||||
public PaymoTasksApiService(PaymoApiClient paymoApiClient, IOptions<PaymoApiOptions> options)
|
||||
{
|
||||
_options = options.Value;
|
||||
_client = paymoApiClient.Client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an existing Task
|
||||
/// </summary>
|
||||
public async Task<GetTasksResponse> GetTask(int taskId)
|
||||
{
|
||||
_client.SetApiKeyHeader(_options.ApiToken);
|
||||
var response = await _client.GetAsync($"/tasks/{taskId}");
|
||||
await response.ThrowExceptionWithDetailsIfUnsuccessful();
|
||||
return await response.Content.ReadAsAsync<GetTasksResponse>();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Task
|
||||
/// </summary>
|
||||
public async Task<CreateTaskResponse> CreateTask(CreateTaskRequest createTaskRequest)
|
||||
{
|
||||
_client.SetApiKeyHeader(_options.ApiToken);
|
||||
var response = await _client.PostAsJsonAsync("/tasks", createTaskRequest);
|
||||
await response.ThrowExceptionWithDetailsIfUnsuccessful();
|
||||
return await response.Content.ReadAsAsync<CreateTaskResponse>();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user