diff --git a/Postall.Domain/Contracts/Repositories/IUserSocialRepository.cs b/Postall.Domain/Contracts/Repositories/IUserSocialRepository.cs
new file mode 100644
index 0000000..1387ea1
--- /dev/null
+++ b/Postall.Domain/Contracts/Repositories/IUserSocialRepository.cs
@@ -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
+ {
+ ///
+ /// Obtém todos os dados sociais dos usuários
+ ///
+ Task> GetAllAsync();
+
+ ///
+ /// Obtém os dados sociais pelo ID do MongoDB
+ ///
+ Task GetByIdAsync(string id);
+
+ ///
+ /// Obtém os dados sociais pelo ID do usuário
+ ///
+ Task GetByUserIdAsync(string userId);
+
+ ///
+ /// Obtém os dados sociais pelo token do Google
+ ///
+ Task GetByGoogleTokenAsync(string googleToken);
+
+ ///
+ /// Adiciona novos dados sociais de usuário
+ ///
+ Task AddAsync(UserSocialData userSocialData);
+
+ ///
+ /// Atualiza os dados sociais de um usuário existente
+ ///
+ Task UpdateAsync(UserSocialData userSocialData);
+
+ ///
+ /// Atualiza ou insere os dados sociais de um usuário
+ ///
+ Task UpsertAsync(UserSocialData userSocialData);
+
+ ///
+ /// Atualiza ou insere os dados sociais de um usuário unico pelo id
+ ///
+ Task UpdateOneAsync(string userId, UpdateDefinition update);
+
+ ///
+ /// Remove os dados sociais pelo ID do MongoDB
+ ///
+ Task DeleteAsync(string id);
+
+ ///
+ /// Remove os dados sociais pelo ID do usuário
+ ///
+ Task DeleteByUserIdAsync(string userId);
+
+ ///
+ /// Atualiza apenas o token do Google para um usuário
+ ///
+ Task UpdateGoogleTokenAsync(string userId, string googleToken);
+
+ ///
+ /// Atualiza apenas o token do Facebook para um usuário
+ ///
+ Task UpdateFacebookTokenAsync(string userId, FacebookToken facebookToken);
+ }
+}
\ No newline at end of file
diff --git a/Postall.Infra.MongoDB/Extensions/ServiceRepositoryExtensions.cs b/Postall.Infra.MongoDB/Extensions/ServiceRepositoryExtensions.cs
index 33368e1..cf53106 100644
--- a/Postall.Infra.MongoDB/Extensions/ServiceRepositoryExtensions.cs
+++ b/Postall.Infra.MongoDB/Extensions/ServiceRepositoryExtensions.cs
@@ -18,6 +18,7 @@ namespace Postall.Infra.MongoDB.Extensions
{
services.AddScoped();
services.AddScoped();
+ services.AddScoped();
return services;
}
diff --git a/Postall.Infra.MongoDB/Repositories/UserSocialRepository.cs b/Postall.Infra.MongoDB/Repositories/UserSocialRepository.cs
new file mode 100644
index 0000000..2ad68fc
--- /dev/null
+++ b/Postall.Infra.MongoDB/Repositories/UserSocialRepository.cs
@@ -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 _userSocialCollection;
+
+ public UserSocialRepository(IOptions mongoDbSettings)
+ {
+ var client = new MongoClient(mongoDbSettings.Value.ConnectionString);
+ var database = client.GetDatabase(mongoDbSettings.Value.DatabaseName);
+ _userSocialCollection = database.GetCollection(mongoDbSettings.Value.UserSocialCollectionName);
+
+ // Cria índice para userId (deve ser único)
+ var indexKeysDefinition = Builders.IndexKeys
+ .Ascending(u => u.UserId);
+ _userSocialCollection.Indexes.CreateOne(new CreateIndexModel(indexKeysDefinition, new CreateIndexOptions { Unique = true }));
+ }
+
+ ///
+ /// Obtém todos os dados sociais dos usuários
+ ///
+ public async Task> GetAllAsync()
+ {
+ return await _userSocialCollection.Find(u => true).ToListAsync();
+ }
+
+ ///
+ /// Obtém os dados sociais pelo ID do MongoDB
+ ///
+ public async Task GetByIdAsync(string id)
+ {
+ if (!ObjectId.TryParse(id, out _))
+ return null;
+
+ return await _userSocialCollection.Find(u => u.Id == ObjectId.Parse(id)).FirstOrDefaultAsync();
+ }
+
+ ///
+ /// Obtém os dados sociais pelo ID do usuário
+ ///
+ public async Task GetByUserIdAsync(string userId)
+ {
+ return await _userSocialCollection.Find(u => u.UserId == userId).FirstOrDefaultAsync();
+ }
+
+ ///
+ /// Obtém os dados sociais pelo token do Google
+ ///
+ public async Task GetByGoogleTokenAsync(string googleToken)
+ {
+ return await _userSocialCollection.Find(u => u.GoogleToken == googleToken).FirstOrDefaultAsync();
+ }
+
+ ///
+ /// Adiciona novos dados sociais de usuário
+ ///
+ public async Task 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;
+ }
+
+ ///
+ /// Atualiza os dados sociais de um usuário existente
+ ///
+ public async Task 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;
+ }
+
+ ///
+ /// Atualiza os dados sociais de um usuário existente
+ ///
+ public async Task 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;
+ }
+
+ ///
+ /// Atualiza ou insere os dados sociais de um usuário
+ ///
+ public async Task 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);
+ }
+ }
+
+ ///
+ /// Remove os dados sociais pelo ID do MongoDB
+ ///
+ public async Task 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;
+ }
+
+ ///
+ /// Remove os dados sociais pelo ID do usuário
+ ///
+ public async Task DeleteByUserIdAsync(string userId)
+ {
+ var result = await _userSocialCollection.DeleteOneAsync(u => u.UserId == userId);
+ return result.IsAcknowledged && result.DeletedCount > 0;
+ }
+
+ ///
+ /// Atualiza apenas o token do Google para um usuário
+ ///
+ public async Task UpdateGoogleTokenAsync(string userId, string googleToken)
+ {
+ var update = Builders.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);
+ }
+
+ ///
+ /// Atualiza apenas o token do Facebook para um usuário
+ ///
+ public async Task UpdateFacebookTokenAsync(string userId, FacebookToken facebookToken)
+ {
+ var update = Builders.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 UpdateOneAsync(string userId, UpdateDefinition update)
+ {
+ var result = await _userSocialCollection.UpdateOneAsync(
+ x => x.UserId == userId,
+ update,
+ new UpdateOptions { IsUpsert = true });
+
+ return result.IsAcknowledged && (result.ModifiedCount > 0 || result.UpsertedId != null);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Postall.Infra.MongoDB/Settings/MongoDbSetting.cs b/Postall.Infra.MongoDB/Settings/MongoDbSetting.cs
index aaf4efe..a350cc5 100644
--- a/Postall.Infra.MongoDB/Settings/MongoDbSetting.cs
+++ b/Postall.Infra.MongoDB/Settings/MongoDbSetting.cs
@@ -15,5 +15,6 @@ namespace Postall.Infra.MongoDB.Settings
public string DatabaseName { get; set; }
public string ChannelsCollectionName { get; set; }
public string VideosCollectionName { get; set; }
+ public string UserSocialCollectionName { get; internal set; }
}
}
diff --git a/Postall.Infra/Services/FacebookTokenService.cs b/Postall.Infra/Services/FacebookTokenService.cs
index 19e110c..dd3aca3 100644
--- a/Postall.Infra/Services/FacebookTokenService.cs
+++ b/Postall.Infra/Services/FacebookTokenService.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Configuration;
using MongoDB.Driver;
+using Postall.Domain;
using Postall.Domain.Dtos.Responses;
using Postall.Domain.Entities;
using Postall.Domain.Services.Contracts;
@@ -14,14 +15,14 @@ namespace Postall.Infra.Services
{
public class FacebookTokenService: IFacebookServices
{
- private readonly IMongoCollection _tokens;
private readonly IConfiguration _config;
+ private readonly IUserSocialRepository _userSocialRepository;
private readonly HttpClient _httpClient;
- public FacebookTokenService(IConfiguration configuration, IMongoCollection tokens, IHttpClientFactory httpClientFactory)
+ public FacebookTokenService(IConfiguration configuration, IHttpClientFactory httpClientFactory, IUserSocialRepository userSocialRepository)
{
_config = configuration;
- _tokens = tokens;
+ this._userSocialRepository = userSocialRepository;
_httpClient = httpClientFactory.CreateClient("Facebook");
}
@@ -46,11 +47,21 @@ namespace Postall.Infra.Services
.Set(x => x.FacebookToken.AccessToken, token)
.Set(x => x.FacebookToken.ExpiresAt, DateTime.UtcNow.AddDays(60));
- await _tokens.UpdateOneAsync(
- x => x.UserId == userId,
- update,
- new UpdateOptions { IsUpsert = true }
+ if (_userSocialRepository.GetByIdAsync(userId) == null)
+ {
+ await _userSocialRepository.AddAsync(new UserSocialData() { UserId = Guid.NewGuid().ToString("N")});
+ return;
+ }
+
+ await _userSocialRepository.UpdateOneAsync(
+ userId,
+ update
);
}
+
+ private async Task UpdateOneAsync(Func