Skip to content

Commit

Permalink
feat(API): publish federation compatiable API (#45)
Browse files Browse the repository at this point in the history
* feat(API): publish federation compatiable API
  • Loading branch information
cyberhck authored Aug 11, 2022
1 parent d758806 commit 4e422d6
Show file tree
Hide file tree
Showing 14 changed files with 117 additions and 42 deletions.
29 changes: 29 additions & 0 deletions API.Tests/QueryTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Business;
using Moq;
using NUnit.Framework;

namespace API.Tests;

public class QueryTest
{
[Test]
public async Task TestKeysReturnsKeys()
{
var mockKeyService = new Mock<IKeyService>();
mockKeyService.Setup(x => x.FetchAllKeys()).ReturnsAsync(new List<Key>
{
new() {Body = "body1", Id = "id1"},
new() {Body = "body2", Id = "id2"}
});
var query = new Query();
var queryResponse = await query.Keys(mockKeyService.Object);
var enumerable = queryResponse.ToList();
Assert.AreEqual(enumerable.First().Body, "body1");
Assert.AreEqual(enumerable.First().Id, "id1");
Assert.AreEqual(enumerable.ElementAt(1).Body, "body2");
Assert.AreEqual(enumerable.ElementAt(1).Id, "id2");
}
}
11 changes: 11 additions & 0 deletions API/ExceptionHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace API;

public class ExceptionHandler : IErrorFilter
{
public IError OnError(IError error)
{
return error.Exception == null
? error
: error.WithMessage(error.Exception.Message);
}
}
6 changes: 4 additions & 2 deletions API/Mutation.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using API.Types;
using Business;
using Key = API.Types.Key;

namespace API;

public class Mutation
{
public Task<Key> RegisterPublicKey([Service] IKeyService keyService, string publicKey)
public async Task<Key> RegisterPublicKey([Service] IKeyService keyService, string publicKey)
{
return keyService.Create(publicKey);
return (await keyService.Create(publicKey)).ToGraphQl();
}
}
12 changes: 4 additions & 8 deletions API/Query.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
using API.types;
using API.Types;
using Business;
using Key = API.Types.Key;

namespace API;

public class Query
{
public Task<User> Me()
public async Task<IEnumerable<Key>> Keys([Service] IKeyService keyService)
{
return Task.FromResult(new User("user_id"));
}

public Task<IEnumerable<Key>> Keys([Service] IKeyService keyService)
{
return keyService.FetchAllKeys();
return (await keyService.FetchAllKeys()).Select(x => x.ToGraphQl());
}
}
5 changes: 2 additions & 3 deletions API/Setup.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using API.types;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

namespace API;
Expand All @@ -12,7 +11,7 @@ public static void SetupGraphqlServer(this IServiceCollection serviceCollection)
.AddGraphQLServer()
.AddApolloFederation()
.AddApolloTracing()
.AddType<User>()
.AddErrorFilter<ExceptionHandler>()
.AddQueryType<Query>()
.AddMutationType<Mutation>();
}
Expand Down
27 changes: 27 additions & 0 deletions API/Types/Key.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Business;

namespace API.Types;

public sealed record Key
{
[Key] public string Id { set; get; }

public string Body { set; get; }

public static async Task<Key> GetKeyById([Service] IKeyService keyService, string Id)
{
return (await keyService.FindById(Id)).ToGraphQl();
}
}

public static class BusinessKeyExtension
{
public static Key ToGraphQl(this Business.Key key)
{
return new Key
{
Body = key.Body,
Id = key.Id
};
}
}
12 changes: 0 additions & 12 deletions API/types/User.cs

This file was deleted.

4 changes: 2 additions & 2 deletions Business.Tests/KeyServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ public async Task FetchAllKeysTest()
var mockKeyRepo = new Mock<IKeyRepository>();
var mockKeys = new List<Storage.Key>
{
new() { Body = "1", Id = "key_1"},
new() { Body = "2", Id = "key_2"},
new() {Body = "1", Id = "key_1"},
new() {Body = "2", Id = "key_2"}
};
mockKeyRepo.Setup(x => x.FindAllKeys()).ReturnsAsync(mockKeys.AsEnumerable());
var service = new KeyService(mockKeyRepo.Object);
Expand Down
8 changes: 7 additions & 1 deletion Business/Business.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Storage\Storage.csproj"/>
<ProjectReference Include="..\Storage\Storage.csproj" />
</ItemGroup>

<ItemGroup>
<Reference Include="HotChocolate.Abstractions">
<HintPath>..\..\..\..\.nuget\packages\hotchocolate.abstractions\12.12.1\lib\net6.0\HotChocolate.Abstractions.dll</HintPath>
</Reference>
</ItemGroup>

</Project>
8 changes: 8 additions & 0 deletions Business/Exceptions/KeyNotFoundException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Business.Exceptions;

public class KeyNotFoundException : Exception
{
public KeyNotFoundException(string? message) : base(message)
{
}
}
9 changes: 9 additions & 0 deletions Business/KeyService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace Business;

public interface IKeyService
{
Task<Key> FindById(string id);
Task<IEnumerable<Key>> FetchAllKeys();
Task<Key> Create(string publicKey);
Task CleanupKeys(int hoursBefore);
Expand All @@ -18,6 +19,14 @@ public KeyService(IKeyRepository keyRepository)
_keyRepository = keyRepository;
}

public async Task<Key> FindById(string id)
{
var key = await _keyRepository.FindById(id);
if (key == null) throw new Exceptions.KeyNotFoundException("key not found");

return key.ToViewModel();
}

public async Task<IEnumerable<Key>> FetchAllKeys()
{
return (await _keyRepository.FindAllKeys())
Expand Down
10 changes: 2 additions & 8 deletions Startup/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@
// but we're trying to use a command pattern
// we just check if this is a entity framework's invocation,
// and simply start the server that it so desires.
if (args[0] == "--applicationName")
{
Cli.StartServer(args);
}
if (args[0] == "--applicationName") Cli.StartServer(args);

var rootCommand = new RootCommand("key management service");

Expand All @@ -27,10 +24,7 @@
var dbArchiveCommand = new Command("archive_keys", "archive old keys");
var keyTtlHours = new Option<int>("--key-ttl-hours", () => 72);
dbArchiveCommand.AddOption(keyTtlHours);
dbArchiveCommand.SetHandler((hoursBefore) =>
{
Cli.CleanupKeys(args, hoursBefore);
}, keyTtlHours);
dbArchiveCommand.SetHandler(hoursBefore => { Cli.CleanupKeys(args, hoursBefore); }, keyTtlHours);
dbCommand.AddCommand(dbArchiveCommand);

dbCommand.AddCommand(dbMigrateCommand);
Expand Down
6 changes: 6 additions & 0 deletions Storage/KeyRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public interface IKeyRepository
Task<IEnumerable<Key>> FindAllKeys();
Task<Key> Create(Key key);
Task CleanupKeys(DateTime createdBefore);
Task<Key?> FindById(string id);
}

public class KeyRepository : IKeyRepository
Expand Down Expand Up @@ -35,4 +36,9 @@ public Task CleanupKeys(DateTime createdBefore)
_db.Keys.RemoveRange(_db.Keys.Where(x => x.CreatedAt < createdBefore));
return _db.SaveChangesAsync();
}

public Task<Key?> FindById(string id)
{
return _db.Keys.FirstOrDefaultAsync(x => x.Id == id);
}
}
12 changes: 6 additions & 6 deletions Storage/Storage.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="EFCore.NamingConventions" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.7" />
<PackageReference Include="EFCore.NamingConventions" Version="6.0.0"/>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.7"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.5" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0" />
<PackageReference Include="Ulid" Version="1.2.6" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.5"/>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0"/>
<PackageReference Include="Ulid" Version="1.2.6"/>
</ItemGroup>

<ItemGroup>
<Folder Include="Migrations" />
<Folder Include="Migrations"/>
</ItemGroup>

</Project>

0 comments on commit 4e422d6

Please sign in to comment.