🎉 Initial Commit
This commit is contained in:
60
DysonNetwork.Sphere/Account/Account.cs
Normal file
60
DysonNetwork.Sphere/Account/Account.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text;
|
||||
using NodaTime;
|
||||
using Org.BouncyCastle.Crypto.Generators;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
namespace DysonNetwork.Sphere.Account;
|
||||
|
||||
public class Account : BaseModel
|
||||
{
|
||||
public long Id { get; set; }
|
||||
[MaxLength(256)] public string Name { get; set; } = string.Empty;
|
||||
[MaxLength(256)] public string Nick { get; set; } = string.Empty;
|
||||
|
||||
public ICollection<AccountContact> Contacts { get; set; } = new List<AccountContact>();
|
||||
public ICollection<AccountAuthFactor> AuthFactors { get; set; } = new List<AccountAuthFactor>();
|
||||
}
|
||||
|
||||
public class AccountContact : BaseModel
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public AccountContactType Type { get; set; }
|
||||
public Instant? VerifiedAt { get; set; }
|
||||
[MaxLength(1024)] public string Content { get; set; } = string.Empty;
|
||||
|
||||
public Account Account { get; set; } = null!;
|
||||
}
|
||||
|
||||
public enum AccountContactType
|
||||
{
|
||||
Email, PhoneNumber, Address
|
||||
}
|
||||
|
||||
public class AccountAuthFactor : BaseModel
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public AccountAuthFactorType Type { get; set; }
|
||||
public string? Secret { get; set; } = null;
|
||||
|
||||
public Account Account { get; set; } = null!;
|
||||
|
||||
public AccountAuthFactor HashSecret(int cost = 12)
|
||||
{
|
||||
if(Secret == null) return this;
|
||||
|
||||
var passwordBytes = Encoding.UTF8.GetBytes(Secret);
|
||||
var random = new SecureRandom();
|
||||
var salt = new byte[16];
|
||||
random.NextBytes(salt);
|
||||
var hashed = BCrypt.Generate(passwordBytes, salt, cost);
|
||||
Secret = Convert.ToBase64String(hashed);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public enum AccountAuthFactorType
|
||||
{
|
||||
Password, EmailCode, InAppCode, TimedCode
|
||||
}
|
57
DysonNetwork.Sphere/Account/AccountController.cs
Normal file
57
DysonNetwork.Sphere/Account/AccountController.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DysonNetwork.Sphere.Account;
|
||||
|
||||
[ApiController]
|
||||
[Route("/accounts")]
|
||||
public class AccountController(AppDatabase db)
|
||||
{
|
||||
[HttpGet("{name}")]
|
||||
[ProducesResponseType<Account>(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult<Account?>> GetByName(string name)
|
||||
{
|
||||
var account = await db.Accounts.FindAsync(name);
|
||||
return account;
|
||||
}
|
||||
|
||||
public class AccountCreateRequest
|
||||
{
|
||||
[Required] [MaxLength(256)] public string Name { get; set; } = string.Empty;
|
||||
[Required] [MaxLength(256)] public string Nick { get; set; } = string.Empty;
|
||||
[Required] [MaxLength(1024)] public string Email { get; set; } = string.Empty;
|
||||
[Required] [MinLength(4)] [MaxLength(128)] public string Password { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ProducesResponseType<Account>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<Account>> CreateAccount([FromBody] AccountCreateRequest request)
|
||||
{
|
||||
var account = new Account
|
||||
{
|
||||
Name = request.Name,
|
||||
Nick = request.Nick,
|
||||
Contacts = new List<AccountContact>()
|
||||
{
|
||||
new AccountContact
|
||||
{
|
||||
Type = AccountContactType.Email,
|
||||
Content = request.Email
|
||||
}
|
||||
},
|
||||
AuthFactors = new List<AccountAuthFactor>
|
||||
{
|
||||
new AccountAuthFactor
|
||||
{
|
||||
Type = AccountAuthFactorType.Password,
|
||||
Secret = request.Password
|
||||
}.HashSecret()
|
||||
}
|
||||
};
|
||||
|
||||
await db.Accounts.AddAsync(account);
|
||||
await db.SaveChangesAsync();
|
||||
return account;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user