Compare commits

...

2 Commits

Author SHA1 Message Date
5757526ea5 Get user blocked users infra 2025-07-03 21:57:16 +08:00
6a9cd0905d Unblock user 2025-07-03 21:47:17 +08:00
3 changed files with 67 additions and 11 deletions

View File

@ -230,4 +230,24 @@ public class RelationshipController(AppDatabase db, RelationshipService rels) :
return BadRequest(err.Message); return BadRequest(err.Message);
} }
} }
[HttpDelete("{userId:guid}/block")]
[Authorize]
public async Task<ActionResult<Relationship>> UnblockUser(Guid userId)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var relatedUser = await db.Accounts.FindAsync(userId);
if (relatedUser is null) return NotFound("Account was not found.");
try
{
var relationship = await rels.UnblockAccount(currentUser, relatedUser);
return relationship;
}
catch (InvalidOperationException err)
{
return BadRequest(err.Message);
}
}
} }

View File

@ -7,6 +7,7 @@ namespace DysonNetwork.Sphere.Account;
public class RelationshipService(AppDatabase db, ICacheService cache) public class RelationshipService(AppDatabase db, ICacheService cache)
{ {
private const string UserFriendsCacheKeyPrefix = "accounts:friends:"; private const string UserFriendsCacheKeyPrefix = "accounts:friends:";
private const string UserBlockedCacheKeyPrefix = "accounts:blocked:";
public async Task<bool> HasExistingRelationship(Guid accountId, Guid relatedId) public async Task<bool> HasExistingRelationship(Guid accountId, Guid relatedId)
{ {
@ -51,8 +52,7 @@ public class RelationshipService(AppDatabase db, ICacheService cache)
db.AccountRelationships.Add(relationship); db.AccountRelationships.Add(relationship);
await db.SaveChangesAsync(); await db.SaveChangesAsync();
await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{relationship.AccountId}"); await PurgeRelationshipCache(sender.Id, target.Id);
await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{relationship.RelatedId}");
return relationship; return relationship;
} }
@ -64,6 +64,18 @@ public class RelationshipService(AppDatabase db, ICacheService cache)
return await CreateRelationship(sender, target, RelationshipStatus.Blocked); return await CreateRelationship(sender, target, RelationshipStatus.Blocked);
} }
public async Task<Relationship> UnblockAccount(Account sender, Account target)
{
var relationship = await GetRelationship(sender.Id, target.Id, RelationshipStatus.Blocked);
if (relationship is null) throw new ArgumentException("There is no relationship between you and the user.");
db.Remove(relationship);
await db.SaveChangesAsync();
await PurgeRelationshipCache(sender.Id, target.Id);
return relationship;
}
public async Task<Relationship> SendFriendRequest(Account sender, Account target) public async Task<Relationship> SendFriendRequest(Account sender, Account target)
{ {
if (await HasExistingRelationship(sender.Id, target.Id)) if (await HasExistingRelationship(sender.Id, target.Id))
@ -92,8 +104,7 @@ public class RelationshipService(AppDatabase db, ICacheService cache)
.Where(r => r.AccountId == accountId && r.RelatedId == relatedId && r.Status == RelationshipStatus.Pending) .Where(r => r.AccountId == accountId && r.RelatedId == relatedId && r.Status == RelationshipStatus.Pending)
.ExecuteDeleteAsync(); .ExecuteDeleteAsync();
await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{accountId}"); await PurgeRelationshipCache(relationship.AccountId, relationship.RelatedId);
await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{relatedId}");
} }
public async Task<Relationship> AcceptFriendRelationship( public async Task<Relationship> AcceptFriendRelationship(
@ -122,8 +133,7 @@ public class RelationshipService(AppDatabase db, ICacheService cache)
await db.SaveChangesAsync(); await db.SaveChangesAsync();
await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{relationship.AccountId}"); await PurgeRelationshipCache(relationship.AccountId, relationship.RelatedId);
await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{relationship.RelatedId}");
return relationshipBackward; return relationshipBackward;
} }
@ -137,15 +147,14 @@ public class RelationshipService(AppDatabase db, ICacheService cache)
db.Update(relationship); db.Update(relationship);
await db.SaveChangesAsync(); await db.SaveChangesAsync();
await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{accountId}"); await PurgeRelationshipCache(accountId, relatedId);
await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{relatedId}");
return relationship; return relationship;
} }
public async Task<List<Guid>> ListAccountFriends(Account account) public async Task<List<Guid>> ListAccountFriends(Account account)
{ {
string cacheKey = $"{UserFriendsCacheKeyPrefix}{account.Id}"; var cacheKey = $"{UserFriendsCacheKeyPrefix}{account.Id}";
var friends = await cache.GetAsync<List<Guid>>(cacheKey); var friends = await cache.GetAsync<List<Guid>>(cacheKey);
if (friends == null) if (friends == null)
@ -162,10 +171,37 @@ public class RelationshipService(AppDatabase db, ICacheService cache)
return friends ?? []; return friends ?? [];
} }
public async Task<List<Guid>> ListAccountBlocked(Account account)
{
var cacheKey = $"{UserBlockedCacheKeyPrefix}{account.Id}";
var blocked = await cache.GetAsync<List<Guid>>(cacheKey);
if (blocked == null)
{
blocked = await db.AccountRelationships
.Where(r => r.RelatedId == account.Id)
.Where(r => r.Status == RelationshipStatus.Blocked)
.Select(r => r.AccountId)
.ToListAsync();
await cache.SetAsync(cacheKey, blocked, TimeSpan.FromHours(1));
}
return blocked ?? [];
}
public async Task<bool> HasRelationshipWithStatus(Guid accountId, Guid relatedId, public async Task<bool> HasRelationshipWithStatus(Guid accountId, Guid relatedId,
RelationshipStatus status = RelationshipStatus.Friends) RelationshipStatus status = RelationshipStatus.Friends)
{ {
var relationship = await GetRelationship(accountId, relatedId, status); var relationship = await GetRelationship(accountId, relatedId, status);
return relationship is not null; return relationship is not null;
} }
private async Task PurgeRelationshipCache(Guid accountId, Guid relatedId)
{
await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{accountId}");
await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{relatedId}");
await cache.RemoveAsync($"{UserBlockedCacheKeyPrefix}{accountId}");
await cache.RemoveAsync($"{UserBlockedCacheKeyPrefix}{relatedId}");
}
} }

View File

@ -126,7 +126,7 @@ public class ActivityService(
var activities = new List<Activity>(); var activities = new List<Activity>();
var userFriends = await rels.ListAccountFriends(currentUser); var userFriends = await rels.ListAccountFriends(currentUser);
var userPublishers = await pub.GetUserPublishers(currentUser.Id); var userPublishers = await pub.GetUserPublishers(currentUser.Id);
debugInclude ??= new HashSet<string>(); debugInclude ??= [];
if (string.IsNullOrEmpty(filter)) if (string.IsNullOrEmpty(filter))
{ {