Skip to content

Commit 0120878

Browse files
author
gauffininteractive
committed
Finalized api keys
1 parent fe20724 commit 0120878

File tree

21 files changed

+205
-104
lines changed

21 files changed

+205
-104
lines changed

src/Server/OneTrueError.Api.Client/OneTrueClient.cs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,25 @@ namespace OneTrueError.Api.Client
1212
/// <summary>
1313
/// Client for the OneTrueError server API
1414
/// </summary>
15-
public class OneTrueClient : IQueryBus, ICommandBus, IEventBus
15+
public class OneTrueApiClient : IQueryBus, ICommandBus, IEventBus
1616
{
17-
private readonly string _apiKey;
17+
private string _apiKey;
1818

1919
private readonly JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings
2020
{
2121
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
2222
Formatting = Formatting.Indented
2323
};
2424

25-
private readonly string _sharedSecret;
25+
private string _sharedSecret;
2626
private Uri _uri;
2727

2828

2929
/// <summary>
30-
/// Creates a new instance of <see cref="OneTrueClient" />.
30+
/// Creates a new instance of <see cref="OneTrueApiClient" />.
3131
/// </summary>
32-
/// <param name="apiKey">Api key from the admin area in OneTrueError web</param>
33-
/// <param name="sharedSecret">Shared secret from the admin area in OneTrueError web</param>
34-
public OneTrueClient(string apiKey, string sharedSecret)
35-
{
36-
if (apiKey == null) throw new ArgumentNullException(nameof(apiKey));
37-
if (sharedSecret == null) throw new ArgumentNullException(nameof(sharedSecret));
32+
public OneTrueApiClient() {
3833

39-
_apiKey = apiKey;
40-
_sharedSecret = sharedSecret;
4134
_jsonSerializerSettings.ContractResolver = new IncludeNonPublicMembersContractResolver();
4235
}
4336

@@ -84,17 +77,23 @@ public async Task<TResult> QueryAsync<TResult>(Query<TResult> query)
8477
/// Open a channel
8578
/// </summary>
8679
/// <param name="uri">Root URL to the OneTrueError web</param>
87-
public void Open(Uri uri)
80+
/// <param name="apiKey">Api key from the admin area in OneTrueError web</param>
81+
/// <param name="sharedSecret">Shared secret from the admin area in OneTrueError web</param>
82+
public void Open(Uri uri, string apiKey, string sharedSecret)
8883
{
84+
if (apiKey == null) throw new ArgumentNullException(nameof(apiKey));
85+
if (sharedSecret == null) throw new ArgumentNullException(nameof(sharedSecret));
8986
if (uri == null) throw new ArgumentNullException(nameof(uri));
9087

88+
_apiKey = apiKey;
89+
_sharedSecret = sharedSecret;
9190
_uri = uri;
9291
}
9392

9493
private async Task<TResult> DeserializeResponse<TResult>(HttpWebResponse response)
9594
{
9695
var responseStream = response.GetResponseStream();
97-
var jsonBuf = new byte[responseStream.Length];
96+
var jsonBuf = new byte[response.ContentLength];
9897
await responseStream.ReadAsync(jsonBuf, 0, jsonBuf.Length);
9998
var jsonStr = Encoding.UTF8.GetString(jsonBuf);
10099
var responseObj = JsonConvert.DeserializeObject(jsonStr, typeof(TResult), _jsonSerializerSettings);
Lines changed: 56 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,63 @@
1-
<?xml version="1.0" encoding="utf-8"?>
2-
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3-
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4-
<PropertyGroup>
5-
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6-
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7-
<ProjectGuid>{017F8863-3DE0-4AD2-9ED3-5ACB87BBBCD0}</ProjectGuid>
8-
<OutputType>Library</OutputType>
9-
<AppDesignerFolder>Properties</AppDesignerFolder>
10-
<RootNamespace>OneTrueError.Api.Client</RootNamespace>
11-
<AssemblyName>OneTrueError.Api.Client</AssemblyName>
12-
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
13-
<FileAlignment>512</FileAlignment>
14-
</PropertyGroup>
15-
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16-
<DebugSymbols>true</DebugSymbols>
17-
<DebugType>full</DebugType>
18-
<Optimize>false</Optimize>
19-
<OutputPath>bin\Debug\</OutputPath>
20-
<DefineConstants>DEBUG;TRACE</DefineConstants>
21-
<ErrorReport>prompt</ErrorReport>
22-
<WarningLevel>4</WarningLevel>
23-
</PropertyGroup>
24-
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
25-
<DebugType>pdbonly</DebugType>
26-
<Optimize>true</Optimize>
27-
<OutputPath>bin\Release\</OutputPath>
28-
<DefineConstants>TRACE</DefineConstants>
29-
<ErrorReport>prompt</ErrorReport>
30-
<WarningLevel>4</WarningLevel>
31-
</PropertyGroup>
32-
<ItemGroup>
33-
<Reference Include="DotNetCqs, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
34-
<HintPath>..\packages\DotNetCqs.1.0.0\lib\net45\DotNetCqs.dll</HintPath>
35-
<Private>True</Private>
36-
</Reference>
37-
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
38-
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
39-
<Private>True</Private>
40-
</Reference>
41-
<Reference Include="System" />
42-
<Reference Include="System.Core" />
43-
<Reference Include="Microsoft.CSharp" />
44-
</ItemGroup>
45-
<ItemGroup>
46-
<Compile Include="Json\IncludeNonPublicMembersContractResolver.cs" />
47-
<Compile Include="OneTrueClient.cs" />
48-
<Compile Include="Properties\AssemblyInfo.cs" />
49-
<Compile Include="StringBuilderExtensions.cs" />
50-
</ItemGroup>
51-
<ItemGroup>
52-
<None Include="packages.config" />
53-
</ItemGroup>
54-
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<ProjectGuid>{017F8863-3DE0-4AD2-9ED3-5ACB87BBBCD0}</ProjectGuid>
8+
<OutputType>Library</OutputType>
9+
<AppDesignerFolder>Properties</AppDesignerFolder>
10+
<RootNamespace>OneTrueError.Api.Client</RootNamespace>
11+
<AssemblyName>OneTrueError.Api.Client</AssemblyName>
12+
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
13+
<FileAlignment>512</FileAlignment>
14+
</PropertyGroup>
15+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16+
<DebugSymbols>true</DebugSymbols>
17+
<DebugType>full</DebugType>
18+
<Optimize>false</Optimize>
19+
<OutputPath>bin\Debug\</OutputPath>
20+
<DefineConstants>DEBUG;TRACE</DefineConstants>
21+
<ErrorReport>prompt</ErrorReport>
22+
<WarningLevel>4</WarningLevel>
23+
</PropertyGroup>
24+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
25+
<DebugType>pdbonly</DebugType>
26+
<Optimize>true</Optimize>
27+
<OutputPath>bin\Release\</OutputPath>
28+
<DefineConstants>TRACE</DefineConstants>
29+
<ErrorReport>prompt</ErrorReport>
30+
<WarningLevel>4</WarningLevel>
31+
<DocumentationFile>bin\Release\OneTrueError.Api.Client.XML</DocumentationFile>
32+
</PropertyGroup>
33+
<ItemGroup>
34+
<Reference Include="DotNetCqs, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
35+
<HintPath>..\packages\DotNetCqs.1.0.0\lib\net45\DotNetCqs.dll</HintPath>
36+
<Private>True</Private>
37+
</Reference>
38+
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
39+
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
40+
<Private>True</Private>
41+
</Reference>
42+
<Reference Include="System" />
43+
<Reference Include="System.Core" />
44+
<Reference Include="Microsoft.CSharp" />
45+
</ItemGroup>
46+
<ItemGroup>
47+
<Compile Include="Json\IncludeNonPublicMembersContractResolver.cs" />
48+
<Compile Include="OneTrueClient.cs" />
49+
<Compile Include="Properties\AssemblyInfo.cs" />
50+
<Compile Include="StringBuilderExtensions.cs" />
51+
</ItemGroup>
52+
<ItemGroup>
53+
<None Include="packages.config" />
54+
</ItemGroup>
55+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
5556
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
5657
Other similar extension points exist, see Microsoft.Common.targets.
5758
<Target Name="BeforeBuild">
5859
</Target>
5960
<Target Name="AfterBuild">
6061
</Target>
61-
-->
62+
-->
6263
</Project>

src/Server/OneTrueError.Api/AuthorizeAttribute.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,25 @@
22

33
namespace OneTrueError.Api
44
{
5+
/// <summary>
6+
/// Authorize on specific roles.
7+
/// </summary>
58
[AttributeUsage(AttributeTargets.Class)]
6-
public class AuthorizeAttribute : Attribute
9+
public class AuthorizeRolesAttribute : Attribute
710
{
8-
public AuthorizeAttribute(params string[] roles)
11+
/// <summary>
12+
/// Creates a new instance of <see cref="AuthorizeRolesAttribute" />.
13+
/// </summary>
14+
/// <param name="roles">roles granted access</param>
15+
public AuthorizeRolesAttribute(params string[] roles)
916
{
1017
if (roles == null) throw new ArgumentNullException("roles");
1118
Roles = roles;
1219
}
1320

14-
public string[] Roles { get; set; }
21+
/// <summary>
22+
/// Roles granted access
23+
/// </summary>
24+
public string[] Roles { get; private set; }
1525
}
1626
}

src/Server/OneTrueError.Api/Core/ApiKeys/Commands/CreateApiKey.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace OneTrueError.Api.Core.ApiKeys.Commands
66
/// <summary>
77
/// Create a new api key
88
/// </summary>
9-
[Authorize("SysAdmin")]
9+
[AuthorizeRoles("SysAdmin")]
1010
public class CreateApiKey : Command
1111
{
1212
/// <summary>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
ApiKeys
2+
========
3+
4+
Used to allow external applications to talk with OneTrueError.
5+
6+
7+
## Example usage
8+
9+
The following example calls a local OneTrueError server to retreive applications.
10+
11+
```csharp
12+
var client = new OneTrueApiClient();
13+
var uri = new Uri("http://yourServer/onetrueerror/");
14+
client.Open(uri, "theApiKey", "sharedSecret");
15+
var apps = await client.QueryAsync(new GetApplicationList());
16+
```
17+
18+
Result (serialized as JSON):
19+
20+
```javascript
21+
[{
22+
"Id" : 1,
23+
"Name" : "PublicWeb"
24+
}, {
25+
"Id" : 9,
26+
"Name" : "Time reporting system"
27+
}, {
28+
"Id" : 10,
29+
"Name" : "Coffee monitor"
30+
}
31+
]
32+
```

src/Server/OneTrueError.Api/OneTrueError.Api.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@
213213
<ItemGroup />
214214
<ItemGroup>
215215
<None Include="Core\Accounts\ReadMe.md" />
216+
<None Include="Core\ApiKeys\ReadMe.md" />
216217
<None Include="Core\Applications\ReadMe.md" />
217218
<None Include="Core\Feedback\ReadMe.md" />
218219
<None Include="Core\Incidents\ReadMe.md" />

src/Server/OneTrueError.App/OneTrueIdentity.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,19 @@ public class OneTrueIdentity : IIdentity
1111
/// <summary>
1212
/// Creates a new instance of <see cref="OneTrueIdentity" />.
1313
/// </summary>
14-
/// <param name="accountId">Account id</param>
14+
/// <param name="accountId">0 = system or api key; otherwise an user account id</param>
1515
/// <param name="userName">User name</param>
1616
public OneTrueIdentity(int accountId, string userName)
1717
{
1818
if (userName == null) throw new ArgumentNullException("userName");
19-
if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
19+
if (accountId < 0) throw new ArgumentOutOfRangeException("accountId");
2020

2121
AccountId = accountId;
2222
Name = userName;
2323
}
2424

2525
/// <summary>
26-
/// Account id
26+
/// 0 = system or api key; otherwise an user account id
2727
/// </summary>
2828
public int AccountId { get; private set; }
2929

src/Server/OneTrueError.App/OneTruePrincipal.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ public class OneTruePrincipal : IPrincipal
1515
/// <summary>
1616
/// Creates a new instance of <see cref="OneTruePrincipal" />.
1717
/// </summary>
18-
/// <param name="accountId"></param>
18+
/// <param name="accountId">0 = system or api key; otherwise an user account id</param>
1919
/// <param name="userName">Logged in user or <c>"system"</c></param>
2020
/// <param name="roles"></param>
2121
/// <exception cref="ArgumentNullException">userName</exception>
2222
public OneTruePrincipal(int accountId, string userName, string[] roles)
2323
{
2424
if (userName == null) throw new ArgumentNullException("userName");
2525
if (roles == null) throw new ArgumentNullException("roles");
26-
if (accountId <= 0) throw new ArgumentOutOfRangeException("accountId");
26+
if (accountId < 0) throw new ArgumentOutOfRangeException("accountId");
2727

2828
Identity = new OneTrueIdentity(accountId, userName);
2929
_roles = roles;

src/Server/OneTrueError.SqlServer.Tests/Core/ApiKeys/Commands/DeleteApiKeyHandlerTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,23 +47,23 @@ private void GetApplicationId()
4747
if (id is DBNull)
4848
{
4949
repos.CreateAsync(new Application(10, "AppTen")).Wait();
50-
_applicationId = (int) _uow.ExecuteScalar("SELECT TOP 1 Id FROM Applications");
50+
_applicationId = (int)_uow.ExecuteScalar("SELECT TOP 1 Id FROM Applications");
5151
}
5252
else
53-
_applicationId = (int) id;
53+
_applicationId = (int)id;
5454

5555

5656
}
5757

5858
[Fact]
5959
public async Task should_be_able_to_delete_key_by_id()
6060
{
61-
var cmd =new DeleteApiKey(_existingEntity.Id);
61+
var cmd = new DeleteApiKey(_existingEntity.Id);
6262

6363
var sut = new DeleteApiKeyHandler(_uow);
6464
await sut.ExecuteAsync(cmd);
6565

66-
var count = _uow.ExecuteScalar("SELECT cast(count(*) as int) FROM ApiKeys WHERE Id = @1", _existingEntity.Id);
66+
var count = _uow.ExecuteScalar("SELECT cast(count(*) as int) FROM ApiKeys WHERE Id = @id", new { id = _existingEntity.Id });
6767
count.Should().Be(0);
6868
}
6969

@@ -75,7 +75,7 @@ public async Task should_be_able_to_delete_key_by_ApiKey()
7575
var sut = new DeleteApiKeyHandler(_uow);
7676
await sut.ExecuteAsync(cmd);
7777

78-
var count = _uow.ExecuteScalar("SELECT cast(count(*) as int) FROM ApiKeys WHERE Id = @1", _existingEntity.Id);
78+
var count = _uow.ExecuteScalar("SELECT cast(count(*) as int) FROM ApiKeys WHERE Id = @id", new { id = _existingEntity.Id });
7979
count.Should().Be(0);
8080
}
8181

src/Server/OneTrueError.SqlServer/Core/ApiKeys/Commands/DeleteApiKeyHandler.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,21 @@ public DeleteApiKeyHandler(IAdoNetUnitOfWork unitOfWork)
2020
_unitOfWork = unitOfWork;
2121
}
2222

23-
public async Task ExecuteAsync(DeleteApiKey command)
23+
public Task ExecuteAsync(DeleteApiKey command)
2424
{
25-
if (string.IsNullOrEmpty(command.ApiKey))
26-
await _unitOfWork.DeleteAsync<ApiKey>(command.Id);
25+
int id;
26+
if (!string.IsNullOrEmpty(command.ApiKey))
27+
{
28+
id = (int) _unitOfWork.ExecuteScalar("SELECT Id FROM ApiKeys WHERE GeneratedKey = @key", new { key=command.ApiKey});
29+
}
2730
else
28-
await _unitOfWork.DeleteAsync<ApiKey>(new {GeneratedKey = command.ApiKey});
31+
{
32+
id = command.Id;
33+
}
34+
35+
_unitOfWork.ExecuteNonQuery("DELETE FROM [ApiKeyApplications] WHERE ApiKeyId = @id", new {id});
36+
_unitOfWork.ExecuteNonQuery("DELETE FROM [ApiKeys] WHERE Id = @id", new { id });
37+
return Task.FromResult<object>(null);
2938
}
3039
}
3140
}

0 commit comments

Comments
 (0)