✨ Sharable rewind point
This commit is contained in:
@@ -8,6 +8,14 @@ namespace DysonNetwork.Pass.Rewind;
|
|||||||
[Route("/api/rewind")]
|
[Route("/api/rewind")]
|
||||||
public class AccountRewindController(AccountRewindService rewindSrv) : ControllerBase
|
public class AccountRewindController(AccountRewindService rewindSrv) : ControllerBase
|
||||||
{
|
{
|
||||||
|
[HttpGet("{code}")]
|
||||||
|
public async Task<ActionResult<SnRewindPoint>> GetRewindPoint([FromRoute] string code)
|
||||||
|
{
|
||||||
|
var point = await rewindSrv.GetPublicRewindPoint(code);
|
||||||
|
if (point is null) return NotFound();
|
||||||
|
return Ok(point);
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet("me")]
|
[HttpGet("me")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public async Task<ActionResult<SnRewindPoint>> GetCurrentRewindPoint()
|
public async Task<ActionResult<SnRewindPoint>> GetCurrentRewindPoint()
|
||||||
@@ -16,4 +24,36 @@ public class AccountRewindController(AccountRewindService rewindSrv) : Controlle
|
|||||||
var point = await rewindSrv.GetOrCreateRewindPoint(currentUser.Id);
|
var point = await rewindSrv.GetOrCreateRewindPoint(currentUser.Id);
|
||||||
return Ok(point);
|
return Ok(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("me/{year:int}/public")]
|
||||||
|
[Authorize]
|
||||||
|
public async Task<ActionResult<SnRewindPoint>> SetRewindPointPublic([FromRoute] int year)
|
||||||
|
{
|
||||||
|
if (HttpContext.Items["CurrentUser"] is not SnAccount currentUser) return Unauthorized();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var point = await rewindSrv.SetRewindPointPublic(currentUser.Id, year);
|
||||||
|
return Ok(point);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException error)
|
||||||
|
{
|
||||||
|
return BadRequest(error.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("me/{year:int}/private")]
|
||||||
|
[Authorize]
|
||||||
|
public async Task<ActionResult<SnRewindPoint>> SetRewindPointPrivate([FromRoute] int year)
|
||||||
|
{
|
||||||
|
if (HttpContext.Items["CurrentUser"] is not SnAccount currentUser) return Unauthorized();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var point = await rewindSrv.SetRewindPointPrivate(currentUser.Id, year);
|
||||||
|
return Ok(point);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException error)
|
||||||
|
{
|
||||||
|
return BadRequest(error.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Security.Cryptography;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Shared.Proto;
|
using DysonNetwork.Shared.Proto;
|
||||||
using Grpc.Net.Client;
|
using Grpc.Net.Client;
|
||||||
@@ -75,4 +76,55 @@ public class AccountRewindService(
|
|||||||
|
|
||||||
return await CreateRewindPoint(accountId);
|
return await CreateRewindPoint(accountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<SnRewindPoint?> GetPublicRewindPoint(string code)
|
||||||
|
{
|
||||||
|
var point = await db.RewindPoints
|
||||||
|
.Where(p => p.SharableCode == code)
|
||||||
|
.OrderBy(p => p.CreatedAt)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SnRewindPoint> SetRewindPointPublic(Guid accountId, int year)
|
||||||
|
{
|
||||||
|
var point = await db.RewindPoints
|
||||||
|
.Where(p => p.AccountId == accountId && p.Year == year)
|
||||||
|
.OrderBy(p => p.CreatedAt)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
if (point is null) throw new InvalidOperationException("No rewind point was found.");
|
||||||
|
point.SharableCode = _GenerateRandomString(16);
|
||||||
|
db.RewindPoints.Update(point);
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SnRewindPoint> SetRewindPointPrivate(Guid accountId, int year)
|
||||||
|
{
|
||||||
|
var point = await db.RewindPoints
|
||||||
|
.Where(p => p.AccountId == accountId && p.Year == year)
|
||||||
|
.OrderBy(p => p.CreatedAt)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
if (point is null) throw new InvalidOperationException("No rewind point was found.");
|
||||||
|
point.SharableCode = null;
|
||||||
|
db.RewindPoints.Update(point);
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string _GenerateRandomString(int length)
|
||||||
|
{
|
||||||
|
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
var result = new char[length];
|
||||||
|
using var rng = RandomNumberGenerator.Create();
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
var bytes = new byte[1];
|
||||||
|
rng.GetBytes(bytes);
|
||||||
|
result[i] = chars[bytes[0] % chars.Length];
|
||||||
|
}
|
||||||
|
return new string(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
namespace DysonNetwork.Shared.Models;
|
namespace DysonNetwork.Shared.Models;
|
||||||
@@ -13,6 +14,7 @@ public class SnRewindPoint : ModelBase
|
|||||||
/// this field provide the clues for the client to parsing the data correctly.
|
/// this field provide the clues for the client to parsing the data correctly.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int SchemaVersion { get; set; } = 1;
|
public int SchemaVersion { get; set; } = 1;
|
||||||
|
[MaxLength(4096)] public string? SharableCode { get; set; }
|
||||||
|
|
||||||
[Column(TypeName = "jsonb")] public Dictionary<string, object?> Data { get; set; } = new();
|
[Column(TypeName = "jsonb")] public Dictionary<string, object?> Data { get; set; } = new();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user