diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
new file mode 100644
index 0000000..00897be
--- /dev/null
+++ b/.github/workflows/build-and-test.yml
@@ -0,0 +1,45 @@
+name: .NET Build & Test
+
+on:
+ push:
+ branches:
+ - 'develop'
+ pull_request:
+ branches:
+ - '*'
+ workflow_dispatch:
+
+env:
+ DOTNET_VERSION: '8.0.x'
+
+jobs:
+ test:
+ name: Build & Test
+ runs-on: ubuntu-latest
+ env:
+ DatabaseConfiguration__UseInMemoryDb: true
+ steps:
+ - name: Checkout Repo
+ uses: actions/checkout@v4
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: ${{ env.DOTNET_VERSION }}
+
+ - name: Restore Tools
+ run: |
+ cd Backend/Bones.Api
+ dotnet tool restore
+ cd ../..
+ cd Frontend/Bones.Api.Client
+ dotnet tool restore
+ cd ../..
+
+ - name: Build
+ run: |
+ dotnet build --no-incremental
+ git diff --quiet || exit 1
+
+ - name: Test
+ run: dotnet test --no-build
\ No newline at end of file
diff --git a/.github/workflows/publish-client.yml b/.github/workflows/publish-client.yml
new file mode 100644
index 0000000..214c4e5
--- /dev/null
+++ b/.github/workflows/publish-client.yml
@@ -0,0 +1,44 @@
+name: Build Client Artifact
+
+on:
+ push:
+ branches:
+ - 'develop'
+ pull_request:
+ branches:
+ - '*'
+ workflow_dispatch:
+
+env:
+ DOTNET_VERSION: '8.0.x'
+
+jobs:
+ client:
+ name: Publish Client
+ runs-on: ubuntu-latest
+ env:
+ DatabaseConfiguration__UseInMemoryDb: true
+ steps:
+ - name: Checkout Repo
+ uses: actions/checkout@v4
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: ${{ env.DOTNET_VERSION }}
+
+ - name: Restore Tools
+ run: |
+ cd Frontend/Bones.Api.Client
+ dotnet tool restore
+ cd ../..
+
+ - name: Publish
+ run: |
+ dotnet publish Frontend/Bones.WebUI/Bones.WebUI.csproj --configuration Release --property PublishDir=~/publish
+
+ - name: Upload Build Artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: webui-wasm-client
+ path: ~/publish
\ No newline at end of file
diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/publish-server.yml
similarity index 55%
rename from .github/workflows/dotnetcore.yml
rename to .github/workflows/publish-server.yml
index 765a396..c70273e 100644
--- a/.github/workflows/dotnetcore.yml
+++ b/.github/workflows/publish-server.yml
@@ -1,4 +1,4 @@
-name: .NET Build & Test
+name: Build Server Artifacts
on:
push:
@@ -13,8 +13,8 @@ env:
DOTNET_VERSION: '8.0.x'
jobs:
- test:
- name: .NET Build & Test
+ server:
+ name: Publish Client
runs-on: ubuntu-latest
env:
DatabaseConfiguration__UseInMemoryDb: true
@@ -32,31 +32,20 @@ jobs:
cd Backend/Bones.Api
dotnet tool restore
cd ../..
- cd Frontend/Bones.Api.Client
- dotnet tool restore
- cd ../..
-
- - name: Build
- run: |
- dotnet build --no-incremental
- git diff --quiet || exit 1
-
- - name: Test
- run: dotnet test --no-build
- name: Publish Client and Server
run: |
- dotnet publish Backend/Bones.Api/Bones.Api.csproj --configuration Release --runtime linux-x64 --self-contained true --property PublishDir=~/publish-server
- dotnet publish Frontend/Bones.WebUI/Bones.WebUI.csproj --configuration Release --property PublishDir=~/publish-client
+ dotnet publish Backend/Bones.Api/Bones.Api.csproj --configuration Release --runtime linux-x64 --self-contained true --property PublishDir=~/publish-api
+ dotnet publish Backend/Bones.BackgroundService/Bones.BackgroundService.csproj --configuration Release --runtime linux-x64 --self-contained true --property PublishDir=~/publish-background-service
- - name: Upload Server Build Artifact
+ - name: Upload API Build Artifact
uses: actions/upload-artifact@v4
with:
- name: server-linux-x64
- path: ~/publish-server
+ name: api-linux-x64
+ path: ~/publish-api
- - name: Upload Client Build Artifact
+ - name: Upload Background Service Build Artifact
uses: actions/upload-artifact@v4
with:
- name: client
- path: ~/publish-client
\ No newline at end of file
+ name: background-service-linux-x64
+ path: ~/publish-background-service
\ No newline at end of file
diff --git a/Backend/Bones.Api/OpenApi/swagger.json b/Backend/Bones.Api/OpenApi/swagger.json
index 1ad15a5..c7b2bba 100644
--- a/Backend/Bones.Api/OpenApi/swagger.json
+++ b/Backend/Bones.Api/OpenApi/swagger.json
@@ -32,6 +32,36 @@
}
},
"responses": {
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
"200": {
"description": "OK",
"content": {
@@ -73,8 +103,8 @@
}
},
"responses": {
- "200": {
- "description": "OK",
+ "401": {
+ "description": "Unauthorized",
"content": {
"application/json": {
"schema": {
@@ -83,8 +113,28 @@
}
}
},
- "401": {
- "description": "Unauthorized",
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "200": {
+ "description": "OK",
"content": {
"application/json": {
"schema": {
@@ -133,8 +183,8 @@
}
],
"responses": {
- "200": {
- "description": "OK",
+ "401": {
+ "description": "Unauthorized",
"content": {
"application/json": {
"schema": {
@@ -143,8 +193,28 @@
}
}
},
- "401": {
- "description": "Unauthorized",
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "200": {
+ "description": "OK",
"content": {
"application/json": {
"schema": {
@@ -175,8 +245,8 @@
"required": true
},
"responses": {
- "200": {
- "description": "OK",
+ "401": {
+ "description": "Unauthorized",
"content": {
"application/json": {
"schema": {
@@ -185,8 +255,28 @@
}
}
},
- "401": {
- "description": "Unauthorized",
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "200": {
+ "description": "OK",
"content": {
"application/json": {
"schema": {
@@ -206,6 +296,36 @@
"summary": "",
"operationId": "LogoutAsync",
"responses": {
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
"200": {
"description": "OK",
"content": {
@@ -227,18 +347,28 @@
"summary": "",
"operationId": "GetMyBasicInfoAsync",
"responses": {
- "200": {
- "description": "OK",
+ "401": {
+ "description": "Unauthorized",
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/GetMyBasicInfoResponseActionResult"
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
}
}
}
},
- "401": {
- "description": "Unauthorized",
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
@@ -246,6 +376,16 @@
}
}
}
+ },
+ "200": {
+ "description": "OK",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/GetMyBasicInfoResponseActionResult"
+ }
+ }
+ }
}
}
}
@@ -268,6 +408,36 @@
}
},
"responses": {
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
"200": {
"description": "OK",
"content": {
@@ -290,6 +460,108 @@
}
}
}
+ },
+ "/Test/bones-exception": {
+ "get": {
+ "tags": [
+ "Test"
+ ],
+ "summary": "Throws a BonesException to test the ApiExceptionHandler",
+ "operationId": "GetBonesExceptionAsync",
+ "responses": {
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "200": {
+ "description": "OK",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/Test/forbidden": {
+ "get": {
+ "tags": [
+ "Test"
+ ],
+ "summary": "Throws a ForbiddenAccessException to test the ApiExceptionHandler",
+ "operationId": "GetForbiddenAsync",
+ "responses": {
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Forbidden",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ },
+ "200": {
+ "description": "OK",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/EmptyResponseActionResult"
+ }
+ }
+ }
+ }
+ }
+ }
}
},
"components": {
diff --git a/Backend/Bones.Backend/Bones.Backend.csproj b/Backend/Bones.Backend/Bones.Backend.csproj
index bad8754..c1eb8ae 100644
--- a/Backend/Bones.Backend/Bones.Backend.csproj
+++ b/Backend/Bones.Backend/Bones.Backend.csproj
@@ -25,6 +25,12 @@
+
+
+
+
+
+
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativeById/GetInitiativeByIdHandler.cs b/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativeById/GetInitiativeByIdHandler.cs
new file mode 100644
index 0000000..836b7ac
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativeById/GetInitiativeByIdHandler.cs
@@ -0,0 +1,11 @@
+using Bones.Database.DbSets.ProjectManagement;
+
+namespace Bones.Backend.Features.ProjectManagement.Initiatives.GetInitiativeById;
+
+internal sealed class GetInitiativeByIdHandler : IRequestHandler>
+{
+ public Task> Handle(GetInitiativeByIdQuery request, CancellationToken cancellationToken)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativeById/GetInitiativeByIdQuery.cs b/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativeById/GetInitiativeByIdQuery.cs
new file mode 100644
index 0000000..bee404a
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativeById/GetInitiativeByIdQuery.cs
@@ -0,0 +1,11 @@
+using Bones.Database.DbSets.AccountManagement;
+using Bones.Database.DbSets.ProjectManagement;
+
+namespace Bones.Backend.Features.ProjectManagement.Initiatives.GetInitiativeById;
+
+///
+/// Gets the initiative by ID
+///
+///
+///
+public sealed record GetInitiativeByIdQuery(Guid InitiativeId, BonesUser RequestingUser) : IRequest>;
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativeById/GetInitiative.cs b/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativeById/GetInitiativeByIdQueryValidator.cs
similarity index 59%
rename from Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativeById/GetInitiative.cs
rename to Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativeById/GetInitiativeByIdQueryValidator.cs
index 0e3149a..93850ea 100644
--- a/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativeById/GetInitiative.cs
+++ b/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativeById/GetInitiativeByIdQueryValidator.cs
@@ -1,6 +1,6 @@
namespace Bones.Backend.Features.ProjectManagement.Initiatives.GetInitiativeById;
-public class GetInitiative
+internal sealed class GetInitiativeByIdQueryValidator
{
-
+
}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativesByOwner/GetInitiatives.cs b/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativesByOwner/GetInitiatives.cs
deleted file mode 100644
index b3a08e3..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/GetInitiativesByOwner/GetInitiatives.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Initiatives.GetInitiativesByOwner;
-
-public class GetInitiatives
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/UpdateInitiativeById/UpdateInitiative.cs b/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/UpdateInitiativeById/UpdateInitiative.cs
deleted file mode 100644
index db7afc1..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Initiatives/UpdateInitiativeById/UpdateInitiative.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Initiatives.UpdateInitiativeById;
-
-public class UpdateInitiative
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Items/CreateItem.cs b/Backend/Bones.Backend/Features/ProjectManagement/Items/CreateItem.cs
deleted file mode 100644
index 5d9eeb7..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Items/CreateItem.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using Bones.Database.Operations.ProjectManagement.WorkItems.CreateWorkItemDb;
-
-namespace Bones.Backend.Features.ProjectManagement.Items;
-
-public class CreateItem(ISender sender) : IRequestHandler
-{
- ///
- /// DB Command for creating an WorkItem.
- ///
- /// Name of the item
- /// Internal ID of the queue this item is in
- /// Internal ID of the layout version this item is using
- /// Internal ID of the queue
- public record Command(string Name, Guid QueueId, Guid LayoutVersionId, Dictionary Values)
- : IValidatableRequest
- {
- ///
- public (bool valid, string? invalidReason) IsRequestValid()
- {
- if (string.IsNullOrWhiteSpace(Name))
- {
- return (false, "");
- }
-
- if (QueueId == Guid.Empty)
- {
- return (false, "");
- }
-
- if (LayoutVersionId == Guid.Empty)
- {
- return (false, "");
- }
-
- return (true, null);
- }
- }
-
- ///
- public async Task Handle(Command request, CancellationToken cancellationToken)
- {
- return await sender.Send(new CreateWorkItemDbHandler.Command(request.Name, request.QueueId, request.LayoutVersionId, request.Values), cancellationToken);
- }
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Items/CreateTag.cs b/Backend/Bones.Backend/Features/ProjectManagement/Items/CreateTag.cs
deleted file mode 100644
index 16ef3a6..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Items/CreateTag.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using Bones.Database.Operations.ProjectManagement.Tags.CreateTagDb;
-
-namespace Bones.Backend.Features.ProjectManagement.Items;
-
-public class CreateTag(ISender sender) : IRequestHandler
-{
- ///
- /// DB Command for creating a Project.
- ///
- /// Name of the project
- public record Command(string Name) : IValidatableRequest
- {
- ///
- public (bool valid, string? invalidReason) IsRequestValid()
- {
- if (string.IsNullOrWhiteSpace(Name))
- {
- return (false, "");
- }
-
- return (true, null);
- }
- }
-
- ///
- public async Task Handle(Command request, CancellationToken cancellationToken)
- {
- return await sender.Send(new CreateTagDbCommand(request.Name), cancellationToken);
- }
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Items/DeleteItem.cs b/Backend/Bones.Backend/Features/ProjectManagement/Items/DeleteItem.cs
deleted file mode 100644
index 1d9fd59..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Items/DeleteItem.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Items;
-
-public class DeleteItem
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Items/DeleteTag.cs b/Backend/Bones.Backend/Features/ProjectManagement/Items/DeleteTag.cs
deleted file mode 100644
index fb040fd..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Items/DeleteTag.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Items;
-
-public class DeleteTag
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Items/GetItem.cs b/Backend/Bones.Backend/Features/ProjectManagement/Items/GetItem.cs
deleted file mode 100644
index 1706c25..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Items/GetItem.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Items;
-
-public class GetItem
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Items/GetItems.cs b/Backend/Bones.Backend/Features/ProjectManagement/Items/GetItems.cs
deleted file mode 100644
index ffe33e3..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Items/GetItems.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Items;
-
-public class GetItems
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Items/UpdateItem.cs b/Backend/Bones.Backend/Features/ProjectManagement/Items/UpdateItem.cs
deleted file mode 100644
index afcfaae..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Items/UpdateItem.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Items;
-
-public class UpdateItem
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Items/UpdateTag.cs b/Backend/Bones.Backend/Features/ProjectManagement/Items/UpdateTag.cs
deleted file mode 100644
index dd9026f..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Items/UpdateTag.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Items;
-
-public class UpdateTag
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Layouts/CreateLayout.cs b/Backend/Bones.Backend/Features/ProjectManagement/Layouts/CreateLayout.cs
deleted file mode 100644
index 99743d2..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Layouts/CreateLayout.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using Bones.Database.Operations.ProjectManagement.WorkItemLayouts.CreateWorkItemLayoutDb;
-
-namespace Bones.Backend.Features.ProjectManagement.Layouts;
-
-public class CreateLayout(ISender sender) : IRequestHandler
-{
- ///
- /// DB Command for creating a layout.
- ///
- /// Name of the layout
- /// Internal IDs of the fields this layout is using
- public record Command(string Name, List ItemFieldIds) : IValidatableRequest
- {
- ///
- public (bool valid, string? invalidReason) IsRequestValid()
- {
- if (string.IsNullOrWhiteSpace(Name))
- {
- return (false, "");
- }
-
- foreach (Guid id in ItemFieldIds)
- {
- if (id == Guid.Empty)
- {
- return (false, "");
- }
- }
-
- return (true, null);
- }
- }
-
- ///
- public async Task Handle(Command request, CancellationToken cancellationToken)
- {
- return await sender.Send(new CreateWorkItemLayoutDbCommand(request.Name, request.ItemFieldIds), cancellationToken);
- }
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Layouts/DeleteLayout.cs b/Backend/Bones.Backend/Features/ProjectManagement/Layouts/DeleteLayout.cs
deleted file mode 100644
index deb8151..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Layouts/DeleteLayout.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Layouts;
-
-public class DeleteLayout
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Layouts/GetLayout.cs b/Backend/Bones.Backend/Features/ProjectManagement/Layouts/GetLayout.cs
deleted file mode 100644
index a0d6395..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Layouts/GetLayout.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Layouts;
-
-public class GetLayout
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Layouts/GetLayouts.cs b/Backend/Bones.Backend/Features/ProjectManagement/Layouts/GetLayouts.cs
deleted file mode 100644
index 1c1aa3a..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Layouts/GetLayouts.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Layouts;
-
-public class GetLayouts
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Layouts/UpdateLayout.cs b/Backend/Bones.Backend/Features/ProjectManagement/Layouts/UpdateLayout.cs
deleted file mode 100644
index 21e3dd9..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Layouts/UpdateLayout.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Layouts;
-
-public class UpdateLayout
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Projects/DeleteProjectById/DeleteProject.cs b/Backend/Bones.Backend/Features/ProjectManagement/Projects/DeleteProjectById/DeleteProject.cs
deleted file mode 100644
index f297c64..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Projects/DeleteProjectById/DeleteProject.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Projects.DeleteProjectById;
-
-public class DeleteProject
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Projects/GetProjectById/GetProject.cs b/Backend/Bones.Backend/Features/ProjectManagement/Projects/GetProjectById/GetProject.cs
deleted file mode 100644
index 2ddf8d7..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Projects/GetProjectById/GetProject.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Projects.GetProjectById;
-
-public class GetProject
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Projects/GetProjectsByOwner/GetProjects.cs b/Backend/Bones.Backend/Features/ProjectManagement/Projects/GetProjectsByOwner/GetProjects.cs
deleted file mode 100644
index b4cbf53..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Projects/GetProjectsByOwner/GetProjects.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Projects.GetProjectsByOwner;
-
-public class GetProjects
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Projects/UpdateProject/UpdateProject.cs b/Backend/Bones.Backend/Features/ProjectManagement/Projects/UpdateProject/UpdateProject.cs
deleted file mode 100644
index ce71cf1..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Projects/UpdateProject/UpdateProject.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Projects.UpdateProject;
-
-public class UpdateProject
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Queues/CreateQueue.cs b/Backend/Bones.Backend/Features/ProjectManagement/Queues/CreateQueue.cs
deleted file mode 100644
index b9896df..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Queues/CreateQueue.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using Bones.Database.Operations.ProjectManagement.Queues.CreateQueueDb;
-
-namespace Bones.Backend.Features.ProjectManagement.Queues;
-
-public class CreateQueue(ISender sender) : IRequestHandler
-{
- ///
- /// DB Command for creating a Queue.
- ///
- /// Name of the queue
- /// Internal ID of the initiative
- public record Command(string Name, Guid InitiativeId) : IValidatableRequest
- {
- ///
- public (bool valid, string? invalidReason) IsRequestValid()
- {
- if (string.IsNullOrWhiteSpace(Name))
- {
- return (false, "");
- }
-
- if (InitiativeId == Guid.Empty)
- {
- return (false, "");
- }
-
- return (true, null);
- }
- }
-
- ///
- public async Task Handle(Command request, CancellationToken cancellationToken)
- {
- return await sender.Send(new CreateQueueDbHandler.Command(request.Name, request.InitiativeId), cancellationToken);
- }
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Queues/CreateQueue/CreateQueueCommand.cs b/Backend/Bones.Backend/Features/ProjectManagement/Queues/CreateQueue/CreateQueueCommand.cs
new file mode 100644
index 0000000..55b69dd
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/Queues/CreateQueue/CreateQueueCommand.cs
@@ -0,0 +1,11 @@
+using Bones.Database.DbSets.AccountManagement;
+
+namespace Bones.Backend.Features.ProjectManagement.Queues.CreateQueue;
+
+///
+/// Command for creating a Queue.
+///
+/// Name of the queue
+/// Internal ID of the initiative
+///
+public sealed record CreateQueueCommand(string Name, Guid InitiativeId, BonesUser RequestingUser) : IRequest;
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Queues/CreateQueue/CreateQueueCommandValidator.cs b/Backend/Bones.Backend/Features/ProjectManagement/Queues/CreateQueue/CreateQueueCommandValidator.cs
new file mode 100644
index 0000000..9352d9e
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/Queues/CreateQueue/CreateQueueCommandValidator.cs
@@ -0,0 +1,6 @@
+namespace Bones.Backend.Features.ProjectManagement.Queues.CreateQueue;
+
+internal sealed class CreateQueueCommandValidator : AbstractValidator
+{
+
+}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Queues/CreateQueue/CreateQueueHandler.cs b/Backend/Bones.Backend/Features/ProjectManagement/Queues/CreateQueue/CreateQueueHandler.cs
new file mode 100644
index 0000000..3dcb781
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/Queues/CreateQueue/CreateQueueHandler.cs
@@ -0,0 +1,12 @@
+using Bones.Database.Operations.ProjectManagement.Queues.CreateQueueDb;
+
+namespace Bones.Backend.Features.ProjectManagement.Queues.CreateQueue;
+
+internal sealed class CreateQueueHandler(ISender sender) : IRequestHandler
+{
+ public async Task Handle(CreateQueueCommand request, CancellationToken cancellationToken)
+ {
+ // TODO: Check permission
+ return await sender.Send(new CreateQueueDbCommand(request.Name, request.InitiativeId), cancellationToken);
+ }
+}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Queues/DeleteQueue.cs b/Backend/Bones.Backend/Features/ProjectManagement/Queues/DeleteQueue.cs
deleted file mode 100644
index d98e30d..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Queues/DeleteQueue.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Queues;
-
-public class DeleteQueue
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Queues/GetQueue.cs b/Backend/Bones.Backend/Features/ProjectManagement/Queues/GetQueue.cs
deleted file mode 100644
index 68e55a7..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Queues/GetQueue.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Queues;
-
-public class GetQueue
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Queues/GetQueues.cs b/Backend/Bones.Backend/Features/ProjectManagement/Queues/GetQueues.cs
deleted file mode 100644
index 68e737d..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Queues/GetQueues.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Queues;
-
-public class GetQueues
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Queues/UpdateQueue.cs b/Backend/Bones.Backend/Features/ProjectManagement/Queues/UpdateQueue.cs
deleted file mode 100644
index c6b2ec5..0000000
--- a/Backend/Bones.Backend/Features/ProjectManagement/Queues/UpdateQueue.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Bones.Backend.Features.ProjectManagement.Queues;
-
-public class UpdateQueue
-{
-
-}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Tags/CreateTag/CreateTagCommand.cs b/Backend/Bones.Backend/Features/ProjectManagement/Tags/CreateTag/CreateTagCommand.cs
new file mode 100644
index 0000000..3d7009e
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/Tags/CreateTag/CreateTagCommand.cs
@@ -0,0 +1,7 @@
+namespace Bones.Backend.Features.ProjectManagement.Tags.CreateTag;
+
+///
+/// Command for creating a tag.
+///
+/// Name of the tag
+public sealed record CreateTagCommand(string Name) : IRequest;
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/Tags/CreateTag/CreateTagHandler.cs b/Backend/Bones.Backend/Features/ProjectManagement/Tags/CreateTag/CreateTagHandler.cs
new file mode 100644
index 0000000..6d4fe62
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/Tags/CreateTag/CreateTagHandler.cs
@@ -0,0 +1,11 @@
+using Bones.Database.Operations.ProjectManagement.Tags.CreateTagDb;
+
+namespace Bones.Backend.Features.ProjectManagement.Tags.CreateTag;
+
+internal sealed class CreateTagHandler(ISender sender) : IRequestHandler
+{
+ public async Task Handle(CreateTagCommand request, CancellationToken cancellationToken)
+ {
+ return await sender.Send(new CreateTagDbCommand(request.Name), cancellationToken);
+ }
+}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/WorkItemLayouts/CreateLayoutCommand.cs b/Backend/Bones.Backend/Features/ProjectManagement/WorkItemLayouts/CreateLayoutCommand.cs
new file mode 100644
index 0000000..ec3a938
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/WorkItemLayouts/CreateLayoutCommand.cs
@@ -0,0 +1,8 @@
+namespace Bones.Backend.Features.ProjectManagement.WorkItemLayouts;
+
+///
+/// Command for creating a layout.
+///
+/// Internal IDs of the project this layout should belong to
+/// Name of the layout
+public record CreateLayoutCommand(Guid ProjectId, string Name) : IRequest;
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/WorkItemLayouts/CreateLayoutHandler.cs b/Backend/Bones.Backend/Features/ProjectManagement/WorkItemLayouts/CreateLayoutHandler.cs
new file mode 100644
index 0000000..92fdf43
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/WorkItemLayouts/CreateLayoutHandler.cs
@@ -0,0 +1,11 @@
+using Bones.Database.Operations.ProjectManagement.WorkItemLayouts.CreateWorkItemLayoutDb;
+
+namespace Bones.Backend.Features.ProjectManagement.WorkItemLayouts;
+
+internal sealed class CreateLayoutHandler(ISender sender) : IRequestHandler
+{
+ public async Task Handle(CreateLayoutCommand request, CancellationToken cancellationToken)
+ {
+ return await sender.Send(new CreateWorkItemLayoutDbCommand(request.ProjectId, request.Name), cancellationToken);
+ }
+}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItem/CreateWorkItemCommand.cs b/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItem/CreateWorkItemCommand.cs
new file mode 100644
index 0000000..4104aa7
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItem/CreateWorkItemCommand.cs
@@ -0,0 +1,10 @@
+namespace Bones.Backend.Features.ProjectManagement.WorkItems.CreateWorkItem;
+
+///
+/// DB Command for creating a WorkItem.
+///
+/// Name of the item
+/// Internal ID of the queue this item is in
+/// Internal ID of the layout version this item is using
+/// Internal ID of the queue
+public sealed record CreateWorkItemCommand(string Name, Guid QueueId, Guid WorkItemLayoutVersionId, Dictionary Values) : IRequest;
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItem/CreateWorkItemCommandValidator.cs b/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItem/CreateWorkItemCommandValidator.cs
new file mode 100644
index 0000000..5a216de
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItem/CreateWorkItemCommandValidator.cs
@@ -0,0 +1,6 @@
+namespace Bones.Backend.Features.ProjectManagement.WorkItems.CreateWorkItem;
+
+internal sealed class CreateWorkItemCommandValidator : AbstractValidator
+{
+
+}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItem/CreateWorkItemHandler.cs b/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItem/CreateWorkItemHandler.cs
new file mode 100644
index 0000000..bd85e78
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItem/CreateWorkItemHandler.cs
@@ -0,0 +1,11 @@
+using Bones.Database.Operations.ProjectManagement.WorkItems.CreateWorkItemDb;
+
+namespace Bones.Backend.Features.ProjectManagement.WorkItems.CreateWorkItem;
+
+internal sealed class CreateWorkItemHandler(ISender sender) : IRequestHandler
+{
+ public async Task Handle(CreateWorkItemCommand request, CancellationToken cancellationToken)
+ {
+ return await sender.Send(new CreateWorkItemDbCommand(request.Name, request.QueueId, request.WorkItemLayoutVersionId, request.Values), cancellationToken);
+ }
+}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItemVersion/CreateWorkItemVersionCommand.cs b/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItemVersion/CreateWorkItemVersionCommand.cs
new file mode 100644
index 0000000..d8eb748
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItemVersion/CreateWorkItemVersionCommand.cs
@@ -0,0 +1,9 @@
+namespace Bones.Backend.Features.ProjectManagement.WorkItems.CreateWorkItemVersion;
+
+///
+/// DB Command for creating a WorkItem.
+///
+/// Internal ID of the queue this item is in
+/// Internal ID of the layout version this item is using
+/// Internal ID of the queue
+public sealed record CreateWorkItemVersionCommand(Guid WorkItemId, Guid WorkItemLayoutVersionId, Dictionary Values) : IRequest;
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItemVersion/CreateWorkItemVersionCommandValidator.cs b/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItemVersion/CreateWorkItemVersionCommandValidator.cs
new file mode 100644
index 0000000..e2a0646
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItemVersion/CreateWorkItemVersionCommandValidator.cs
@@ -0,0 +1,6 @@
+namespace Bones.Backend.Features.ProjectManagement.WorkItems.CreateWorkItemVersion;
+
+internal sealed class CreateWorkItemVersionCommandValidator : AbstractValidator
+{
+
+}
\ No newline at end of file
diff --git a/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItemVersion/CreateWorkItemVersionHandler.cs b/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItemVersion/CreateWorkItemVersionHandler.cs
new file mode 100644
index 0000000..c7cb8a5
--- /dev/null
+++ b/Backend/Bones.Backend/Features/ProjectManagement/WorkItems/CreateWorkItemVersion/CreateWorkItemVersionHandler.cs
@@ -0,0 +1,11 @@
+using Bones.Database.Operations.ProjectManagement.WorkItems.CreateWorkItemVersionDb;
+
+namespace Bones.Backend.Features.ProjectManagement.WorkItems.CreateWorkItemVersion;
+
+internal sealed class CreateWorkItemVersionHandler(ISender sender) : IRequestHandler
+{
+ public async Task Handle(CreateWorkItemVersionCommand request, CancellationToken cancellationToken)
+ {
+ return await sender.Send(new CreateWorkItemVersionDbCommand(request.WorkItemId, request.WorkItemLayoutVersionId, request.Values), cancellationToken);
+ }
+}
\ No newline at end of file
diff --git a/Backend/Bones.BackgroundService/GlobalUsings.cs b/Backend/Bones.BackgroundService/GlobalUsings.cs
index 041a6d1..6c30d5a 100644
--- a/Backend/Bones.BackgroundService/GlobalUsings.cs
+++ b/Backend/Bones.BackgroundService/GlobalUsings.cs
@@ -1,6 +1,4 @@
global using MediatR;
global using Serilog;
global using FluentValidation;
-global using Microsoft.Extensions.Hosting;
-global using Microsoft.Extensions.Logging;
global using Bones.Shared.Backend.Models;
\ No newline at end of file
diff --git a/Backend/Bones.BackgroundService/Tasks/Minutely/MinutelyTaskBase.cs b/Backend/Bones.BackgroundService/Tasks/Minutely/MinutelyTaskBase.cs
index 8b829d6..52fc869 100644
--- a/Backend/Bones.BackgroundService/Tasks/Minutely/MinutelyTaskBase.cs
+++ b/Backend/Bones.BackgroundService/Tasks/Minutely/MinutelyTaskBase.cs
@@ -1,8 +1,10 @@
namespace Bones.BackgroundService.Tasks.Minutely;
-internal abstract class MinutelyTaskBase(ILogger logger, ISender sender) : TaskBase(logger, sender)
+internal abstract class MinutelyTaskBase(ISender sender) : TaskBase(sender)
{
- protected override TimeSpan? Interval { get; } = TimeSpan.FromMinutes(1);
+ protected override TimeSpan Interval { get; } = TimeSpan.FromMinutes(1);
+
+ protected override bool IsStartupOnlyTask { get; set; } = false;
protected override Task ShouldTaskRunAsync(CancellationToken cancellationToken) => Task.FromResult(IsEnabled);
}
\ No newline at end of file
diff --git a/Backend/Bones.BackgroundService/Tasks/Minutely/SendConfirmationEmailTask.cs b/Backend/Bones.BackgroundService/Tasks/Minutely/SendConfirmationEmailTask.cs
index e15ae27..06a2525 100644
--- a/Backend/Bones.BackgroundService/Tasks/Minutely/SendConfirmationEmailTask.cs
+++ b/Backend/Bones.BackgroundService/Tasks/Minutely/SendConfirmationEmailTask.cs
@@ -1,6 +1,6 @@
namespace Bones.BackgroundService.Tasks.Minutely;
-internal class SendConfirmationEmailTask(ILogger logger, ISender sender) : MinutelyTaskBase(logger, sender)
+internal class SendConfirmationEmailTask(ISender sender) : MinutelyTaskBase(sender)
{
protected override Task ShouldTaskRunAsync(CancellationToken cancellationToken)
{
@@ -11,7 +11,7 @@ protected override Task ShouldTaskRunAsync(CancellationToken cancellationT
// TODO: Check if there are any emails in the queue
- return Task.FromResult(false);
+ return Task.FromResult(true);
}
protected override Task RunTaskAsync(CancellationToken cancellationToken)
diff --git a/Backend/Bones.BackgroundService/Tasks/Startup/SetupBackgroundTaskUserTask.cs b/Backend/Bones.BackgroundService/Tasks/Startup/SetupBackgroundTaskUserTask.cs
index 3d353c2..12aee9d 100644
--- a/Backend/Bones.BackgroundService/Tasks/Startup/SetupBackgroundTaskUserTask.cs
+++ b/Backend/Bones.BackgroundService/Tasks/Startup/SetupBackgroundTaskUserTask.cs
@@ -1,9 +1,19 @@
namespace Bones.BackgroundService.Tasks.Startup;
-internal class SetupBackgroundTaskUserTask(Logger logger, ISender sender) : StartupTaskBase(logger, sender)
+internal class SetupBackgroundTaskUserTask(ISender sender) : StartupTaskBase(sender)
{
protected override Task RunTaskAsync(CancellationToken cancellationToken)
{
- throw new NotImplementedException();
+ // TODO:
+ // Get the email for the background task user
+ // Get the optional userId for if you want to change the email after
+ // If the user id is set, get that user
+ // if the users email matches whats configured, do nothing
+ // if the email doesn't match, update it
+ // If its not set, check if any users in the DB have the configured email
+ // If none exist with that email, create the user
+ // If it exists, do nothing
+
+ return Task.CompletedTask;
}
}
\ No newline at end of file
diff --git a/Backend/Bones.BackgroundService/Tasks/Startup/StartupTaskBase.cs b/Backend/Bones.BackgroundService/Tasks/Startup/StartupTaskBase.cs
index cb4b546..ec5c7fe 100644
--- a/Backend/Bones.BackgroundService/Tasks/Startup/StartupTaskBase.cs
+++ b/Backend/Bones.BackgroundService/Tasks/Startup/StartupTaskBase.cs
@@ -1,8 +1,10 @@
namespace Bones.BackgroundService.Tasks.Startup;
-internal abstract class StartupTaskBase(ILogger logger, ISender sender) : TaskBase(logger, sender)
+internal abstract class StartupTaskBase(ISender sender) : TaskBase(sender)
{
- protected override TimeSpan? Interval { get; } = null;
+ protected override TimeSpan Interval { get; } = TimeSpan.FromSeconds(1);
+
+ protected override bool IsStartupOnlyTask { get; set; } = true;
protected override Task ShouldTaskRunAsync(CancellationToken cancellationToken) => Task.FromResult(IsEnabled);
}
\ No newline at end of file
diff --git a/Backend/Bones.BackgroundService/Tasks/TaskBase.cs b/Backend/Bones.BackgroundService/Tasks/TaskBase.cs
index ac9259f..3ba94e8 100644
--- a/Backend/Bones.BackgroundService/Tasks/TaskBase.cs
+++ b/Backend/Bones.BackgroundService/Tasks/TaskBase.cs
@@ -1,11 +1,15 @@
+using Serilog.Events;
+
namespace Bones.BackgroundService.Tasks;
-internal abstract class TaskBase(ILogger logger, ISender sender) : Microsoft.Extensions.Hosting.BackgroundService
+internal abstract class TaskBase(ISender sender) : Microsoft.Extensions.Hosting.BackgroundService
{
protected readonly ISender Sender = sender;
- protected abstract TimeSpan? Interval { get; }
+ protected abstract TimeSpan Interval { get; }
protected bool IsEnabled { get; set; } = true;
+
+ protected abstract bool IsStartupOnlyTask { get; set; }
protected abstract Task ShouldTaskRunAsync(CancellationToken cancellationToken);
@@ -13,7 +17,7 @@ internal abstract class TaskBase(ILogger logger, ISender sender) : Microso
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{
- using PeriodicTimer timer = new(Interval ?? TimeSpan.MaxValue);
+ using PeriodicTimer timer = new(Interval);
while (!cancellationToken.IsCancellationRequested
&& await timer.WaitForNextTickAsync(cancellationToken))
{
@@ -24,34 +28,33 @@ protected override async Task ExecuteAsync(CancellationToken cancellationToken)
try
{
- if (logger.IsEnabled(LogLevel.Information))
+ if (Log.IsEnabled(LogEventLevel.Information))
{
- logger.LogInformation("{Name} started at: {Time}", typeof(T).Name, DateTimeOffset.Now);
+ Log.Information("{Name} started at: {Time}", GetType().Name, DateTimeOffset.Now);
}
await RunTaskAsync(cancellationToken);
- if (logger.IsEnabled(LogLevel.Information))
+ if (Log.IsEnabled(LogEventLevel.Information))
{
- logger.LogInformation("{Name} finished at: {Time}", typeof(T).Name, DateTimeOffset.Now);
+ Log.Information("{Name} finished at: {Time}", GetType().Name, DateTimeOffset.Now);
}
}
catch (Exception ex)
{
// TODO: add to TaskErrors table
IsEnabled = false;
- logger.LogError(ex,
+ Log.Error(ex,
"{Time} | {Name} has unhandled exception: {ExceptionMessage}\n{ExceptionStackTrace}",
- DateTimeOffset.Now, typeof(T).Name, ex.Message, ex.StackTrace);
+ DateTimeOffset.Now, GetType().Name, ex.Message, ex.StackTrace);
}
finally
{
- // Startup only task
- if (Interval is null)
+ if (IsStartupOnlyTask)
{
IsEnabled = false;
- // Lets also cancel it to clear this from memory
+ // Lets also cancel it
await CancellationTokenSource.CreateLinkedTokenSource(cancellationToken).CancelAsync();
}
}
diff --git a/Backend/Bones.Database/Migrations/20240908032021_IDontRememberWhatIChanged.Designer.cs b/Backend/Bones.Database/Migrations/20240908032021_IDontRememberWhatIChanged.Designer.cs
new file mode 100644
index 0000000..fc921ad
--- /dev/null
+++ b/Backend/Bones.Database/Migrations/20240908032021_IDontRememberWhatIChanged.Designer.cs
@@ -0,0 +1,1152 @@
+//
+using System;
+using Bones.Database;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace Bones.Database.Migrations
+{
+ [DbContext(typeof(BonesDbContext))]
+ [Migration("20240908032021_IDontRememberWhatIChanged")]
+ partial class IDontRememberWhatIChanged
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.8")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("Bones.Database.DbSets.AccountManagement.BonesRole", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnType("text");
+
+ b.Property("IsSystemRole")
+ .HasColumnType("boolean");
+
+ b.Property("Name")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("NormalizedName")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("OrganizationId")
+ .HasColumnType("uuid");
+
+ b.Property("ReadOnlyRole")
+ .HasColumnType("boolean");
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedName")
+ .IsUnique()
+ .HasDatabaseName("RoleNameIndex");
+
+ b.HasIndex("OrganizationId");
+
+ b.ToTable("BonesRoles", "AccountManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AccountManagement.BonesRoleClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ClaimType")
+ .HasColumnType("text");
+
+ b.Property("ClaimValue")
+ .HasColumnType("text");
+
+ b.Property("RoleId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("BonesRoleClaims", "AccountManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AccountManagement.BonesUser", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("AccessFailedCount")
+ .HasColumnType("integer");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnType("text");
+
+ b.Property("DisplayName")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("Email")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("EmailConfirmed")
+ .HasColumnType("boolean");
+
+ b.Property("EmailConfirmedDateTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("LockoutEnabled")
+ .HasColumnType("boolean");
+
+ b.Property("LockoutEnd")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("NormalizedEmail")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("NormalizedUserName")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("PasswordExpired")
+ .HasColumnType("boolean");
+
+ b.Property("PasswordHash")
+ .HasColumnType("text");
+
+ b.Property("PhoneNumber")
+ .HasColumnType("text");
+
+ b.Property("PhoneNumberConfirmed")
+ .HasColumnType("boolean");
+
+ b.Property("SecurityStamp")
+ .HasColumnType("text");
+
+ b.Property("TwoFactorEnabled")
+ .HasColumnType("boolean");
+
+ b.Property("UserName")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedEmail")
+ .HasDatabaseName("EmailIndex");
+
+ b.HasIndex("NormalizedUserName")
+ .IsUnique()
+ .HasDatabaseName("UserNameIndex");
+
+ b.ToTable("BonesUsers", "AccountManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AccountManagement.BonesUserClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ClaimType")
+ .HasColumnType("text");
+
+ b.Property("ClaimValue")
+ .HasColumnType("text");
+
+ b.Property("UserId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("BonesUserClaims", "AccountManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AccountManagement.BonesUserLogin", b =>
+ {
+ b.Property("LoginProvider")
+ .HasColumnType("text");
+
+ b.Property("ProviderKey")
+ .HasColumnType("text");
+
+ b.Property("ProviderDisplayName")
+ .HasColumnType("text");
+
+ b.Property("UserId")
+ .HasColumnType("uuid");
+
+ b.HasKey("LoginProvider", "ProviderKey");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("BonesUserLogins", "AccountManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AccountManagement.BonesUserRole", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("uuid");
+
+ b.Property("RoleId")
+ .HasColumnType("uuid");
+
+ b.HasKey("UserId", "RoleId");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("BonesUserRoles", "AccountManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AccountManagement.BonesUserToken", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("uuid");
+
+ b.Property("LoginProvider")
+ .HasColumnType("text");
+
+ b.Property("Name")
+ .HasColumnType("text");
+
+ b.Property("Value")
+ .HasColumnType("text");
+
+ b.HasKey("UserId", "LoginProvider", "Name");
+
+ b.ToTable("BonesUserTokens", "AccountManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetFields.AssetField", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("AssetLayoutVersionId")
+ .HasColumnType("uuid");
+
+ b.Property("IsRequired")
+ .HasColumnType("boolean");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("OwnerType")
+ .HasColumnType("integer");
+
+ b.Property("OwningOrganizationId")
+ .HasColumnType("uuid");
+
+ b.Property("OwningUserId")
+ .HasColumnType("uuid");
+
+ b.Property("Type")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AssetLayoutVersionId");
+
+ b.HasIndex("OwningOrganizationId");
+
+ b.HasIndex("OwningUserId");
+
+ b.ToTable("AssetFields", "AssetManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetFields.AssetFieldListEntry", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("MatchingType")
+ .HasColumnType("integer");
+
+ b.Property("ParentFieldId")
+ .HasColumnType("uuid");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ParentFieldId");
+
+ b.ToTable("AssetFieldListEntries", "AssetManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetLayouts.AssetLayout", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("OwnerType")
+ .HasColumnType("integer");
+
+ b.Property("OwningOrganizationId")
+ .HasColumnType("uuid");
+
+ b.Property("OwningUserId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OwningOrganizationId");
+
+ b.HasIndex("OwningUserId");
+
+ b.ToTable("AssetLayouts", "AssetManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetLayouts.AssetLayoutVersion", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("AssetLayoutId")
+ .HasColumnType("uuid");
+
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
+ b.Property("Version")
+ .HasColumnType("bigint");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AssetLayoutId");
+
+ b.ToTable("AssetLayoutVersions", "AssetManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.Assets.Asset", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("OwnerType")
+ .HasColumnType("integer");
+
+ b.Property("OwningOrganizationId")
+ .HasColumnType("uuid");
+
+ b.Property("OwningUserId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OwningOrganizationId");
+
+ b.HasIndex("OwningUserId");
+
+ b.ToTable("Assets", "AssetManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.Assets.AssetValue", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("AssetVersionId")
+ .HasColumnType("uuid");
+
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
+ b.Property("FieldId")
+ .HasColumnType("uuid");
+
+ b.Property("LocationType")
+ .HasColumnType("integer");
+
+ b.Property("Value")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AssetVersionId");
+
+ b.HasIndex("FieldId");
+
+ b.ToTable("AssetValues", "AssetManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.Assets.AssetVersion", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("AssetId")
+ .HasColumnType("uuid");
+
+ b.Property("AssetLayoutId")
+ .HasColumnType("uuid");
+
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
+ b.Property("Version")
+ .HasColumnType("bigint");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AssetId");
+
+ b.HasIndex("AssetLayoutId");
+
+ b.ToTable("AssetVersions", "AssetManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.OrganizationManagement.BonesOrganization", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.HasKey("Id");
+
+ b.ToTable("BonesOrganizations", "OrganizationManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.Initiative", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("ProjectId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ProjectId");
+
+ b.ToTable("Initiatives", "ProjectManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.Project", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("OwnerType")
+ .HasColumnType("integer");
+
+ b.Property("OwningOrganizationId")
+ .HasColumnType("uuid");
+
+ b.Property("OwningUserId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OwningOrganizationId");
+
+ b.HasIndex("OwningUserId");
+
+ b.ToTable("Projects", "ProjectManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.Queue", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
+ b.Property("InitiativeId")
+ .HasColumnType("uuid");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("InitiativeId");
+
+ b.ToTable("Queues", "ProjectManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.Tag", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("WorkItemId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("WorkItemId");
+
+ b.ToTable("Tags", "ProjectManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemFields.WorkItemField", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("IsRequired")
+ .HasColumnType("boolean");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("Type")
+ .HasColumnType("integer");
+
+ b.Property("WorkItemLayoutVersionId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("WorkItemLayoutVersionId");
+
+ b.ToTable("WorkItemFields", "ProjectManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemFields.WorkItemFieldListEntry", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("MatchingType")
+ .HasColumnType("integer");
+
+ b.Property("ParentFieldId")
+ .HasColumnType("uuid");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ParentFieldId");
+
+ b.ToTable("WorkItemFieldListEntries", "ProjectManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemLayouts.WorkItemLayout", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("ProjectId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ProjectId");
+
+ b.ToTable("WorkItemLayouts", "ProjectManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemLayouts.WorkItemLayoutVersion", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
+ b.Property("Version")
+ .HasColumnType("bigint");
+
+ b.Property("WorkItemLayoutId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("WorkItemLayoutId");
+
+ b.ToTable("WorkItemLayoutVersions", "ProjectManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItems.WorkItem", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("AddedToQueueDateTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("QueueId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("QueueId");
+
+ b.ToTable("WorkItems", "ProjectManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItems.WorkItemValue", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
+ b.Property("FieldId")
+ .HasColumnType("uuid");
+
+ b.Property("LocationType")
+ .HasColumnType("integer");
+
+ b.Property("Value")
+ .HasColumnType("text");
+
+ b.Property("WorkItemVersionId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("FieldId");
+
+ b.HasIndex("WorkItemVersionId");
+
+ b.ToTable("WorkItemValues", "ProjectManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItems.WorkItemVersion", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
+ b.Property("Version")
+ .HasColumnType("bigint");
+
+ b.Property("WorkItemId")
+ .HasColumnType("uuid");
+
+ b.Property("WorkItemLayoutId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("WorkItemId");
+
+ b.HasIndex("WorkItemLayoutId");
+
+ b.ToTable("WorkItemVersions", "ProjectManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.System.TaskError", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("ErrorMessage")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ErrorTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("StackTrace")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("TaskErrors", "System");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AccountManagement.BonesRole", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.OrganizationManagement.BonesOrganization", "Organization")
+ .WithMany("Roles")
+ .HasForeignKey("OrganizationId");
+
+ b.Navigation("Organization");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AccountManagement.BonesRoleClaim", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.AccountManagement.BonesRole", null)
+ .WithMany()
+ .HasForeignKey("RoleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AccountManagement.BonesUserClaim", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.AccountManagement.BonesUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AccountManagement.BonesUserLogin", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.AccountManagement.BonesUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AccountManagement.BonesUserRole", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.AccountManagement.BonesRole", null)
+ .WithMany()
+ .HasForeignKey("RoleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Bones.Database.DbSets.AccountManagement.BonesUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AccountManagement.BonesUserToken", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.AccountManagement.BonesUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetFields.AssetField", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.AssetManagement.AssetLayouts.AssetLayoutVersion", null)
+ .WithMany("Fields")
+ .HasForeignKey("AssetLayoutVersionId");
+
+ b.HasOne("Bones.Database.DbSets.OrganizationManagement.BonesOrganization", "OwningOrganization")
+ .WithMany()
+ .HasForeignKey("OwningOrganizationId");
+
+ b.HasOne("Bones.Database.DbSets.AccountManagement.BonesUser", "OwningUser")
+ .WithMany()
+ .HasForeignKey("OwningUserId");
+
+ b.Navigation("OwningOrganization");
+
+ b.Navigation("OwningUser");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetFields.AssetFieldListEntry", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.AssetManagement.AssetFields.AssetField", "ParentField")
+ .WithMany("PossibleValues")
+ .HasForeignKey("ParentFieldId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("ParentField");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetLayouts.AssetLayout", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.OrganizationManagement.BonesOrganization", "OwningOrganization")
+ .WithMany("AssetLayouts")
+ .HasForeignKey("OwningOrganizationId");
+
+ b.HasOne("Bones.Database.DbSets.AccountManagement.BonesUser", "OwningUser")
+ .WithMany("AssetLayouts")
+ .HasForeignKey("OwningUserId");
+
+ b.Navigation("OwningOrganization");
+
+ b.Navigation("OwningUser");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetLayouts.AssetLayoutVersion", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.AssetManagement.AssetLayouts.AssetLayout", "AssetLayout")
+ .WithMany("Versions")
+ .HasForeignKey("AssetLayoutId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("AssetLayout");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.Assets.Asset", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.OrganizationManagement.BonesOrganization", "OwningOrganization")
+ .WithMany("Assets")
+ .HasForeignKey("OwningOrganizationId");
+
+ b.HasOne("Bones.Database.DbSets.AccountManagement.BonesUser", "OwningUser")
+ .WithMany("Assets")
+ .HasForeignKey("OwningUserId");
+
+ b.Navigation("OwningOrganization");
+
+ b.Navigation("OwningUser");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.Assets.AssetValue", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.AssetManagement.Assets.AssetVersion", null)
+ .WithMany("Values")
+ .HasForeignKey("AssetVersionId");
+
+ b.HasOne("Bones.Database.DbSets.AssetManagement.AssetFields.AssetField", "Field")
+ .WithMany()
+ .HasForeignKey("FieldId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Field");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.Assets.AssetVersion", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.AssetManagement.Assets.Asset", "Asset")
+ .WithMany("Versions")
+ .HasForeignKey("AssetId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Bones.Database.DbSets.AssetManagement.AssetLayouts.AssetLayoutVersion", "AssetLayout")
+ .WithMany()
+ .HasForeignKey("AssetLayoutId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Asset");
+
+ b.Navigation("AssetLayout");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.Initiative", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.ProjectManagement.Project", "Project")
+ .WithMany("Initiatives")
+ .HasForeignKey("ProjectId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Project");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.Project", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.OrganizationManagement.BonesOrganization", "OwningOrganization")
+ .WithMany("Projects")
+ .HasForeignKey("OwningOrganizationId");
+
+ b.HasOne("Bones.Database.DbSets.AccountManagement.BonesUser", "OwningUser")
+ .WithMany("Projects")
+ .HasForeignKey("OwningUserId");
+
+ b.Navigation("OwningOrganization");
+
+ b.Navigation("OwningUser");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.Queue", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.ProjectManagement.Initiative", "Initiative")
+ .WithMany("Queues")
+ .HasForeignKey("InitiativeId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Initiative");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.Tag", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.ProjectManagement.WorkItems.WorkItem", null)
+ .WithMany("Tags")
+ .HasForeignKey("WorkItemId");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemFields.WorkItemField", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.ProjectManagement.WorkItemLayouts.WorkItemLayoutVersion", null)
+ .WithMany("Fields")
+ .HasForeignKey("WorkItemLayoutVersionId");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemFields.WorkItemFieldListEntry", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.ProjectManagement.WorkItemFields.WorkItemField", "ParentField")
+ .WithMany("PossibleValues")
+ .HasForeignKey("ParentFieldId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("ParentField");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemLayouts.WorkItemLayout", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.ProjectManagement.Project", "Project")
+ .WithMany()
+ .HasForeignKey("ProjectId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Project");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemLayouts.WorkItemLayoutVersion", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.ProjectManagement.WorkItemLayouts.WorkItemLayout", "WorkItemLayout")
+ .WithMany("Versions")
+ .HasForeignKey("WorkItemLayoutId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("WorkItemLayout");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItems.WorkItem", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.ProjectManagement.Queue", "Queue")
+ .WithMany("WorkItems")
+ .HasForeignKey("QueueId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Queue");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItems.WorkItemValue", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.ProjectManagement.WorkItemFields.WorkItemField", "Field")
+ .WithMany()
+ .HasForeignKey("FieldId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Bones.Database.DbSets.ProjectManagement.WorkItems.WorkItemVersion", null)
+ .WithMany("Values")
+ .HasForeignKey("WorkItemVersionId");
+
+ b.Navigation("Field");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItems.WorkItemVersion", b =>
+ {
+ b.HasOne("Bones.Database.DbSets.ProjectManagement.WorkItems.WorkItem", "WorkItem")
+ .WithMany("Versions")
+ .HasForeignKey("WorkItemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Bones.Database.DbSets.ProjectManagement.WorkItemLayouts.WorkItemLayoutVersion", "WorkItemLayout")
+ .WithMany()
+ .HasForeignKey("WorkItemLayoutId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("WorkItem");
+
+ b.Navigation("WorkItemLayout");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AccountManagement.BonesUser", b =>
+ {
+ b.Navigation("AssetLayouts");
+
+ b.Navigation("Assets");
+
+ b.Navigation("Projects");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetFields.AssetField", b =>
+ {
+ b.Navigation("PossibleValues");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetLayouts.AssetLayout", b =>
+ {
+ b.Navigation("Versions");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetLayouts.AssetLayoutVersion", b =>
+ {
+ b.Navigation("Fields");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.Assets.Asset", b =>
+ {
+ b.Navigation("Versions");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.Assets.AssetVersion", b =>
+ {
+ b.Navigation("Values");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.OrganizationManagement.BonesOrganization", b =>
+ {
+ b.Navigation("AssetLayouts");
+
+ b.Navigation("Assets");
+
+ b.Navigation("Projects");
+
+ b.Navigation("Roles");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.Initiative", b =>
+ {
+ b.Navigation("Queues");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.Project", b =>
+ {
+ b.Navigation("Initiatives");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.Queue", b =>
+ {
+ b.Navigation("WorkItems");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemFields.WorkItemField", b =>
+ {
+ b.Navigation("PossibleValues");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemLayouts.WorkItemLayout", b =>
+ {
+ b.Navigation("Versions");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemLayouts.WorkItemLayoutVersion", b =>
+ {
+ b.Navigation("Fields");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItems.WorkItem", b =>
+ {
+ b.Navigation("Tags");
+
+ b.Navigation("Versions");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItems.WorkItemVersion", b =>
+ {
+ b.Navigation("Values");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Backend/Bones.Database/Migrations/20240908032021_IDontRememberWhatIChanged.cs b/Backend/Bones.Database/Migrations/20240908032021_IDontRememberWhatIChanged.cs
new file mode 100644
index 0000000..81dda06
--- /dev/null
+++ b/Backend/Bones.Database/Migrations/20240908032021_IDontRememberWhatIChanged.cs
@@ -0,0 +1,302 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace Bones.Database.Migrations
+{
+ ///
+ public partial class IDontRememberWhatIChanged : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.EnsureSchema(
+ name: "System");
+
+ migrationBuilder.AddColumn(
+ name: "ProjectId",
+ schema: "ProjectManagement",
+ table: "WorkItemLayouts",
+ type: "uuid",
+ nullable: false,
+ defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
+
+ migrationBuilder.AddColumn(
+ name: "DeleteFlag",
+ schema: "ProjectManagement",
+ table: "Initiatives",
+ type: "boolean",
+ nullable: false,
+ defaultValue: false);
+
+ migrationBuilder.AlterColumn(
+ name: "DisplayName",
+ schema: "AccountManagement",
+ table: "BonesUsers",
+ type: "character varying(256)",
+ maxLength: 256,
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "text",
+ oldNullable: true);
+
+ migrationBuilder.AddColumn(
+ name: "ReadOnlyRole",
+ schema: "AccountManagement",
+ table: "BonesRoles",
+ type: "boolean",
+ nullable: false,
+ defaultValue: false);
+
+ migrationBuilder.AddColumn(
+ name: "OwnerType",
+ schema: "AssetManagement",
+ table: "AssetLayouts",
+ type: "integer",
+ nullable: false,
+ defaultValue: 0);
+
+ migrationBuilder.AddColumn(
+ name: "OwningOrganizationId",
+ schema: "AssetManagement",
+ table: "AssetLayouts",
+ type: "uuid",
+ nullable: true);
+
+ migrationBuilder.AddColumn(
+ name: "OwningUserId",
+ schema: "AssetManagement",
+ table: "AssetLayouts",
+ type: "uuid",
+ nullable: true);
+
+ migrationBuilder.AddColumn(
+ name: "OwnerType",
+ schema: "AssetManagement",
+ table: "AssetFields",
+ type: "integer",
+ nullable: false,
+ defaultValue: 0);
+
+ migrationBuilder.AddColumn(
+ name: "OwningOrganizationId",
+ schema: "AssetManagement",
+ table: "AssetFields",
+ type: "uuid",
+ nullable: true);
+
+ migrationBuilder.AddColumn(
+ name: "OwningUserId",
+ schema: "AssetManagement",
+ table: "AssetFields",
+ type: "uuid",
+ nullable: true);
+
+ migrationBuilder.CreateTable(
+ name: "TaskErrors",
+ schema: "System",
+ columns: table => new
+ {
+ Id = table.Column(type: "uuid", nullable: false),
+ ErrorTime = table.Column(type: "timestamp with time zone", nullable: false),
+ ErrorMessage = table.Column(type: "text", nullable: false),
+ StackTrace = table.Column(type: "text", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_TaskErrors", x => x.Id);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_WorkItemLayouts_ProjectId",
+ schema: "ProjectManagement",
+ table: "WorkItemLayouts",
+ column: "ProjectId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_AssetLayouts_OwningOrganizationId",
+ schema: "AssetManagement",
+ table: "AssetLayouts",
+ column: "OwningOrganizationId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_AssetLayouts_OwningUserId",
+ schema: "AssetManagement",
+ table: "AssetLayouts",
+ column: "OwningUserId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_AssetFields_OwningOrganizationId",
+ schema: "AssetManagement",
+ table: "AssetFields",
+ column: "OwningOrganizationId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_AssetFields_OwningUserId",
+ schema: "AssetManagement",
+ table: "AssetFields",
+ column: "OwningUserId");
+
+ migrationBuilder.AddForeignKey(
+ name: "FK_AssetFields_BonesOrganizations_OwningOrganizationId",
+ schema: "AssetManagement",
+ table: "AssetFields",
+ column: "OwningOrganizationId",
+ principalSchema: "OrganizationManagement",
+ principalTable: "BonesOrganizations",
+ principalColumn: "Id");
+
+ migrationBuilder.AddForeignKey(
+ name: "FK_AssetFields_BonesUsers_OwningUserId",
+ schema: "AssetManagement",
+ table: "AssetFields",
+ column: "OwningUserId",
+ principalSchema: "AccountManagement",
+ principalTable: "BonesUsers",
+ principalColumn: "Id");
+
+ migrationBuilder.AddForeignKey(
+ name: "FK_AssetLayouts_BonesOrganizations_OwningOrganizationId",
+ schema: "AssetManagement",
+ table: "AssetLayouts",
+ column: "OwningOrganizationId",
+ principalSchema: "OrganizationManagement",
+ principalTable: "BonesOrganizations",
+ principalColumn: "Id");
+
+ migrationBuilder.AddForeignKey(
+ name: "FK_AssetLayouts_BonesUsers_OwningUserId",
+ schema: "AssetManagement",
+ table: "AssetLayouts",
+ column: "OwningUserId",
+ principalSchema: "AccountManagement",
+ principalTable: "BonesUsers",
+ principalColumn: "Id");
+
+ migrationBuilder.AddForeignKey(
+ name: "FK_WorkItemLayouts_Projects_ProjectId",
+ schema: "ProjectManagement",
+ table: "WorkItemLayouts",
+ column: "ProjectId",
+ principalSchema: "ProjectManagement",
+ principalTable: "Projects",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropForeignKey(
+ name: "FK_AssetFields_BonesOrganizations_OwningOrganizationId",
+ schema: "AssetManagement",
+ table: "AssetFields");
+
+ migrationBuilder.DropForeignKey(
+ name: "FK_AssetFields_BonesUsers_OwningUserId",
+ schema: "AssetManagement",
+ table: "AssetFields");
+
+ migrationBuilder.DropForeignKey(
+ name: "FK_AssetLayouts_BonesOrganizations_OwningOrganizationId",
+ schema: "AssetManagement",
+ table: "AssetLayouts");
+
+ migrationBuilder.DropForeignKey(
+ name: "FK_AssetLayouts_BonesUsers_OwningUserId",
+ schema: "AssetManagement",
+ table: "AssetLayouts");
+
+ migrationBuilder.DropForeignKey(
+ name: "FK_WorkItemLayouts_Projects_ProjectId",
+ schema: "ProjectManagement",
+ table: "WorkItemLayouts");
+
+ migrationBuilder.DropTable(
+ name: "TaskErrors",
+ schema: "System");
+
+ migrationBuilder.DropIndex(
+ name: "IX_WorkItemLayouts_ProjectId",
+ schema: "ProjectManagement",
+ table: "WorkItemLayouts");
+
+ migrationBuilder.DropIndex(
+ name: "IX_AssetLayouts_OwningOrganizationId",
+ schema: "AssetManagement",
+ table: "AssetLayouts");
+
+ migrationBuilder.DropIndex(
+ name: "IX_AssetLayouts_OwningUserId",
+ schema: "AssetManagement",
+ table: "AssetLayouts");
+
+ migrationBuilder.DropIndex(
+ name: "IX_AssetFields_OwningOrganizationId",
+ schema: "AssetManagement",
+ table: "AssetFields");
+
+ migrationBuilder.DropIndex(
+ name: "IX_AssetFields_OwningUserId",
+ schema: "AssetManagement",
+ table: "AssetFields");
+
+ migrationBuilder.DropColumn(
+ name: "ProjectId",
+ schema: "ProjectManagement",
+ table: "WorkItemLayouts");
+
+ migrationBuilder.DropColumn(
+ name: "DeleteFlag",
+ schema: "ProjectManagement",
+ table: "Initiatives");
+
+ migrationBuilder.DropColumn(
+ name: "ReadOnlyRole",
+ schema: "AccountManagement",
+ table: "BonesRoles");
+
+ migrationBuilder.DropColumn(
+ name: "OwnerType",
+ schema: "AssetManagement",
+ table: "AssetLayouts");
+
+ migrationBuilder.DropColumn(
+ name: "OwningOrganizationId",
+ schema: "AssetManagement",
+ table: "AssetLayouts");
+
+ migrationBuilder.DropColumn(
+ name: "OwningUserId",
+ schema: "AssetManagement",
+ table: "AssetLayouts");
+
+ migrationBuilder.DropColumn(
+ name: "OwnerType",
+ schema: "AssetManagement",
+ table: "AssetFields");
+
+ migrationBuilder.DropColumn(
+ name: "OwningOrganizationId",
+ schema: "AssetManagement",
+ table: "AssetFields");
+
+ migrationBuilder.DropColumn(
+ name: "OwningUserId",
+ schema: "AssetManagement",
+ table: "AssetFields");
+
+ migrationBuilder.AlterColumn(
+ name: "DisplayName",
+ schema: "AccountManagement",
+ table: "BonesUsers",
+ type: "text",
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "character varying(256)",
+ oldMaxLength: 256,
+ oldNullable: true);
+ }
+ }
+}
diff --git a/Backend/Bones.Database/Migrations/BonesDbContextModelSnapshot.cs b/Backend/Bones.Database/Migrations/BonesDbContextModelSnapshot.cs
index ca89c56..e94125f 100644
--- a/Backend/Bones.Database/Migrations/BonesDbContextModelSnapshot.cs
+++ b/Backend/Bones.Database/Migrations/BonesDbContextModelSnapshot.cs
@@ -46,6 +46,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Property("OrganizationId")
.HasColumnType("uuid");
+ b.Property("ReadOnlyRole")
+ .HasColumnType("boolean");
+
b.HasKey("Id");
b.HasIndex("NormalizedName")
@@ -95,7 +98,8 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasColumnType("text");
b.Property("DisplayName")
- .HasColumnType("text");
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
b.Property("Email")
.HasMaxLength(256)
@@ -234,13 +238,16 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("BonesUserTokens", "AccountManagement");
});
- modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.Asset", b =>
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetFields.AssetField", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
- b.Property("DeleteFlag")
+ b.Property("AssetLayoutVersionId")
+ .HasColumnType("uuid");
+
+ b.Property("IsRequired")
.HasColumnType("boolean");
b.Property("Name")
@@ -257,32 +264,6 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Property("OwningUserId")
.HasColumnType("uuid");
- b.HasKey("Id");
-
- b.HasIndex("OwningOrganizationId");
-
- b.HasIndex("OwningUserId");
-
- b.ToTable("Assets", "AssetManagement");
- });
-
- modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetField", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uuid");
-
- b.Property("AssetLayoutVersionId")
- .HasColumnType("uuid");
-
- b.Property("IsRequired")
- .HasColumnType("boolean");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(512)
- .HasColumnType("character varying(512)");
-
b.Property("Type")
.HasColumnType("integer");
@@ -290,10 +271,14 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.HasIndex("AssetLayoutVersionId");
+ b.HasIndex("OwningOrganizationId");
+
+ b.HasIndex("OwningUserId");
+
b.ToTable("AssetFields", "AssetManagement");
});
- modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetFieldListEntry", b =>
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetFields.AssetFieldListEntry", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
@@ -316,7 +301,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("AssetFieldListEntries", "AssetManagement");
});
- modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetLayout", b =>
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetLayouts.AssetLayout", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
@@ -330,12 +315,25 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasMaxLength(512)
.HasColumnType("character varying(512)");
+ b.Property("OwnerType")
+ .HasColumnType("integer");
+
+ b.Property("OwningOrganizationId")
+ .HasColumnType("uuid");
+
+ b.Property("OwningUserId")
+ .HasColumnType("uuid");
+
b.HasKey("Id");
+ b.HasIndex("OwningOrganizationId");
+
+ b.HasIndex("OwningUserId");
+
b.ToTable("AssetLayouts", "AssetManagement");
});
- modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetLayoutVersion", b =>
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetLayouts.AssetLayoutVersion", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
@@ -357,7 +355,39 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("AssetLayoutVersions", "AssetManagement");
});
- modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetValue", b =>
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.Assets.Asset", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("OwnerType")
+ .HasColumnType("integer");
+
+ b.Property("OwningOrganizationId")
+ .HasColumnType("uuid");
+
+ b.Property("OwningUserId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OwningOrganizationId");
+
+ b.HasIndex("OwningUserId");
+
+ b.ToTable("Assets", "AssetManagement");
+ });
+
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.Assets.AssetValue", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
@@ -387,7 +417,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("AssetValues", "AssetManagement");
});
- modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.AssetVersion", b =>
+ modelBuilder.Entity("Bones.Database.DbSets.AssetManagement.Assets.AssetVersion", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
@@ -436,6 +466,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
+ b.Property("DeleteFlag")
+ .HasColumnType("boolean");
+
b.Property("Name")
.IsRequired()
.HasMaxLength(512)
@@ -528,34 +561,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("Tags", "ProjectManagement");
});
- modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItem", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uuid");
-
- b.Property("AddedToQueueDateTime")
- .HasColumnType("timestamp with time zone");
-
- b.Property("DeleteFlag")
- .HasColumnType("boolean");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(512)
- .HasColumnType("character varying(512)");
-
- b.Property("QueueId")
- .HasColumnType("uuid");
-
- b.HasKey("Id");
-
- b.HasIndex("QueueId");
-
- b.ToTable("WorkItems", "ProjectManagement");
- });
-
- modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemField", b =>
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemFields.WorkItemField", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
@@ -582,7 +588,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("WorkItemFields", "ProjectManagement");
});
- modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemFieldListEntry", b =>
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemFields.WorkItemFieldListEntry", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
@@ -605,7 +611,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("WorkItemFieldListEntries", "ProjectManagement");
});
- modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemLayout", b =>
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemLayouts.WorkItemLayout", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
@@ -619,12 +625,17 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasMaxLength(512)
.HasColumnType("character varying(512)");
+ b.Property("ProjectId")
+ .HasColumnType("uuid");
+
b.HasKey("Id");
+ b.HasIndex("ProjectId");
+
b.ToTable("WorkItemLayouts", "ProjectManagement");
});
- modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemLayoutVersion", b =>
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemLayouts.WorkItemLayoutVersion", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
@@ -646,7 +657,34 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("WorkItemLayoutVersions", "ProjectManagement");
});
- modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItemValue", b =>
+ modelBuilder.Entity("Bones.Database.DbSets.ProjectManagement.WorkItems.WorkItem", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("AddedToQueueDateTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property