A .NET scaffolding tool to help you stop worrying about boilerplate and focus on your business logic 🚀
MIT License
Bot releases are hidden (Show)
Published by pdevito3 over 1 year ago
IConfiguration
instead of custom EnvironmentService
launchsetting
to appsettings
UserPolicyHandler
refactorPublished by pdevito3 almost 2 years ago
MigrationHostedService
to automatically apply migrations when starting your projectEnvironmentService
for easy access to environment variablesValidators
and in favor of direct validation in entiy factories and methods.ValidationException
UserPolicyHandler
to include a HasPermission()
implementationPublished by pdevito3 almost 2 years ago
Published by pdevito3 almost 2 years ago
Published by pdevito3 almost 2 years ago
Test Utility Mapper for Unit Tests
New User
and UserRole
entities when using auth
Your auth server will still store users, but it's only role is now AuthN. The basic premise is still the same though
Authorize
attributes on your controllers will guard for application level access by checking if the request has a valid JWT from your auth server
Feature and business level access can be handled in your MediatR handlers with HeimGuard, for example:
await _heimGuard.HasPermissionAsync(Permissions.CanAddRecipe)
? Ok()
: Forbidden();
// OR...
await _heimGuard.MustHavePermission<ForbiddenAccessException>(Permissions.CanAddRecipe);
As usual, this will use the UserPolicyHandler
logic to check if a user meets the given criteria. The implementation of HeimGuard's UserPolicyHandler
in the scaffolding will still check the token to see who you are Authenticated as, but will get the user's roles based on the configuration for that authenticated user within the boundary using the new concepts and logic described below.
Your auth server will still store users and their metadata that we want for AuthN and the new User
entity will capture user metadata to be easily accessed in your app. Say you want to send back a list of recipes and show who created them, this gives you that info without having to reach out to your auth server
Identifier
property, which should generally be populated with the NameIdentifier
on your token.Roles will also not be dictated by your auth server anymore and will be stored in the context of your boundary (not the shared kernel anymore, though you could move them there if it makes sense for your setup). They are still restricted with a smart enum to Super Admin
and User
, but feel free to modify or extend these as you wish.
When starting your api for the first time, you will not have any User
or UserRole
entries. To add an initial root user, you just need to authenticate (e.g. swagger) and hit a protected endpoint. This is because, by default, the UserPolicyHandler
will now check if you have any users and, if not, add the requesting user as a root user with Super Admin
access.
If you have multiple boundaries, you can make the call on how you manage things. By default each boundary will store its own set of users and roles. This might be useful if say you want to manage users in your billing boundary separate from your inventory boundary, but you may want to combine them too. Feel free to consolidate this as you wish if desired.
Users can be managed at the /users
endpoints. This includes adding and removing their roles as user roles have no standalone meaning without a user.
Updated functional tests to properly handle the token setup
New RolesController
and PermissionsController
when using auth
New Email
Value Object. Used on User
if you want to see it in use
Functional tests use a docker db
Simple fake Builder
scaffold for each entity
Add Date Time Provider
Fakers for Address
Various new commands for working with the NextJS Template, but it's still in progress so not documenting this much yet.
Query
or Command
respectivelyjboss
to sleighzy
for Apple Silicon supportTask<int>
Development
Cors has AllowCredentials
GetList
feature defaults to -CreatedOn
sort order if none is givenDateOnly
serialization supportNewtonsoft
-> System.Text.Json
Update
feature calls update in repository8632
to NoWarn
list in API projects -- [CS8632] The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
docker-compose
MonetaryAmount
VOCanReadRecipes
). All permissions will use the entity plural.AsNoTracking
AddSwaggerGen
Respawn
to v6 with simplified TestFixture
setupMoq
package in shared test helperUpdate
methods return entity instanceadd bff
and add bff entity
commandsPublished by pdevito3 about 2 years ago
Published by pdevito3 about 2 years ago
Published by pdevito3 about 2 years ago
WebAppServiceConfiguration
if(builder.Environment.EnvironmentName != Consts.Testing.FunctionalTestingEnvName)
{
var typeAdapterConfig = TypeAdapterConfig.GlobalSettings;
typeAdapterConfig.Scan(Assembly.GetExecutingAssembly());
var mapperConfig = new Mapper(typeAdapterConfig);
builder.Services.AddSingleton<IMapper>(mapperConfig);
}
var typeAdapterConfig = TypeAdapterConfig.GlobalSettings;
typeAdapterConfig.Scan(Assembly.GetExecutingAssembly());
var mapperConfig = new Mapper(typeAdapterConfig);
services.AddSingleton<IMapper>(mapperConfig);
Published by pdevito3 about 2 years ago
Published by pdevito3 about 2 years ago
Published by pdevito3 about 2 years ago
Published by pdevito3 about 2 years ago
ServiceCollectionServiceExtensions
in Integration TextFixture
for easier service mocking with ReplaceServiceWithSingletonMock
Add default database configuration abstraction for each entity along with db context usage. Includes value object examples
Json serialization extension to better handle DateOnly
and TimeOnly
in swagger
Common value object scaffolding (Address
, Percent
, MonetaryAmount
)
Address
Port customization for RMQ broker and ui
Added ForbiddenAccessException
and InvalidSmartEnumPropertyName
handling to ErrorHandlerFilterAttribute
Removed faulty producer assertion in integration tests for better performance
Remove .AddFluentValidation(cfg => {{ cfg.AutomaticValidationEnabled = false; }});
from registration as validation should be happening directly at domain level
Integration and functional tests parallelized
Integration tests updated to use DotNet.Testcontainers
for simpler docker db setup
Moved pagination, filter, and sort testing to unit tests
UserPolicyHandler
uses RolePermission repo and handles finding no roles
Value Object cleanup
Better migration warning on integration tests
Move most UserPolicyHandler
tests to unit tests
Move CurrentUserServiceTests
test dir
Update LocalConfig
to Consts
for all constants in app (other than permissions and roles)
Update AutoBogus
to AutobogusLifesupport
to support .NET 6 and UTC
RequireHttpsMetadata
off in dev for BFF and boundaries
SuperAdmin
text to Super Admin
UserPolicyHandler
can accommodate realm roles for keycloak
Moved permission guards to each feature handler (still using Authorize
attribute on controllers for authenication check).
Simplified return on batch add feature
CLI updates for auth server and bff scaffolds
Migrated mapper to use Mapster
instead of Automapper
for easier value object usage and better performance. To migrate your project
Update your mappers to look like this (almost identicial to Automapper
:
public class AuthorMappings : IRegister
{
public void Register(TypeAdapterConfig config)
{
config.NewConfig<AuthorDto, Author>()
.TwoWays();
config.NewConfig<AuthorForCreationDto, Author>()
.TwoWays();
config.NewConfig<AuthorForUpdateDto, Author>()
.TwoWays();
}
}
Manaully do mapping in your entity factories (due to recurssive nature of the dtos and mapping happining in the factories)
Update usings to using MapsterMapper;
Your ProjectTo
mappings should look like this:
var dtoCollection = appliedCollection
.ProjectToType<AuthorDto>();
and import:
using MapsterMapper;
using Mapster;
Your registration should now be:
var config = TypeAdapterConfig.GlobalSettings;
builder.Services.AddSingleton(config);
builder.Services.AddScoped<IMapper, ServiceMapper>();
Published by pdevito3 over 2 years ago
Open Telemetry and Jaeger tracing support
ValueObject
class scaffolding to SharedKernel
Domain Event support for all BaseEntities
. Automatically scaffolded for the Create
and Update
methods that call messages in a new DomainEvents
directory under that entity. It works by adding messages to a new DomainEvents
prop on each entity and publishing all messages on an EF save using MediatR.
INotificationHandler
like normal.Smart enum property support. Just add a property and give it a list of options using the SmartNames
property and you're good to go. They will all be strings with smart enum backing. Attributes like filtering and sorting are supported
Entities:
- Name: Recipe
Features:
#...
Properties:
- Name: Title
Type: string
CanFilter: true
CanSort: true
- Name: Visibility
SmartNames:
- Public
- Friends Only
- Private
CanFilter: true
CanSort: true
CLI commands no longer use :
and use the more traditional space delimiter. For exmaple, craftsman new example
Moved from old Startup model to new Program only for .NET 6. Includes updating test projects and service registrations for compatible setup
All features will now use a repository instead of using dbcontext directly.
Batch does not require a dbset name anymore, but does require a plural entity name for the FK if using one. Functionally, this is the same as before just with a new name for the prop: ParentEntityPlural
Entity props now virtual
by default with a protected
constructor for mocking in unit tests. This is mostly for foreign entities (since we don't have EF to populate our foreign entities in unit tests), but in order to have our mocks accurately reflect all our props, we need to make them virtual.
Add FakeItEasy
and FakeItEasyAnalyzer
to unit test project
Colocate DTOs with entities by default. Can be moved to shared kernel when needed
Default db provider set to postgres
Removed ?
's on strings in BaseEntity
Update integration test consumer registration to non-obsolete model
Testing cleanup
Performance optimizations for integration and functional tests
Removed sort integration tests
Messages get a class for better typing as well as an interface.
Add postman client to example scaffolding
Add support for offline access and client secret requirement settings for client credentials clients
Automatically add a SuperAdmin
role claim to machines
Updated services to use Newtonsoft to keep support for patchdocs. System.Text.Json
is still available if patchdocs aren't needed for a project.
Integration Test TestBase
has global autobogus settings
Permission and role validations are not case sensitive
Added client_role
to UserPolicyHandler
role check to accomodate machines with a new scaffolded test.
TrustServerCertificate=True;
Published by pdevito3 over 2 years ago
useQuery
import to GET api in BFFPublished by pdevito3 over 2 years ago
Published by pdevito3 over 2 years ago
last minute commits before a release without testing is asking for trouble...
Published by pdevito3 over 2 years ago
A Dockerfile
and .dockerignore
will be added to each bounded context automatically (except BFFs)
A docker-compose.yaml
will be added to your solution root by default for local development
Just run docker-compose up --build
to spin up your databases (and RMQ if needed)
Then set an env and apply migrations. For a postgres example:
env
Powershell
$Env:ASPNETCORE_ENVIRONMENT = "anything"
Bash
export ASPNETCORE_ENVIRONMENT=anything
dotnet ef database update
or dotnet ef database update --connection "Host=localhost;Port=3125;Database=dev_recipemanagement;Username=postgres;Password=postgres"
SA
will always be default user for sqlserver so it can work properly
If no ports are given for api or db, they'll be auto assigned a free port on your machine
New john
user to auth server (with no role)
Login hints for auth server
Minor helper override on fake generators
New add:bff
command to add a bff to your solution
New add:bffentity
command to add entities to your bff
Basic unit test scaffolding for create and update methods
Unit tests for updating rolepermissions
Fixed bug in Add
feature that had a chained action after ProjectTo
. They will now be filtered like so:
var {entityNameLowercase}List = await _db.{entity.Plural}
.AsNoTracking()
.FirstOrDefaultAsync({entity.Lambda} => {entity.Lambda}.{primaryKeyPropName} == {entityNameLowercase}.{primaryKeyPropName}, cancellationToken);
return _mapper.Map<{readDto}>({entityNameLowercase}List);
Removed ProjectTo
from GetRecord
feature in favor of direct mapper.
Initial commit will use system git user and email as author. Courtesy of @sshquack
Id
on BaseEntity
is sortable and filterable by default
Minor logging updates for better json formatting and more information in prod
GET record, PUT, and DELETE all have typed ids (e.g. {id:guid}
) on their controllers
Development
environment uses a connection string to an actual database now, instead of an in memory db. This can easily be spun up with a docker-compose
for local development
Environment is now a singular object that will take in values for local environment variables for development and placed in launch settings and your docker compose. When deploying to other environments, you will use these same environment variables, but pass the appropriate value for that env.
AuthSettings
object like we do for broker settingsConnectionString
from env. Docker connection will be added automatically in launch settingsEnvironmentName
as it will always be Development
Removed unused mapper from delete feature
Updated entity property definition with optional ColumnType
attribute
Fixed a bug that broke registration of the bus in development env
Logger modifications
Cleanup batch add feature
Updated Created
response for batch add
Use entity plural directory for tests
MassTransit bumped to v8
Bumped Nuget packages to latest
Updated checkpoint in test fixture for major version bump
Published by pdevito3 over 2 years ago
add:entity
command will now use the correct solution folderPublished by pdevito3 over 2 years ago
Lots of updates here! Highlights are
DDD promoted entities (private setters, factory methods, associated fakers)
Huge permissions upgrade. Significantly simplified setup which resulted in a new library (HeimGuard) that can be used in any .NET project.
Message bus scaffolding and testing improvements
New register:producer command
Added soft delete capability
Added Shared Kernel
Added Complex example for new:example command
Also, big shout out to @sshquack for his first contributions!
Create
method and an Update
method to promote a DDD workflow
SuperAdmin
role is added by default and will automatically be given all permissions.User
role with also be created. This role will not have any permissions assigned to it by default and can be removed if you would like as long as you add another role in addition to SuperAdmin
. This will allow for integration tests of the UserPolicyHandler
to be fully scoped.CanFEATURENAME
, but can be overridden if desired.ProjectName
, but can be overridden
IsProtected
that, if true, will add an authorization attribute to your endpoint with the PolicyName
and add tests that check for accessUserPolicyHandler
RolePermission
Policies
prop removed from FeatureSetUserRole
and SetUserRoles
methods to integreation tests' TestFixture
for easy role management in integration testsrole
instead of scope
SuperAdmin
and bob is a User
register:producer
command with CLI promptUseSoftDelete
property to the ApiTemplate
which is set to true. When adding an entity after the fact, Craftsman will automatically detect whether or not your project is using soft deletion by checking base entity for the appropriate property.SharedKernel
project at the root to capture DTOs, exceptions, and roles (if using auth)Complex
example for new:example
Updated FK and basic examples to have more features on the entities
Updated tests to work with new private entity workflow
CurrentUserServer has a method to get the User from the ClaimsPrincipal
Swagger question removed from add:feature
as it wasn't being used. Will be set to true.
Removed unused Unauthorized
and Forbidden
MediatR filters
Test Fixture updated to better handle MassTransit
_provider
will always be injected, even when not using MassTransit
The end of the fixture has been slightly updated to look like this:
// MassTransit Harness Setup -- Do Not Delete Comment
_provider = services.BuildServiceProvider();
_scopeFactory = _provider.GetService<IServiceScopeFactory>();
// MassTransit Start Setup -- Do Not Delete Comment
Added several helper methods to the test fixture
Updated the consumer test to use the helper methods
Producer doesn't take in placeholder props
Producer test generated
Minor update to naming of producer in the bus example
Default exchange type now Fanout
for producer and consumer
Added optional (but recommended) DomainDirectory
prop to producers and consumers. This will move them from the EventHandlers
directory and keep them directly with features for better colocation.
Updated the 1:1 relationships to use proper scaffolding.
Updated the FK example to show proper 1:1 relationship
Entities with a Guid prop will no longer have a default of Guid.NewGuid()
Updated default library from NewtonSoft.Json to System.text.Json (https://github.com/pdevito3/craftsman/issues/52)
Took audit fields off of DTO
Bumped LibGit2Sharp to preview for M1 compatibility
batch
along with a functional testing routeIHttpContextAccessor
fixted to a singleton in integration tests' TestFixture
add:feature
batch list options where neededPublished by pdevito3 almost 3 years ago