feat: versão inicial com login do google funcional

This commit is contained in:
Ricardo Carneiro 2025-01-26 22:22:36 -03:00
parent ca36b7d085
commit 4b04639ad7
2205 changed files with 612 additions and 70 deletions

View File

@ -0,0 +1,78 @@
using BaseDomain.SimpleValidator;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseDomain.Base
{
public abstract class AEntity<T, TKey> where TKey : class
where T : class
{
ObjectValidatorBuilder<T> objectValidatorBuilder;
bool rulesAdded;
public ObjectValidatorBuilder<T> ValidatorBuilder { get { return objectValidatorBuilder; } }
public AEntity()
{
T entity;
try
{
entity = (T)Convert.ChangeType(this, typeof(T));
}
catch (InvalidCastException)
{
entity = default;
}
objectValidatorBuilder = new ObjectValidatorBuilder<T>(entity);
AddRules();
}
public ObjectValidatorBuilder<T> InitValidator()
{
T entity;
try
{
entity = (T)Convert.ChangeType(this, typeof(T));
}
catch (InvalidCastException)
{
entity = default;
}
objectValidatorBuilder = new ObjectValidatorBuilder<T>(entity);
return objectValidatorBuilder;
}
public abstract TKey Id { get; set; }
public void ValidateAndThrow()
{
SetClearAndRules();
objectValidatorBuilder.ThrowErrorMessages();
}
public string GetErrorMessages()
{
SetClearAndRules();
return objectValidatorBuilder.ErrorMessagesAsString();
}
public bool IsValid()
{
SetClearAndRules();
return objectValidatorBuilder.IsValid();
}
private void SetClearAndRules()
{
objectValidatorBuilder.ClearRules();
AddRules();
objectValidatorBuilder.Build();
}
public abstract void AddRules();
}
}

View File

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseDomain
{
public abstract class AValueObject
{
protected static bool EqualOperator(AValueObject left, AValueObject right)
{
if (ReferenceEquals(left, null) ^ ReferenceEquals(right, null))
{
return false;
}
return ReferenceEquals(left, right) || left.Equals(right);
}
protected static bool NotEqualOperator(AValueObject left, AValueObject right)
{
return !EqualOperator(left, right);
}
protected abstract IEnumerable<object> GetEqualityComponents();
public override bool Equals(object obj)
{
if (obj == null || obj.GetType() != GetType())
{
return false;
}
var other = (AValueObject)obj;
return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents());
}
public static bool operator ==(AValueObject one, AValueObject two)
{
return EqualOperator(one, two);
}
public static bool operator !=(AValueObject one, AValueObject two)
{
return NotEqualOperator(one, two);
}
public override int GetHashCode()
{
return GetEqualityComponents()
.Select(x => x != null ? x.GetHashCode() : 0)
.Aggregate((x, y) => x ^ y);
}
public Func<bool> GetValidationFunc() => GetValidationExpression;
public abstract bool GetValidationExpression();
public const string ErrorMessage = "";
public bool IsValid { get; protected set; }
}
}

View File

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Folder Include="Repositories\Contracts\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="4.0.2" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
<PackageReference Include="Serilog.Enrichers.Context" Version="4.6.5" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.Grafana.Loki" Version="8.3.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,10 @@
namespace DIC.Test.Data.Contracts
{
public interface IRepoCommand<T, TId> where T : class
where TId : struct
{
void Add(T entity);
void Update(T entity);
void Delete(T entity);
}
}

View File

@ -0,0 +1,14 @@
using System.Linq.Expressions;
namespace DIC.Test.Data.Contracts
{
public interface IRepoQuery<T, TId> where T : class
where TId : struct
{
public T GetById(TId id);
public IEnumerable<T> GetAll();
public IEnumerable<T> FindAll(Expression<T> expression);
}
}

View File

@ -0,0 +1,8 @@
namespace DIC.Test.Data.Contracts
{
public interface IRepoReadOnly<T, TId> : IRepoQuery<T, TId>
where T : class
where TId : struct
{
}
}

View File

@ -0,0 +1,10 @@
using System.Runtime.InteropServices;
namespace DIC.Test.Data.Contracts
{
public interface IRepository<T, TId> : IRepoCommand<T, TId>, IRepoQuery<T, TId>
where T : class
where TId : struct
{
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseDomain.Results
{
public class Error
{
public enum ErrorTypeEnum
{
None = 0, //Erro vazio (para result)
Failure = 1, //Quando for uma falha que eu queira retornar no lugar de uma Exception
Validation = 2, //Quando for um problema de validação
Others = 3 //Inesperado ou sem categoria
}
public Error(ErrorTypeEnum error, string message, string description="")
{
ErrorType = error;
Message = message;
}
public static Error None => new Error(ErrorTypeEnum.None, string.Empty, string.Empty);
public ErrorTypeEnum ErrorType { get; }
public string Message { get; }
public string Description { get; }
public static implicit operator string(Error error) => error.Message;
//Permitir atribuir um error diretamente ao resultado.
public static implicit operator Result(Error error) => Result.Failure(error);
}
}

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseDomain.Results
{
public class Result
{
protected Result(bool isSuccess, Error error)
{
if (isSuccess && error != Error.None)
{
throw new InvalidOperationException();
}
if (!isSuccess && error == Error.None)
{
throw new InvalidOperationException();
}
this.IsSuccess = isSuccess;
this.Error = error;
}
public bool IsSuccess { get; }
public bool IsFalilure => !IsSuccess;
public Error Error { get; }
public static Result Success() => new(true, Error.None);
public static Result Failure(Error error) => new(false, Error.None);
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseDomain.Results
{
public class Result<TValue> : Result
{
private readonly TValue _value;
protected Result(TValue value, bool isSuccess, Error error) : base(isSuccess, error)
{
_value = value;
}
protected Result(TValue value) : base(true, Error.None)
{
_value = value;
}
public TValue Value => IsSuccess ? _value : throw new InvalidOperationException("O valor náo pode ser processado!");
public static implicit operator Result<TValue>(TValue? value) => Create(value);
public static Result<TValue> Success<TValue>(TValue value) => new(value);
public static Result<TValue> Create(TValue value)
{
return new Result<TValue>(value, true, Error.None);
}
}
}

View File

@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseDomain.SimpleValidator
{
public class ObjectValidatorBuilder<T>
{
/// <summary>
/// model that is validated
/// </summary>
private T model;
private bool isValid;
public ObjectValidatorBuilder(T objectOrEntity)
{
model = objectOrEntity;
}
/// <summary>
/// Check if model meetf all rules
/// </summary>
public ObjectValidatorBuilder<T> Build()
{
//select all ruiles without OnlyIf expression or with satisfied OnlyIf expression
var invalidResults = _rules.Where(m => m.OnlyIf == null || (m.OnlyIf != null && m.OnlyIf(model)));
//select all rules that arent satisfied
invalidResults = invalidResults.Where(m => !m.ValidationExpression(model));
//set error messages of unsatisfied rules
ErrorMessages = invalidResults.Select(m => m.ErrorMessage).ToList();
isValid =!invalidResults.Any();
return this;
}
public bool IsValid()
{
return isValid;
}
public void ThrowErrorMessages()
{
if (!isValid) throw new ArgumentException(this.ErrorMessagesAsString());
}
public string ErrorMessagesAsString()
{
return String.Join("\n", this.ErrorMessages);
}
/// <summary>
/// Get error messages for rules that are not satisfied
/// </summary>
public List<string> ErrorMessages { get; set; }
/// <summary>
/// List of rules that are specified for model
/// </summary>
private readonly List<ValidationRule<T>> _rules = new List<ValidationRule<T>>();
public ObjectValidatorBuilder<T> AddRule(Func<T, bool> validationExpression, Func<T, bool> onlyIf, String errorMessage)
{
_rules.Add(new ValidationRule<T>()
{
ValidationExpression = validationExpression,
OnlyIf = onlyIf,
ErrorMessage = errorMessage
});
return this;
}
public ObjectValidatorBuilder<T> AddRule(Func<T, bool> validationExpression, String errorMessage)
{
AddRule(validationExpression, null, errorMessage);
return this;
}
public ObjectValidatorBuilder<T> AddRule(AValueObject valueObject)
{
AddRule((valueObject) => (valueObject as AValueObject).GetValidationExpression(), null, AValueObject.ErrorMessage);
return this;
}
public ObjectValidatorBuilder<T> AddRule(ValidationRule<T> rule)
{
AddRule(rule);
return this;
}
public void ClearRules()
{
_rules.Clear();
}
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseDomain.SimpleValidator
{
public class ValidationRule<T>
{
public ValidationRule()
{
}
public ValidationRule(Func<T, bool> validationExpression, Func<T, bool> onlyIf, String errorMessage)
{
ValidationExpression = validationExpression;
OnlyIf = onlyIf;
ErrorMessage = errorMessage;
}
public ValidationRule(Func<T, bool> validationExpression, String errorMessage)
{
ValidationExpression = validationExpression;
ErrorMessage = errorMessage;
}
/// <summary>
/// Validation rule expression, examp. check is string null or empty !string.IsNullOrEmpty(o.Name)
/// </summary>
public Func<T, bool> ValidationExpression { get; set; }
/// <summary>
/// You can specify OnlyIf expression, if this expresion is specified than ValidationExpression is going to be evaluated only if OnlyIf rule is satisfied
/// </summary>
public Func<T, bool> OnlyIf { get; set; }
/// <summary>
/// Specify error message that will be returned if rule is not satisifed
/// </summary>
public string ErrorMessage { get; set; }
}
}

43
MVCPostall.sln Normal file
View File

@ -0,0 +1,43 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.7.34031.279
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Postall", "Postall\Postall.csproj", "{2913C42A-071B-483D-8004-1D9B4E10557E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Postall.Infra", "Postall.Infra\Postall.Infra.csproj", "{6CEE683B-CEC7-42EC-AB67-CFA124DDB8FD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Postall.Domain", "Postall.Domain\Postall.Domain.csproj", "{373B1329-C49C-4F24-B67F-2F977225160A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BaseDomain", "BaseDomain\BaseDomain.csproj", "{72324CE0-8009-4876-9CF9-9F2BA8288B87}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2913C42A-071B-483D-8004-1D9B4E10557E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2913C42A-071B-483D-8004-1D9B4E10557E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2913C42A-071B-483D-8004-1D9B4E10557E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2913C42A-071B-483D-8004-1D9B4E10557E}.Release|Any CPU.Build.0 = Release|Any CPU
{6CEE683B-CEC7-42EC-AB67-CFA124DDB8FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6CEE683B-CEC7-42EC-AB67-CFA124DDB8FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6CEE683B-CEC7-42EC-AB67-CFA124DDB8FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6CEE683B-CEC7-42EC-AB67-CFA124DDB8FD}.Release|Any CPU.Build.0 = Release|Any CPU
{373B1329-C49C-4F24-B67F-2F977225160A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{373B1329-C49C-4F24-B67F-2F977225160A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{373B1329-C49C-4F24-B67F-2F977225160A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{373B1329-C49C-4F24-B67F-2F977225160A}.Release|Any CPU.Build.0 = Release|Any CPU
{72324CE0-8009-4876-9CF9-9F2BA8288B87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{72324CE0-8009-4876-9CF9-9F2BA8288B87}.Debug|Any CPU.Build.0 = Debug|Any CPU
{72324CE0-8009-4876-9CF9-9F2BA8288B87}.Release|Any CPU.ActiveCfg = Release|Any CPU
{72324CE0-8009-4876-9CF9-9F2BA8288B87}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EC4AB36F-49CB-4819-ACA4-3A14CB1D9B50}
EndGlobalSection
EndGlobal

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace Blinks.Controllers namespace Postall.Controllers
{ {
public class CartHomeController : Controller public class CartHomeController : Controller
{ {

View File

@ -2,7 +2,7 @@
using System.Diagnostics; using System.Diagnostics;
using Blinks.Models; using Blinks.Models;
namespace Blinks.Controllers namespace Postall.Controllers
{ {
public class HomeController : Controller public class HomeController : Controller
{ {

View File

@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Globalization; using System.Globalization;
namespace Blinks.Controllers namespace Postall.Controllers
{ {
public class LanguageController : Controller public class LanguageController : Controller
{ {

View File

@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Stripe; using Stripe;
namespace Blinks.Controllers namespace Postall.Controllers
{ {
public class LoginController : Controller public class LoginController : Controller
{ {
@ -38,9 +38,10 @@ namespace Blinks.Controllers
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public ActionResult ExternalLoginGoogle(string provider, string returnUrl) public ActionResult ExternalLoginGoogle(string provider, string returnUrl)
{ {
var redirectUrl = Url.Action("ExternalLoginCallback", "Login", new { ReturnUrl = returnUrl }); var redirectUrl = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}{Url.Action("ExternalLoginCallback", "Login")}";
var properties = new AuthenticationProperties { RedirectUri = "http://localhost:5094" + redirectUrl }; //var properties = new AuthenticationProperties { RedirectUri = "https://localhost:7078" + redirectUrl };
return Challenge(properties, "Google"); var properties = new AuthenticationProperties { RedirectUri = redirectUrl };
return Challenge(properties, "Google");
} }
[AllowAnonymous] [AllowAnonymous]

View File

@ -0,0 +1,52 @@
// AccountController.cs
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Facebook;
using Microsoft.AspNetCore.Mvc;
namespace Postall.Controllers
{
public class OtherLoginsController : Controller
{
[HttpGet]
public IActionResult Index()
{
return View();
}
[HttpGet]
public IActionResult FacebookLogin()
{
var properties = new AuthenticationProperties { RedirectUri = Url.Action("FacebookResponse") };
return Challenge(properties, FacebookDefaults.AuthenticationScheme);
}
[HttpGet]
public async Task<IActionResult> FacebookResponse()
{
var result = await HttpContext.AuthenticateAsync(FacebookDefaults.AuthenticationScheme);
if (!result.Succeeded)
return RedirectToAction("Login");
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
return RedirectToAction("Index", "Home");
}
[HttpPost]
public IActionResult Logout()
{
return SignOut("Cookies", FacebookDefaults.AuthenticationScheme);
}
}
}

View File

@ -2,7 +2,7 @@
using Stripe; using Stripe;
using Stripe.Checkout; using Stripe.Checkout;
namespace Blinks.Controllers namespace Postall.Controllers
{ {
[Route("Pay")] [Route("Pay")]
public class PayController : Controller public class PayController : Controller

View File

@ -4,7 +4,7 @@ using Stripe;
using Stripe.Checkout; using Stripe.Checkout;
using Blinks.Models; using Blinks.Models;
namespace Blinks.Controllers namespace Postall.Controllers
{ {
public class PlansController : Controller public class PlansController : Controller
{ {

View File

@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Diagnostics; using System.Diagnostics;
namespace Blinks.Controllers namespace Postall.Controllers
{ {
[Route("signin-microsoft")] [Route("signin-microsoft")]
public class SignInController : Controller public class SignInController : Controller

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace Blinks.Controllers namespace Postall.Controllers
{ {
public class StartupController : Controller public class StartupController : Controller
{ {

View File

@ -10,6 +10,14 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="Views\CartHome\**" />
<Content Remove="Views\CartHome\**" />
<EmbeddedResource Remove="Views\CartHome\**" />
<None Remove="Views\CartHome\**" />
</ItemGroup>
<ItemGroup>
<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" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="8.0.7" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="8.0.7" />
<PackageReference Include="Serilog" Version="4.0.2" /> <PackageReference Include="Serilog" Version="4.0.2" />
@ -21,7 +29,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Views\CartHome\" />
<Folder Include="wwwroot\img\" /> <Folder Include="wwwroot\img\" />
</ItemGroup> </ItemGroup>

View File

@ -1,7 +1,6 @@
using Blinks.LogConfig; using Blinks.LogConfig;
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.Google; using Microsoft.AspNetCore.Authentication.Google;
using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -43,7 +42,6 @@ options =>
{ {
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = MicrosoftAccountDefaults.AuthenticationScheme;
}) })
.AddCookie(options => .AddCookie(options =>
{ {
@ -53,15 +51,15 @@ options =>
}) })
.AddGoogle(googleOptions => .AddGoogle(googleOptions =>
{ {
googleOptions.ClientId = config["Authentication:Google:ClientId"]; googleOptions.ClientId = builder.Configuration.GetSection("Authentication:Google:AppId").Value;
googleOptions.ClientSecret = config["Authentication:Google:ClientSecret"]; googleOptions.ClientSecret = builder.Configuration.GetSection("Authentication:Google:AppSecret").Value;
googleOptions.CallbackPath = "/signin-google";
}) })
.AddMicrosoftAccount(microsoftOptions => .AddFacebook(options =>
{ {
microsoftOptions.ClientId = config["Authentication:Microsoft:ClientId"]; options.AppId = builder.Configuration.GetSection("Authentication:Facebook:AppId").Value;
//microsoftOptions.ClientSecret = "2a7cb1bd-037a-49fa-9e5e-2b2655431af9"; options.AppSecret = builder.Configuration.GetSection("Authentication:Facebook:AppSecret").Value;
microsoftOptions.ClientSecret = config["Authentication:Microsoft:ClientSecret"]; });
})
; ;
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");

View File

@ -39,7 +39,7 @@ namespace Blinks {
public static global::System.Resources.ResourceManager ResourceManager { public static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Blinks.Resource", typeof(Resource).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Postall.Resource", typeof(Resource).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;

View File

@ -0,0 +1,16 @@
@{
ViewData["Title"] = "Site";
}
<div class="text-center">
<h1 class="display-4">Login</h1>
<div class="row justify-content-center">
<div class="col-md-4">
<form asp-action="FacebookLogin" method="get">
<button type="submit" class="btn btn-primary btn-block">
<i class="fab fa-facebook"></i> Login com Facebook
</button>
</form>
</div>
</div>
</div>

View File

@ -5,11 +5,11 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Blinks</title> <title>@ViewData["Title"] - PostAll</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" /> <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/Blinks.styles.css" asp-append-version="true" /> <link rel="stylesheet" href="~/Postall.styles.css" asp-append-version="true" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
@await RenderSectionAsync("Styles", required: false) @await RenderSectionAsync("Styles", required: false)
</head> </head>
@ -17,7 +17,7 @@
<partial name="_Busy" /> <partial name="_Busy" />
<div id="wrapper"> <div id="wrapper">
<nav id="nav-bar" class="navbar navbar-expand-lg navbar-dark"> <nav id="nav-bar" class="navbar navbar-expand-lg navbar-dark">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Blinks</a> <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">PostAll</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
@ -44,11 +44,16 @@
} }
else else
{ {
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link text-white" asp-area="" asp-controller="OtherLogins" asp-action="Index">Sites</a>
</li>
</ul>
<ul class="navbar-nav ml-auto"> <ul class="navbar-nav ml-auto">
<partial name="_Language"/> <partial name="_Language"/>
<li class="nav-item dropdown" style="margin-right: 10px"> <li class="nav-item dropdown" style="margin-right: 10px">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="bi bi-person"></i> @(User.FindFirst("FullName")!=null ? User.FindFirst("FullName").Value : "N/A") <i class="bi bi-person"></i> @(User.FindFirst("FullName") != null ? User.FindFirst("FullName").Value : "N/A")
</a> </a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown"> <div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" asp-area="" asp-controller="Login" asp-action="Logout">Sair</a> <a class="dropdown-item" asp-area="" asp-controller="Login" asp-action="Logout">Sair</a>
@ -80,7 +85,7 @@
<footer class="border-top footer text-muted"> <footer class="border-top footer text-muted">
<div class="container"> <div class="container">
&copy; 2024 - Blinks - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a> &copy; 2024 - PostAll - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</div> </div>
</footer> </footer>
</div> </div>
@ -124,6 +129,9 @@
$(document).ready(function () { $(document).ready(function () {
$('#wrapper').fadeIn('slow'); $('#wrapper').fadeIn('slow');
$('a.nav-link').click(function () { $('a.nav-link').click(function () {
if ($(this).hasClass('dropdown-toggle')) {
return;
}
$('#wrapper').fadeOut('slow'); $('#wrapper').fadeOut('slow');
}); });
setActiveByLocation(); setActiveByLocation();

View File

@ -11,5 +11,15 @@
"Stripe": { "Stripe": {
"SecretKey": "sua_secret_key_aqui", "SecretKey": "sua_secret_key_aqui",
"PublishableKey": "sua_publishable_key_aqui" "PublishableKey": "sua_publishable_key_aqui"
},
"Authentication": {
"Google": {
"AppId": "497040298141-0b44r4nod12igc34hv2chfd7ut0kbog6.apps.googleusercontent.com",
"AppSecret": "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"
},
"Facebook": {
"AppId": "seu_app_id_aqui",
"AppSecret": "seu_app_secret_aqui"
}
} }
} }

View File

Before

Width:  |  Height:  |  Size: 476 B

After

Width:  |  Height:  |  Size: 476 B

View File

Before

Width:  |  Height:  |  Size: 507 B

After

Width:  |  Height:  |  Size: 507 B

View File

Before

Width:  |  Height:  |  Size: 514 B

After

Width:  |  Height:  |  Size: 514 B

View File

Before

Width:  |  Height:  |  Size: 579 B

After

Width:  |  Height:  |  Size: 579 B

View File

Before

Width:  |  Height:  |  Size: 250 B

After

Width:  |  Height:  |  Size: 250 B

View File

Before

Width:  |  Height:  |  Size: 279 B

After

Width:  |  Height:  |  Size: 279 B

View File

Before

Width:  |  Height:  |  Size: 286 B

After

Width:  |  Height:  |  Size: 286 B

View File

Before

Width:  |  Height:  |  Size: 366 B

After

Width:  |  Height:  |  Size: 366 B

View File

Before

Width:  |  Height:  |  Size: 854 B

After

Width:  |  Height:  |  Size: 854 B

View File

Before

Width:  |  Height:  |  Size: 457 B

After

Width:  |  Height:  |  Size: 457 B

View File

Before

Width:  |  Height:  |  Size: 477 B

After

Width:  |  Height:  |  Size: 477 B

View File

Before

Width:  |  Height:  |  Size: 484 B

After

Width:  |  Height:  |  Size: 484 B

View File

Before

Width:  |  Height:  |  Size: 564 B

After

Width:  |  Height:  |  Size: 564 B

View File

Before

Width:  |  Height:  |  Size: 607 B

After

Width:  |  Height:  |  Size: 607 B

View File

Before

Width:  |  Height:  |  Size: 642 B

After

Width:  |  Height:  |  Size: 642 B

View File

Before

Width:  |  Height:  |  Size: 634 B

After

Width:  |  Height:  |  Size: 634 B

View File

Before

Width:  |  Height:  |  Size: 714 B

After

Width:  |  Height:  |  Size: 714 B

Some files were not shown because too many files have changed in this diff Show More