From bd4e77725055d01d835a65885c4ff7c0747fb23f Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Sun, 10 Aug 2025 14:14:57 +0000
Subject: [PATCH 1/8] chore(*): Update aspnetboilerplate to 8.4.0
---
.../AcmStatisticsBackend.Core.csproj | 4 ++--
.../AcmStatisticsBackend.Web.Core.csproj | 4 ++--
.../AcmStatisticsBackend.Web.Host.csproj | 2 +-
.../AcmStatisticsBackend.Tests.csproj | 2 +-
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/backend/src/AcmStatisticsBackend.Core/AcmStatisticsBackend.Core.csproj b/backend/src/AcmStatisticsBackend.Core/AcmStatisticsBackend.Core.csproj
index 608df666e..b47338a40 100644
--- a/backend/src/AcmStatisticsBackend.Core/AcmStatisticsBackend.Core.csproj
+++ b/backend/src/AcmStatisticsBackend.Core/AcmStatisticsBackend.Core.csproj
@@ -14,8 +14,8 @@
-
-
+
+
diff --git a/backend/src/AcmStatisticsBackend.Web.Core/AcmStatisticsBackend.Web.Core.csproj b/backend/src/AcmStatisticsBackend.Web.Core/AcmStatisticsBackend.Web.Core.csproj
index 687137292..e6254c17d 100644
--- a/backend/src/AcmStatisticsBackend.Web.Core/AcmStatisticsBackend.Web.Core.csproj
+++ b/backend/src/AcmStatisticsBackend.Web.Core/AcmStatisticsBackend.Web.Core.csproj
@@ -23,7 +23,7 @@
-
-
+
+
diff --git a/backend/src/AcmStatisticsBackend.Web.Host/AcmStatisticsBackend.Web.Host.csproj b/backend/src/AcmStatisticsBackend.Web.Host/AcmStatisticsBackend.Web.Host.csproj
index cfe7f9a19..46de5a83d 100644
--- a/backend/src/AcmStatisticsBackend.Web.Host/AcmStatisticsBackend.Web.Host.csproj
+++ b/backend/src/AcmStatisticsBackend.Web.Host/AcmStatisticsBackend.Web.Host.csproj
@@ -30,7 +30,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/backend/test/AcmStatisticsBackend.Tests/AcmStatisticsBackend.Tests.csproj b/backend/test/AcmStatisticsBackend.Tests/AcmStatisticsBackend.Tests.csproj
index 5df0b4ab5..c497fecfa 100644
--- a/backend/test/AcmStatisticsBackend.Tests/AcmStatisticsBackend.Tests.csproj
+++ b/backend/test/AcmStatisticsBackend.Tests/AcmStatisticsBackend.Tests.csproj
@@ -28,7 +28,7 @@
all
runtime; build; native; contentfiles; analyzers
-
+
From a8ddd2021faf25e7ad5131d261c95b729432b4ee Mon Sep 17 00:00:00 2001
From: Shumin Liu
Date: Tue, 12 Aug 2025 21:18:42 +1000
Subject: [PATCH 2/8] build(ohunt): upgrade dotnet to 8.0
---
ohunt/OHunt.Tests/OHunt.Tests.csproj | 28 +-
.../SwaggerTests.It_ShouldOutputDocument.snap | 433 ++++++++++++++++--
ohunt/OHunt.Web/Crawlers/CrawlerBase.cs | 4 +-
.../Crawlers/ZojSubmissionCrawler.cs | 3 +-
ohunt/OHunt.Web/Dockerfile | 4 +-
ohunt/OHunt.Web/GlobalConfigurer.cs | 16 +-
ohunt/OHunt.Web/OHunt.Web.csproj | 18 +-
ohunt/dev.Dockerfile | 2 +-
ohunt/global.json | 7 +
9 files changed, 437 insertions(+), 78 deletions(-)
create mode 100644 ohunt/global.json
diff --git a/ohunt/OHunt.Tests/OHunt.Tests.csproj b/ohunt/OHunt.Tests/OHunt.Tests.csproj
index bf0bd1034..94cb74280 100644
--- a/ohunt/OHunt.Tests/OHunt.Tests.csproj
+++ b/ohunt/OHunt.Tests/OHunt.Tests.csproj
@@ -1,31 +1,31 @@
- net7.0
+ net8.0
false
enable
-
-
-
-
-
-
-
+
+
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
+
+
+
-
+
-
-
+
+
all
runtime; build; native; contentfiles; analyzers
diff --git a/ohunt/OHunt.Tests/Web/__snapshots__/SwaggerTests.It_ShouldOutputDocument.snap b/ohunt/OHunt.Tests/Web/__snapshots__/SwaggerTests.It_ShouldOutputDocument.snap
index b16a4bef6..beea1a2ff 100644
--- a/ohunt/OHunt.Tests/Web/__snapshots__/SwaggerTests.It_ShouldOutputDocument.snap
+++ b/ohunt/OHunt.Tests/Web/__snapshots__/SwaggerTests.It_ShouldOutputDocument.snap
@@ -1,5 +1,5 @@
{
- "openapi": "3.0.1",
+ "openapi": "3.0.4",
"info": {
"title": "OHunt API",
"description": "OHunt is a crawler that reads data from online coding competition platform and serve them as API, just like uHunt of UVA.",
@@ -14,7 +14,7 @@
"operationId": "api/ohunt/$metadata",
"responses": {
"200": {
- "description": "Success",
+ "description": "OK",
"content": {
"application/json;odata.metadata=minimal;odata.streaming=true": {
"schema": {
@@ -76,6 +76,126 @@
"$ref": "#/components/schemas/IEdmModel"
}
},
+ "application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=minimal;odata.streaming=false;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=minimal;odata.streaming=false;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=minimal;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=minimal;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=full;odata.streaming=true;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=full;odata.streaming=true;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=full;odata.streaming=false;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=full;odata.streaming=false;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=full;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=full;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=none;odata.streaming=true;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=none;odata.streaming=true;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=none;odata.streaming=false;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=none;odata.streaming=false;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=none;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.metadata=none;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.streaming=true;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.streaming=true;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.streaming=false;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;odata.streaming=false;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
+ "application/json;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/IEdmModel"
+ }
+ },
"application/xml": {
"schema": {
"$ref": "#/components/schemas/IEdmModel"
@@ -109,7 +229,7 @@
"operationId": "api/ohunt/",
"responses": {
"200": {
- "description": "Success",
+ "description": "OK",
"content": {
"application/json;odata.metadata=minimal;odata.streaming=true": {
"schema": {
@@ -171,6 +291,126 @@
"$ref": "#/components/schemas/ODataServiceDocument"
}
},
+ "application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=minimal;odata.streaming=false;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=minimal;odata.streaming=false;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=minimal;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=minimal;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=full;odata.streaming=true;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=full;odata.streaming=true;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=full;odata.streaming=false;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=full;odata.streaming=false;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=full;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=full;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=none;odata.streaming=true;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=none;odata.streaming=true;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=none;odata.streaming=false;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=none;odata.streaming=false;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=none;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.metadata=none;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.streaming=true;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.streaming=true;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.streaming=false;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;odata.streaming=false;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
+ "application/json;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ODataServiceDocument"
+ }
+ },
"application/xml": {
"schema": {
"$ref": "#/components/schemas/ODataServiceDocument"
@@ -264,6 +504,126 @@
"$ref": "#/components/schemas/ResolveLabelInput"
}
},
+ "application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=minimal;odata.streaming=false;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=minimal;odata.streaming=false;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=minimal;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=minimal;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=full;odata.streaming=true;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=full;odata.streaming=true;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=full;odata.streaming=false;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=full;odata.streaming=false;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=full;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=full;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=none;odata.streaming=true;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=none;odata.streaming=true;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=none;odata.streaming=false;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=none;odata.streaming=false;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=none;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.metadata=none;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.streaming=true;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.streaming=true;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.streaming=false;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;odata.streaming=false;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;IEEE754Compatible=false": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
+ "application/json;IEEE754Compatible=true": {
+ "schema": {
+ "$ref": "#/components/schemas/ResolveLabelInput"
+ }
+ },
"application/xml": {
"schema": {
"$ref": "#/components/schemas/ResolveLabelInput"
@@ -288,7 +648,7 @@
},
"responses": {
"200": {
- "description": "Success",
+ "description": "OK",
"content": {
"application/json": {
"schema": {
@@ -306,7 +666,7 @@
"Submissions"
],
"summary": "Get the submission in an OJ.",
- "description": "The api uses odata to create arbitrary query requests.\r\nSee the document https://www.odata.org/ for more information.\r\n\r\nSample request:\r\n\r\n GET /api/ohunt/submissions?oj=zoj&$filter=userName eq 'vjudge5' and status eq 'Accepted'&$count=true",
+ "description": "The api uses odata to create arbitrary query requests.\nSee the document https://www.odata.org/ for more information.\n\nSample request:\n\n GET /api/ohunt/submissions?oj=zoj&$filter=userName eq 'vjudge5' and status eq 'Accepted'&$count=true",
"parameters": [
{
"name": "oj",
@@ -416,7 +776,7 @@
"Path",
"If",
"Cast",
- "IsType",
+ "IsOf",
"FunctionApplication",
"LabeledExpressionReference",
"Labeled",
@@ -462,11 +822,8 @@
"IEdmEntityContainer": {
"type": "object",
"properties": {
- "elements": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/IEdmEntityContainerElement"
- },
+ "name": {
+ "type": "string",
"nullable": true,
"readOnly": true
},
@@ -478,8 +835,11 @@
"nullable": true,
"readOnly": true
},
- "name": {
- "type": "string",
+ "elements": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/IEdmEntityContainerElement"
+ },
"nullable": true,
"readOnly": true
}
@@ -489,16 +849,16 @@
"IEdmEntityContainerElement": {
"type": "object",
"properties": {
+ "name": {
+ "type": "string",
+ "nullable": true,
+ "readOnly": true
+ },
"containerElementKind": {
"$ref": "#/components/schemas/EdmContainerElementKind"
},
"container": {
"$ref": "#/components/schemas/IEdmEntityContainer"
- },
- "name": {
- "type": "string",
- "nullable": true,
- "readOnly": true
}
},
"additionalProperties": false
@@ -559,15 +919,15 @@
"IEdmSchemaElement": {
"type": "object",
"properties": {
- "schemaElementKind": {
- "$ref": "#/components/schemas/EdmSchemaElementKind"
- },
- "namespace": {
+ "name": {
"type": "string",
"nullable": true,
"readOnly": true
},
- "name": {
+ "schemaElementKind": {
+ "$ref": "#/components/schemas/EdmSchemaElementKind"
+ },
+ "namespace": {
"type": "string",
"nullable": true,
"readOnly": true
@@ -578,28 +938,28 @@
"IEdmTerm": {
"type": "object",
"properties": {
- "type": {
- "$ref": "#/components/schemas/IEdmTypeReference"
- },
- "appliesTo": {
+ "name": {
"type": "string",
"nullable": true,
"readOnly": true
},
- "defaultValue": {
+ "schemaElementKind": {
+ "$ref": "#/components/schemas/EdmSchemaElementKind"
+ },
+ "namespace": {
"type": "string",
"nullable": true,
"readOnly": true
},
- "schemaElementKind": {
- "$ref": "#/components/schemas/EdmSchemaElementKind"
+ "type": {
+ "$ref": "#/components/schemas/IEdmTypeReference"
},
- "namespace": {
+ "appliesTo": {
"type": "string",
"nullable": true,
"readOnly": true
},
- "name": {
+ "defaultValue": {
"type": "string",
"nullable": true,
"readOnly": true
@@ -649,6 +1009,10 @@
},
"value": {
"$ref": "#/components/schemas/IEdmExpression"
+ },
+ "usesDefault": {
+ "type": "boolean",
+ "readOnly": true
}
},
"additionalProperties": false
@@ -800,7 +1164,8 @@
"result": {
"type": "object",
"additionalProperties": {
- "type": "string"
+ "type": "string",
+ "nullable": true
},
"description": "The result from the output",
"nullable": true
@@ -836,7 +1201,7 @@
"submissionId": {
"minimum": 1,
"type": "integer",
- "description": "The id of the submission. It should be unique per oj.\r\n \r\nIt is used to identify submissions, so newer submission\r\nshould have larger id.",
+ "description": "The id of the submission. It should be unique per oj.\n \nIt is used to identify submissions, so newer submission\nshould have larger id.",
"format": "int64"
},
"onlineJudgeId": {
diff --git a/ohunt/OHunt.Web/Crawlers/CrawlerBase.cs b/ohunt/OHunt.Web/Crawlers/CrawlerBase.cs
index b3d5f9f63..b20893f9c 100644
--- a/ohunt/OHunt.Web/Crawlers/CrawlerBase.cs
+++ b/ohunt/OHunt.Web/Crawlers/CrawlerBase.cs
@@ -29,7 +29,7 @@ protected async Task GetDocument(
await Task.Delay(delta, cancellationToken);
}
- var response = await url.GetStreamAsync(cancellationToken);
+ var response = await url.GetStreamAsync(cancellationToken: cancellationToken);
var document = await Context.OpenAsync(
req => req.Content(response),
cancellationToken);
@@ -48,7 +48,7 @@ protected async Task GetJson(
await Task.Delay(delta, cancellationToken);
}
- var result = await request.GetStreamAsync(cancellationToken);
+ var result = await request.GetStreamAsync(cancellationToken: cancellationToken);
_lastRequestTime = DateTime.Now;
return await JsonDocument.ParseAsync(result, cancellationToken: cancellationToken);
diff --git a/ohunt/OHunt.Web/Crawlers/ZojSubmissionCrawler.cs b/ohunt/OHunt.Web/Crawlers/ZojSubmissionCrawler.cs
index fd696a34c..35dbb7109 100644
--- a/ohunt/OHunt.Web/Crawlers/ZojSubmissionCrawler.cs
+++ b/ohunt/OHunt.Web/Crawlers/ZojSubmissionCrawler.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Net;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
@@ -65,7 +64,7 @@ private async Task Request(
cancellationToken.ThrowIfCancellationRequested();
var request = BaseUrl.SetQueryParam("after", after)
.WithHeader("Accept", "application/json;charset=UTF-8")
- .AllowHttpStatus(HttpStatusCode.InternalServerError);
+ .AllowHttpStatus(500);
if (before != null)
{
request = request.SetQueryParam("before", before);
diff --git a/ohunt/OHunt.Web/Dockerfile b/ohunt/OHunt.Web/Dockerfile
index ba13d484d..b1e553819 100644
--- a/ohunt/OHunt.Web/Dockerfile
+++ b/ohunt/OHunt.Web/Dockerfile
@@ -1,11 +1,11 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
-FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
+FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
-FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["OHunt.Web/OHunt.Web.csproj", "OHunt.Web/"]
RUN dotnet restore "OHunt.Web/OHunt.Web.csproj"
diff --git a/ohunt/OHunt.Web/GlobalConfigurer.cs b/ohunt/OHunt.Web/GlobalConfigurer.cs
index 356366e85..6c1b28ea8 100644
--- a/ohunt/OHunt.Web/GlobalConfigurer.cs
+++ b/ohunt/OHunt.Web/GlobalConfigurer.cs
@@ -1,8 +1,5 @@
-using System.Net.Http;
-using System.Net.Security;
using System.Runtime.CompilerServices;
using Flurl.Http;
-using Flurl.Http.Configuration;
namespace OHunt.Web
{
@@ -14,17 +11,8 @@ public class GlobalConfigurer
[ModuleInitializer]
public static void Configure()
{
- FlurlHttp.ConfigureClient("https://icpcarchive.ecs.baylor.edu/uhunt", cli =>
- cli.Settings.HttpClientFactory = new UntrustedCertClientFactory());
- }
- }
-
- public class UntrustedCertClientFactory : DefaultHttpClientFactory
- {
- public override HttpMessageHandler CreateMessageHandler() {
- return new HttpClientHandler {
- ServerCertificateCustomValidationCallback = (a, b, c, d) => true
- };
+ FlurlHttp.ConfigureClientForUrl("https://icpcarchive.ecs.baylor.edu/uhunt")
+ .ConfigureInnerHandler(handler => handler.ServerCertificateCustomValidationCallback = (msg, cert, chain, errors) => true);
}
}
}
diff --git a/ohunt/OHunt.Web/OHunt.Web.csproj b/ohunt/OHunt.Web/OHunt.Web.csproj
index e513d5ab4..f54c7788e 100644
--- a/ohunt/OHunt.Web/OHunt.Web.csproj
+++ b/ohunt/OHunt.Web/OHunt.Web.csproj
@@ -1,7 +1,7 @@
- net7.0
+ net8.0
enable
@@ -14,21 +14,21 @@
-
-
-
-
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
+
diff --git a/ohunt/dev.Dockerfile b/ohunt/dev.Dockerfile
index d0166081b..c3b006481 100644
--- a/ohunt/dev.Dockerfile
+++ b/ohunt/dev.Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:7.0
+FROM mcr.microsoft.com/dotnet/sdk:8.0
WORKDIR /src
diff --git a/ohunt/global.json b/ohunt/global.json
new file mode 100644
index 000000000..b5b37b60d
--- /dev/null
+++ b/ohunt/global.json
@@ -0,0 +1,7 @@
+{
+ "sdk": {
+ "version": "8.0.0",
+ "rollForward": "latestMajor",
+ "allowPrerelease": false
+ }
+}
\ No newline at end of file
From 9a86c55dfa5eee5a571e3d615670f2df8fa89f4d Mon Sep 17 00:00:00 2001
From: Shumin Liu
Date: Tue, 12 Aug 2025 21:35:33 +1000
Subject: [PATCH 3/8] build(ohunt): drop xbehave
It is deprecated and can be simply replaced with comments.
---
.../Dataflow/CrawlerPropagatorTests.cs | 78 ++--
.../SubmissionCrawlerCoordinatorTests.cs | 438 ++++++++----------
ohunt/OHunt.Tests/OHunt.Tests.csproj | 1 -
.../OHunt.Tests/Web/ProblemControllerTests.cs | 118 ++---
4 files changed, 282 insertions(+), 353 deletions(-)
diff --git a/ohunt/OHunt.Tests/Dataflow/CrawlerPropagatorTests.cs b/ohunt/OHunt.Tests/Dataflow/CrawlerPropagatorTests.cs
index 374f9c8f6..fb168c0b8 100644
--- a/ohunt/OHunt.Tests/Dataflow/CrawlerPropagatorTests.cs
+++ b/ohunt/OHunt.Tests/Dataflow/CrawlerPropagatorTests.cs
@@ -6,7 +6,6 @@
using OHunt.Web.Crawlers;
using OHunt.Web.Dataflow;
using OHunt.Web.Models;
-using Xbehave;
using Xunit;
namespace OHunt.Tests.Dataflow
@@ -26,51 +25,44 @@ public CrawlerPropagatorTests()
_propagator = new CrawlerPropagator(_submissionOutput, _errorOutput);
}
- [Scenario]
- public void It_ShouldWork()
+ [Fact]
+ public async Task It_ShouldWork()
{
- "Given a propagator".x(() => { });
-
- "When receiving data"
- .x(() => _propagator.SendAsync(new CrawlerMessage
- {
- Submission = new Submission
- {
- Status = RunResult.Accepted,
- Time = new DateTime(2020, 4, 1, 0, 0, 0),
- ProblemLabel = "1001",
- SubmissionId = 42,
- UserName = "user1",
- OnlineJudgeId = OnlineJudge.ZOJ,
- },
- CrawlerError = new CrawlerError
- {
- Crawler = "zoj",
- Data = null,
- Message = "An error",
- Time = new DateTime(2020, 4, 1, 1, 0, 0),
- },
- })
- );
-
- "Then they are cached"
- .x(async () =>
+ // Given a propagator
+
+ // When receiving data
+ await _propagator.SendAsync(new CrawlerMessage
+ {
+ Submission = new Submission
+ {
+ Status = RunResult.Accepted,
+ Time = new DateTime(2020, 4, 1, 0, 0, 0),
+ ProblemLabel = "1001",
+ SubmissionId = 42,
+ UserName = "user1",
+ OnlineJudgeId = OnlineJudge.ZOJ,
+ },
+ CrawlerError = new CrawlerError
{
- await Utils.WaitSecond();
- _submissionOutput.Count.Should().Be(0);
- _errorOutput.Count.Should().Be(0);
- });
+ Crawler = "zoj",
+ Data = null,
+ Message = "An error",
+ Time = new DateTime(2020, 4, 1, 1, 0, 0),
+ },
+ });
- "When a checkpoint is sent"
- .x(() => _propagator.SendAsync(new CrawlerMessage { Checkpoint = true }));
+ // Then they are cached
+ await Utils.WaitSecond();
+ _submissionOutput.Count.Should().Be(0);
+ _errorOutput.Count.Should().Be(0);
- "Then data are dispatched"
- .x(async () =>
- {
- await Utils.WaitSecond();
- _submissionOutput.Count.Should().Be(1);
- _errorOutput.Count.Should().Be(1);
- });
+ // When a checkpoint is sent
+ await _propagator.SendAsync(new CrawlerMessage { Checkpoint = true });
+
+ // Then data are dispatched
+ await Utils.WaitSecond();
+ _submissionOutput.Count.Should().Be(1);
+ _errorOutput.Count.Should().Be(1);
}
[Fact]
@@ -107,7 +99,7 @@ await _propagator.SendAsync(new CrawlerMessage
await _propagator.SendAsync(new CrawlerMessage
{
Submission = new Submission
- {
+ {
SubmissionId = 4,
},
Checkpoint = true,
diff --git a/ohunt/OHunt.Tests/Dataflow/SubmissionCrawlerCoordinatorTests.cs b/ohunt/OHunt.Tests/Dataflow/SubmissionCrawlerCoordinatorTests.cs
index 70916e48d..cfe7a4f9b 100644
--- a/ohunt/OHunt.Tests/Dataflow/SubmissionCrawlerCoordinatorTests.cs
+++ b/ohunt/OHunt.Tests/Dataflow/SubmissionCrawlerCoordinatorTests.cs
@@ -10,7 +10,6 @@
using OHunt.Web.Crawlers;
using OHunt.Web.Dataflow;
using OHunt.Web.Models;
-using Xbehave;
using Xunit;
using Xunit.Abstractions;
@@ -42,120 +41,111 @@ private static Submission CreateSubmission(long id)
};
}
- [Scenario]
- public void It_ShouldWork()
+ [Fact]
+ public async Task It_ShouldWork()
{
- "Given a coordinator".x(() => { });
+ // Given a coordinator
- "When it is initialized"
- .x(() => _coordinator.Initialize(new[] { _crawlerMock }));
+ // When it is initialized
+ _coordinator.Initialize(new[] { _crawlerMock });
- "But crawler does not immediately work"
- .x(() => _crawlerMock.CalledCount.Should().Be(0));
+ // But crawler does not immediately work
+ _crawlerMock.CalledCount.Should().Be(0);
- $"When calling {nameof(_coordinator.StartAllCrawlers)}"
- .x(() => _coordinator.StartAllCrawlers());
+ // When calling StartAllCrawlers
+ await _coordinator.StartAllCrawlers();
- $"Then crawler's {nameof(_crawlerMock.WorkAsync)} is called"
- .x(() => _crawlerMock.CalledCount.Should().Be(1));
+ // Then crawler's WorkAsync is called
+ _crawlerMock.CalledCount.Should().Be(1);
- "And there is nothing in the database"
- .x(() => WithDb(context =>
- {
- context.Submission.Should().BeEmpty();
- context.CrawlerErrors.Should().BeEmpty();
- }));
+ // And there is nothing in the database
+ WithDb(context =>
+ {
+ context.Submission.Should().BeEmpty();
+ context.CrawlerErrors.Should().BeEmpty();
+ });
- "And lastSubmissionId sent to crawler should be null"
- .x(() => _crawlerMock.LastSubmissionId.Should().BeNull());
+ // And lastSubmissionId sent to crawler should be null
+ _crawlerMock.LastSubmissionId.Should().BeNull();
- "When crawler sends data"
- .x(async () =>
+ // When crawler sends data
+ await _crawlerMock.Pipeline.SendAsync(new CrawlerMessage
+ {
+ Submission = new Submission
{
- await _crawlerMock.Pipeline.SendAsync(new CrawlerMessage
- {
- Submission = new Submission
- {
- Status = RunResult.Accepted,
- Time = new DateTime(2020, 4, 1, 0, 0, 0),
- ProblemLabel = "1001",
- SubmissionId = 42,
- UserName = "user1",
- OnlineJudgeId = OnlineJudge.ZOJ,
- },
- });
- await _crawlerMock.Pipeline.SendAsync(new CrawlerMessage
- {
- CrawlerError = new CrawlerError
- {
- Crawler = "zoj",
- Data = null,
- Message = "An error",
- Time = new DateTime(2020, 4, 1, 1, 0, 0),
- },
- });
- await Utils.WaitSecond();
- });
-
- "But data are not saved to database immediately"
- .x(() => WithDb(context =>
+ Status = RunResult.Accepted,
+ Time = new DateTime(2020, 4, 1, 0, 0, 0),
+ ProblemLabel = "1001",
+ SubmissionId = 42,
+ UserName = "user1",
+ OnlineJudgeId = OnlineJudge.ZOJ,
+ },
+ });
+ await _crawlerMock.Pipeline.SendAsync(new CrawlerMessage
+ {
+ CrawlerError = new CrawlerError
{
- context.Submission.Should().BeEmpty();
- context.CrawlerErrors.Should().BeEmpty();
- }));
+ Crawler = "zoj",
+ Data = null,
+ Message = "An error",
+ Time = new DateTime(2020, 4, 1, 1, 0, 0),
+ },
+ });
+ await Utils.WaitSecond();
- "When crawler sends a checkpoint"
- .x(async () =>
- {
- await _crawlerMock.Pipeline.SendAsync(new CrawlerMessage
- {
- Checkpoint = true,
- });
- await Utils.WaitSecond();
- });
+ // But data are not saved to database immediately
+ WithDb(context =>
+ {
+ context.Submission.Should().BeEmpty();
+ context.CrawlerErrors.Should().BeEmpty();
+ });
- "But data are not saved to database immediately"
- .x(() => WithDb(context =>
- {
- context.Submission.Should().BeEmpty();
- context.CrawlerErrors.Should().BeEmpty();
- }));
+ // When crawler sends a checkpoint
+ await _crawlerMock.Pipeline.SendAsync(new CrawlerMessage
+ {
+ Checkpoint = true,
+ });
+ await Utils.WaitSecond();
+
+ // But data are not saved to database immediately
+ WithDb(context =>
+ {
+ context.Submission.Should().BeEmpty();
+ context.CrawlerErrors.Should().BeEmpty();
+ });
+
+ // When crawler finished
+ _crawlerMock.TaskSource.SetResult(1);
+ // wait longer to insert database
+ await Utils.WaitSecond();
- "When crawler finished"
- .x(async () =>
+ // Then data are saved to database
+ WithDb(context =>
+ {
+ context.Submission.Should().HaveCount(1);
+ context.Submission.Should().AllBeEquivalentTo(new Submission
{
- _crawlerMock.TaskSource.SetResult(1);
- // wait longer to insert database
- await Utils.WaitSecond();
+ Status = RunResult.Accepted,
+ Time = new DateTime(2020, 4, 1, 0, 0, 0),
+ ProblemLabel = "1001",
+ SubmissionId = 42,
+ UserName = "user1",
+ OnlineJudgeId = OnlineJudge.ZOJ,
});
- "Then data are saved to database"
- .x(() => WithDb(context =>
+ context.CrawlerErrors.Should().HaveCount(1);
+ context.CrawlerErrors.Single().Invoking(it =>
{
- context.Submission.Should().HaveCount(1);
- context.Submission.Should().AllBeEquivalentTo(new Submission
- {
- Status = RunResult.Accepted,
- Time = new DateTime(2020, 4, 1, 0, 0, 0),
- ProblemLabel = "1001",
- SubmissionId = 42,
- UserName = "user1",
- OnlineJudgeId = OnlineJudge.ZOJ,
- });
-
- context.CrawlerErrors.Should().HaveCount(1);
- context.CrawlerErrors.Single().Invoking(it =>
- {
- it.Crawler.Should().Be("zoj");
- it.Data.Should().BeNull();
- it.Message.Should().Be("An error");
- it.Time.Should().Be(new DateTime(2020, 4, 1, 1, 0, 0));
- it.Id.Should().NotBe(0);
- });
- }));
+ it.Crawler.Should().Be("zoj");
+ it.Data.Should().BeNull();
+ it.Message.Should().Be("An error");
+ it.Time.Should().Be(new DateTime(2020, 4, 1, 1, 0, 0));
+ it.Id.Should().NotBe(0);
+ });
+ });
- "When cancelling a coordinator, it should not throw"
- .x(() => _coordinator.Cancel());
+ // When cancelling a coordinator, it should not throw
+ await _coordinator.Cancel();
}
[Fact]
@@ -211,78 +201,61 @@ public void WhenNotInitialized_ItShouldThrow()
.Should().ThrowExactlyAsync();
}
- [Scenario]
- public void WhenCrawlerThrows()
+ [Fact]
+ public async Task WhenCrawlerThrows()
{
- "Given an initialized coordinator"
- .x(() =>
- {
- _coordinator.Initialize(new[] { _crawlerMock });
- _coordinator.StartAllCrawlers();
- });
-
- "And some data"
- .x(async () =>
- {
- _crawlerMock.CalledCount.Should().Be(1);
+ // Given an initialized coordinator
+ _coordinator.Initialize(new[] { _crawlerMock });
+ await _coordinator.StartAllCrawlers();
- await SendToPipeline(new CrawlerMessage
- {
- Submission = CreateSubmission(1),
- Checkpoint = true,
- });
- await SendToPipeline(new CrawlerMessage
- {
- Submission = CreateSubmission(2),
- });
- });
+ // And some data
+ _crawlerMock.CalledCount.Should().Be(1);
+ await SendToPipeline(new CrawlerMessage
+ {
+ Submission = CreateSubmission(1),
+ Checkpoint = true,
+ });
+ await SendToPipeline(new CrawlerMessage
+ {
+ Submission = CreateSubmission(2),
+ });
- "When crawler throws"
- .x(() => _crawlerMock.TaskSource.SetException(new Exception("Crawler throws")));
+ // When crawler throws
+ _crawlerMock.TaskSource.SetException(new Exception("Crawler throws"));
- "Then coordinator should complete"
- .x(async () =>
- {
- // cannot test it
- await Utils.WaitSecond();
- });
+ // Then coordinator should complete (allow processing to settle)
+ await Utils.WaitSecond();
- "And data before checkpoint should be saved"
- .x(() => WithDb(context =>
- {
- context.Submission.Should().HaveCount(1);
- context.Submission.Single().Should()
- .Match(it => it.As().SubmissionId == 1);
- }));
+ // And data before checkpoint should be saved
+ WithDb(context =>
+ {
+ context.Submission.Should().HaveCount(1);
+ context.Submission.Single().Should()
+ .Match(it => it.As().SubmissionId == 1);
+ });
- "When start coordinator again"
- .x(() => _coordinator.StartAllCrawlers());
+ // When start coordinator again
+ await _coordinator.StartAllCrawlers();
- "And send some data"
- .x(() =>
- {
- _crawlerMock.CalledCount.Should().Be(2);
- return SendToPipeline(new CrawlerMessage
- {
- Submission = CreateSubmission(3),
- Checkpoint = true,
- });
- });
+ // And send some data
+ _crawlerMock.CalledCount.Should().Be(2);
+ await SendToPipeline(new CrawlerMessage
+ {
+ Submission = CreateSubmission(3),
+ Checkpoint = true,
+ });
- "And complete crawler"
- .x(() => _crawlerMock.TaskSource.SetResult(1));
+ // And complete crawler
+ _crawlerMock.TaskSource.SetResult(1);
- "Then data should be saved"
- .x(async () =>
- {
- await Utils.WaitSecond();
- WithDb(context =>
- {
- context.Submission.Should().HaveCount(2);
- context.Submission.Select(it => it.SubmissionId)
- .Should().Equal(1, 3);
- });
- });
+ // Then data should be saved
+ await Utils.WaitSecond();
+ WithDb(context =>
+ {
+ context.Submission.Should().HaveCount(2);
+ context.Submission.Select(it => it.SubmissionId)
+ .Should().Equal(1, 3);
+ });
}
[Fact]
@@ -319,99 +292,84 @@ await SendToPipeline(new CrawlerMessage
});
}
- [Scenario]
- public void WhenCancelled(Task cancelTask)
+ [Fact]
+ public async Task WhenCancelled()
{
- "Given an initialized coordinator"
- .x(() =>
- {
- _coordinator.Initialize(new[] { _crawlerMock });
- _coordinator.StartAllCrawlers();
- });
+ // Given an initialized coordinator
+ _coordinator.Initialize(new[] { _crawlerMock });
+ await _coordinator.StartAllCrawlers();
- "And some data"
- .x(async () =>
- {
- await SendToPipeline(new CrawlerMessage
- {
- Submission = CreateSubmission(1),
- Checkpoint = true,
- });
- await SendToPipeline(new CrawlerMessage
- {
- Submission = CreateSubmission(2),
- });
- });
+ // And some data
+ await SendToPipeline(new CrawlerMessage
+ {
+ Submission = CreateSubmission(1),
+ Checkpoint = true,
+ });
+ await SendToPipeline(new CrawlerMessage
+ {
+ Submission = CreateSubmission(2),
+ });
- "When calling coordinator.cancel"
- .x(() => { cancelTask = _coordinator.Cancel(); });
+ // When calling coordinator.cancel
+ var cancelTask = _coordinator.Cancel();
- "Then crawler should receive cancel"
- .x(() => _crawlerMock.CancellationToken.IsCancellationRequested.Should().BeTrue());
+ // Then crawler should receive cancel
+ _crawlerMock.CancellationToken.IsCancellationRequested.Should().BeTrue();
- "And cancelling task is still not completed"
- .x(() => cancelTask.IsCompleted.Should().BeFalse());
+ // And cancelling task is still not completed
+ cancelTask.IsCompleted.Should().BeFalse();
- "And crawler can still sending data until exit"
- .x(async () =>
- {
- await SendToPipeline(new CrawlerMessage
- {
- Submission = CreateSubmission(3),
- Checkpoint = true,
- });
- await SendToPipeline(new CrawlerMessage
- {
- Submission = CreateSubmission(4),
- });
- });
+ // And crawler can still sending data until exit
+ await SendToPipeline(new CrawlerMessage
+ {
+ Submission = CreateSubmission(3),
+ Checkpoint = true,
+ });
+ await SendToPipeline(new CrawlerMessage
+ {
+ Submission = CreateSubmission(4),
+ });
- "When crawler is exited"
- .x(() => _crawlerMock.TaskSource.SetCanceled());
+ // When crawler is exited
+ _crawlerMock.TaskSource.SetCanceled();
- "Then cancel task is completed"
- .x(() => cancelTask);
+ // Then cancel task is completed
+ await cancelTask;
- "And data before checkpoint is saved to database without needing to wait"
- .x(() => WithDb(context =>
- {
- context.Submission.Should().HaveCount(3);
- context.Submission.Select(it => it.SubmissionId)
- .Should().Equal(1, 2, 3);
- }));
+ // And data before checkpoint is saved to database without needing to wait
+ WithDb(context =>
+ {
+ context.Submission.Should().HaveCount(3);
+ context.Submission.Select(it => it.SubmissionId)
+ .Should().Equal(1, 2, 3);
+ });
- "When start crawlers without initializing, it should throw"
- .x(() => _coordinator.StartAllCrawlers()
- .ShouldResult().ThrowAsync());
+ // When start crawlers without initializing, it should throw
+ await _coordinator.StartAllCrawlers()
+ .ShouldResult().ThrowAsync();
- "When restarting crawlers"
- .x(async () =>
- {
- _coordinator.Initialize(new[] { _crawlerMock });
- await _coordinator.StartAllCrawlers();
- await Utils.WaitSecond();
- _crawlerMock.CalledCount.Should().Be(2);
- });
+ // When restarting crawlers
+ _coordinator.Initialize(new[] { _crawlerMock });
+ await _coordinator.StartAllCrawlers();
+ await Utils.WaitSecond();
+ _crawlerMock.CalledCount.Should().Be(2);
- "And send some data and finish the crawler"
- .x(async () =>
- {
- await SendToPipeline(new CrawlerMessage
- {
- Checkpoint = true,
- Submission = CreateSubmission(5),
- });
- _crawlerMock.TaskSource.SetResult(1);
- await Utils.WaitSecond();
- });
+ // And send some data and finish the crawler
+ await SendToPipeline(new CrawlerMessage
+ {
+ Checkpoint = true,
+ Submission = CreateSubmission(5),
+ });
+ _crawlerMock.TaskSource.SetResult(1);
+ await Utils.WaitSecond();
- "Then data after checkpoint of previous run are discarded"
- .x(() => WithDb(context =>
- {
- context.Submission.Should().HaveCount(4);
- context.Submission.Select(it => it.SubmissionId)
- .Should().Equal(1, 2, 3, 5);
- }));
+ // Then data after checkpoint of previous run are discarded
+ WithDb(context =>
+ {
+ context.Submission.Should().HaveCount(4);
+ context.Submission.Select(it => it.SubmissionId)
+ .Should().Equal(1, 2, 3, 5);
+ });
}
[Fact]
diff --git a/ohunt/OHunt.Tests/OHunt.Tests.csproj b/ohunt/OHunt.Tests/OHunt.Tests.csproj
index 94cb74280..637bebfde 100644
--- a/ohunt/OHunt.Tests/OHunt.Tests.csproj
+++ b/ohunt/OHunt.Tests/OHunt.Tests.csproj
@@ -23,7 +23,6 @@
-
all
diff --git a/ohunt/OHunt.Tests/Web/ProblemControllerTests.cs b/ohunt/OHunt.Tests/Web/ProblemControllerTests.cs
index c103075ef..79f6fd350 100644
--- a/ohunt/OHunt.Tests/Web/ProblemControllerTests.cs
+++ b/ohunt/OHunt.Tests/Web/ProblemControllerTests.cs
@@ -4,86 +4,19 @@
using System.Net.Http;
using System.Net.Mime;
using System.Text;
+using System.Threading.Tasks;
using FluentAssertions;
using Flurl.Http.Testing;
using OHunt.Tests.Dependency;
using OHunt.Web;
using OHunt.Web.Controllers.Dto;
-using Xbehave;
+using Xunit;
using Xunit.Abstractions;
namespace OHunt.Tests.Web
{
public class ProblemControllerTests : OHuntTestBase
{
- [Scenario]
- public void TestResolveLabel(HttpTest httpTest, HttpResponseMessage response)
- {
- "When request label at the first time"
- .x(async () =>
- {
- httpTest = new HttpTest();
- httpTest.RespondWithJson(new
- {
- num = 2001,
- });
-
- using var client = Factory.CreateClient();
- response = await client.PostAsync("/api/ohunt/problems/resolve-label",
- new StringContent("{\"onlineJudge\": \"uva\", \"list\": [1]}",
- Encoding.Default,
- MediaTypeNames.Application.Json));
- });
-
- "Then we should get the correct label"
- .x(async () =>
- {
- response.StatusCode.Should().Be(HttpStatusCode.OK);
-
- var output = await ResponseJson(response);
- output.Result.Should().HaveCount(1);
- output.Result.Single().Should().Be(
- new KeyValuePair("1", "2001"));
- });
-
- "And a request should be made by crawler"
- .x(() =>
- {
- httpTest.ShouldHaveMadeACall();
- httpTest.CallLog.Should().HaveCount(1);
- httpTest.Dispose();
- });
-
- "When we request it again"
- .x(async () =>
- {
- httpTest = new HttpTest();
- using var client = Factory.CreateClient();
- response = await client.PostAsync("/api/ohunt/problems/resolve-label",
- new StringContent("{\"onlineJudge\": \"uva\", \"list\": [1]}",
- Encoding.Default,
- MediaTypeNames.Application.Json));
- });
-
- "Then we should get the same result"
- .x(async () =>
- {
- response.StatusCode.Should().Be(HttpStatusCode.OK);
-
- var output = await ResponseJson(response);
- output.Result.Should().HaveCount(1);
- output.Result.Single().Should().Be(
- new KeyValuePair("1", "2001"));
- });
-
- "And there is not crawler request made"
- .x(() =>
- {
- httpTest.ShouldNotHaveMadeACall();
- httpTest.Dispose();
- });
- }
-
public ProblemControllerTests(
TestWebApplicationFactory factory,
ITestOutputHelper outputHelper) : base(factory, outputHelper)
@@ -92,5 +25,52 @@ public ProblemControllerTests(
// see https://github.com/tmenier/Flurl/issues/504#issuecomment-601817280
Factory.Server.PreserveExecutionContext = true;
}
+ [Fact]
+ public async Task TestResolveLabel()
+ {
+ // When request label at the first time
+ var httpTest = new HttpTest();
+ httpTest.RespondWithJson(new
+ {
+ num = 2001,
+ });
+
+ using var client = Factory.CreateClient();
+ var response = await client.PostAsync("/api/ohunt/problems/resolve-label",
+ new StringContent("{\"onlineJudge\": \"uva\", \"list\": [1]}",
+ Encoding.Default,
+ MediaTypeNames.Application.Json));
+
+ // Then we should get the correct label
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ var output = await ResponseJson(response);
+ output.Result.Should().HaveCount(1);
+ output.Result.Single().Should().Be(
+ new KeyValuePair("1", "2001"));
+
+ // And a request should be made by crawler
+ httpTest.ShouldHaveMadeACall();
+ httpTest.CallLog.Should().HaveCount(1);
+ httpTest.Dispose();
+
+ // When we request it again
+ httpTest = new HttpTest();
+ using var client2 = Factory.CreateClient();
+ response = await client2.PostAsync("/api/ohunt/problems/resolve-label",
+ new StringContent("{\"onlineJudge\": \"uva\", \"list\": [1]}",
+ Encoding.Default,
+ MediaTypeNames.Application.Json));
+
+ // Then we should get the same result
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ var output2 = await ResponseJson(response);
+ output2.Result.Should().HaveCount(1);
+ output2.Result.Single().Should().Be(
+ new KeyValuePair("1", "2001"));
+
+ // And there is not crawler request made
+ httpTest.ShouldNotHaveMadeACall();
+ httpTest.Dispose();
+ }
}
}
From c795db2910eb3f5f4424b6a1a4ddcefbe0d9066f Mon Sep 17 00:00:00 2001
From: Shumin Liu
Date: Tue, 12 Aug 2025 22:03:04 +1000
Subject: [PATCH 4/8] build(backend): upgrade dotnet to 8.0
---
backend/dev.Dockerfile | 2 +-
backend/global.json | 7 +++++++
.../AcmStatisticsBackend.Application.csproj | 7 +++++--
.../Crawlers/Dto/QueryWorkerHistoryDto.cs | 3 +--
.../AcmStatisticsBackend.Core.csproj | 6 +++---
...mStatisticsBackend.EntityFrameworkCore.csproj | 6 +++---
.../AcmStatisticsBackend.Web.Core.csproj | 6 +++---
.../AcmStatisticsBackend.Web.Host.csproj | 6 +++---
.../src/AcmStatisticsBackend.Web.Host/Dockerfile | 4 ++--
.../AcmStatisticsBackend.Tests.csproj | 16 ++++++++--------
10 files changed, 36 insertions(+), 27 deletions(-)
create mode 100644 backend/global.json
diff --git a/backend/dev.Dockerfile b/backend/dev.Dockerfile
index 42b5c5c8d..47224d580 100644
--- a/backend/dev.Dockerfile
+++ b/backend/dev.Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:7.0
+FROM mcr.microsoft.com/dotnet/sdk:8.0
# needed in sln file
RUN mkdir /build && echo '' > /build/docker-compose.dcproj
diff --git a/backend/global.json b/backend/global.json
new file mode 100644
index 000000000..b5b37b60d
--- /dev/null
+++ b/backend/global.json
@@ -0,0 +1,7 @@
+{
+ "sdk": {
+ "version": "8.0.0",
+ "rollForward": "latestMajor",
+ "allowPrerelease": false
+ }
+}
\ No newline at end of file
diff --git a/backend/src/AcmStatisticsBackend.Application/AcmStatisticsBackend.Application.csproj b/backend/src/AcmStatisticsBackend.Application/AcmStatisticsBackend.Application.csproj
index 4d815c251..fd3b1e4a1 100644
--- a/backend/src/AcmStatisticsBackend.Application/AcmStatisticsBackend.Application.csproj
+++ b/backend/src/AcmStatisticsBackend.Application/AcmStatisticsBackend.Application.csproj
@@ -1,7 +1,7 @@
1.0.0.0
- net7.0
+ net8.0
AcmStatisticsBackend.Application
AcmStatisticsBackend.Application
false
@@ -21,6 +21,9 @@
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/backend/src/AcmStatisticsBackend.Application/Crawlers/Dto/QueryWorkerHistoryDto.cs b/backend/src/AcmStatisticsBackend.Application/Crawlers/Dto/QueryWorkerHistoryDto.cs
index 3fe54bd40..2d593646b 100644
--- a/backend/src/AcmStatisticsBackend.Application/Crawlers/Dto/QueryWorkerHistoryDto.cs
+++ b/backend/src/AcmStatisticsBackend.Application/Crawlers/Dto/QueryWorkerHistoryDto.cs
@@ -3,7 +3,6 @@
using System.Diagnostics.CodeAnalysis;
using Abp.AutoMapper;
using Abp.Runtime.Validation;
-using Castle.Core.Internal;
namespace AcmStatisticsBackend.Crawlers.Dto
{
@@ -63,7 +62,7 @@ public class QueryWorkerHistoryDto : ICustomValidate
public void AddValidationErrors(CustomValidationContext context)
{
- if (!ErrorMessage.IsNullOrEmpty())
+ if (!string.IsNullOrEmpty(ErrorMessage))
{
if (SolvedList != null || SubmissionsByCrawlerName != null)
{
diff --git a/backend/src/AcmStatisticsBackend.Core/AcmStatisticsBackend.Core.csproj b/backend/src/AcmStatisticsBackend.Core/AcmStatisticsBackend.Core.csproj
index b47338a40..b824c812a 100644
--- a/backend/src/AcmStatisticsBackend.Core/AcmStatisticsBackend.Core.csproj
+++ b/backend/src/AcmStatisticsBackend.Core/AcmStatisticsBackend.Core.csproj
@@ -1,7 +1,7 @@
1.0.0.0
- net7.0
+ net8.0
AcmStatisticsBackend.Core
AcmStatisticsBackend.Core
false
@@ -16,7 +16,7 @@
-
-
+
+
diff --git a/backend/src/AcmStatisticsBackend.EntityFrameworkCore/AcmStatisticsBackend.EntityFrameworkCore.csproj b/backend/src/AcmStatisticsBackend.EntityFrameworkCore/AcmStatisticsBackend.EntityFrameworkCore.csproj
index 4f514e7a4..11660a235 100644
--- a/backend/src/AcmStatisticsBackend.EntityFrameworkCore/AcmStatisticsBackend.EntityFrameworkCore.csproj
+++ b/backend/src/AcmStatisticsBackend.EntityFrameworkCore/AcmStatisticsBackend.EntityFrameworkCore.csproj
@@ -1,17 +1,17 @@
- net7.0
+ net8.0
AcmStatisticsBackend
true
true
true
-
+
all
runtime; build; native; contentfiles; analyzers
-
+
diff --git a/backend/src/AcmStatisticsBackend.Web.Core/AcmStatisticsBackend.Web.Core.csproj b/backend/src/AcmStatisticsBackend.Web.Core/AcmStatisticsBackend.Web.Core.csproj
index e6254c17d..d7b8a42cc 100644
--- a/backend/src/AcmStatisticsBackend.Web.Core/AcmStatisticsBackend.Web.Core.csproj
+++ b/backend/src/AcmStatisticsBackend.Web.Core/AcmStatisticsBackend.Web.Core.csproj
@@ -1,7 +1,7 @@
1.0.0.0
- net7.0
+ net8.0
AcmStatisticsBackend.Web.Core
AcmStatisticsBackend.Web.Core
false
@@ -21,8 +21,8 @@
-
-
+
+
diff --git a/backend/src/AcmStatisticsBackend.Web.Host/AcmStatisticsBackend.Web.Host.csproj b/backend/src/AcmStatisticsBackend.Web.Host/AcmStatisticsBackend.Web.Host.csproj
index 46de5a83d..089d8d573 100644
--- a/backend/src/AcmStatisticsBackend.Web.Host/AcmStatisticsBackend.Web.Host.csproj
+++ b/backend/src/AcmStatisticsBackend.Web.Host/AcmStatisticsBackend.Web.Host.csproj
@@ -1,6 +1,6 @@
- net7.0
+ net8.0
true
AcmStatisticsBackend.Web.Host
Exe
@@ -31,11 +31,11 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/backend/src/AcmStatisticsBackend.Web.Host/Dockerfile b/backend/src/AcmStatisticsBackend.Web.Host/Dockerfile
index f3b099652..d3a16129a 100644
--- a/backend/src/AcmStatisticsBackend.Web.Host/Dockerfile
+++ b/backend/src/AcmStatisticsBackend.Web.Host/Dockerfile
@@ -1,10 +1,10 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
-FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
+FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
-FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["src/AcmStatisticsBackend.Web.Host/AcmStatisticsBackend.Web.Host.csproj", "src/AcmStatisticsBackend.Web.Host/"]
COPY ["src/AcmStatisticsBackend.Web.Core/AcmStatisticsBackend.Web.Core.csproj", "src/AcmStatisticsBackend.Web.Core/"]
diff --git a/backend/test/AcmStatisticsBackend.Tests/AcmStatisticsBackend.Tests.csproj b/backend/test/AcmStatisticsBackend.Tests/AcmStatisticsBackend.Tests.csproj
index c497fecfa..f45f64cea 100644
--- a/backend/test/AcmStatisticsBackend.Tests/AcmStatisticsBackend.Tests.csproj
+++ b/backend/test/AcmStatisticsBackend.Tests/AcmStatisticsBackend.Tests.csproj
@@ -1,7 +1,7 @@
1.0.0.0
- net7.0
+ net8.0
AcmStatisticsBackend.Tests
AcmStatisticsBackend.Tests
true
@@ -18,18 +18,18 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
-
+
+
-
-
-
-
+
+
+
+
all
runtime; build; native; contentfiles; analyzers
-
+
From 0330fe57491c237a4a1e8b490da68da2ae9de9c9 Mon Sep 17 00:00:00 2001
From: Shumin Liu
Date: Tue, 12 Aug 2025 22:12:13 +1000
Subject: [PATCH 5/8] fix(backend): type is wrong for error
This was not an issue because the testing code did not check it. It is fixed now.
---
.../ServiceClients/CrawlerApiBackendClient.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/backend/src/AcmStatisticsBackend.Core/ServiceClients/CrawlerApiBackendClient.cs b/backend/src/AcmStatisticsBackend.Core/ServiceClients/CrawlerApiBackendClient.cs
index 0ea2de170..4065ecfa9 100644
--- a/backend/src/AcmStatisticsBackend.Core/ServiceClients/CrawlerApiBackendClient.cs
+++ b/backend/src/AcmStatisticsBackend.Core/ServiceClients/CrawlerApiBackendClient.cs
@@ -37,7 +37,7 @@ public async Task> GetCrawlerMeta()
#pragma warning disable SA1300
private class GetMetaReturn
{
- public string error { get; set; }
+ public bool error { get; set; }
public IDictionary data { get; set; }
}
From 225cb8725001a5fa445d4cf6529cdc704e4623f4 Mon Sep 17 00:00:00 2001
From: Shumin Liu
Date: Tue, 12 Aug 2025 22:55:01 +1000
Subject: [PATCH 6/8] build(compose): Fix db backup command
The image is changed, and now it uses a different interface.
We have to specify the command, and use different env variables for db name.
The OPTS options is not available anymore so we are not able to exclude the logs table.
---
build/docker-compose.yml | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/build/docker-compose.yml b/build/docker-compose.yml
index 954f4f30c..4a0ccaedb 100644
--- a/build/docker-compose.yml
+++ b/build/docker-compose.yml
@@ -90,21 +90,20 @@ services:
db-backup:
image: databack/mysql-backup
+ command: dump
restart: always
user: "${DB_BACKUP_UID}"
volumes:
- ./db-backup:/db
environment:
- DB_NAMES: acm_statistics
DB_DUMP_TARGET: /db
DB_USER: root
DB_PASS: ${MYSQL_ROOT_PASSWORD}
# DB_DUMP_BEGIN: +2
# backup at 3:00 am
- DB_DUMP_BEGIN: " 0300"
+ DB_DUMP_BEGIN: "0300"
DB_SERVER: db
- # Do not backup Logs table
- MYSQLDUMP_OPTS: --ignore-table=acm_statistics.AbpAuditLogs --ignore-table=acm_statistics.AbpUserLoginAttempts
+ DB_DUMP_INCLUDE: acm_statistics
depends_on:
- db
labels:
From de6d7528e639971a9c2c81dfbb3c3340822c0c13 Mon Sep 17 00:00:00 2001
From: Shumin Liu
Date: Wed, 13 Aug 2025 00:08:08 +1000
Subject: [PATCH 7/8] build(backend): Fix exposed ports
The default port is changed and no longer 80. So we have to use env var to specify it.
For OHunt with Host, we use ASPNETCORE_HTTP_PORTS . For backend we use the old WebHost, we use ASPNETCORE_URLS.
---
backend/src/AcmStatisticsBackend.Web.Host/Dockerfile | 1 +
ohunt/OHunt.Web/Dockerfile | 1 +
2 files changed, 2 insertions(+)
diff --git a/backend/src/AcmStatisticsBackend.Web.Host/Dockerfile b/backend/src/AcmStatisticsBackend.Web.Host/Dockerfile
index d3a16129a..673452ce4 100644
--- a/backend/src/AcmStatisticsBackend.Web.Host/Dockerfile
+++ b/backend/src/AcmStatisticsBackend.Web.Host/Dockerfile
@@ -24,4 +24,5 @@ RUN apt-get update && apt-get install -y wait-for-it
ENV WAIT_COMMAND true
WORKDIR /app
COPY --from=publish /app/publish .
+ENV ASPNETCORE_URLS=http://0.0.0.0:80
CMD $WAIT_COMMAND && dotnet AcmStatisticsBackend.Web.Host.dll
diff --git a/ohunt/OHunt.Web/Dockerfile b/ohunt/OHunt.Web/Dockerfile
index b1e553819..105449bbb 100644
--- a/ohunt/OHunt.Web/Dockerfile
+++ b/ohunt/OHunt.Web/Dockerfile
@@ -21,4 +21,5 @@ RUN apt-get update && apt-get install -y wait-for-it
ENV WAIT_COMMAND true
WORKDIR /app
COPY --from=publish /app/publish .
+ENV ASPNETCORE_HTTP_PORTS 80
CMD $WAIT_COMMAND && dotnet OHunt.Web.dll
From 8f341596acf1749bf9b6d61d1ffe772314618bb0 Mon Sep 17 00:00:00 2001
From: Shumin Liu
Date: Wed, 13 Aug 2025 12:53:38 +1000
Subject: [PATCH 8/8] build(backend): generate migration for new version
For both abp and mysql extension.
---
.../20250813025256_UpgradeAbp840.Designer.cs | 2332 +++++++++++++++++
.../20250813025256_UpgradeAbp840.cs | 739 ++++++
...StatisticsBackendDbContextModelSnapshot.cs | 108 +-
3 files changed, 3173 insertions(+), 6 deletions(-)
create mode 100644 backend/src/AcmStatisticsBackend.EntityFrameworkCore/Migrations/20250813025256_UpgradeAbp840.Designer.cs
create mode 100644 backend/src/AcmStatisticsBackend.EntityFrameworkCore/Migrations/20250813025256_UpgradeAbp840.cs
diff --git a/backend/src/AcmStatisticsBackend.EntityFrameworkCore/Migrations/20250813025256_UpgradeAbp840.Designer.cs b/backend/src/AcmStatisticsBackend.EntityFrameworkCore/Migrations/20250813025256_UpgradeAbp840.Designer.cs
new file mode 100644
index 000000000..bdda75aeb
--- /dev/null
+++ b/backend/src/AcmStatisticsBackend.EntityFrameworkCore/Migrations/20250813025256_UpgradeAbp840.Designer.cs
@@ -0,0 +1,2332 @@
+//
+using System;
+using AcmStatisticsBackend.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace AcmStatisticsBackend.Migrations
+{
+ [DbContext(typeof(AcmStatisticsBackendDbContext))]
+ [Migration("20250813025256_UpgradeAbp840")]
+ partial class UpgradeAbp840
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.19")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
+
+ modelBuilder.Entity("Abp.Application.Editions.Edition", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("DeleterUserId")
+ .HasColumnType("bigint");
+
+ b.Property("DeletionTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("varchar(64)");
+
+ b.Property("IsDeleted")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LastModifierUserId")
+ .HasColumnType("bigint");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("varchar(32)");
+
+ b.HasKey("Id");
+
+ b.ToTable("AbpEditions");
+ });
+
+ modelBuilder.Entity("Abp.Application.Features.FeatureSetting", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("Discriminator")
+ .IsRequired()
+ .HasMaxLength(21)
+ .HasColumnType("varchar(21)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasMaxLength(2000)
+ .HasColumnType("varchar(2000)");
+
+ b.HasKey("Id");
+
+ b.ToTable("AbpFeatures");
+
+ b.HasDiscriminator().HasValue("FeatureSetting");
+
+ b.UseTphMappingStrategy();
+ });
+
+ modelBuilder.Entity("Abp.Auditing.AuditLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("BrowserInfo")
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("ClientIpAddress")
+ .HasMaxLength(64)
+ .HasColumnType("varchar(64)");
+
+ b.Property("ClientName")
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("CustomData")
+ .HasMaxLength(2000)
+ .HasColumnType("varchar(2000)");
+
+ b.Property("Exception")
+ .HasMaxLength(2000)
+ .HasColumnType("varchar(2000)");
+
+ b.Property("ExceptionMessage")
+ .HasMaxLength(1024)
+ .HasColumnType("varchar(1024)");
+
+ b.Property("ExecutionDuration")
+ .HasColumnType("int");
+
+ b.Property("ExecutionTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("ImpersonatorTenantId")
+ .HasColumnType("int");
+
+ b.Property("ImpersonatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("MethodName")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("Parameters")
+ .HasMaxLength(1024)
+ .HasColumnType("varchar(1024)");
+
+ b.Property("ReturnValue")
+ .HasColumnType("longtext");
+
+ b.Property("ServiceName")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("bigint");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "ExecutionDuration");
+
+ b.HasIndex("TenantId", "ExecutionTime");
+
+ b.HasIndex("TenantId", "UserId");
+
+ b.ToTable("AbpAuditLogs");
+ });
+
+ modelBuilder.Entity("Abp.Authorization.PermissionSetting", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("Discriminator")
+ .IsRequired()
+ .HasMaxLength(21)
+ .HasColumnType("varchar(21)");
+
+ b.Property("IsGranted")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "Name");
+
+ b.ToTable("AbpPermissions");
+
+ b.HasDiscriminator().HasValue("PermissionSetting");
+
+ b.UseTphMappingStrategy();
+ });
+
+ modelBuilder.Entity("Abp.Authorization.Roles.RoleClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("ClaimType")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("ClaimValue")
+ .HasColumnType("longtext");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("RoleId")
+ .HasColumnType("int");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleId");
+
+ b.HasIndex("TenantId", "ClaimType");
+
+ b.ToTable("AbpRoleClaims");
+ });
+
+ modelBuilder.Entity("Abp.Authorization.Users.UserAccount", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("DeleterUserId")
+ .HasColumnType("bigint");
+
+ b.Property("DeletionTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("EmailAddress")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("IsDeleted")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LastModifierUserId")
+ .HasColumnType("bigint");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("bigint");
+
+ b.Property("UserLinkId")
+ .HasColumnType("bigint");
+
+ b.Property("UserName")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("EmailAddress");
+
+ b.HasIndex("UserName");
+
+ b.HasIndex("TenantId", "EmailAddress");
+
+ b.HasIndex("TenantId", "UserId");
+
+ b.HasIndex("TenantId", "UserName");
+
+ b.ToTable("AbpUserAccounts");
+ });
+
+ modelBuilder.Entity("Abp.Authorization.Users.UserClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("ClaimType")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("ClaimValue")
+ .HasColumnType("longtext");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("bigint");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("TenantId", "ClaimType");
+
+ b.ToTable("AbpUserClaims");
+ });
+
+ modelBuilder.Entity("Abp.Authorization.Users.UserLogin", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("LoginProvider")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("ProviderKey")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("bigint");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("ProviderKey", "TenantId")
+ .IsUnique();
+
+ b.HasIndex("TenantId", "UserId");
+
+ b.HasIndex("TenantId", "LoginProvider", "ProviderKey");
+
+ b.ToTable("AbpUserLogins");
+ });
+
+ modelBuilder.Entity("Abp.Authorization.Users.UserLoginAttempt", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("BrowserInfo")
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("ClientIpAddress")
+ .HasMaxLength(64)
+ .HasColumnType("varchar(64)");
+
+ b.Property("ClientName")
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Result")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("TenancyName")
+ .HasMaxLength(64)
+ .HasColumnType("varchar(64)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("bigint");
+
+ b.Property("UserNameOrEmailAddress")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId", "TenantId");
+
+ b.HasIndex("TenancyName", "UserNameOrEmailAddress", "Result");
+
+ b.ToTable("AbpUserLoginAttempts");
+ });
+
+ modelBuilder.Entity("Abp.Authorization.Users.UserOrganizationUnit", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("IsDeleted")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("OrganizationUnitId")
+ .HasColumnType("bigint");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("bigint");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "OrganizationUnitId");
+
+ b.HasIndex("TenantId", "UserId");
+
+ b.ToTable("AbpUserOrganizationUnits");
+ });
+
+ modelBuilder.Entity("Abp.Authorization.Users.UserRole", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("RoleId")
+ .HasColumnType("int");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("bigint");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("TenantId", "RoleId");
+
+ b.HasIndex("TenantId", "UserId");
+
+ b.ToTable("AbpUserRoles");
+ });
+
+ modelBuilder.Entity("Abp.Authorization.Users.UserToken", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("ExpireDate")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LoginProvider")
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("Name")
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("bigint");
+
+ b.Property("Value")
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("TenantId", "UserId");
+
+ b.ToTable("AbpUserTokens");
+ });
+
+ modelBuilder.Entity("Abp.BackgroundJobs.BackgroundJobInfo", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("IsAbandoned")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("JobArgs")
+ .IsRequired()
+ .HasMaxLength(1048576)
+ .HasColumnType("longtext");
+
+ b.Property("JobType")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("LastTryTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("NextTryTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Priority")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("TryCount")
+ .HasColumnType("smallint");
+
+ b.HasKey("Id");
+
+ b.HasIndex("IsAbandoned", "NextTryTime");
+
+ b.ToTable("AbpBackgroundJobs");
+ });
+
+ modelBuilder.Entity("Abp.Configuration.Setting", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LastModifierUserId")
+ .HasColumnType("bigint");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("bigint");
+
+ b.Property("Value")
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("TenantId", "Name", "UserId")
+ .IsUnique();
+
+ b.ToTable("AbpSettings");
+ });
+
+ modelBuilder.Entity("Abp.DynamicEntityProperties.DynamicEntityProperty", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("DynamicPropertyId")
+ .HasColumnType("int");
+
+ b.Property("EntityFullName")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DynamicPropertyId");
+
+ b.HasIndex("EntityFullName", "DynamicPropertyId", "TenantId")
+ .IsUnique();
+
+ b.ToTable("AbpDynamicEntityProperties");
+ });
+
+ modelBuilder.Entity("Abp.DynamicEntityProperties.DynamicEntityPropertyValue", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("DynamicEntityPropertyId")
+ .HasColumnType("int");
+
+ b.Property("EntityId")
+ .HasColumnType("longtext");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DynamicEntityPropertyId");
+
+ b.ToTable("AbpDynamicEntityPropertyValues");
+ });
+
+ modelBuilder.Entity("Abp.DynamicEntityProperties.DynamicProperty", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("DisplayName")
+ .HasColumnType("longtext");
+
+ b.Property("InputType")
+ .HasColumnType("longtext");
+
+ b.Property("Permission")
+ .HasColumnType("longtext");
+
+ b.Property("PropertyName")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("PropertyName", "TenantId")
+ .IsUnique();
+
+ b.ToTable("AbpDynamicProperties");
+ });
+
+ modelBuilder.Entity("Abp.DynamicEntityProperties.DynamicPropertyValue", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("DynamicPropertyId")
+ .HasColumnType("int");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DynamicPropertyId");
+
+ b.ToTable("AbpDynamicPropertyValues");
+ });
+
+ modelBuilder.Entity("Abp.EntityHistory.EntityChange", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("ChangeTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("ChangeType")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("EntityChangeSetId")
+ .HasColumnType("bigint");
+
+ b.Property("EntityId")
+ .HasMaxLength(48)
+ .HasColumnType("varchar(48)");
+
+ b.Property("EntityTypeFullName")
+ .HasMaxLength(192)
+ .HasColumnType("varchar(192)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("EntityChangeSetId");
+
+ b.HasIndex("EntityTypeFullName", "EntityId");
+
+ b.ToTable("AbpEntityChanges");
+ });
+
+ modelBuilder.Entity("Abp.EntityHistory.EntityChangeSet", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("BrowserInfo")
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("ClientIpAddress")
+ .HasMaxLength(64)
+ .HasColumnType("varchar(64)");
+
+ b.Property("ClientName")
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("ExtensionData")
+ .HasColumnType("longtext");
+
+ b.Property("ImpersonatorTenantId")
+ .HasColumnType("int");
+
+ b.Property("ImpersonatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("Reason")
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("bigint");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "CreationTime");
+
+ b.HasIndex("TenantId", "Reason");
+
+ b.HasIndex("TenantId", "UserId");
+
+ b.ToTable("AbpEntityChangeSets");
+ });
+
+ modelBuilder.Entity("Abp.EntityHistory.EntityPropertyChange", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("EntityChangeId")
+ .HasColumnType("bigint");
+
+ b.Property("NewValue")
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("NewValueHash")
+ .HasColumnType("longtext");
+
+ b.Property("OriginalValue")
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("OriginalValueHash")
+ .HasColumnType("longtext");
+
+ b.Property("PropertyName")
+ .HasMaxLength(96)
+ .HasColumnType("varchar(96)");
+
+ b.Property("PropertyTypeFullName")
+ .HasMaxLength(192)
+ .HasColumnType("varchar(192)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("EntityChangeId");
+
+ b.ToTable("AbpEntityPropertyChanges");
+ });
+
+ modelBuilder.Entity("Abp.Localization.ApplicationLanguage", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("DeleterUserId")
+ .HasColumnType("bigint");
+
+ b.Property("DeletionTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("varchar(64)");
+
+ b.Property("Icon")
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("IsDeleted")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("IsDisabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LastModifierUserId")
+ .HasColumnType("bigint");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "Name");
+
+ b.ToTable("AbpLanguages");
+ });
+
+ modelBuilder.Entity("Abp.Localization.ApplicationLanguageText", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("Key")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("LanguageName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LastModifierUserId")
+ .HasColumnType("bigint");
+
+ b.Property("Source")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasMaxLength(67108864)
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "Source", "LanguageName", "Key");
+
+ b.ToTable("AbpLanguageTexts");
+ });
+
+ modelBuilder.Entity("Abp.Notifications.NotificationInfo", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("char(36)");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("Data")
+ .HasMaxLength(1048576)
+ .HasColumnType("longtext");
+
+ b.Property("DataTypeName")
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("EntityId")
+ .HasMaxLength(96)
+ .HasColumnType("varchar(96)");
+
+ b.Property("EntityTypeAssemblyQualifiedName")
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("EntityTypeName")
+ .HasMaxLength(250)
+ .HasColumnType("varchar(250)");
+
+ b.Property("ExcludedUserIds")
+ .HasMaxLength(131072)
+ .HasColumnType("longtext");
+
+ b.Property("NotificationName")
+ .IsRequired()
+ .HasMaxLength(96)
+ .HasColumnType("varchar(96)");
+
+ b.Property("Severity")
+ .HasColumnType("tinyint unsigned");
+
+ b.Property("TargetNotifiers")
+ .HasMaxLength(1024)
+ .HasColumnType("varchar(1024)");
+
+ b.Property("TenantIds")
+ .HasMaxLength(131072)
+ .HasColumnType("longtext");
+
+ b.Property("UserIds")
+ .HasMaxLength(131072)
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("AbpNotifications");
+ });
+
+ modelBuilder.Entity("Abp.Notifications.NotificationSubscriptionInfo", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("char(36)");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("EntityId")
+ .HasMaxLength(96)
+ .HasColumnType("varchar(96)");
+
+ b.Property("EntityTypeAssemblyQualifiedName")
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("EntityTypeName")
+ .HasMaxLength(250)
+ .HasColumnType("varchar(250)");
+
+ b.Property("NotificationName")
+ .HasMaxLength(96)
+ .HasColumnType("varchar(96)");
+
+ b.Property("TargetNotifiers")
+ .HasMaxLength(1024)
+ .HasColumnType("varchar(1024)");
+
+ b.Property("TenantId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("bigint");
+
+ b.HasKey("Id");
+
+ b.HasIndex("NotificationName", "EntityTypeName", "EntityId", "UserId");
+
+ b.HasIndex("TenantId", "NotificationName", "EntityTypeName", "EntityId", "UserId");
+
+ b.ToTable("AbpNotificationSubscriptions");
+ });
+
+ modelBuilder.Entity("Abp.Notifications.TenantNotificationInfo", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("char(36)");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("CreatorUserId")
+ .HasColumnType("bigint");
+
+ b.Property("Data")
+ .HasMaxLength(1048576)
+ .HasColumnType("longtext");
+
+ b.Property("DataTypeName")
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("EntityId")
+ .HasMaxLength(96)
+ .HasColumnType("varchar(96)");
+
+ b.Property("EntityTypeAssemblyQualifiedName")
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("EntityTypeName")
+ .HasMaxLength(250)
+ .HasColumnType("varchar(250)");
+
+ b.Property