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

feat(artistalley): submit/delete image with registration #161

Merged
merged 14 commits into from
Aug 20, 2024
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 25 additions & 17 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG MYSQL_VERSION=10.11.8-MariaDB
WORKDIR /app
ENV NUGET_PACKAGES=/dotnet/packages

# Allow results of `dotnet restore` to be cached if there are no changes to dependencies.
COPY ./NuGet.config /app/
COPY ./ef-app_backend-dotnet-core.sln /app/
COPY ./src/Eurofurence.App.Common/Eurofurence.App.Common.csproj /app/src/Eurofurence.App.Common/Eurofurence.App.Common.csproj
COPY ./src/Eurofurence.App.Tools.CliToolBox/Eurofurence.App.Tools.CliToolBox.csproj /app/src/Eurofurence.App.Tools.CliToolBox/Eurofurence.App.Tools.CliToolBox.csproj
COPY ./src/Eurofurence.App.Server.Services/Eurofurence.App.Server.Services.csproj /app/src/Eurofurence.App.Server.Services/Eurofurence.App.Server.Services.csproj
COPY ./src/Eurofurence.App.Server.Web/Eurofurence.App.Server.Web.csproj /app/src/Eurofurence.App.Server.Web/Eurofurence.App.Server.Web.csproj
COPY ./src/Eurofurence.App.Backoffice/Eurofurence.App.Backoffice.csproj /app/src/Eurofurence.App.Backoffice/Eurofurence.App.Backoffice.csproj
COPY ./src/Eurofurence.App.Infrastructure.EntityFramework/Eurofurence.App.Infrastructure.EntityFramework.csproj /app/src/Eurofurence.App.Infrastructure.EntityFramework/Eurofurence.App.Infrastructure.EntityFramework.csproj
COPY ./src/Eurofurence.App.Domain.Model/Eurofurence.App.Domain.Model.csproj /app/src/Eurofurence.App.Domain.Model/Eurofurence.App.Domain.Model.csproj
COPY ./test/Eurofurence.App.Server.Services.Tests/Eurofurence.App.Server.Services.Tests.csproj /app/test/Eurofurence.App.Server.Services.Tests/Eurofurence.App.Server.Services.Tests.csproj
COPY ./test/Eurofurence.App.Server.Web.Tests/Eurofurence.App.Server.Web.Tests.csproj /app/test/Eurofurence.App.Server.Web.Tests/Eurofurence.App.Server.Web.Tests.csproj
COPY ./test/Eurofurence.App.Tests.Common/Eurofurence.App.Tests.Common.csproj /app/test/Eurofurence.App.Tests.Common/Eurofurence.App.Tests.Common.csproj
RUN dotnet restore
COPY ./NuGet.config /app/NuGet.config
RUN --mount=type=cache,target=/dotnet/packages \
--mount=type=cache,target=/dotnet/global-packages \
--mount=type=bind,source=./ef-app_backend-dotnet-core.sln,target=/app/ef-app_backend-dotnet-core.sln \
--mount=type=bind,source=./src/Eurofurence.App.Common/Eurofurence.App.Common.csproj,target=/app/src/Eurofurence.App.Common/Eurofurence.App.Common.csproj \
--mount=type=bind,source=./src/Eurofurence.App.Tools.CliToolBox/Eurofurence.App.Tools.CliToolBox.csproj,target=/app/src/Eurofurence.App.Tools.CliToolBox/Eurofurence.App.Tools.CliToolBox.csproj \
--mount=type=bind,source=./src/Eurofurence.App.Server.Services/Eurofurence.App.Server.Services.csproj,target=/app/src/Eurofurence.App.Server.Services/Eurofurence.App.Server.Services.csproj \
--mount=type=bind,source=./src/Eurofurence.App.Server.Web/Eurofurence.App.Server.Web.csproj,target=/app/src/Eurofurence.App.Server.Web/Eurofurence.App.Server.Web.csproj \
--mount=type=bind,source=./src/Eurofurence.App.Backoffice/Eurofurence.App.Backoffice.csproj,target=/app/src/Eurofurence.App.Backoffice/Eurofurence.App.Backoffice.csproj \
--mount=type=bind,source=./src/Eurofurence.App.Infrastructure.EntityFramework/Eurofurence.App.Infrastructure.EntityFramework.csproj,target=/app/src/Eurofurence.App.Infrastructure.EntityFramework/Eurofurence.App.Infrastructure.EntityFramework.csproj \
--mount=type=bind,source=./src/Eurofurence.App.Domain.Model/Eurofurence.App.Domain.Model.csproj,target=/app/src/Eurofurence.App.Domain.Model/Eurofurence.App.Domain.Model.csproj \
--mount=type=bind,source=./test/Eurofurence.App.Server.Services.Tests/Eurofurence.App.Server.Services.Tests.csproj,target=/app/test/Eurofurence.App.Server.Services.Tests/Eurofurence.App.Server.Services.Tests.csproj \
--mount=type=bind,source=./test/Eurofurence.App.Server.Web.Tests/Eurofurence.App.Server.Web.Tests.csproj,target=/app/test/Eurofurence.App.Server.Web.Tests/Eurofurence.App.Server.Web.Tests.csproj \
--mount=type=bind,source=./test/Eurofurence.App.Tests.Common/Eurofurence.App.Tests.Common.csproj,target=/app/test/Eurofurence.App.Tests.Common/Eurofurence.App.Tests.Common.csproj \
dotnet nuget config set repositoryPath /dotnet/packages --configfile /app/NuGet.config \
&& dotnet nuget config set globalPackagesFolder /dotnet/global-packages --configfile /app/NuGet.config \
&& dotnet restore

COPY ./src/ /app/src/
COPY ./test/ /app/test/
RUN dotnet build src/Eurofurence.App.Server.Web/Eurofurence.App.Server.Web.csproj --configuration Release \
&& dotnet publish src/Eurofurence.App.Tools.CliToolBox/Eurofurence.App.Tools.CliToolBox.csproj --output "/app/artifacts" --configuration Release \
&& dotnet publish src/Eurofurence.App.Server.Web/Eurofurence.App.Server.Web.csproj --output "/app/artifacts" --configuration Release
RUN dotnet tool install --global dotnet-ef \
RUN --mount=type=cache,target=/dotnet/packages \
--mount=type=cache,target=/dotnet/global-packages \
--mount=type=cache,target=/dotnet/artifacts \
--mount=type=bind,source=./ef-app_backend-dotnet-core.sln,target=/app/ef-app_backend-dotnet-core.sln \
dotnet build src/Eurofurence.App.Server.Web/Eurofurence.App.Server.Web.csproj --artifacts-path /dotnet/artifacts --configuration Release \
&& dotnet publish src/Eurofurence.App.Server.Web/Eurofurence.App.Server.Web.csproj --artifacts-path /dotnet/artifacts --no-build --output "/app/artifacts" --configuration Release \
&& dotnet tool install --global dotnet-ef \
&& export PATH="$PATH:/root/.dotnet/tools" \
&& export ASPNETCORE_ENVIRONMENT="sample" \
&& dotnet ef migrations bundle -o "/app/artifacts/db-migration-bundle" -p src/Eurofurence.App.Infrastructure.EntityFramework
Expand Down
41 changes: 24 additions & 17 deletions Dockerfile-backoffice
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,33 @@ FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app

# Allow results of `dotnet restore` to be cached if there are no changes to dependencies.
COPY ./NuGet.config /app/
COPY ./ef-app_backend-dotnet-core.sln /app/
COPY ./src/Eurofurence.App.Common/Eurofurence.App.Common.csproj /app/src/Eurofurence.App.Common/Eurofurence.App.Common.csproj
COPY ./src/Eurofurence.App.Tools.CliToolBox/Eurofurence.App.Tools.CliToolBox.csproj /app/src/Eurofurence.App.Tools.CliToolBox/Eurofurence.App.Tools.CliToolBox.csproj
COPY ./src/Eurofurence.App.Server.Services/Eurofurence.App.Server.Services.csproj /app/src/Eurofurence.App.Server.Services/Eurofurence.App.Server.Services.csproj
COPY ./src/Eurofurence.App.Server.Web/Eurofurence.App.Server.Web.csproj /app/src/Eurofurence.App.Server.Web/Eurofurence.App.Server.Web.csproj
COPY ./src/Eurofurence.App.Backoffice/Eurofurence.App.Backoffice.csproj /app/src/Eurofurence.App.Backoffice/Eurofurence.App.Backoffice.csproj
COPY ./src/Eurofurence.App.Infrastructure.EntityFramework/Eurofurence.App.Infrastructure.EntityFramework.csproj /app/src/Eurofurence.App.Infrastructure.EntityFramework/Eurofurence.App.Infrastructure.EntityFramework.csproj
COPY ./src/Eurofurence.App.Domain.Model/Eurofurence.App.Domain.Model.csproj /app/src/Eurofurence.App.Domain.Model/Eurofurence.App.Domain.Model.csproj
COPY ./test/Eurofurence.App.Server.Services.Tests/Eurofurence.App.Server.Services.Tests.csproj /app/test/Eurofurence.App.Server.Services.Tests/Eurofurence.App.Server.Services.Tests.csproj
COPY ./test/Eurofurence.App.Server.Web.Tests/Eurofurence.App.Server.Web.Tests.csproj /app/test/Eurofurence.App.Server.Web.Tests/Eurofurence.App.Server.Web.Tests.csproj
COPY ./test/Eurofurence.App.Tests.Common/Eurofurence.App.Tests.Common.csproj /app/test/Eurofurence.App.Tests.Common/Eurofurence.App.Tests.Common.csproj
RUN dotnet restore
COPY ./NuGet.config /app/NuGet.config
RUN --mount=type=cache,target=/dotnet/packages \
--mount=type=cache,target=/dotnet/global-packages \
--mount=type=bind,source=./ef-app_backend-dotnet-core.sln,target=/app/ef-app_backend-dotnet-core.sln \
--mount=type=bind,source=./src/Eurofurence.App.Common/Eurofurence.App.Common.csproj,target=/app/src/Eurofurence.App.Common/Eurofurence.App.Common.csproj \
--mount=type=bind,source=./src/Eurofurence.App.Tools.CliToolBox/Eurofurence.App.Tools.CliToolBox.csproj,target=/app/src/Eurofurence.App.Tools.CliToolBox/Eurofurence.App.Tools.CliToolBox.csproj \
--mount=type=bind,source=./src/Eurofurence.App.Server.Services/Eurofurence.App.Server.Services.csproj,target=/app/src/Eurofurence.App.Server.Services/Eurofurence.App.Server.Services.csproj \
--mount=type=bind,source=./src/Eurofurence.App.Server.Web/Eurofurence.App.Server.Web.csproj,target=/app/src/Eurofurence.App.Server.Web/Eurofurence.App.Server.Web.csproj \
--mount=type=bind,source=./src/Eurofurence.App.Backoffice/Eurofurence.App.Backoffice.csproj,target=/app/src/Eurofurence.App.Backoffice/Eurofurence.App.Backoffice.csproj \
--mount=type=bind,source=./src/Eurofurence.App.Infrastructure.EntityFramework/Eurofurence.App.Infrastructure.EntityFramework.csproj,target=/app/src/Eurofurence.App.Infrastructure.EntityFramework/Eurofurence.App.Infrastructure.EntityFramework.csproj \
--mount=type=bind,source=./src/Eurofurence.App.Domain.Model/Eurofurence.App.Domain.Model.csproj,target=/app/src/Eurofurence.App.Domain.Model/Eurofurence.App.Domain.Model.csproj \
--mount=type=bind,source=./test/Eurofurence.App.Server.Services.Tests/Eurofurence.App.Server.Services.Tests.csproj,target=/app/test/Eurofurence.App.Server.Services.Tests/Eurofurence.App.Server.Services.Tests.csproj \
--mount=type=bind,source=./test/Eurofurence.App.Server.Web.Tests/Eurofurence.App.Server.Web.Tests.csproj,target=/app/test/Eurofurence.App.Server.Web.Tests/Eurofurence.App.Server.Web.Tests.csproj \
--mount=type=bind,source=./test/Eurofurence.App.Tests.Common/Eurofurence.App.Tests.Common.csproj,target=/app/test/Eurofurence.App.Tests.Common/Eurofurence.App.Tests.Common.csproj \
dotnet nuget config set repositoryPath /dotnet/packages --configfile /app/NuGet.config \
&& dotnet nuget config set globalPackagesFolder /dotnet/global-packages --configfile /app/NuGet.config \
&& dotnet restore

COPY ./src/ /app/src/
COPY ./test/ /app/test/
RUN touch src/Eurofurence.App.Backoffice/wwwroot/appsettings.json \
&& dotnet restore \
&& dotnet build src/Eurofurence.App.Backoffice/Eurofurence.App.Backoffice.csproj --configuration Release \
&& dotnet publish src/Eurofurence.App.Backoffice/Eurofurence.App.Backoffice.csproj --output "/app/backoffice" --configuration Release
RUN --mount=type=cache,target=/dotnet/packages \
--mount=type=cache,target=/dotnet/global-packages \
--mount=type=cache,target=/dotnet/artifacts \
--mount=type=bind,source=./ef-app_backend-dotnet-core.sln,target=/app/ef-app_backend-dotnet-core.sln \
touch src/Eurofurence.App.Backoffice/wwwroot/appsettings.json \
&& dotnet build src/Eurofurence.App.Backoffice/Eurofurence.App.Backoffice.csproj --artifacts-path /dotnet/artifacts --configuration Release \
&& dotnet publish src/Eurofurence.App.Backoffice/Eurofurence.App.Backoffice.csproj --artifacts-path /dotnet/artifacts --no-build --output "/app/backoffice" --configuration Release
ENTRYPOINT dotnet artifacts/Eurofurence.App.Backoffice.dll http://*:30002
EXPOSE 30002

Expand Down
12 changes: 9 additions & 3 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,15 @@ build $MYSQL_VERSION=env_var('EF_MOBILE_APP_MYSQL_VERSION'): (_create_if_not_exi
build-cli:
dotnet publish src/Eurofurence.App.Tools.CliToolBox/Eurofurence.App.Tools.CliToolBox.csproj --output "$(pwd)/artifacts" --configuration Release --sc -p:PublishSingleFile=true -p:DebugType=None -p:DebugSymbols=false -p:GenerateDocumentationFile=false

# Build release container using spec from docker-compose.yml
containerize *ARGS:
docker compose build {{ARGS}}
# Build release container for service using spec from docker-compose.yml and refresh service if stack is running
containerize SERVICE *ARGS:
#!/bin/bash
set -euxo pipefail
docker compose build {{ARGS}} {{SERVICE}}
if [[ $(docker compose ps --services --status running | wc -w) -gt 0 ]]; then
echo "Detected running stack! Refreshing service {{SERVICE}} …"
docker compose create --force-recreate {{SERVICE}} && docker compose start {{SERVICE}}
fi

# Build sdk container for backend without executing second stage
containerize-dev:
Expand Down
8 changes: 4 additions & 4 deletions scripts/import.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ def processImages(
image_id_new = json.loads(image_post_response.data)["Id"]
image_ids_new.append(image_id_new)
logger.info(
f"Successfully uploaded image {image_id} ({image_meta_data["InternalReference"]}) to {image_source} with new ID {image_id_new}."
f"Successfully uploaded image {image_id} ({image_meta_data["InternalReference"]}) to {api.host} with new ID {image_id_new}."
)
else:
logger.warning(
Expand Down Expand Up @@ -239,7 +239,7 @@ def processData(
continue

if image_source is not None and item["ImageIds"] is not None and len(item["ImageIds"]) > 0:
if api.request("GET", f"{api_base}/{types[type_name]["path"]}/{item["Id"]}").status != 404:
if api.request("GET", f"{api_base}{types[type_name]["path"]}/{item["Id"]}").status != 404:
logger.warning(f"{type_name} with ID {item["Id"]} seems to already exist, skipping image upload…")
continue
else:
Expand All @@ -251,7 +251,7 @@ def processData(
continue

try:
api_response = api.request("POST", f"{api_base}/{types[type_name]["path"]}", json=item)
api_response = api.request("POST", f"{api_base}{types[type_name]["path"]}", json=item)

if api_response.status != 200 and api_response.status != 204:
logger.error(
Expand All @@ -277,7 +277,7 @@ def main():
urllib3.connection_from_url(args.api, headers={"Authorization": f"Bearer {args.token}"}) as api,
urllib3.PoolManager() as http,
):
api_base = urllib3.util.parse_url(args.api).request_uri
api_base = urllib3.util.parse_url(args.api).request_uri.removeprefix("/")
schemas, types = loadSchemas(api, api_base)

if args.list:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class TableRegistrationRecord : EntityBase
{
public class StateChangeRecord : EntityBase
{
public DateTime ChangedDateTimeUtc{ get; set; }
public DateTime ChangedDateTimeUtc { get; set; }
public string ChangedByUid { get; set; }
public RegistrationStateEnum OldState { get; set; }
public RegistrationStateEnum NewState { get; set; }
Expand Down Expand Up @@ -56,7 +56,7 @@ public enum RegistrationStateEnum
public ImageRecord Image { get; set; }

[DataMember]
public RegistrationStateEnum State { get; set; }
public RegistrationStateEnum State { get; set; } = RegistrationStateEnum.Pending;

[JsonIgnore]
public IList<StateChangeRecord> StateChangeLog { get; set; }
Expand All @@ -66,17 +66,21 @@ public TableRegistrationRecord()
this.StateChangeLog = new List<StateChangeRecord>();
}

public void ChangeState(RegistrationStateEnum newState, string uid)
public StateChangeRecord ChangeState(RegistrationStateEnum newState, string uid)
{
StateChangeLog.Add(new StateChangeRecord()
var stateChange = new StateChangeRecord()
{
ChangedByUid = uid,
ChangedDateTimeUtc = DateTime.UtcNow,
NewState = newState,
OldState = State
});
};

StateChangeLog.Add(stateChange);

State = newState;

return stateChange;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;

namespace Eurofurence.App.Domain.Model.ArtistsAlley
namespace Eurofurence.App.Domain.Model.ArtistsAlley
{
public class TableRegistrationRequest
{
Expand All @@ -10,8 +8,6 @@ public class TableRegistrationRequest

public string ShortDescription { get; set; }

public Guid ImageId { get; set; }

public string Location { get; set; }

public string TelegramHandle { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public AppDbContext(DbContextOptions<AppDbContext> options)

public virtual DbSet<AnnouncementRecord> Announcements { get; set; }
public virtual DbSet<TableRegistrationRecord> TableRegistrations { get; set; }
// FIXME: Should be TableRegistrationRecordStateChangeRecords #EF29
public virtual DbSet<TableRegistrationRecord.StateChangeRecord> StateChangeRecord { get; set; }
public virtual DbSet<AgentClosingResultRecord> AgentClosingResults { get; set; }
public virtual DbSet<ItemActivityRecord> ItemActivitys { get; set; }
public virtual DbSet<PrivateMessageRecord> PrivateMessages { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
using System.Security.Claims;
using System.Threading.Tasks;
using Eurofurence.App.Domain.Model.ArtistsAlley;
using Eurofurence.App.Domain.Model.Images;

namespace Eurofurence.App.Server.Services.Abstractions.ArtistsAlley
{
public interface ITableRegistrationService :
IEntityServiceOperations<TableRegistrationRecord>,
IPatchOperationProcessor<TableRegistrationRecord>
{
Task RegisterTableAsync(ClaimsPrincipal user, TableRegistrationRequest request);
Task RegisterTableAsync(ClaimsPrincipal user, TableRegistrationRequest request, ImageRecord image = null);
IQueryable<TableRegistrationRecord> GetRegistrations(TableRegistrationRecord.RegistrationStateEnum? state);
Task<TableRegistrationRecord> GetLatestRegistrationByUidAsync(string uid);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ public interface IImageService : IEntityServiceOperations<ImageRecord>
Task<ImageRecord> InsertImageAsync(
string internalReference,
Stream stream,
int? width = null,
int? height = null,
CancellationToken cancellationToken = default);

Task<ImageRecord> ReplaceImageAsync(
Guid id,
string internalReference,
Stream stream,
int? width = null,
int? height = null,
CancellationToken cancellationToken = default);

Task<Stream> GetImageContentByImageIdAsync(
Expand All @@ -25,6 +29,7 @@ Task<Stream> GetImageContentByImageIdAsync(

Stream GeneratePlaceholderImage();

[Obsolete("Use InsertImageAsync or ReplaceImageAsync with dimensions instead.")]
Task<ImageRecord> EnforceMaximumDimensionsAsync(
ImageRecord image,
int width,
Expand Down
Loading