Skip to content

Commit b54679f

Browse files
authoredAug 23, 2018
Merge pull request #1 from PowerDMS/chiho/some-updates
initial changes to make it work
2 parents 78b5868 + a7dcd48 commit b54679f

22 files changed

+451
-83
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>netcoreapp2.0</TargetFramework>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.1" />
10+
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.1.1" />
11+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<ProjectReference Include="..\..\PowerDms.Api.Rest.Client\PowerDms.Api.Rest.Client\PowerDms.Api.Rest.Client.csproj" />
16+
<ProjectReference Include="..\..\PowerDms.Api.Rest.Client\PowerDms.Api.Rest.Dto\PowerDms.Api.Rest.Dto.csproj" />
17+
</ItemGroup>
18+
19+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using System;
2+
using System.Linq;
3+
using System.Threading.Tasks;
4+
using Microsoft.Extensions.Configuration;
5+
using PowerDms.Api.Rest.Client;
6+
using PowerDms.Api.Rest.Dto;
7+
8+
namespace DemoConsoleApp
9+
{
10+
class Program
11+
{
12+
static void Main(string[] args)
13+
{
14+
// because there is no async Main until c# 7
15+
try
16+
{
17+
DoDemo().Wait();
18+
}
19+
catch (Exception e)
20+
{
21+
Console.WriteLine(e);
22+
throw;
23+
}
24+
}
25+
26+
public static async Task DoDemo()
27+
{
28+
// do not check in credentials, copy the sample appsettings.json file here
29+
var appsettingsPath = "c:\\temp";
30+
var configuration = new ConfigurationBuilder()
31+
.SetBasePath(appsettingsPath)
32+
.AddJsonFile("appsettings.json")
33+
.Build();
34+
35+
var credentials =
36+
new Credentials
37+
{
38+
SiteKey = configuration["Credentials:SiteKey"],
39+
Username = configuration["Credentials:Username"],
40+
Password = configuration["Credentials:Password"],
41+
ClientSecret = configuration["Credentials:ClientSecret"]
42+
};
43+
44+
var requestManager =
45+
new HttpRequestManagerBuilder()
46+
.SetApiHost(configuration["Host"]) // only needed if not using public PowerDMS API
47+
.SetOAuthHost(configuration["Host"]) // only needed if not using public PowerDMS API
48+
.Build(credentials);
49+
50+
var newGroup = new GroupDto
51+
{
52+
Name = "ApiCreated" + Guid.NewGuid()
53+
};
54+
55+
var createdGroup = await NewGroup(requestManager, newGroup);
56+
57+
Console.WriteLine($" ID: {createdGroup.Id}");
58+
Console.WriteLine($" Name: {createdGroup.Name}");
59+
60+
var getItAgain = await GetGroup(requestManager, createdGroup.Id);
61+
62+
var getBogusOne = await GetGroup(requestManager, "0");
63+
64+
Console.WriteLine("-- press any key to exit --");
65+
Console.ReadKey();
66+
}
67+
68+
private static async Task<GroupDto> GetGroup(HttpRequestManager requestManager, string groupId)
69+
{
70+
// I don't like the fact credentials need to be set on each builder, why not in the manager?
71+
var requestBuilder = requestManager.PowerDmsRestApiClient.Groups
72+
.GetGroupRequestBuilder(groupId);
73+
74+
var result = await requestManager
75+
.SendAsync(requestBuilder)
76+
.AwaitGetServiceResponse<GroupDto>();
77+
78+
if (!result.IsSuccessful)
79+
{
80+
Console.WriteLine($"-- Error! Code: {result.Error.Code}, Message: {result.Error.Messages?.FirstOrDefault()} --");
81+
return null;
82+
}
83+
84+
return result.Data;
85+
}
86+
87+
private static async Task<GroupDto> NewGroup(HttpRequestManager requestManager, GroupDto groupDto)
88+
{
89+
var requestBuilder = requestManager.PowerDmsRestApiClient.Groups
90+
.PostGroupRequestBuilder(groupDto);
91+
92+
var result = await requestManager
93+
.SendAsync(requestBuilder)
94+
.AwaitGetServiceResponse<GroupDto>();
95+
96+
if (!result.IsSuccessful)
97+
{
98+
Console.WriteLine($"-- Error! Code: {result.Error.Code}, Message: {result.Error.Messages?.FirstOrDefault()} --");
99+
return null;
100+
}
101+
102+
return result.Data;
103+
}
104+
}
105+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"Host": "https://api.powerdms.com",
3+
"Credentials": {
4+
"SiteKey": "SiteKey",
5+
"Username": "Username",
6+
"Password": "****",
7+
"ClientSecret": "****"
8+
}
9+
}

‎PowerDms.Api.Rest.Client/PowerDms.Api.Rest.Client.sln

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 15
4-
VisualStudioVersion = 15.0.27004.2008
4+
VisualStudioVersion = 15.0.27130.2024
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerDms.Api.Rest.Client", "PowerDms.Api.Rest.Client\PowerDms.Api.Rest.Client.csproj", "{52E79D0A-1E1C-47E4-B8C7-7A6888E73AC3}"
77
EndProject
88
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerDms.Api.Rest.Dto", "PowerDms.Api.Rest.Dto\PowerDms.Api.Rest.Dto.csproj", "{82C847A5-BD6B-4C02-A798-9F3E929368F6}"
99
EndProject
10+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DemoConsoleApp", "..\PowerDms.Api.Rest.Client.Demo\DemoConsoleApp\DemoConsoleApp.csproj", "{4DF7714E-2E85-4183-8BC4-B5519606F2E6}"
11+
EndProject
1012
Global
1113
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1214
Debug|Any CPU = Debug|Any CPU
@@ -21,6 +23,10 @@ Global
2123
{82C847A5-BD6B-4C02-A798-9F3E929368F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
2224
{82C847A5-BD6B-4C02-A798-9F3E929368F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
2325
{82C847A5-BD6B-4C02-A798-9F3E929368F6}.Release|Any CPU.Build.0 = Release|Any CPU
26+
{4DF7714E-2E85-4183-8BC4-B5519606F2E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{4DF7714E-2E85-4183-8BC4-B5519606F2E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{4DF7714E-2E85-4183-8BC4-B5519606F2E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{4DF7714E-2E85-4183-8BC4-B5519606F2E6}.Release|Any CPU.Build.0 = Release|Any CPU
2430
EndGlobalSection
2531
GlobalSection(SolutionProperties) = preSolution
2632
HideSolutionNode = FALSE
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.Collections.Generic;
1+
using System.Net.Http.Headers;
22
using System.Threading.Tasks;
33
using PowerDms.Api.Rest.Client.Clients;
44
using PowerDms.Api.Rest.Dto;
@@ -7,34 +7,35 @@ namespace PowerDms.Api.Rest.Client
77
{
88
public class AuthenticationTokenProvider : IAuthenticationTokenProvider
99
{
10-
private readonly OAuthClient _OAuthClient;
10+
// TODO: must implement token refreshing at some point
1111

12-
private readonly string _OAuthClientSecret;
12+
private readonly OAuthClient _oAuthClient;
1313

14-
private IDictionary<Credentials, string> _CachedCredentials;
14+
private readonly Credentials _credentials;
1515

16-
public AuthenticationTokenProvider(
17-
OAuthClient oAuthClient,
18-
string oAuthClientSecret)
16+
private OAuthAuthorizationDto _authAuthorization;
17+
18+
public AuthenticationTokenProvider(OAuthClient oAuthClient, Credentials credentials)
1919
{
20-
_OAuthClient = oAuthClient;
21-
_OAuthClientSecret = oAuthClientSecret;
22-
_CachedCredentials = new Dictionary<Credentials, string>();
20+
_oAuthClient = oAuthClient;
21+
_credentials = credentials;
2322
}
2423

25-
public async Task<string> GetAccessToken(Credentials credentials)
24+
public async Task<AuthenticationHeaderValue> GetAccessToken()
2625
{
27-
if (_CachedCredentials.ContainsKey(credentials))
26+
if (_authAuthorization?.access_token == null)
2827
{
29-
return _CachedCredentials[credentials];
28+
var response = await _oAuthClient.GetAccessToken(
29+
_credentials.Username,
30+
_credentials.Password,
31+
_credentials.SiteKey,
32+
_credentials.ClientSecret
33+
);
34+
35+
_authAuthorization = await response.GetContent<OAuthAuthorizationDto>();
3036
}
3137

32-
return await (await _OAuthClient.GetAccessToken(
33-
credentials.Username,
34-
credentials.Password,
35-
credentials.SiteKey,
36-
_OAuthClientSecret
37-
)).GetContent<string>();
38+
return new AuthenticationHeaderValue("Bearer", _authAuthorization.access_token);
3839
}
3940
}
4041
}

‎PowerDms.Api.Rest.Client/PowerDms.Api.Rest.Client/Clients/GroupsClient.cs

+5-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ namespace PowerDms.Api.Rest.Client.Clients
77

88
public class GroupsClient
99
{
10+
/// <summary>
11+
/// I think this is going away, Manager will handle the sending
12+
/// </summary>
1013
private readonly HttpClient _HttpClient;
1114

1215
public GroupsClient(HttpClient httpClient)
@@ -40,8 +43,8 @@ public HttpRequestMessage PostGroupRequest(GroupDto groupDto)
4043
}
4144
public HttpRequestBuilder<GroupDto> PostGroupRequestBuilder(GroupDto groupDto)
4245
{
43-
return new HttpRequestBuilder<GroupDto>(
44-
PostGroupRequest(groupDto));
46+
return new HttpRequestBuilder<GroupDto>(PostGroupRequest(groupDto))
47+
.AddJsonBody(groupDto);
4548
}
4649
}
4750
}

‎PowerDms.Api.Rest.Client/PowerDms.Api.Rest.Client/Clients/OAuthClient.cs

+3-4
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,9 @@ public Task<HttpResponseMessage> GetAccessToken(
2222
string siteKey,
2323
string oauthClientSecret)
2424
{
25-
var httpRequestMessage = new HttpRequestMessage
26-
{
27-
Method = HttpMethod.Post
28-
};
25+
var httpRequestMessage = new HttpRequestMessage(
26+
HttpMethod.Post,
27+
RestApiRoutes.OAuthAccessToken);
2928

3029
httpRequestMessage.Headers.Authorization =
3130
new AuthenticationHeaderValue(

‎PowerDms.Api.Rest.Client/PowerDms.Api.Rest.Client/HttpRequestBuilder.cs

+13-7
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,31 @@
11
using System.Net.Http;
2+
using System.Text;
3+
using Newtonsoft.Json;
24

35
namespace PowerDms.Api.Rest.Client
46
{
5-
using PowerDms.Api.Rest.Dto;
6-
77
public class HttpRequestBuilder<TResponse>
88
{
9-
public HttpRequestMessage HttpRequestMessage;
9+
// TODO: replace this when .net std 2.1 is out:
10+
// https://github.com/dotnet/corefx/issues/26201
11+
private static string _applicationJson = "application/json";
1012

11-
public Credentials Credentials;
13+
public HttpRequestMessage HttpRequestMessage;
14+
15+
public object Body { get; private set; }
1216

1317
public HttpRequestBuilder(
1418
HttpRequestMessage httpRequestMessage)
1519
{
1620
HttpRequestMessage = httpRequestMessage;
1721
}
1822

19-
public HttpRequestBuilder<TResponse> AuthenticateWith(
20-
Credentials credentials)
23+
public HttpRequestBuilder<TResponse> AddJsonBody(object body)
2124
{
22-
Credentials = credentials;
25+
// NOTE: I defined this here instead of using an extension method, because FakeItEasy can't fake extension methods
26+
Body = body;
27+
var json = JsonConvert.SerializeObject(body);
28+
HttpRequestMessage.Content = new StringContent(json, Encoding.UTF8, _applicationJson);
2329
return this;
2430
}
2531
}

‎PowerDms.Api.Rest.Client/PowerDms.Api.Rest.Client/HttpRequestManager.cs

+12-17
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,37 @@
11
using System.Net.Http;
22
using System.Threading.Tasks;
33
using PowerDms.Api.Rest.Client.Clients;
4+
using PowerDms.Api.Rest.Dto;
45

56
namespace PowerDms.Api.Rest.Client
67
{
78
public class HttpRequestManager
89
{
9-
private readonly HttpClient _HttpClient;
10+
private readonly HttpClient _httpClient;
1011

1112
public readonly PowerDmsRestApiClient PowerDmsRestApiClient;
1213

13-
private readonly IAuthenticationTokenProvider _AuthenticationTokenProvider;
14+
private readonly IAuthenticationTokenProvider _authenticationTokenProvider;
1415

15-
public HttpRequestManager(
16-
HttpClient httpClient,
17-
AuthenticationTokenProvider authenticationTokenProvider)
16+
public HttpRequestManager(HttpClient httpClient, IAuthenticationTokenProvider authenticationTokenProvider)
1817
{
19-
_HttpClient = httpClient;
18+
_httpClient = httpClient;
2019
PowerDmsRestApiClient = new PowerDmsRestApiClient(httpClient);
21-
_AuthenticationTokenProvider = authenticationTokenProvider;
20+
_authenticationTokenProvider = authenticationTokenProvider;
2221
}
2322

24-
public async Task<HttpResponseMessage> SendAsync<T>(HttpRequestBuilder<T> httpRequestBuilder)
23+
public virtual async Task<HttpResponseMessage> SendAsync<T>(HttpRequestBuilder<T> httpRequestBuilder)
2524
{
25+
// virtual to facilitate faking during unit testing
2626
await AddAuthentication(httpRequestBuilder);
27-
return await _HttpClient.SendAsync(httpRequestBuilder.HttpRequestMessage);
27+
return await _httpClient.SendAsync(httpRequestBuilder.HttpRequestMessage);
2828
}
2929

3030
private async Task<HttpRequestBuilder<T>> AddAuthentication<T>(
3131
HttpRequestBuilder<T> httpRequestBuilder)
3232
{
33-
if (httpRequestBuilder.Credentials != null)
34-
{
35-
httpRequestBuilder.HttpRequestMessage
36-
.AddAccessToken(
37-
await _AuthenticationTokenProvider.GetAccessToken(httpRequestBuilder.Credentials));
38-
39-
}
33+
httpRequestBuilder.HttpRequestMessage
34+
.AddAccessToken(await _authenticationTokenProvider.GetAccessToken());
4035

4136
return httpRequestBuilder;
4237
}
@@ -48,7 +43,7 @@ public async Task<TResponse> GetSuccessfulResponse<TResponse>(
4843
.AwaitGetSuccessfulResponse<TResponse>();
4944
}
5045

51-
public async Task<TError> GetErrorResponse<TResponse, TError>(
46+
public async Task<ErrorDto> GetErrorResponse<TResponse, TError>(
5247
HttpRequestBuilder<TResponse> httpRequestBuilder)
5348
{
5449
return await SendAsync(httpRequestBuilder)

0 commit comments

Comments
 (0)