feat: Ajuste de repository para dados do usuario

This commit is contained in:
Ricardo Carneiro 2025-03-25 12:04:44 -03:00
parent fa8aa0b610
commit 058b38a664
8 changed files with 305 additions and 16 deletions

View File

@ -0,0 +1,70 @@
using MongoDB.Driver;
using Postall.Domain.Entities;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Postall.Domain
{
public interface IUserSocialRepository
{
/// <summary>
/// Obtém todos os dados sociais dos usuários
/// </summary>
Task<IEnumerable<UserSocialData>> GetAllAsync();
/// <summary>
/// Obtém os dados sociais pelo ID do MongoDB
/// </summary>
Task<UserSocialData> GetByIdAsync(string id);
/// <summary>
/// Obtém os dados sociais pelo ID do usuário
/// </summary>
Task<UserSocialData> GetByUserIdAsync(string userId);
/// <summary>
/// Obtém os dados sociais pelo token do Google
/// </summary>
Task<UserSocialData> GetByGoogleTokenAsync(string googleToken);
/// <summary>
/// Adiciona novos dados sociais de usuário
/// </summary>
Task<UserSocialData> AddAsync(UserSocialData userSocialData);
/// <summary>
/// Atualiza os dados sociais de um usuário existente
/// </summary>
Task<bool> UpdateAsync(UserSocialData userSocialData);
/// <summary>
/// Atualiza ou insere os dados sociais de um usuário
/// </summary>
Task<UserSocialData> UpsertAsync(UserSocialData userSocialData);
/// <summary>
/// Atualiza ou insere os dados sociais de um usuário unico pelo id
/// </summary>
Task<bool> UpdateOneAsync(string userId, UpdateDefinition<UserSocialData> update);
/// <summary>
/// Remove os dados sociais pelo ID do MongoDB
/// </summary>
Task<bool> DeleteAsync(string id);
/// <summary>
/// Remove os dados sociais pelo ID do usuário
/// </summary>
Task<bool> DeleteByUserIdAsync(string userId);
/// <summary>
/// Atualiza apenas o token do Google para um usuário
/// </summary>
Task<bool> UpdateGoogleTokenAsync(string userId, string googleToken);
/// <summary>
/// Atualiza apenas o token do Facebook para um usuário
/// </summary>
Task<bool> UpdateFacebookTokenAsync(string userId, FacebookToken facebookToken);
}
}

View File

@ -18,6 +18,7 @@ namespace Postall.Infra.MongoDB.Extensions
{ {
services.AddScoped<IChannelRepository, ChannelRepository>(); services.AddScoped<IChannelRepository, ChannelRepository>();
services.AddScoped<IVideoRepository, VideoRepository>(); services.AddScoped<IVideoRepository, VideoRepository>();
services.AddScoped<IUserSocialRepository, UserSocialRepository>();
return services; return services;
} }

View File

@ -0,0 +1,210 @@
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver;
using Postall.Domain;
using Postall.Domain.Entities;
using Postall.Infra.MongoDB.Settings;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Postall.Infra.MongoDB.Repositories
{
public class UserSocialRepository : IUserSocialRepository
{
private readonly IMongoCollection<UserSocialData> _userSocialCollection;
public UserSocialRepository(IOptions<MongoDbSettings> mongoDbSettings)
{
var client = new MongoClient(mongoDbSettings.Value.ConnectionString);
var database = client.GetDatabase(mongoDbSettings.Value.DatabaseName);
_userSocialCollection = database.GetCollection<UserSocialData>(mongoDbSettings.Value.UserSocialCollectionName);
// Cria índice para userId (deve ser único)
var indexKeysDefinition = Builders<UserSocialData>.IndexKeys
.Ascending(u => u.UserId);
_userSocialCollection.Indexes.CreateOne(new CreateIndexModel<UserSocialData>(indexKeysDefinition, new CreateIndexOptions { Unique = true }));
}
/// <summary>
/// Obtém todos os dados sociais dos usuários
/// </summary>
public async Task<IEnumerable<UserSocialData>> GetAllAsync()
{
return await _userSocialCollection.Find(u => true).ToListAsync();
}
/// <summary>
/// Obtém os dados sociais pelo ID do MongoDB
/// </summary>
public async Task<UserSocialData> GetByIdAsync(string id)
{
if (!ObjectId.TryParse(id, out _))
return null;
return await _userSocialCollection.Find(u => u.Id == ObjectId.Parse(id)).FirstOrDefaultAsync();
}
/// <summary>
/// Obtém os dados sociais pelo ID do usuário
/// </summary>
public async Task<UserSocialData> GetByUserIdAsync(string userId)
{
return await _userSocialCollection.Find(u => u.UserId == userId).FirstOrDefaultAsync();
}
/// <summary>
/// Obtém os dados sociais pelo token do Google
/// </summary>
public async Task<UserSocialData> GetByGoogleTokenAsync(string googleToken)
{
return await _userSocialCollection.Find(u => u.GoogleToken == googleToken).FirstOrDefaultAsync();
}
/// <summary>
/// Adiciona novos dados sociais de usuário
/// </summary>
public async Task<UserSocialData> AddAsync(UserSocialData userSocialData)
{
var existingUserSocial = await GetByUserIdAsync(userSocialData.UserId);
if (existingUserSocial != null)
return existingUserSocial;
if (userSocialData.Id == ObjectId.Empty)
{
userSocialData.Id = ObjectId.GenerateNewId();
}
try
{
await _userSocialCollection.InsertOneAsync(userSocialData);
}
catch (MongoWriteException ex)
{
if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey)
{
return await GetByUserIdAsync(userSocialData.UserId);
}
else
{
throw;
}
}
return userSocialData;
}
/// <summary>
/// Atualiza os dados sociais de um usuário existente
/// </summary>
public async Task<bool> UpdateAsync(UserSocialData userSocialData)
{
if (userSocialData.Id == ObjectId.Empty)
return false;
var result = await _userSocialCollection.ReplaceOneAsync(
u => u.Id == userSocialData.Id,
userSocialData,
new ReplaceOptions { IsUpsert = false });
return result.IsAcknowledged && result.ModifiedCount > 0;
}
/// <summary>
/// Atualiza os dados sociais de um usuário existente
/// </summary>
public async Task<bool> UpdateOneAsync(UserSocialData userSocialData)
{
if (userSocialData.Id == ObjectId.Empty)
return false;
var result = await _userSocialCollection.ReplaceOneAsync(
u => u.Id == userSocialData.Id,
userSocialData,
new ReplaceOptions { IsUpsert = false });
return result.IsAcknowledged && result.ModifiedCount > 0;
}
/// <summary>
/// Atualiza ou insere os dados sociais de um usuário
/// </summary>
public async Task<UserSocialData> UpsertAsync(UserSocialData userSocialData)
{
var existingData = await GetByUserIdAsync(userSocialData.UserId);
if (existingData != null)
{
userSocialData.Id = existingData.Id;
await _userSocialCollection.ReplaceOneAsync(
u => u.Id == existingData.Id,
userSocialData,
new ReplaceOptions { IsUpsert = true });
return userSocialData;
}
else
{
return await AddAsync(userSocialData);
}
}
/// <summary>
/// Remove os dados sociais pelo ID do MongoDB
/// </summary>
public async Task<bool> DeleteAsync(string id)
{
if (!ObjectId.TryParse(id, out _))
return false;
var result = await _userSocialCollection.DeleteOneAsync(u => u.Id == ObjectId.Parse(id));
return result.IsAcknowledged && result.DeletedCount > 0;
}
/// <summary>
/// Remove os dados sociais pelo ID do usuário
/// </summary>
public async Task<bool> DeleteByUserIdAsync(string userId)
{
var result = await _userSocialCollection.DeleteOneAsync(u => u.UserId == userId);
return result.IsAcknowledged && result.DeletedCount > 0;
}
/// <summary>
/// Atualiza apenas o token do Google para um usuário
/// </summary>
public async Task<bool> UpdateGoogleTokenAsync(string userId, string googleToken)
{
var update = Builders<UserSocialData>.Update.Set(u => u.GoogleToken, googleToken);
var result = await _userSocialCollection.UpdateOneAsync(
u => u.UserId == userId,
update,
new UpdateOptions { IsUpsert = true });
return result.IsAcknowledged && (result.ModifiedCount > 0 || result.UpsertedId != null);
}
/// <summary>
/// Atualiza apenas o token do Facebook para um usuário
/// </summary>
public async Task<bool> UpdateFacebookTokenAsync(string userId, FacebookToken facebookToken)
{
var update = Builders<UserSocialData>.Update.Set(u => u.FacebookToken, facebookToken);
var result = await _userSocialCollection.UpdateOneAsync(
u => u.UserId == userId,
update,
new UpdateOptions { IsUpsert = true });
return result.IsAcknowledged && (result.ModifiedCount > 0 || result.UpsertedId != null);
}
public async Task<bool> UpdateOneAsync(string userId, UpdateDefinition<UserSocialData> update)
{
var result = await _userSocialCollection.UpdateOneAsync(
x => x.UserId == userId,
update,
new UpdateOptions { IsUpsert = true });
return result.IsAcknowledged && (result.ModifiedCount > 0 || result.UpsertedId != null);
}
}
}

View File

@ -15,5 +15,6 @@ namespace Postall.Infra.MongoDB.Settings
public string DatabaseName { get; set; } public string DatabaseName { get; set; }
public string ChannelsCollectionName { get; set; } public string ChannelsCollectionName { get; set; }
public string VideosCollectionName { get; set; } public string VideosCollectionName { get; set; }
public string UserSocialCollectionName { get; internal set; }
} }
} }

View File

@ -1,5 +1,6 @@
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using MongoDB.Driver; using MongoDB.Driver;
using Postall.Domain;
using Postall.Domain.Dtos.Responses; using Postall.Domain.Dtos.Responses;
using Postall.Domain.Entities; using Postall.Domain.Entities;
using Postall.Domain.Services.Contracts; using Postall.Domain.Services.Contracts;
@ -14,14 +15,14 @@ namespace Postall.Infra.Services
{ {
public class FacebookTokenService: IFacebookServices public class FacebookTokenService: IFacebookServices
{ {
private readonly IMongoCollection<UserSocialData> _tokens;
private readonly IConfiguration _config; private readonly IConfiguration _config;
private readonly IUserSocialRepository _userSocialRepository;
private readonly HttpClient _httpClient; private readonly HttpClient _httpClient;
public FacebookTokenService(IConfiguration configuration, IMongoCollection<UserSocialData> tokens, IHttpClientFactory httpClientFactory) public FacebookTokenService(IConfiguration configuration, IHttpClientFactory httpClientFactory, IUserSocialRepository userSocialRepository)
{ {
_config = configuration; _config = configuration;
_tokens = tokens; this._userSocialRepository = userSocialRepository;
_httpClient = httpClientFactory.CreateClient("Facebook"); _httpClient = httpClientFactory.CreateClient("Facebook");
} }
@ -46,11 +47,21 @@ namespace Postall.Infra.Services
.Set(x => x.FacebookToken.AccessToken, token) .Set(x => x.FacebookToken.AccessToken, token)
.Set(x => x.FacebookToken.ExpiresAt, DateTime.UtcNow.AddDays(60)); .Set(x => x.FacebookToken.ExpiresAt, DateTime.UtcNow.AddDays(60));
await _tokens.UpdateOneAsync( if (_userSocialRepository.GetByIdAsync(userId) == null)
x => x.UserId == userId, {
update, await _userSocialRepository.AddAsync(new UserSocialData() { UserId = Guid.NewGuid().ToString("N")});
new UpdateOptions { IsUpsert = true } return;
}
await _userSocialRepository.UpdateOneAsync(
userId,
update
); );
} }
private async Task UpdateOneAsync(Func<object, bool> value, UpdateDefinition<UserSocialData> update, UpdateOptions updateOptions)
{
throw new NotImplementedException();
}
} }
} }

View File

@ -9,13 +9,6 @@
<DockerfileContext>.</DockerfileContext> <DockerfileContext>.</DockerfileContext>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Compile Remove="Views\CartHome\**" />
<Content Remove="Views\CartHome\**" />
<EmbeddedResource Remove="Views\CartHome\**" />
<None Remove="Views\CartHome\**" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.Facebook" Version="8.0.12" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.Facebook" Version="8.0.12" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="8.0.7" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="8.0.7" />

View File

@ -8,6 +8,8 @@
"MongoDbSettings": { "MongoDbSettings": {
"ConnectionString": "mongodb://localhost:27017", "ConnectionString": "mongodb://localhost:27017",
"DatabaseName": "YouTubeChannelsDB", "DatabaseName": "YouTubeChannelsDB",
"ChannelsCollectionName": "Channels" "ChannelsCollectionName": "Channels",
"VideosCollectionName": "Videos",
"UserSocialCollectionName": "UserSocial"
} }
} }

View File

@ -29,6 +29,7 @@
"ConnectionString": "mongodb://localhost:27017", "ConnectionString": "mongodb://localhost:27017",
"DatabaseName": "YouTubeChannelsDB", "DatabaseName": "YouTubeChannelsDB",
"ChannelsCollectionName": "Channels", "ChannelsCollectionName": "Channels",
"VideosCollectionName": "Videos" "VideosCollectionName": "Videos",
"UserSocialCollectionName": "UserSocial"
} }
} }