Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.Net8 and integration tests #191

Merged
merged 18 commits into from
Feb 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/core-build.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Build and test solution

env:
DOTNET_VERSION: 6
DOTNET_VERSION: 8

on:
workflow_call:
5 changes: 2 additions & 3 deletions coffeecard/CoffeeCard.Common/CoffeeCard.Common.csproj
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ProjectGuid>33C1BE09-BD3A-4584-B195-C57B47B9063C</ProjectGuid>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="NetEscapades.Configuration.Validation" Version="2.0.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
</ItemGroup>
</Project>
</Project>
134 changes: 134 additions & 0 deletions coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;

namespace CoffeeCard.Generators.Builder;

[Generator]
public class BuilderGenerator : IIncrementalGenerator

Check warning on line 9 in coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs

GitHub Actions / build / Build codebase / Build and test analog-core

'CoffeeCard.Generators.Builder.BuilderGenerator': A project containing analyzers or source generators should specify the property '<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>'
{
private const string BuilderForAttribute = "CoffeeCard.Tests.Common.BuilderForAttribute";

public void Initialize(IncrementalGeneratorInitializationContext context)
{
var namedTypeSymbols = context.SyntaxProvider
.ForAttributeWithMetadataName(
fullyQualifiedMetadataName: BuilderForAttribute,
predicate: IsSyntaxTargetForGeneration,
transform: GetSemanticTargetForGeneration)
.Where(t => t is not null).Collect();

context.RegisterSourceOutput(namedTypeSymbols, (productionContext, array) =>
{
foreach (var typeSymbol in array)
{
//Retrieve the entity it is a builder for
var entity = (INamedTypeSymbol)typeSymbol.GetAttributes()

Check warning on line 27 in coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs

GitHub Actions / build / Build codebase / Build and test analog-core

Converting null literal or possible null value to non-nullable type.
.Single(attr => attr.AttributeClass.Name == "BuilderForAttribute").ConstructorArguments[0].Value;

Check warning on line 28 in coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs

GitHub Actions / build / Build codebase / Build and test analog-core

Dereference of a possibly null reference.
var code = GenerateBuilderCode(typeSymbol, entity);

Check warning on line 29 in coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs

GitHub Actions / build / Build codebase / Build and test analog-core

Possible null reference argument for parameter 'entity' in 'string BuilderGenerator.GenerateBuilderCode(INamedTypeSymbol typeSymbol, ITypeSymbol entity)'.
var sourceText = SourceText.From(code, Encoding.UTF8);
productionContext.AddSource($"{typeSymbol.Name}.g.cs", sourceText);
}
});
}

private static bool IsSyntaxTargetForGeneration(
SyntaxNode syntaxNode,
CancellationToken cancellationToken)
{
return syntaxNode is ClassDeclarationSyntax classDeclaration;
}

private static INamedTypeSymbol GetSemanticTargetForGeneration(GeneratorAttributeSyntaxContext context,
CancellationToken cancellationToken)
{
return (INamedTypeSymbol)context.TargetSymbol;
}

private string GenerateBuilderCode(INamedTypeSymbol typeSymbol, ITypeSymbol entity)
{
var codeBuilder = new StringBuilder();

codeBuilder.AppendLine("// <auto-generated/>");
codeBuilder.AppendLine("using System;");
codeBuilder.AppendLine("using AutoBogus.Conventions;");
codeBuilder.AppendLine($"using {entity.ContainingNamespace};");
codeBuilder.AppendLine();
codeBuilder.AppendLine($"namespace {typeSymbol.ContainingNamespace};");
codeBuilder.AppendLine();

codeBuilder.AppendLine($"public partial class {typeSymbol.Name} : BaseBuilder<{entity.Name}>, IBuilder<{typeSymbol.Name}>");
codeBuilder.AppendLine("{");

// Retrieve all properties of the given entity
var properties = entity.GetMembers().OfType<IPropertySymbol>().Where(p => p.Kind == SymbolKind.Property);

var entityNameChar = entity.Name.ToLowerInvariant()[0];
// Generate builder methods for all properties
var configBuilder = new StringBuilder();
foreach (var property in properties)
{
if (property.Name.Contains("Id"))
{
configBuilder.AppendLine($" .WithSkip<{entity.Name}>(\"{property.Name}\")");
}
AddWithPropertyValueToCodeBuilder(codeBuilder: codeBuilder,
typeSymbol: typeSymbol,
property: property,
entityNameChar: entityNameChar);

AddWithPropertySetterToCodeBuilder(
codeBuilder: codeBuilder,
typeSymbol: typeSymbol,
property: property,
entityNameChar: entityNameChar);
}
AddPrivateConstructorToCodeBuilder(codeBuilder, typeSymbol, configBuilder);

// End class
codeBuilder.AppendLine("}");

return codeBuilder.ToString();
}

/// <summary>
/// Generates a private constructor for the builder, to ensure the simple, or typical methods are used for instantiation
/// </summary>
/// <param name="codeBuilder"></param>
/// <param name="typeSymbol"></param>
/// <param name="configBuilder"></param>
private void AddPrivateConstructorToCodeBuilder(StringBuilder codeBuilder, ITypeSymbol typeSymbol, StringBuilder configBuilder)
{
codeBuilder.AppendLine(
$" private {typeSymbol.Name} ()");
codeBuilder.AppendLine(" {");
codeBuilder.AppendLine(" Faker.Configure(builder => builder");
codeBuilder.Append($"{configBuilder}");
codeBuilder.AppendLine(" .WithConventions());");
codeBuilder.AppendLine(" }");
}

private void AddWithPropertyValueToCodeBuilder(StringBuilder codeBuilder, ITypeSymbol typeSymbol, IPropertySymbol property, char entityNameChar)
{
codeBuilder.AppendLine(
$" public {typeSymbol.Name} With{property.Name}({property.Type} {property.Name}Value)");
codeBuilder.AppendLine(" {");

codeBuilder.AppendLine(
$" Faker.RuleFor({entityNameChar} => {entityNameChar}.{property.Name}, {property.Name}Value);");
codeBuilder.AppendLine(" return this;");
codeBuilder.AppendLine(" }");
}
private void AddWithPropertySetterToCodeBuilder(StringBuilder codeBuilder, ITypeSymbol typeSymbol, IPropertySymbol property, char entityNameChar)
{
codeBuilder.AppendLine(
$" public {typeSymbol.Name} With{property.Name}(Func<Bogus.Faker, {property.Type}> {property.Name}Setter)");
codeBuilder.AppendLine(" {");

codeBuilder.AppendLine(
$" Faker.RuleFor({entityNameChar} => {entityNameChar}.{property.Name}, {property.Name}Setter);");
codeBuilder.AppendLine(" return this;");
codeBuilder.AppendLine(" }");
}
}
23 changes: 23 additions & 0 deletions coffeecard/CoffeeCard.Generators/CoffeeCard.Generators.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>11.0</LangVersion>
</PropertyGroup>
<PropertyGroup>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)GeneratedCode\</CompilerGeneratedFilesOutputPath>
</PropertyGroup>


<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.7.0" />
</ItemGroup>

</Project>
81 changes: 37 additions & 44 deletions coffeecard/CoffeeCard.Library/CoffeeCard.Library.csproj
Original file line number Diff line number Diff line change
@@ -1,46 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<LangVersion>8</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="MailKit" Version="3.4.2" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="4.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.11">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="6.0.11" />
<PackageReference Include="MimeKit" Version="3.4.2" />
<PackageReference Include="NetEscapades.Configuration.Validation" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.11" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.10" />
<PackageReference Include="RestSharp" Version="108.0.2" />
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
<PackageReference Include="Serilog.Enrichers.CorrelationId" Version="3.0.1" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.25.0" />
<PackageReference Include="TimeZoneConverter" Version="6.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CoffeeCard.Common\CoffeeCard.Common.csproj" />
<ProjectReference Include="..\CoffeeCard.MobilePay\CoffeeCard.MobilePay.csproj" />
<ProjectReference Include="..\CoffeeCard.Models\CoffeeCard.Models.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Migrations\20220519210629_RestApiV2Changes.cs" />
<Compile Remove="Migrations\20220519210629_RestApiV2Changes.Designer.cs" />
<Compile Remove="Migrations\20191012125617_Initial - test.cs" />
<Compile Remove="Migrations\20191012125617_Initial - test.Designer.cs" />
</ItemGroup>

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>default</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MailKit" Version="3.4.2" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.1.1" />
<PackageReference Include="MimeKit" Version="3.4.2" />
<PackageReference Include="NetEscapades.Configuration.Validation" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.10" />
<PackageReference Include="RestSharp" Version="108.0.2" />
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
<PackageReference Include="Serilog.Enrichers.CorrelationId" Version="3.0.1" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" />
<PackageReference Include="TimeZoneConverter" Version="6.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CoffeeCard.Common\CoffeeCard.Common.csproj" />
<ProjectReference Include="..\CoffeeCard.MobilePay\CoffeeCard.MobilePay.csproj" />
<ProjectReference Include="..\CoffeeCard.Models\CoffeeCard.Models.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Migrations\20220519210629_RestApiV2Changes.cs" />
<Compile Remove="Migrations\20220519210629_RestApiV2Changes.Designer.cs" />
<Compile Remove="Migrations\20191012125617_Initial - test.cs" />
<Compile Remove="Migrations\20191012125617_Initial - test.Designer.cs" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>8</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="NSwag.CodeGeneration.CSharp" Version="13.17.0" />
<PackageReference Include="NSwag.Core" Version="13.17.0" />
</ItemGroup>

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>default</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NSwag.CodeGeneration.CSharp" Version="13.17.0" />
<PackageReference Include="NSwag.Core" Version="13.17.0" />
</ItemGroup>
</Project>
11 changes: 5 additions & 6 deletions coffeecard/CoffeeCard.MobilePay/CoffeeCard.MobilePay.csproj
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ProjectGuid>AFF9D584-58F4-4A8D-A6BF-515890A9A3EF</ProjectGuid>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="jose-jwt" Version="4.0.1" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CoffeeCard.Common\CoffeeCard.Common.csproj" />
36 changes: 16 additions & 20 deletions coffeecard/CoffeeCard.Models/CoffeeCard.Models.csproj
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Nullable>enable</Nullable>
<LangVersion>default</LangVersion>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\CoffeeCard.Common\CoffeeCard.Common.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="6.0.11" />
<PackageReference Include="NJsonSchema" Version="10.8.0" />
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" PrivateAssets="all" />
<PackageReference Include="System.Text.Encoding.Extensions" Version="4.3.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.NETCore.Targets" Version="5.0.0" ExcludeAssets="all" PrivateAssets="all" />
</ItemGroup>

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Nullable>enable</Nullable>
<LangVersion>default</LangVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\CoffeeCard.Common\CoffeeCard.Common.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NJsonSchema" Version="11.0.0" />
<PackageReference Include="Microsoft.NETCore.Targets" Version="5.0.0" ExcludeAssets="all" PrivateAssets="all" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.0" />
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" PrivateAssets="all" />
<PackageReference Include="System.Text.Encoding.Extensions" Version="4.3.0" PrivateAssets="all" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.Runtime.Serialization;
using System.Text.Json.Serialization;
using NJsonSchema.Converters;

namespace CoffeeCard.Models.DataTransferObjects.v2.Purchase
{
@@ -14,7 +12,6 @@ namespace CoffeeCard.Models.DataTransferObjects.v2.Purchase
/// }
/// </example>
[KnownType(typeof(FreePurchasePaymentDetails))]
[JsonConverter(typeof(JsonInheritanceConverter))]
public class FreePurchasePaymentDetails : PaymentDetails
{
/// <summary>
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Newtonsoft.Json;
using NJsonSchema.Converters;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;

@@ -17,7 +16,6 @@ namespace CoffeeCard.Models.DataTransferObjects.v2.Purchase
/// }
/// </example>
[KnownType(typeof(MobilePayPaymentDetails))]
[JsonConverter(typeof(JsonInheritanceConverter))]
public class MobilePayPaymentDetails : PaymentDetails
{
/// <summary>
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
using System.Text.Json.Serialization;
using NJsonSchema.Converters;

namespace CoffeeCard.Models.DataTransferObjects.v2.Purchase
{
[KnownType(typeof(MobilePayPaymentDetails))]
[KnownType(typeof(FreePurchasePaymentDetails))]
[JsonConverter(typeof(JsonInheritanceConverter))]
public abstract class PaymentDetails
{
/// <summary>
17 changes: 17 additions & 0 deletions coffeecard/CoffeeCard.Tests.Common/BuilderForAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace CoffeeCard.Tests.Common;

/// <summary>
/// Serves as a marker attribute used for source generation
/// The Type given, will have builder methods generated for it
/// The methods will be in the format WithPropertyName and allow for fluent api style configuration
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
sealed class BuilderForAttribute : Attribute
{
public Type EntityType { get; }

public BuilderForAttribute(Type entityType)
{
EntityType = entityType;
}
}
48 changes: 48 additions & 0 deletions coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using AutoBogus;
using AutoBogus.Conventions;

namespace CoffeeCard.Tests.Common.Builders
{
public abstract class BaseBuilder<T> where T : class
{
protected readonly AutoFaker<T> Faker = new();
protected BaseBuilder()
{
Faker.Configure(builder => builder.WithConventions());
}

/// <summary>
/// Creates a new instance of type T,
/// using the configuration set by using the builderMethods
/// </summary>
public T Build()
{
return Faker.Generate();
}

/// <summary>
/// Creates a new list of type T,
/// using the configuration set by using the builderMethods
/// </summary>
public List<T> Build(int count)
{
return Faker.Generate(count);
}
}

public interface IBuilder<T> where T : class
{
/// <summary>
/// Gives a standard configured builder,
/// where lists of linked entities are empty
/// and nullable enities are null
/// </summary>
public static abstract T Simple();

/// <summary>
/// Gives a standard configured builder,
/// where all linked entities are populated
/// </summary>
public static abstract T Typical();
}
}
22 changes: 22 additions & 0 deletions coffeecard/CoffeeCard.Tests.Common/Builders/ProductBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using CoffeeCard.Models.Entities;

namespace CoffeeCard.Tests.Common.Builders
{
[BuilderFor(typeof(Product))]
public partial class ProductBuilder
{
public static ProductBuilder Simple()
{
return new ProductBuilder()
.WithName(f => f.Commerce.ProductName())
.WithDescription(f => f.Commerce.ProductDescription())
.WithNumberOfTickets(f => f.PickRandom(1, 10))
.WithProductUserGroup(new List<ProductUserGroup>());
}

public static ProductBuilder Typical()
{
return Simple();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using CoffeeCard.Models.Entities;

namespace CoffeeCard.Tests.Common.Builders
{
[BuilderFor(typeof(ProductUserGroup))]
public partial class ProductUserGroupBuilder
{
public static ProductUserGroupBuilder Simple()
{
var product = ProductBuilder.Simple().Build();
return new ProductUserGroupBuilder()
.WithProduct(product)
.WithUserGroup(f =>
f.PickRandom(UserGroup.Barista, UserGroup.Board, UserGroup.Customer, UserGroup.Manager));
}

public static ProductUserGroupBuilder Typical()
{
return Simple();
}
}
}
21 changes: 21 additions & 0 deletions coffeecard/CoffeeCard.Tests.Common/Builders/ProgrammeBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using CoffeeCard.Models.Entities;

namespace CoffeeCard.Tests.Common.Builders
{
[BuilderFor(typeof(Programme))]
public partial class ProgrammeBuilder
{
public static ProgrammeBuilder Simple()
{
return new ProgrammeBuilder()
.WithUsers(new List<User>())
.WithShortName(f => f.Random.String2(3))
.WithFullName(f => f.Commerce.Department());
}

public static ProgrammeBuilder Typical()
{
return Simple();
}
}
}
23 changes: 23 additions & 0 deletions coffeecard/CoffeeCard.Tests.Common/Builders/PurchaseBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using CoffeeCard.Models.Entities;

namespace CoffeeCard.Tests.Common.Builders
{
[BuilderFor(typeof(Purchase))]
public partial class PurchaseBuilder
{
public static PurchaseBuilder Simple()
{
var purchasedBy = UserBuilder.Simple().Build();
return new PurchaseBuilder().WithPurchasedBy(purchasedBy)
.WithProductName(f => f.Commerce.ProductName())
.WithTickets(new List<Ticket>())
.WithTickets(new List<Ticket>())
.WithNumberOfTickets(0);
}

public static PurchaseBuilder Typical()
{
return Simple();
}
}
}
20 changes: 20 additions & 0 deletions coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using CoffeeCard.Models.Entities;

namespace CoffeeCard.Tests.Common.Builders
{
[BuilderFor(typeof(Statistic))]
public partial class StatisticBuilder
{
public static StatisticBuilder Simple()
{
var user = UserBuilder.Simple().Build();
return new StatisticBuilder()
.WithUser(user);
}

public static StatisticBuilder Typical()
{
return Simple();
}
}
}
22 changes: 22 additions & 0 deletions coffeecard/CoffeeCard.Tests.Common/Builders/TicketBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using CoffeeCard.Models.Entities;

namespace CoffeeCard.Tests.Common.Builders
{
[BuilderFor(typeof(Ticket))]
public partial class TicketBuilder
{
public static TicketBuilder Simple()
{
var owner = UserBuilder.Simple().Build();
var purchase = PurchaseBuilder.Simple().Build();
return new TicketBuilder()
.WithOwner(owner)
.WithPurchase(purchase);
}

public static TicketBuilder Typical()
{
return Simple();
}
}
}
19 changes: 19 additions & 0 deletions coffeecard/CoffeeCard.Tests.Common/Builders/TokenBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using CoffeeCard.Models.Entities;

namespace CoffeeCard.Tests.Common.Builders
{
[BuilderFor(typeof(Token))]
public partial class TokenBuilder
{
public static TokenBuilder Simple()
{
return new TokenBuilder()
.WithUser(UserBuilder.Simple().Build());
}

public static TokenBuilder Typical()
{
return Simple();
}
}
}
34 changes: 34 additions & 0 deletions coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using CoffeeCard.Models.Entities;

namespace CoffeeCard.Tests.Common.Builders
{
[BuilderFor(typeof(User))]
public partial class UserBuilder
{
public static UserBuilder Simple()
{
var programme = ProgrammeBuilder.Simple().Build();

return new UserBuilder()
.WithProgramme(programme)
.WithPurchases(new List<Purchase>())
.WithStatistics(new List<Statistic>())
.WithLoginAttempts(new List<LoginAttempt>())
.WithTokens(new List<Token>())
.WithUserState(UserState.Active)
.WithTickets(new List<Ticket>());
}

public static UserBuilder DefaultCustomer()
{
return Simple()
.WithUserGroup(UserGroup.Customer)
.WithIsVerified(true);
}

public static UserBuilder Typical()
{
return Simple();
}
}
}
21 changes: 21 additions & 0 deletions coffeecard/CoffeeCard.Tests.Common/Builders/VoucherBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using CoffeeCard.Models.Entities;

namespace CoffeeCard.Tests.Common.Builders
{
[BuilderFor(typeof(Voucher))]
public partial class VoucherBuilder
{
public static VoucherBuilder Simple()
{
var product = ProductBuilder.Simple().Build();
return new VoucherBuilder()
.WithProduct(product)
.WithUser(f => null);
}

public static VoucherBuilder Typical()
{
return Simple();
}
}
}
15 changes: 15 additions & 0 deletions coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\CoffeeCard.Generators\CoffeeCard.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\CoffeeCard.Models\CoffeeCard.Models.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AutoBogus" Version="2.13.1" />
<PackageReference Include="AutoBogus.Conventions" Version="2.13.1" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,38 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable>
<LangVersion>8</LangVersion>
<LangVersion>default</LangVersion>
<ProjectGuid>81E81CE9-7DDA-4A9B-860B-6A473BC4F06F</ProjectGuid>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="3.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="6.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.11">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
<PackageReference Include="NetEscapades.Configuration.Validation" Version="2.0.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PackageReference Include="xunit" Version="2.5.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CoffeeCard.WebApi\CoffeeCard.WebApi.csproj" />
<ProjectReference Include="..\CoffeeCard.Tests.Common\CoffeeCard.Tests.Common.csproj" />
</ItemGroup>
<ItemGroup>
<Content Include="..\CoffeeCard.WebApi\appsettings.json">
@@ -42,4 +40,4 @@
<ItemGroup>
<Folder Include="Controllers\" />
</ItemGroup>
</Project>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Threading.Tasks;
using CoffeeCard.Tests.Integration.WebApplication;
using CoffeeCard.WebApi;
using Xunit;
using CoffeeCard.Models.DataTransferObjects.v2.User;
using CoffeeCard.Tests.Common.Builders;
using CoffeeCard.Models.Entities;

namespace CoffeeCard.Tests.Integration.Controllers.Account
{

public class GetAccountTest : BaseIntegrationTest
{
private const string GetAccountUrl = "api/v2/account";
public GetAccountTest(CustomWebApplicationFactory<Startup> factory) : base(factory)
{
}

[Fact]
public async Task Get_account_succeeds_when_authenticated_for_existing_account()
{
var user = UserBuilder.DefaultCustomer().Build();
await Context.Users.AddAsync(user);
await Context.SaveChangesAsync();
SetDefaultAuthHeader(user);

var response = await Client.GetAsync(GetAccountUrl);
var account = await DeserializeResponseAsync<UserResponse>(response);

Assert.Equal(user.Email, account.Email);
Assert.Equal(user.Name, account.Name);
Assert.Equal(user.Programme.FullName, account.Programme.FullName);
Assert.Equal(user.UserGroup.toUserRole(), account.Role);
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using CoffeeCard.Models.DataTransferObjects.User;
using CoffeeCard.Tests.Common.Builders;
using CoffeeCard.Tests.Integration.WebApplication;
using CoffeeCard.WebApi;
using Xunit;

namespace CoffeeCard.Tests.Integration.Controllers.Account
{

public class LoginTest : BaseIntegrationTest
{
private const string LoginUrl = "api/v1/account/login";
public LoginTest(CustomWebApplicationFactory<Startup> factory) : base(factory)
{
}

[Fact]
public async Task Unknown_user_login_fails()
{
var loginRequest = new LoginDto
{
Password = "test",
Email = "test@email.dk",
Version = "2.1.0"
};

var response = await Client.PostAsJsonAsync(LoginUrl, loginRequest);

Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
}

[Fact]
public async Task Known_user_login_succeeds_returns_token()
{
var user = UserBuilder.DefaultCustomer().Build();
var plaintextPassword = user.Password;
user.Password = HashPassword(plaintextPassword + user.Salt);

await Context.Users.AddAsync(user);
await Context.SaveChangesAsync();

var loginRequest = new LoginDto
{
Password = plaintextPassword,
Email = user.Email,
Version = "2.1.0"
};
var response = await Client.PostAsJsonAsync(LoginUrl, loginRequest);

var token = await DeserializeResponseAsync<TokenDto>(response);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.NotEmpty(token.Token!);
}

private static string HashPassword(string password)
{
var byteArr = Encoding.UTF8.GetBytes(password);
using var hasher = SHA256.Create();
var hashBytes = hasher.ComputeHash(byteArr);
return Convert.ToBase64String(hashBytes);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using CoffeeCard.Common.Configuration;
using CoffeeCard.Library.Persistence;
using CoffeeCard.Models.Entities;
using CoffeeCard.WebApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using Xunit;

namespace CoffeeCard.Tests.Integration.WebApplication
{
[Collection("Integration tests, to be run sequentially")]
public abstract class BaseIntegrationTest : CustomWebApplicationFactory<Startup>, IClassFixture<CustomWebApplicationFactory<Startup>>
{
private readonly CustomWebApplicationFactory<Startup> _factory;
private readonly IServiceScope _scope;
protected readonly HttpClient Client;
protected readonly CoffeeCardContext Context;

protected BaseIntegrationTest(CustomWebApplicationFactory<Startup> factory)
{
// Set the random seed used for generation of data in the builders
// This ensures our tests are deterministic within a specific version of the code
var seed = new Random(42);
Bogus.Randomizer.Seed = seed;
_factory = factory;
_scope = _factory.Services.CreateScope();

Client = GetHttpClient();
Context = GetCoffeeCardContext();
}

private HttpClient GetHttpClient()
{
var client = CreateClient();

return client;
}

protected void SetDefaultAuthHeader(User user)
{
var claims = new[]
{
new Claim(ClaimTypes.Email, user.Email),
new Claim(ClaimTypes.Name, user.Name),
new Claim("UserId", user.Id.ToString()),
new Claim(ClaimTypes.Role, user.UserGroup.ToString())
};
var token = GenerateToken(claims);
Client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", token);
}

private string GenerateToken(IEnumerable<Claim> claims)
{
var scopedServices = _scope.ServiceProvider;
var identitySettings = scopedServices.GetRequiredService<IdentitySettings>();
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(identitySettings.TokenKey)); // get token from appsettings.json

var jwt = new JwtSecurityToken("AnalogIO",
"Everyone",
claims,
DateTime.UtcNow,
DateTime.UtcNow.AddHours(24),
new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
);

return new JwtSecurityTokenHandler().WriteToken(jwt); //the method is called WriteToken but returns a string
}

protected void RemoveRequestHeaders()
{
Client.DefaultRequestHeaders.Clear();
}

private CoffeeCardContext GetCoffeeCardContext()
{
// Create a scope to obtain a reference to the database context (ApplicationDbContext).
var scopedServices = _scope.ServiceProvider;
var context = scopedServices.GetRequiredService<CoffeeCardContext>();

// Ensure the database is cleaned for each test run
context.Database.EnsureDeleted();
context.Database.EnsureCreated();

return context;
}

/// <summary>
/// Helper method to deserialize a response from the api
/// </summary>
protected static async Task<T> DeserializeResponseAsync<T>(HttpResponseMessage response)
{
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(content);
}

public override ValueTask DisposeAsync()
{
_scope.Dispose();
return base.DisposeAsync();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Linq;
using CoffeeCard.Common.Configuration;
using CoffeeCard.Library.Persistence;
@@ -51,13 +52,6 @@ protected override void ConfigureWebHost(IWebHostBuilder builder)
// Build the service provider
var sp = services.BuildServiceProvider();

// Create a scope to obtain a reference to the database context (ApplicationDbContext).
using var scope = sp.CreateScope();
var scopedServices = scope.ServiceProvider;
var db = scopedServices.GetRequiredService<CoffeeCardContext>();

// Ensure the database is created.
db.Database.EnsureCreated();
});
}
}
8 changes: 4 additions & 4 deletions coffeecard/CoffeeCard.Tests.Unit/CoffeeCard.Tests.Unit.csproj
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>false</IsPackable>
<LangVersion>8</LangVersion>
<LangVersion>default</LangVersion>
<ProjectGuid>24274C8F-678F-4E4D-98A0-2899163BCCBA</ProjectGuid>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="3.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.11" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
<PackageReference Include="Moq" Version="4.18.2" />
<PackageReference Include="xunit" Version="2.4.2" />
@@ -22,9 +21,10 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CoffeeCard.Library\CoffeeCard.Library.csproj" />
<ProjectReference Include="..\CoffeeCard.WebApi\CoffeeCard.WebApi.csproj" />
</ItemGroup>
</Project>
</Project>
Original file line number Diff line number Diff line change
@@ -632,7 +632,7 @@ public async Task VerifyRegistrationReturnsTrueGivenValidToken()
};
var identitySettings = new IdentitySettings
{
TokenKey = "This is a long test token key"
TokenKey = "SuperLongSigningKeySuperLongSigningKey"
};
var tokenService = new TokenService(identitySettings, new ClaimsUtilities(context));

@@ -697,7 +697,7 @@ private static string WriteTokenString(IEnumerable<Claim> claims)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes("This is a long test token key"));
Encoding.UTF8.GetBytes("SuperLongSigningKeySuperLongSigningKey"));

var jwt = new JwtSecurityToken("AnalogIO",
"Everyone",
6 changes: 3 additions & 3 deletions coffeecard/CoffeeCard.Tests.Unit/Services/TokenServiceTest.cs
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ public TokenServiceTest()
_identity = new IdentitySettings();

//creates the key for signing the token
const string keyForHmacSha256 = "signingKey";
const string keyForHmacSha256 = "SuperLongSigningKey";
_identity.TokenKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(keyForHmacSha256)).ToString();
}

@@ -99,7 +99,7 @@ public async Task ValidateTokenGivenInvalidSignedTokenReturnsFalse()
await using (context)
{
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes("Invalid signing key"));
Encoding.UTF8.GetBytes("Super long invalid signing key, longer than 256bytes"));

var jwt = new JwtSecurityToken("AnalogIO",
"Everyone",
@@ -213,4 +213,4 @@ private CoffeeCardContext GenerateCoffeeCardContext(string uniqueString)
return new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings);
}
}
}
}
30 changes: 13 additions & 17 deletions coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
<LangVersion>8</LangVersion>
<LangVersion>default</LangVersion>
<ProjectGuid>5562C898-513F-493A-A335-417C39476714</ProjectGuid>
<UserSecretsId>d3bbf778-c5fe-4240-b2ca-dfa64082cc0e</UserSecretsId>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@@ -30,29 +30,25 @@
<PackageReference Include="Microsoft.ApplicationInsights.Profiler.AspNetCore" Version="2.5.1" />
<PackageReference Include="Microsoft.AspNetCore.ApplicationInsights.HostingStartup" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.11">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Logging.ApplicationInsights" Version="2.21.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageReference Include="NetEscapades.Configuration.Validation" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.11" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.10" />
<PackageReference Include="NSwag.AspNetCore" Version="13.17.0" />
<PackageReference Include="NSwag.AspNetCore" Version="14.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.ApplicationInsights" Version="4.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.25.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />

</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CoffeeCard.Common\CoffeeCard.Common.csproj" />
@@ -62,4 +58,4 @@
<ItemGroup>
<Folder Include="logs" />
</ItemGroup>
</Project>
</Project>
4 changes: 2 additions & 2 deletions coffeecard/CoffeeCard.WebApi/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["CoffeeCard.WebApi/CoffeeCard.WebApi.csproj", "CoffeeCard.WebApi/"]
COPY ["CoffeeCard.Common/CoffeeCard.Common.csproj", "CoffeeCard.Common/"]
6 changes: 3 additions & 3 deletions coffeecard/CoffeeCard.WebApi/Startup.cs
Original file line number Diff line number Diff line change
@@ -241,7 +241,7 @@ private static void GenerateOpenApiDocument(IServiceCollection services)
config.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("apikey"));

// Assume not null as default unless parameter is marked as nullable
config.DefaultReferenceTypeNullHandling = ReferenceTypeNullHandling.NotNull;
// config.DefaultReferenceTypeNullHandling = ReferenceTypeNullHandling.NotNull;
});
}
}
@@ -260,7 +260,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVers
app.UseHsts();

app.UseOpenApi();
app.UseSwaggerUi3();
app.UseSwaggerUi();

app.UseHttpsRedirection();

@@ -289,4 +289,4 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVers
}
}
#pragma warning restore CS1591
}
}
4 changes: 2 additions & 2 deletions coffeecard/CoffeeCard.WebApi/appsettings.json
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
"SchemaName": "dbo"
},
"IdentitySettings": {
"TokenKey": "local-development-token",
"TokenKey": "super-long-local-development-token",
"AdminToken": "local-development-admintoken",
"ApiKey": "local-development-apikey"
},
@@ -43,7 +43,7 @@
"Default": "Information",
"Override": {
"System": "Information",
"Microsoft": "Warning"
"Microsoft": "Information"
}
},
"WriteTo": [
20 changes: 16 additions & 4 deletions coffeecard/CoffeeCardAPI.sln
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29806.167
@@ -13,11 +13,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.MobilePay", "Cof
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.Common", "CoffeeCard.Common\CoffeeCard.Common.csproj", "{2CCAF827-E341-48FC-ABCE-7EDFA3E84E65}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoffeeCard.Library", "CoffeeCard.Library\CoffeeCard.Library.csproj", "{F05C6E90-C02D-43BF-8BBB-615785C465DF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.Library", "CoffeeCard.Library\CoffeeCard.Library.csproj", "{F05C6E90-C02D-43BF-8BBB-615785C465DF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoffeeCard.Models", "CoffeeCard.Models\CoffeeCard.Models.csproj", "{0BF48733-C3DF-4006-BD25-F5340710B5FA}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.Models", "CoffeeCard.Models\CoffeeCard.Models.csproj", "{0BF48733-C3DF-4006-BD25-F5340710B5FA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoffeeCard.MobilePay.GenerateApi", "CoffeeCard.MobilePay.GenerateApi\CoffeeCard.MobilePay.GenerateApi.csproj", "{D295CCD7-DDB7-477D-82B6-53AFA97F5749}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.MobilePay.GenerateApi", "CoffeeCard.MobilePay.GenerateApi\CoffeeCard.MobilePay.GenerateApi.csproj", "{D295CCD7-DDB7-477D-82B6-53AFA97F5749}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.Common.Test", "CoffeeCard.Tests.Common\CoffeeCard.Tests.Common.csproj", "{938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoffeeCard.Generators", "CoffeeCard.Generators\CoffeeCard.Generators.csproj", "{BE332D7E-FD07-4878-B7E3-A06988F0C382}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -57,6 +61,14 @@ Global
{D295CCD7-DDB7-477D-82B6-53AFA97F5749}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D295CCD7-DDB7-477D-82B6-53AFA97F5749}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D295CCD7-DDB7-477D-82B6-53AFA97F5749}.Release|Any CPU.Build.0 = Release|Any CPU
{938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}.Release|Any CPU.Build.0 = Release|Any CPU
{BE332D7E-FD07-4878-B7E3-A06988F0C382}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BE332D7E-FD07-4878-B7E3-A06988F0C382}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BE332D7E-FD07-4878-B7E3-A06988F0C382}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BE332D7E-FD07-4878-B7E3-A06988F0C382}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
6 changes: 3 additions & 3 deletions coffeecard/global.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"sdk": {
"version": "6.0.0",
"rollForward": "latestMajor",
"allowPrerelease": true
"version": "8.0.0",
"rollForward": "latestMinor",
"allowPrerelease": false
}
}

Unchanged files with check annotations Beta

StatusCode = statusCode;
}
protected ApiException(SerializationInfo info, StreamingContext context) : base(info, context)

Check warning on line 21 in coffeecard/CoffeeCard.Common/Errors/ApiException.cs

GitHub Actions / build / Build codebase / Build and test analog-core

'Exception.Exception(SerializationInfo, StreamingContext)' is obsolete: 'This API supports obsolete formatter-based serialization. It should not be called or extended by application code.' (https://aka.ms/dotnet-warnings/SYSLIB0051)
{
StatusCode = info.GetInt32("StatusCode");
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)

Check warning on line 26 in coffeecard/CoffeeCard.Common/Errors/ApiException.cs

GitHub Actions / build / Build codebase / Build and test analog-core

Member 'ApiException.GetObjectData(SerializationInfo, StreamingContext)' overrides obsolete member 'Exception.GetObjectData(SerializationInfo, StreamingContext)'. Add the Obsolete attribute to 'ApiException.GetObjectData(SerializationInfo, StreamingContext)'.
{
base.GetObjectData(info, context);

Check warning on line 28 in coffeecard/CoffeeCard.Common/Errors/ApiException.cs

GitHub Actions / build / Build codebase / Build and test analog-core

'Exception.GetObjectData(SerializationInfo, StreamingContext)' is obsolete: 'This API supports obsolete formatter-based serialization. It should not be called or extended by application code.' (https://aka.ms/dotnet-warnings/SYSLIB0051)
info.AddValue("StatusCode", StatusCode);
}
/// Voucher code to be redeemed in the app
/// </summary>
[Required]
public string VoucherCode { get; set; }

Check warning on line 23 in coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Voucher/IssueVoucherResponse.cs

GitHub Actions / build / Build codebase / Build and test analog-core

Non-nullable property 'VoucherCode' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
/// <summary>
/// The id of the product the voucher code is for
/// The name of the product the voucher code is for
/// </summary>
[Required]
public string ProductName { get; set; }

Check warning on line 35 in coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Voucher/IssueVoucherResponse.cs

GitHub Actions / build / Build codebase / Build and test analog-core

Non-nullable property 'ProductName' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
/// <summary>
/// The date the voucher code was created
public class LoginAttempt
{
public LoginAttempt()

Check warning on line 10 in coffeecard/CoffeeCard.Models/Entities/LoginAttempt.cs

GitHub Actions / build / Build codebase / Build and test analog-core

Non-nullable property 'User' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
{
Time = DateTime.UtcNow;
}