Account region

This commit is contained in:
2025-09-07 01:55:34 +08:00
parent d2f5ba36ab
commit 4a27794ccc
9 changed files with 2091 additions and 9 deletions

View File

@@ -18,6 +18,7 @@ public class Account : ModelBase
[MaxLength(256)] public string Name { get; set; } = string.Empty; [MaxLength(256)] public string Name { get; set; } = string.Empty;
[MaxLength(256)] public string Nick { get; set; } = string.Empty; [MaxLength(256)] public string Nick { get; set; } = string.Empty;
[MaxLength(32)] public string Language { get; set; } = string.Empty; [MaxLength(32)] public string Language { get; set; } = string.Empty;
[MaxLength(32)] public string Region { get; set; } = string.Empty;
public Instant? ActivatedAt { get; set; } public Instant? ActivatedAt { get; set; }
public bool IsSuperuser { get; set; } = false; public bool IsSuperuser { get; set; } = false;
@@ -46,6 +47,7 @@ public class Account : ModelBase
Name = Name, Name = Name,
Nick = Nick, Nick = Nick,
Language = Language, Language = Language,
Region = Region,
ActivatedAt = ActivatedAt?.ToTimestamp(), ActivatedAt = ActivatedAt?.ToTimestamp(),
IsSuperuser = IsSuperuser, IsSuperuser = IsSuperuser,
Profile = Profile.ToProtoValue(), Profile = Profile.ToProtoValue(),
@@ -75,6 +77,7 @@ public class Account : ModelBase
Name = proto.Name, Name = proto.Name,
Nick = proto.Nick, Nick = proto.Nick,
Language = proto.Language, Language = proto.Language,
Region = proto.Region,
ActivatedAt = proto.ActivatedAt?.ToInstant(), ActivatedAt = proto.ActivatedAt?.ToInstant(),
IsSuperuser = proto.IsSuperuser, IsSuperuser = proto.IsSuperuser,
PerkSubscription = proto.PerkSubscription is not null PerkSubscription = proto.PerkSubscription is not null

View File

@@ -3,6 +3,7 @@ using DysonNetwork.Pass.Auth;
using DysonNetwork.Pass.Credit; using DysonNetwork.Pass.Credit;
using DysonNetwork.Pass.Wallet; using DysonNetwork.Pass.Wallet;
using DysonNetwork.Shared.Error; using DysonNetwork.Shared.Error;
using DysonNetwork.Shared.GeoIp;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using NodaTime; using NodaTime;
@@ -17,7 +18,8 @@ public class AccountController(
AccountService accounts, AccountService accounts,
SubscriptionService subscriptions, SubscriptionService subscriptions,
AccountEventService events, AccountEventService events,
SocialCreditService socialCreditService SocialCreditService socialCreditService,
GeoIpService geo
) : ControllerBase ) : ControllerBase
{ {
[HttpGet("{name}")] [HttpGet("{name}")]
@@ -32,10 +34,10 @@ public class AccountController(
.Where(a => a.Name == name) .Where(a => a.Name == name)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
if (account is null) return NotFound(ApiError.NotFound(name, traceId: HttpContext.TraceIdentifier)); if (account is null) return NotFound(ApiError.NotFound(name, traceId: HttpContext.TraceIdentifier));
var perk = await subscriptions.GetPerkSubscriptionAsync(account.Id); var perk = await subscriptions.GetPerkSubscriptionAsync(account.Id);
account.PerkSubscription = perk?.ToReference(); account.PerkSubscription = perk?.ToReference();
return account; return account;
} }
@@ -48,9 +50,11 @@ public class AccountController(
.Include(e => e.Badges) .Include(e => e.Badges)
.Where(a => a.Name == name) .Where(a => a.Name == name)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
return account is null ? NotFound(ApiError.NotFound(name, traceId: HttpContext.TraceIdentifier)) : account.Badges.ToList(); return account is null
? NotFound(ApiError.NotFound(name, traceId: HttpContext.TraceIdentifier))
: account.Badges.ToList();
} }
[HttpGet("{name}/credits")] [HttpGet("{name}/credits")]
[ProducesResponseType<double>(StatusCodes.Status200OK)] [ProducesResponseType<double>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
@@ -60,12 +64,12 @@ public class AccountController(
.Where(a => a.Name == name) .Where(a => a.Name == name)
.Select(a => new { a.Id }) .Select(a => new { a.Id })
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
if (account is null) if (account is null)
{ {
return NotFound(ApiError.NotFound(name, traceId: HttpContext.TraceIdentifier)); return NotFound(ApiError.NotFound(name, traceId: HttpContext.TraceIdentifier));
} }
var credits = await socialCreditService.GetSocialCredit(account.Id); var credits = await socialCreditService.GetSocialCredit(account.Id);
return credits; return credits;
} }
@@ -93,7 +97,7 @@ public class AccountController(
[MaxLength(128)] [MaxLength(128)]
public string Password { get; set; } = string.Empty; public string Password { get; set; } = string.Empty;
[MaxLength(128)] public string Language { get; set; } = "en-us"; [MaxLength(32)] public string Language { get; set; } = "en-us";
[Required] public string CaptchaToken { get; set; } = string.Empty; [Required] public string CaptchaToken { get; set; } = string.Empty;
} }
@@ -109,6 +113,10 @@ public class AccountController(
[nameof(request.CaptchaToken)] = ["Invalid captcha token."] [nameof(request.CaptchaToken)] = ["Invalid captcha token."]
}, traceId: HttpContext.TraceIdentifier)); }, traceId: HttpContext.TraceIdentifier));
var ip = HttpContext.Connection.RemoteIpAddress?.ToString();
if (ip is null) return BadRequest(ApiError.NotFound(request.Name, traceId: HttpContext.TraceIdentifier));
var region = geo.GetFromIp(ip)?.Country.IsoCode ?? "us";
try try
{ {
var account = await accounts.CreateAccount( var account = await accounts.CreateAccount(
@@ -116,7 +124,8 @@ public class AccountController(
request.Nick, request.Nick,
request.Email, request.Email,
request.Password, request.Password,
request.Language request.Language,
region
); );
return Ok(account); return Ok(account);
} }

View File

@@ -52,6 +52,7 @@ public class AccountCurrentController(
{ {
[MaxLength(256)] public string? Nick { get; set; } [MaxLength(256)] public string? Nick { get; set; }
[MaxLength(32)] public string? Language { get; set; } [MaxLength(32)] public string? Language { get; set; }
[MaxLength(32)] public string? Region { get; set; }
} }
[HttpPatch] [HttpPatch]
@@ -63,6 +64,7 @@ public class AccountCurrentController(
if (request.Nick is not null) account.Nick = request.Nick; if (request.Nick is not null) account.Nick = request.Nick;
if (request.Language is not null) account.Language = request.Language; if (request.Language is not null) account.Language = request.Language;
if (request.Region is not null) account.Region = request.Region;
await db.SaveChangesAsync(); await db.SaveChangesAsync();
await accounts.PurgeAccountCache(currentUser); await accounts.PurgeAccountCache(currentUser);

View File

@@ -88,6 +88,7 @@ public class AccountService(
string email, string email,
string? password, string? password,
string language = "en-US", string language = "en-US",
string region = "en",
bool isEmailVerified = false, bool isEmailVerified = false,
bool isActivated = false bool isActivated = false
) )
@@ -107,6 +108,7 @@ public class AccountService(
Name = name, Name = name,
Nick = nick, Nick = nick,
Language = language, Language = language,
Region = region,
Contacts = new List<AccountContact> Contacts = new List<AccountContact>
{ {
new() new()
@@ -181,6 +183,7 @@ public class AccountService(
userInfo.Email, userInfo.Email,
null, null,
"en-US", "en-US",
"en",
userInfo.EmailVerified, userInfo.EmailVerified,
userInfo.EmailVerified userInfo.EmailVerified
); );

View File

@@ -13,6 +13,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Nager.Holiday" Version="1.0.1" />
<PackageReference Include="NATS.Client.Core" Version="2.6.6" /> <PackageReference Include="NATS.Client.Core" Version="2.6.6" />
<PackageReference Include="Nerdbank.GitVersioning" Version="3.7.115"> <PackageReference Include="Nerdbank.GitVersioning" Version="3.7.115">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace DysonNetwork.Pass.Migrations
{
/// <inheritdoc />
public partial class AddAccountRegion : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "region",
table: "accounts",
type: "character varying(32)",
maxLength: 32,
nullable: false,
defaultValue: "");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "region",
table: "accounts");
}
}
}

View File

@@ -132,6 +132,12 @@ namespace DysonNetwork.Pass.Migrations
.HasColumnType("character varying(256)") .HasColumnType("character varying(256)")
.HasColumnName("nick"); .HasColumnName("nick");
b.Property<string>("Region")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)")
.HasColumnName("region");
b.Property<Instant>("UpdatedAt") b.Property<Instant>("UpdatedAt")
.HasColumnType("timestamp with time zone") .HasColumnType("timestamp with time zone")
.HasColumnName("updated_at"); .HasColumnName("updated_at");

View File

@@ -18,6 +18,7 @@ message Account {
string name = 2; string name = 2;
string nick = 3; string nick = 3;
string language = 4; string language = 4;
string region = 18;
google.protobuf.Timestamp activated_at = 5; google.protobuf.Timestamp activated_at = 5;
bool is_superuser = 6; bool is_superuser = 6;