diff --git a/LogoPoost.png b/LogoPoost.png new file mode 100644 index 0000000..445995c Binary files /dev/null and b/LogoPoost.png differ diff --git a/Postall.Domain/Dtos/Responses/FacebookTokenResponse.cs b/Postall.Domain/Dtos/Responses/FacebookTokenResponse.cs new file mode 100644 index 0000000..92579a3 --- /dev/null +++ b/Postall.Domain/Dtos/Responses/FacebookTokenResponse.cs @@ -0,0 +1,17 @@ +// Models/FacebookTokenResponse.cs +using System.Text.Json.Serialization; + +namespace Postall.Domain.Dtos.Responses +{ + public class FacebookTokenResponse + { + [JsonPropertyName("access_token")] + public string AccessToken { get; set; } + + [JsonPropertyName("token_type")] + public string TokenType { get; set; } + + [JsonPropertyName("expires_in")] + public long ExpiresIn { get; set; } + } +} diff --git a/Postall.Domain/Entities/FacebookToken.cs b/Postall.Domain/Entities/FacebookToken.cs new file mode 100644 index 0000000..a4f2170 --- /dev/null +++ b/Postall.Domain/Entities/FacebookToken.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Postall.Domain.Entities +{ + public class FacebookToken + { + public string AccessToken { get; set; } + public DateTime ExpiresAt { get; set; } + } +} diff --git a/Postall.Domain/Entities/UserSocialData.cs b/Postall.Domain/Entities/UserSocialData.cs new file mode 100644 index 0000000..481a3fc --- /dev/null +++ b/Postall.Domain/Entities/UserSocialData.cs @@ -0,0 +1,20 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static System.Runtime.InteropServices.JavaScript.JSType; + +namespace Postall.Domain.Entities +{ + public class UserSocialData + { + [BsonId] + public ObjectId Id { get; set; } + public string UserId { get; set; } + public string GoogleToken { get; set; } + public FacebookToken FacebookToken { get; set; } + } +} diff --git a/Postall.Domain/Postall.Domain.csproj b/Postall.Domain/Postall.Domain.csproj index b6e91af..7c79f16 100644 --- a/Postall.Domain/Postall.Domain.csproj +++ b/Postall.Domain/Postall.Domain.csproj @@ -7,6 +7,8 @@ + + @@ -15,7 +17,7 @@ - + diff --git a/Postall.Domain/Services/IFacebookServices.cs b/Postall.Domain/Services/IFacebookServices.cs new file mode 100644 index 0000000..ed06869 --- /dev/null +++ b/Postall.Domain/Services/IFacebookServices.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Postall.Domain.Services +{ + public interface IFacebookServices + { + Task GetLongLivedToken(string shortLivedToken); + Task SaveFacebookToken(string userId, string token); + } +} diff --git a/Postall.Infra/Postall.Infra.csproj b/Postall.Infra/Postall.Infra.csproj index 41cbdd4..54b2459 100644 --- a/Postall.Infra/Postall.Infra.csproj +++ b/Postall.Infra/Postall.Infra.csproj @@ -7,8 +7,8 @@ - - + + @@ -16,4 +16,8 @@ + + + + diff --git a/Postall.Infra/Services/FacebookTokenService.cs b/Postall.Infra/Services/FacebookTokenService.cs new file mode 100644 index 0000000..345ef5d --- /dev/null +++ b/Postall.Infra/Services/FacebookTokenService.cs @@ -0,0 +1,49 @@ +using Microsoft.Extensions.Configuration; +using MongoDB.Driver; +using Postall.Domain.Dtos.Responses; +using Postall.Domain.Entities; +using Postall.Domain.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http.Json; +using System.Text; +using System.Threading.Tasks; + +namespace Postall.Infra.Services +{ + public class FacebookTokenService: IFacebookServices + { + private readonly IMongoCollection _tokens; + private readonly IConfiguration _config; + private readonly HttpClient _httpClient; + + public async Task GetLongLivedToken(string shortLivedToken) + { + var appId = _config["Authentication:Facebook:AppId"]; + var appSecret = _config["Authentication:Facebook:AppSecret"]; + + var response = await _httpClient.GetFromJsonAsync( + $"https://graph.facebook.com/oauth/access_token?" + + $"grant_type=fb_exchange_token&" + + $"client_id={appId}&" + + $"client_secret={appSecret}&" + + $"fb_exchange_token={shortLivedToken}"); + + return response.AccessToken; + } + + public async Task SaveFacebookToken(string userId, string token) + { + var update = Builders.Update + .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 } + ); + } + } +} diff --git a/Postall/Controllers/OtherLoginsController.cs b/Postall/Controllers/OtherLoginsController.cs index 6c1e76f..a195188 100644 --- a/Postall/Controllers/OtherLoginsController.cs +++ b/Postall/Controllers/OtherLoginsController.cs @@ -2,11 +2,19 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Facebook; using Microsoft.AspNetCore.Mvc; +using Postall.Domain.Services; +using System.Security.Claims; namespace Postall.Controllers { public class OtherLoginsController : Controller { + private readonly IFacebookServices _facebookServices; + + public OtherLoginsController(IFacebookServices facebookServices) + { + this._facebookServices = facebookServices; + } [HttpGet] public IActionResult Index() { @@ -24,21 +32,13 @@ namespace Postall.Controllers public async Task FacebookResponse() { var result = await HttpContext.AuthenticateAsync(FacebookDefaults.AuthenticationScheme); + if (!result.Succeeded) return RedirectToAction("Login"); - if (!result.Succeeded) - return RedirectToAction("Login"); + var accessToken = result.Properties.GetTokenValue("access_token"); + var longLivedToken = await _facebookServices.GetLongLivedToken(accessToken); - var claims = result.Principal.Identities.FirstOrDefault() - .Claims.Select(claim => new - { - claim.Issuer, - claim.OriginalIssuer, - claim.Type, - claim.Value - }); - - // Aqui você pode implementar sua lógica de login - // Por exemplo, criar ou atualizar o usuário no banco de dados + var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; + await _facebookServices.SaveFacebookToken(userId, longLivedToken); return RedirectToAction("Index", "Home"); } diff --git a/Postall/Controllers/SocialMediaController.cs b/Postall/Controllers/SocialMediaController.cs new file mode 100644 index 0000000..ff3121f --- /dev/null +++ b/Postall/Controllers/SocialMediaController.cs @@ -0,0 +1,91 @@ +using Microsoft.AspNetCore.Mvc; +using Postall.Models; + +namespace Postall.Controllers +{ + public class SocialMediaController : Controller + { + [HttpGet] + public IActionResult Index() + { + // Implementar lógica para buscar lista de posts + return View(); + } + + [HttpGet] + public JsonResult GetPostDetails(int postId) + { + try + { + // Implementar lógica para buscar detalhes do post + return Json(new { success = true }); + } + catch (Exception ex) + { + return Json(new { success = false, message = ex.Message }); + } + } + + [HttpGet] + public JsonResult GetSocialMediaStatus(int postId) + { + try + { + // Implementar lógica para buscar status das redes sociais + return Json(new { success = true }); + } + catch (Exception ex) + { + return Json(new { success = false, message = ex.Message }); + } + } + + [HttpGet] + public IActionResult Post() + { + return View(); + } + + [HttpPost] + public JsonResult SaveDraft([FromBody] PostViewModel model) + { + try + { + // Lógica para salvar rascunho + return Json(new { success = true }); + } + catch (Exception ex) + { + return Json(new { success = false, message = ex.Message }); + } + } + + [HttpPost] + public JsonResult PublishPost([FromBody] PostViewModel model) + { + try + { + // Lógica para publicar post + return Json(new { success = true }); + } + catch (Exception ex) + { + return Json(new { success = false, message = ex.Message }); + } + } + + [HttpPost] + public JsonResult SchedulePost([FromBody] PostScheduleViewModel model) + { + try + { + // Lógica para agendar post + return Json(new { success = true }); + } + catch (Exception ex) + { + return Json(new { success = false, message = ex.Message }); + } + } + } +} diff --git a/Postall/Models/PostListViewModel.cs b/Postall/Models/PostListViewModel.cs new file mode 100644 index 0000000..fffe0c9 --- /dev/null +++ b/Postall/Models/PostListViewModel.cs @@ -0,0 +1,12 @@ +namespace Postall.Models +{ + public class PostListViewModel + { + public int Id { get; set; } + public string Channel { get; set; } + public string Title { get; set; } + public DateTime? NextScheduledDate { get; set; } + public DateTime LastUpdate { get; set; } + public List SocialMediaStatus { get; set; } + } +} diff --git a/Postall/Models/PostScheduleViewModel.cs b/Postall/Models/PostScheduleViewModel.cs new file mode 100644 index 0000000..c0248d9 --- /dev/null +++ b/Postall/Models/PostScheduleViewModel.cs @@ -0,0 +1,9 @@ +namespace Postall.Models +{ + public class PostScheduleViewModel + { + public bool IsManual { get; set; } + public DayOfWeek? WeekDay { get; set; } + public TimeSpan? Time { get; set; } + } +} diff --git a/Postall/Models/PostViewModel.cs b/Postall/Models/PostViewModel.cs new file mode 100644 index 0000000..d15d608 --- /dev/null +++ b/Postall/Models/PostViewModel.cs @@ -0,0 +1,10 @@ +namespace Postall.Models +{ + public class PostViewModel + { + public string Title { get; set; } + public string Content { get; set; } + public string ImageUrl { get; set; } + public List SelectedPlatforms { get; set; } + } +} diff --git a/Postall/Models/SocialMediaStatusViewModel.cs b/Postall/Models/SocialMediaStatusViewModel.cs new file mode 100644 index 0000000..21c6128 --- /dev/null +++ b/Postall/Models/SocialMediaStatusViewModel.cs @@ -0,0 +1,9 @@ +namespace Postall.Models +{ + public class SocialMediaStatusViewModel + { + public string Platform { get; set; } + public DateTime? NextScheduledDate { get; set; } + public string Status { get; set; } + } +} diff --git a/Postall/Postall.csproj b/Postall/Postall.csproj index c496931..e2f4b9b 100644 --- a/Postall/Postall.csproj +++ b/Postall/Postall.csproj @@ -32,6 +32,11 @@ + + + + + True diff --git a/Postall/Program.cs b/Postall/Program.cs index 1c88c0a..8a02ed6 100644 --- a/Postall/Program.cs +++ b/Postall/Program.cs @@ -4,6 +4,8 @@ using Microsoft.AspNetCore.Authentication.Google; using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.Extensions.Options; +using Postall.Domain.Services; +using Postall.Infra.Services; using Serilog; using Serilog.Sinks.Grafana.Loki; using Stripe; @@ -86,6 +88,8 @@ builder.Services.AddControllersWithViews(); builder.Services.AddHttpClient(); builder.Services.AddSerilog(); +builder.Services.AddScoped(); + var app = builder.Build(); var locOptions = app.Services.GetService>(); diff --git a/Postall/Views/OtherLogins/Index.cshtml b/Postall/Views/OtherLogins/Index.cshtml index 5f2cad9..c6603b1 100644 --- a/Postall/Views/OtherLogins/Index.cshtml +++ b/Postall/Views/OtherLogins/Index.cshtml @@ -1,16 +1,54 @@ @{ - ViewData["Title"] = "Site"; + ViewData["Title"] = "Sites"; } -
-

Login

-
-
-
- -
+ +
+
+
+
+
+

Bem-vindo

+

+ Faça login com sua conta Microsoft para acessar o chat. +

+ +
+ +
+
+
+ +@section Styles { + +} + +@section Scripts { + +} diff --git a/Postall/Views/Shared/_Layout.cshtml b/Postall/Views/Shared/_Layout.cshtml index b9bbb0b..e26105c 100644 --- a/Postall/Views/Shared/_Layout.cshtml +++ b/Postall/Views/Shared/_Layout.cshtml @@ -32,6 +32,15 @@ + @if (User!=null && User.Identity!=null && User.Identity.IsAuthenticated) + { + + + } @if (User!=null && User.Identity!=null && !User.Identity.IsAuthenticated) { @@ -44,11 +53,6 @@ } else { -