forked from gongxuegit/tiku-backend.net
feat: enforce tenant isolation and shared question bank
This commit is contained in:
@@ -10,11 +10,11 @@ namespace Tiku.Api.Contracts;
|
||||
public sealed class PasswordLoginDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 租户 ID。登录阶段允许客户端指定租户,登录后的业务接口以 JWT/session 解析出的当前租户为准。
|
||||
/// 平台控制域名登录时使用的租户代码;自定义域名登录可省略。
|
||||
/// </summary>
|
||||
[Required]
|
||||
[Description("租户 ID。登录阶段允许客户端指定租户,登录后的业务接口以 JWT/session 解析出的当前租户为准。")]
|
||||
public Guid TenantId { get; set; }
|
||||
[StringLength(100)]
|
||||
[Description("平台控制域名登录时使用的租户代码;自定义域名登录可省略。")]
|
||||
public string? TenantCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 手机号,建议前端提交规范化后的中国大陆手机号。
|
||||
@@ -39,11 +39,11 @@ public sealed class PasswordLoginDto
|
||||
public sealed class SmsLoginDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 租户 ID。
|
||||
/// 平台控制域名登录时使用的租户代码;自定义域名登录可省略。
|
||||
/// </summary>
|
||||
[Required]
|
||||
[Description("租户 ID。")]
|
||||
public Guid TenantId { get; set; }
|
||||
[StringLength(100)]
|
||||
[Description("平台控制域名登录时使用的租户代码;自定义域名登录可省略。")]
|
||||
public string? TenantCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 中国大陆手机号。
|
||||
@@ -68,11 +68,11 @@ public sealed class SmsLoginDto
|
||||
public sealed class OAuthCodeDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 租户 ID。
|
||||
/// 平台控制域名登录时使用的租户代码;自定义域名登录可省略。
|
||||
/// </summary>
|
||||
[Required]
|
||||
[Description("租户 ID。")]
|
||||
public Guid TenantId { get; set; }
|
||||
[StringLength(100)]
|
||||
[Description("平台控制域名登录时使用的租户代码;自定义域名登录可省略。")]
|
||||
public string? TenantCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// OAuth 平台返回的一次性授权 code。
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json;
|
||||
using Tiku.Application.Content;
|
||||
using Tiku.Application.QuestionBanks;
|
||||
using Tiku.Domain.Common;
|
||||
using Tiku.Domain.Content;
|
||||
|
||||
namespace Tiku.Api.Contracts;
|
||||
|
||||
@@ -252,6 +254,9 @@ public sealed class CollectionQuestionDto
|
||||
[Required]
|
||||
public Guid QuestionId { get; set; }
|
||||
|
||||
[Required]
|
||||
public QuestionSource Source { get; set; } = QuestionSource.Tenant;
|
||||
|
||||
[StringLength(100)]
|
||||
public string? SectionKey { get; set; }
|
||||
|
||||
@@ -265,7 +270,13 @@ public sealed class CollectionQuestionDto
|
||||
|
||||
public CollectionQuestionCommand ToCommand()
|
||||
{
|
||||
return new CollectionQuestionCommand(QuestionId, SectionKey, Order, Score, Required, Metadata);
|
||||
return new CollectionQuestionCommand(
|
||||
new QuestionLocator(Source, QuestionId),
|
||||
SectionKey,
|
||||
Order,
|
||||
Score,
|
||||
Required,
|
||||
Metadata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json;
|
||||
using Tiku.Application.Learning;
|
||||
using Tiku.Application.QuestionBanks;
|
||||
using Tiku.Domain.Common;
|
||||
using Tiku.Domain.Content;
|
||||
|
||||
namespace Tiku.Api.Contracts;
|
||||
|
||||
@@ -107,9 +109,7 @@ public sealed class SubmitPracticeSessionDto
|
||||
public sealed class SubmitAnswerDto
|
||||
{
|
||||
[Required]
|
||||
public Guid QuestionId { get; set; }
|
||||
|
||||
public Guid? PracticeSessionId { get; set; }
|
||||
public Guid SessionQuestionId { get; set; }
|
||||
|
||||
public IReadOnlyCollection<string>? SelectedOptions { get; set; }
|
||||
|
||||
@@ -121,8 +121,7 @@ public sealed class SubmitAnswerDto
|
||||
public SubmitAnswerCommand ToCommand()
|
||||
{
|
||||
return new SubmitAnswerCommand(
|
||||
QuestionId,
|
||||
PracticeSessionId,
|
||||
SessionQuestionId,
|
||||
SelectedOptions,
|
||||
AnswerText,
|
||||
SelfJudgedCorrect);
|
||||
@@ -134,11 +133,14 @@ public sealed class QuestionActionDto
|
||||
[Required]
|
||||
public Guid QuestionId { get; set; }
|
||||
|
||||
[Required]
|
||||
public QuestionSource Source { get; set; } = QuestionSource.Tenant;
|
||||
|
||||
public bool? Favorite { get; set; }
|
||||
|
||||
public QuestionActionCommand ToCommand()
|
||||
{
|
||||
return new QuestionActionCommand(QuestionId, Favorite);
|
||||
return new QuestionActionCommand(new QuestionLocator(Source, QuestionId), Favorite);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Tiku.Application.QuestionBanks;
|
||||
using Tiku.Domain.Content;
|
||||
|
||||
namespace Tiku.Api.Contracts;
|
||||
|
||||
@@ -24,6 +25,8 @@ public sealed class QuestionBankQueryDto
|
||||
|
||||
public Guid? CollectionId { get; set; }
|
||||
|
||||
public QuestionSource? Source { get; set; }
|
||||
|
||||
[StringLength(50)]
|
||||
public string? Type { get; set; }
|
||||
|
||||
@@ -54,7 +57,8 @@ public sealed class QuestionBankQueryDto
|
||||
ParseQuestionIds(),
|
||||
Type,
|
||||
Keyword,
|
||||
Limit);
|
||||
Limit,
|
||||
Source);
|
||||
}
|
||||
|
||||
private Guid[] ParseQuestionIds()
|
||||
|
||||
31
Tiku.Api/Contracts/TaxonomyDtos.cs
Normal file
31
Tiku.Api/Contracts/TaxonomyDtos.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json;
|
||||
using Tiku.Application.Catalog;
|
||||
using Tiku.Domain.Catalog;
|
||||
using Tiku.Domain.Common;
|
||||
using Tiku.Domain.Content;
|
||||
|
||||
namespace Tiku.Api.Contracts;
|
||||
|
||||
public sealed class CreateTaxonomyNodeDto
|
||||
{
|
||||
public Guid? ParentId { get; set; }
|
||||
public QuestionSource? ParentSource { get; set; }
|
||||
[Required]
|
||||
public TaxonomyNodeType NodeType { get; set; }
|
||||
[Required, StringLength(100)]
|
||||
public string Code { get; set; } = string.Empty;
|
||||
[Required, StringLength(300)]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public int SortOrder { get; set; }
|
||||
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
||||
|
||||
public CreateTaxonomyNodeCommand ToCommand() => new(
|
||||
ParentId,
|
||||
ParentSource,
|
||||
NodeType,
|
||||
Code,
|
||||
Name,
|
||||
SortOrder,
|
||||
Metadata);
|
||||
}
|
||||
28
Tiku.Api/Contracts/TenantFrontendConfigDtos.cs
Normal file
28
Tiku.Api/Contracts/TenantFrontendConfigDtos.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json;
|
||||
using Tiku.Application.Tenancy;
|
||||
using Tiku.Domain.Common;
|
||||
|
||||
namespace Tiku.Api.Contracts;
|
||||
|
||||
public sealed class SaveTenantFrontendConfigDraftDto
|
||||
{
|
||||
public JsonElement Branding { get; set; } = JsonDefaults.Object();
|
||||
public JsonElement Theme { get; set; } = JsonDefaults.Object();
|
||||
public JsonElement Features { get; set; } = JsonDefaults.Object();
|
||||
public JsonElement Navigation { get; set; } = JsonDefaults.Array();
|
||||
public JsonElement HomeModules { get; set; } = JsonDefaults.Array();
|
||||
|
||||
public TenantFrontendConfigDraft ToDraft() => new(
|
||||
Branding,
|
||||
Theme,
|
||||
Features,
|
||||
Navigation,
|
||||
HomeModules);
|
||||
}
|
||||
|
||||
public sealed class PublishTenantFrontendConfigDto
|
||||
{
|
||||
[Range(1, int.MaxValue)]
|
||||
public int ExpectedVersion { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user