Skip to content
This repository has been archived by the owner on Oct 28, 2024. It is now read-only.

break out into Core, Application, Infrastructure, and Web #311

Merged
merged 8 commits into from
Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 3 additions & 3 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
],
"containerEnv": {
"BINDLE_URL": "http://localhost:8080/v1",
"HIPPO_URL": "https://localhost:5001",
"HIPPO_URL": "https://localhost:5309",
"GLOBAL_AGENT_FORCE_GLOBAL_AGENT": "false",
// This places bindle server data in the workspace so that state is retained across multiple invocations of the bindle server
// Delete this folder and Hippo/hippo.db.* files to reset Hippo
Expand All @@ -40,7 +40,7 @@
// restore and build the application, add the dev cert.
"postCreateCommand": "cd Hippo && dotnet restore && npm run build && dotnet build && dotnet dev-certs https",
"portsAttributes": {
"5001": {
"5309": {
"label": "Hippo HTTPS Port",
"protocol": "https"
},
Expand All @@ -61,4 +61,4 @@
"protocol": "http"
}
}
}
}
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
* text=auto eol=lf
*.{cmd,[cC][mM][dD]} text eol=crlf
*.{bat,[bB][aA][tT]} text eol=crlf
*.{bat,[bB][aA][tT]} text eol=crlf
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ updates:
time: "08:00"
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-patch"]
update-types: ["version-update:semver-patch"]
14 changes: 3 additions & 11 deletions .github/release-image/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -71,30 +71,22 @@ ENV GLOBAL_AGENT_FORCE_GLOBAL_AGENT ${FORCE_GLOBAL_AGENT}

# Docker/WSL2 has an issue exposing ports from localhost. the following tries to work around this issue.
# See https://github.com/microsoft/WSL/issues/4983

ARG HIPPO_HTTP_PORT="5000"
ARG HIPPO_HTTPS_PORT="5001"
ARG HIPPO_HTTP_PORT="5308"
ARG HIPPO_HTTPS_PORT="5309"

ARG HIPPOURL=https://localhost:${HIPPO_HTTPS_PORT}
ENV HIPPO_URL ${HIPPOURL}

ARG YARP_HTTP_PORT="5002"
ARG YARP_HTTPS_PORT="5003"

ENV ASPNETCORE_URLS http://0.0.0.0:${HIPPO_HTTP_PORT};https://0.0.0.0:${HIPPO_HTTPS_PORT}
ENV HIPPO_REVERSE_PROXY_KESTREL__ENDPOINTS__HTTP__URL http://0.0.0.0:${YARP_HTTP_PORT}
ENV HIPPO_REVERSE_PROXY_KESTREL__ENDPOINTS__HTTPS__URL https://0.0.0.0:${YARP_HTTPS_PORT}

# Generate certs for hippo-server and proxy

WORKDIR /data/certs
RUN openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout localhost.key -out localhost.crt -config /hippo/certs/localhost.conf && openssl pkcs12 -export -out localhost.pfx -inkey localhost.key -in localhost.crt -password pass: && sudo chgrp ${USER} localhost.pfx && chmod g+r localhost.pfx
RUN cp /data/certs/localhost.crt /usr/local/share/ca-certificates && update-ca-certificates
ENV KESTREL__CERTIFICATES__DEFAULT__PATH /data/certs/localhost.pfx
ENV HIPPO_REVERSE_PROXY_KESTREL__CERTIFICATES__DEFAULT__PATH /data/certs/localhost.pfx

# Set the data source to a local folder that can be mounted from the host.

ENV CONNECTIONSTRINGS__HIPPO Data Source=/data/hippo/hippo.db;Cache=Shared

WORKDIR /hippo
Expand All @@ -103,4 +95,4 @@ WORKDIR /hippo

USER 1000

ENTRYPOINT if [ -z ${BINDLE_PASSWORD} ]; then export BINDLE_PASSWORD=$(openssl rand -base64 12);echo export BINDLE_PASSWORD=${BINDLE_PASSWORD} >> ~/.bashrc; fi && echo ${BINDLE_PASSWORD}|htpasswd -Bic /data/bindleserver/bindle-htpasswd ${BINDLE_USERNAME} && RUST_LOG=info bindle-server -i ${BINDLE_LISTEN_ADDRESS} --htpasswd-file /data/bindleserver/bindle-htpasswd -d /data/bindleserver >> /data/logs/bindle-server.log 2>&1 & ./hippo-server >> /data/logs/hippo-server.log 2>&1
ENTRYPOINT if [ -z ${BINDLE_PASSWORD} ]; then export BINDLE_PASSWORD=$(openssl rand -base64 12);echo export BINDLE_PASSWORD=${BINDLE_PASSWORD} >> ~/.bashrc; fi && echo ${BINDLE_PASSWORD}|htpasswd -Bic /data/bindleserver/bindle-htpasswd ${BINDLE_USERNAME} && RUST_LOG=info bindle-server -i ${BINDLE_LISTEN_ADDRESS} --htpasswd-file /data/bindleserver/bindle-htpasswd -d /data/bindleserver >> /data/logs/bindle-server.log 2>&1 & ./hippo-server >> /data/logs/hippo-server.log 2>&1
2 changes: 1 addition & 1 deletion .github/release-image/localhost.conf
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ keyUsage = keyCertSign, cRLSign, digitalSignature,keyEncipherment
DNS.1 = localhost
DNS.2 = 127.0.0.1
DNS.3 = *.localhost
DNS.4 = *.hippofactory.io
DNS.4 = *.hippofactory.io
2 changes: 1 addition & 1 deletion .github/workflows/configuration.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@
"labels": []
}
]
}
}
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# Artifacts
hippo.db*
*.db*

# User-specific files
*.rsuser
Expand Down
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/Hippo/bin/Debug/net6.0/hippo-server.dll",
"program": "${workspaceFolder}/src/Web/bin/Debug/net6.0/Hippo.Web.dll",
"args": [],
"cwd": "${workspaceFolder}/Hippo",
"cwd": "${workspaceFolder}/src/Web",
"stopAtEntry": false,
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
"serverReadyAction": {
Expand Down
8 changes: 4 additions & 4 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"type": "process",
"args": [
"build",
"${workspaceFolder}/Hippo/Hippo.csproj",
"${workspaceFolder}/src/Web/Web.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
Expand All @@ -19,7 +19,7 @@
"type": "process",
"args": [
"publish",
"${workspaceFolder}/Hippo/Hippo.csproj",
"${workspaceFolder}/src/Web/Web.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
Expand All @@ -32,11 +32,11 @@
"args": [
"watch",
"run",
"${workspaceFolder}/Hippo/Hippo.csproj",
"${workspaceFolder}/src/Web/Web.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}
}
68 changes: 48 additions & 20 deletions Hippo.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,23 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CAA698E8-2A2C-4523-AC31-1513B0AB3633}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A432DA6D-ADCE-4EA1-9697-7A637F75605D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hippo", "src\Hippo\Hippo.csproj", "{1E2837B6-0B9D-40C1-A0DB-0416B89BF929}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Application", "src\Application\Application.csproj", "{96764F9E-66BB-4F64-A1BA-DE92537996E1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{4AA8306D-E862-4CC2-8F8C-1A7E1B714201}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "src\Core\Core.csproj", "{1FD50DE9-0E1C-413D-B034-0266835574C6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hippo.FunctionalTests", "tests\Hippo.FunctionalTests\Hippo.FunctionalTests.csproj", "{CDCBB1D6-880E-4C43-891B-C7DBB4A50654}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "src\Infrastructure\Infrastructure.csproj", "{DBD7AE2C-2405-45D5-AEE5-CF46D3200138}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hippo.UnitTests", "tests\Hippo.UnitTests\Hippo.UnitTests.csproj", "{3CA6E316-4C70-4123-96A4-B82EFC269396}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web", "src\Web\Web.csproj", "{AE9D2078-6A9E-4451-A3E6-79491749902E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{3043D016-B9BF-4706-9773-3D58457A78AC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Application.UnitTests", "tests\Application.UnitTests\Application.UnitTests.csproj", "{AE958DF1-B480-4556-A68C-E042072DB7A6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.UnitTests", "tests\Core.UnitTests\Core.UnitTests.csproj", "{0BFC9718-3107-4E48-B952-C0B345A55A20}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hippo.FunctionalTests", "tests\Hippo.FunctionalTests\Hippo.FunctionalTests.csproj", "{8C25A909-52B2-4326-BF00-23C053376EB5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -22,22 +30,42 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1E2837B6-0B9D-40C1-A0DB-0416B89BF929}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1E2837B6-0B9D-40C1-A0DB-0416B89BF929}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E2837B6-0B9D-40C1-A0DB-0416B89BF929}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E2837B6-0B9D-40C1-A0DB-0416B89BF929}.Release|Any CPU.Build.0 = Release|Any CPU
{CDCBB1D6-880E-4C43-891B-C7DBB4A50654}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CDCBB1D6-880E-4C43-891B-C7DBB4A50654}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CDCBB1D6-880E-4C43-891B-C7DBB4A50654}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CDCBB1D6-880E-4C43-891B-C7DBB4A50654}.Release|Any CPU.Build.0 = Release|Any CPU
{3CA6E316-4C70-4123-96A4-B82EFC269396}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3CA6E316-4C70-4123-96A4-B82EFC269396}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3CA6E316-4C70-4123-96A4-B82EFC269396}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3CA6E316-4C70-4123-96A4-B82EFC269396}.Release|Any CPU.Build.0 = Release|Any CPU
{96764F9E-66BB-4F64-A1BA-DE92537996E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{96764F9E-66BB-4F64-A1BA-DE92537996E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96764F9E-66BB-4F64-A1BA-DE92537996E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96764F9E-66BB-4F64-A1BA-DE92537996E1}.Release|Any CPU.Build.0 = Release|Any CPU
{1FD50DE9-0E1C-413D-B034-0266835574C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1FD50DE9-0E1C-413D-B034-0266835574C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1FD50DE9-0E1C-413D-B034-0266835574C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1FD50DE9-0E1C-413D-B034-0266835574C6}.Release|Any CPU.Build.0 = Release|Any CPU
{DBD7AE2C-2405-45D5-AEE5-CF46D3200138}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DBD7AE2C-2405-45D5-AEE5-CF46D3200138}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DBD7AE2C-2405-45D5-AEE5-CF46D3200138}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DBD7AE2C-2405-45D5-AEE5-CF46D3200138}.Release|Any CPU.Build.0 = Release|Any CPU
{AE9D2078-6A9E-4451-A3E6-79491749902E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE9D2078-6A9E-4451-A3E6-79491749902E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE9D2078-6A9E-4451-A3E6-79491749902E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE9D2078-6A9E-4451-A3E6-79491749902E}.Release|Any CPU.Build.0 = Release|Any CPU
{AE958DF1-B480-4556-A68C-E042072DB7A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE958DF1-B480-4556-A68C-E042072DB7A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE958DF1-B480-4556-A68C-E042072DB7A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE958DF1-B480-4556-A68C-E042072DB7A6}.Release|Any CPU.Build.0 = Release|Any CPU
{0BFC9718-3107-4E48-B952-C0B345A55A20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0BFC9718-3107-4E48-B952-C0B345A55A20}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0BFC9718-3107-4E48-B952-C0B345A55A20}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0BFC9718-3107-4E48-B952-C0B345A55A20}.Release|Any CPU.Build.0 = Release|Any CPU
{8C25A909-52B2-4326-BF00-23C053376EB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8C25A909-52B2-4326-BF00-23C053376EB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8C25A909-52B2-4326-BF00-23C053376EB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8C25A909-52B2-4326-BF00-23C053376EB5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{1E2837B6-0B9D-40C1-A0DB-0416B89BF929} = {CAA698E8-2A2C-4523-AC31-1513B0AB3633}
{CDCBB1D6-880E-4C43-891B-C7DBB4A50654} = {4AA8306D-E862-4CC2-8F8C-1A7E1B714201}
{3CA6E316-4C70-4123-96A4-B82EFC269396} = {4AA8306D-E862-4CC2-8F8C-1A7E1B714201}
{96764F9E-66BB-4F64-A1BA-DE92537996E1} = {A432DA6D-ADCE-4EA1-9697-7A637F75605D}
{1FD50DE9-0E1C-413D-B034-0266835574C6} = {A432DA6D-ADCE-4EA1-9697-7A637F75605D}
{DBD7AE2C-2405-45D5-AEE5-CF46D3200138} = {A432DA6D-ADCE-4EA1-9697-7A637F75605D}
{AE9D2078-6A9E-4451-A3E6-79491749902E} = {A432DA6D-ADCE-4EA1-9697-7A637F75605D}
{AE958DF1-B480-4556-A68C-E042072DB7A6} = {3043D016-B9BF-4706-9773-3D58457A78AC}
{0BFC9718-3107-4E48-B952-C0B345A55A20} = {3043D016-B9BF-4706-9773-3D58457A78AC}
{8C25A909-52B2-4326-BF00-23C053376EB5} = {3043D016-B9BF-4706-9773-3D58457A78AC}
EndGlobalSection
EndGlobal
6 changes: 3 additions & 3 deletions scripts/build-image.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ dotnet publish Hippo/Hippo.csproj -c Release --self-contained -r linux-x64

cd $ROOT_DIR/.github/release-image

mkdir -p $ROOT_DIR/Hippo/bin/Release/net5.0/linux-x64/publish/certs
cp localhost.conf $ROOT_DIR/Hippo/bin/Release/net5.0/linux-x64/publish/certs
docker build -t hippo -f $ROOT_DIR/.github/release-image/Dockerfile $ROOT_DIR/Hippo/bin/Release/net5.0/linux-x64/publish
mkdir -p $ROOT_DIR/src/Web/bin/Release/net6.0/linux-x64/publish/certs
cp localhost.conf $ROOT_DIR/src/Web/bin/Release/net6.0/linux-x64/publish/certs
docker build -t hippo -f $ROOT_DIR/.github/release-image/Dockerfile $ROOT_DIR/src/Web/bin/Release/net6.0/linux-x64/publish
30 changes: 30 additions & 0 deletions src/Application/Accounts/Commands/CreateAccountCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Hippo.Application.Common.Interfaces;
using MediatR;

namespace Hippo.Application.Accounts.Commands;

public class CreateAccountCommand : IRequest<string>
{
public string? UserName { get; set; }

public string? Password { get; set; }

public string? PasswordConfirm { get; set; }
}

public class CreateAccountCommandHandler : IRequestHandler<CreateAccountCommand, string>
{
private readonly IIdentityService _identityService;

public CreateAccountCommandHandler(IIdentityService identityService)
{
_identityService = identityService;
}

public async Task<string> Handle(CreateAccountCommand request, CancellationToken cancellationToken)
{
var result = await _identityService.CreateUserAsync(request.UserName!, request.Password!);

return result.UserId;
}
}
38 changes: 38 additions & 0 deletions src/Application/Accounts/Commands/CreateAccountCommandValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using FluentValidation;
using Hippo.Application.Common.Interfaces;

namespace Hippo.Application.Accounts.Commands;

public class CreateAccountCommandValidator : AbstractValidator<CreateAccountCommand>
{
private readonly IIdentityService _identityService;
public CreateAccountCommandValidator(IIdentityService identityService)
{
_identityService = identityService;

RuleFor(a => a.UserName)
.MaximumLength(32).WithMessage("username must not exceed 32 characters.")
.MustAsync(BeUniqueUserName).WithMessage("username already exists.")
.NotEmpty();

RuleFor(a => a.Password)
.MinimumLength(8)
.NotEmpty();

RuleFor(a => a.PasswordConfirm)
.Equal(a => a.Password).WithMessage("Passwords do not match");
}

public async Task<bool> BeUniqueUserName(string userName, CancellationToken cancellationToken)
{
try
{
await _identityService.GetUserIdAsync(userName);
return false;
}
catch (Exception)
{
return true;
}
}
}
40 changes: 40 additions & 0 deletions src/Application/Accounts/Commands/CreateTokenCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Hippo.Application.Common.Exceptions;
using Hippo.Application.Common.Interfaces;
using MediatR;

namespace Hippo.Application.Accounts.Commands;

public class CreateTokenCommand : IRequest<TokenInfo>
{
public string UserName { get; set; }

public string Password { get; set; }

public CreateTokenCommand(string username, string password)
{
UserName = username;
Password = password;
}
}

public class CreateTokenCommandHandler : IRequestHandler<CreateTokenCommand, TokenInfo>
{
private readonly IIdentityService _identityService;
private readonly ITokenService _tokenService;

public CreateTokenCommandHandler(IIdentityService identityService, ITokenService tokenService)
{
_identityService = identityService;
_tokenService = tokenService;
}

public async Task<TokenInfo> Handle(CreateTokenCommand request, CancellationToken cancellationToken)
{
if (await _identityService.CheckPasswordAsync(request.UserName, request.Password))
{
return _tokenService.CreateSecurityToken(await _identityService.GetUserIdAsync(request.UserName));
}

throw new LoginFailedException();
}
}
38 changes: 38 additions & 0 deletions src/Application/Accounts/Commands/LoginAccountCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Hippo.Application.Common.Exceptions;
using Hippo.Application.Common.Interfaces;
using MediatR;

namespace Hippo.Application.Accounts.Commands;

public class LoginAccountCommand : IRequest
{
public string? UserName { get; set; }

public string? Password { get; set; }

public bool RememberMe { get; set; }
}

public class LoginAccountCommandHandler : IRequestHandler<LoginAccountCommand>
{
private readonly IIdentityService _identityService;
private readonly ISignInService _signInService;

public LoginAccountCommandHandler(IIdentityService identityService, ISignInService signInService)
{
_identityService = identityService;
_signInService = signInService;
}

public async Task<Unit> Handle(LoginAccountCommand request, CancellationToken cancellationToken)
{
var result = await _signInService.PasswordSignInAsync(request.UserName!, request.Password!, request.RememberMe);

if (!result.Succeeded)
{
throw new LoginFailedException(result.Errors);
}

return Unit.Value;
}
}
Loading