fix: diversos ajustes para deixar funcional

This commit is contained in:
Ricardo Carneiro 2025-04-20 23:33:46 -03:00
parent 2e64ee836f
commit 7b3c63ff37
64 changed files with 1212 additions and 202 deletions

View File

@ -0,0 +1,19 @@
using SumaTube.Infra.MongoDB.Documents;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SumaTube.Infra.Contracts.Repositories.UserPlan
{
public interface IPersonUserRepository
{
Task<PersonUserDocument> GetByIdAsync(string id);
Task<PersonUserDocument> GetByEmailAsync(string email);
Task<IEnumerable<PersonUserDocument>> GetAllAsync();
Task CreateAsync(PersonUserDocument PersonUserDocument);
Task UpdateAsync(PersonUserDocument PersonUserDocument);
Task DeleteAsync(string id);
}
}

View File

@ -0,0 +1,43 @@
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SumaTube.Infra.MongoDB.Documents
{
public class PersonUserDocument
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public string Username { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public DateTime LastChanged { get; set; }
public bool IsActive { get; set; }
public bool IsProfileCompleted { get; set; }
public int CountryId { get; set; }
public int BusinessAreaId { get; set; }
public string DesiredName { get; set; }
public DateTime CreatedAt { get; set; }
public UserPaymentDocument CurrentPlan { get; set; }
public List<UserPaymentDocument> PastPlans { get; set; } = new List<UserPaymentDocument>();
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SumaTube.Infra.MongoDB.Documents
{
public class UserPaymentDocument
{
public string Id { get; set; }
public string Name { get; set; }
public decimal Value { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public bool IsActive { get; set; }
}
}

View File

@ -0,0 +1,19 @@
using SumaTube.Domain.Entities.UserPlan;
using SumaTube.Infra.MongoDB.Documents;
using SumaTube.Crosscutting.Mappers;
namespace SumaTube.Infra.MongoDB.Mappers.UserPlan
{
public static class PersonUserMapper
{
public static PersonUserDocument ToDocument(this PersonUser entity)
{
return entity.MapTo<PersonUser, PersonUserDocument>();
}
public static PersonUser ToDomain(this PersonUserDocument document)
{
return document.MapTo<PersonUserDocument, PersonUser>();
}
}
}

View File

@ -0,0 +1,76 @@
using SumaTube.Infra.MongoDB;
using MongoDB.Bson.Serialization.Conventions;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Bson.Serialization.IdGenerators;
using MongoDB.Bson;
using SumaTube.Domain;
using SumaTube.Domain.Entities.UserPlan;
namespace SumaTube.Infra.MongoDB
{
public static class MongoConfig
{
public static void Configure()
{
var conventionPack = new ConventionPack { new IgnoreIfNullConvention(true) };
ConventionRegistry.Register("IgnoreIfNull", conventionPack, t => true);
if (!BsonClassMap.IsClassMapRegistered(typeof(PersonUser)))
{
BsonClassMap.RegisterClassMap<PersonUser>(cm =>
{
cm.MapIdProperty(p => p.Id)
.SetSerializer(new StringSerializer(BsonType.ObjectId))
.SetIdGenerator(StringObjectIdGenerator.Instance);
cm.MapProperty(p => p.Username);
cm.MapProperty(p => p.Name);
cm.MapProperty(p => p.Email);
cm.MapProperty(p => p.DateChanged);
cm.MapProperty(p => p.IsProfileCompleted);
cm.MapProperty(p => p.CountryId);
cm.MapProperty(p => p.BusinessAreaId);
cm.MapProperty(p => p.DesiredName);
cm.MapProperty(p => p.CreatedAt);
cm.MapProperty(p => p.Plano);
cm.MapProperty(p => p.PastPlans);
cm.MapCreator(p => new PersonUser(
p.Id.Value,
p.Username,
p.Name,
p.Email,
p.DateChanged,
p.IsProfileCompleted,
p.CountryId,
p.BusinessAreaId,
p.DesiredName,
p.CreatedAt,
p.Plano,
p.PastPlans
));
cm.AutoMap();
});
}
// Configure também as classes ValueObject se necessário
ConfigureValueObjects();
}
private static void ConfigureValueObjects()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(Name)))
{
BsonClassMap.RegisterClassMap<Name>(cm =>
{
cm.AutoMap();
cm.MapCreator(n => new Name(n.FirstName, n.LastName));
});
}
// Adicione mapeamento para outros value objects conforme necessário
}
}
}

View File

@ -4,8 +4,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MongoDB.Driver;
using SumaTube.Domain.Entities.UserPlan;
namespace Blinks.Infra.MongoDB
namespace SumaTube.Infra.MongoDB
{
public class MongoDbContext
{

View File

@ -0,0 +1,40 @@
using MongoDB.Driver;
using SumaTube.Infra.MongoDB.Documents;
namespace SumaTube.Infra.MongoDB.Repositories
{
public class PersonUserRepository
{
private readonly IMongoCollection<PersonUserDocument> _collection;
public PersonUserRepository(IMongoDatabase database)
{
_collection = database.GetCollection<PersonUserDocument>("PersonUsers");
}
public async Task<PersonUserDocument> GetByIdAsync(string id)
{
return await _collection.Find(p => p.Id == id).FirstOrDefaultAsync();
}
public async Task<IEnumerable<PersonUserDocument>> GetAllAsync()
{
return await _collection.Find(_ => true).ToListAsync();
}
public async Task CreateAsync(PersonUserDocument PersonUserDocument)
{
await _collection.InsertOneAsync(PersonUserDocument);
}
public async Task UpdateAsync(PersonUserDocument PersonUserDocument)
{
await _collection.ReplaceOneAsync(p => p.Id == PersonUserDocument.Id, PersonUserDocument);
}
public async Task DeleteAsync(string id)
{
await _collection.DeleteOneAsync(p => p.Id == id);
}
}
}

View File

@ -1,10 +1,10 @@
using global::MongoDB.Bson.Serialization.Attributes;
using global::MongoDB.Bson;
namespace Blinks.Infra.MongoDB
namespace SumaTube.Infra.MongoDB
{
public class PersonUser
public class UserPerson
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]

View File

@ -9,11 +9,21 @@
<ItemGroup>
<PackageReference Include="MongoDB.Bson" Version="2.28.0" />
<PackageReference Include="MongoDB.Driver" Version="2.28.0" />
<PackageReference Include="Serilog" Version="4.0.2" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
<PackageReference Include="RabbitMQ.Client" Version="7.1.2" />
<PackageReference Include="Serilog" Version="4.2.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<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>
<ItemGroup>
<ProjectReference Include="..\SumaTube.Crosscutting\SumaTube.Crosscutting.csproj" />
<ProjectReference Include="..\SumaTube.Domain\SumaTube.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Stripe\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SumaTube.Infra.VideoSumarizer.Videos
{
public class VideoProcessingMessageDocument
{
public VideoProcessingMessageDocument(string sessionId, string url, string language)
{
SessionId = sessionId;
Url = url;
Language = language;
}
public string SessionId { get; private set; }
public string Url { get; private set; }
public string Language { get; private set; }
}
}

View File

@ -0,0 +1,87 @@
using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace SumaTube.Infra.VideoSumarizer.Videos
{
public class VideoSumarizerService
{
private static string _hostName = Environment.GetEnvironmentVariable("RABBITMQ_HOST") ?? "localhost";
private static string _userName = Environment.GetEnvironmentVariable("RABBITMQ_USER") ?? "guest";
private static string _password = Environment.GetEnvironmentVariable("RABBITMQ_PASSWORD") ?? "guest";
private static string _queueName = "video-processing-queue";
public async Task RequestVideoSummarization(string sessionId, string url, string language)
{
Console.WriteLine("### Video Processor Publisher ###");
Console.WriteLine($"Conectando ao RabbitMQ em {_hostName}...");
try
{
var factory = new ConnectionFactory()
{
HostName = _hostName,
UserName = _userName,
Password = _password
};
using (var connection = await factory.CreateConnectionAsync())
using (var channel = await connection.CreateChannelAsync())
{
await channel.QueueDeclareAsync(
queue: _queueName,
durable: true,
exclusive: false,
autoDelete: false,
arguments: null);
var properties = new BasicProperties
{
Persistent = true
};
Console.WriteLine("Conexão estabelecida com RabbitMQ");
Console.WriteLine("Pressione 'Ctrl+C' para sair");
// Loop para publicar mensagens
while (true)
{
if (string.IsNullOrWhiteSpace(language))
language = "pt";
// Criar objeto de mensagem
var message = new VideoProcessingMessageDocument(
sessionId,
url,
language);
// Serializar para JSON
var messageJson = JsonSerializer.Serialize(message);
var body = Encoding.UTF8.GetBytes(messageJson);
// Publicar mensagem
await channel.BasicPublishAsync(exchange: string.Empty,
routingKey: _queueName,
mandatory: true,
basicProperties: properties,
body: body);
Console.WriteLine($"[x] Mensagem enviada: {messageJson}");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Erro: {ex.Message}");
Console.WriteLine(ex.StackTrace);
}
Console.WriteLine("Publicador finalizado.");
Console.ReadLine();
}
}
}

View File

@ -0,0 +1,116 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog.Events;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Serilog.Extensions.Hosting;
using Microsoft.AspNetCore.Builder;
namespace SumaTube.Crosscutting.Logging.Configuration
{
public static class SerilogConfiguration
{
public static LoggerConfiguration SetLoggerConfiguration(this WebApplicationBuilder builder, LoggerConfiguration config, IServiceProvider services, IConfiguration configuration)
{
var workspace = configuration["Serilog:Properties:Workspace"];
var seqServer = configuration.GetValue<string>("Serilog:WriteTo:2:Args:serverUrl"); ;
config
.ReadFrom.Configuration(configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext()
.Enrich.WithEnvironmentName()
.Enrich.WithMachineName()
.Enrich.WithProperty("Application", "SumaTube")
.Enrich.WithProperty("Workspace", workspace)
.WriteTo.Seq(seqServer)
;
return config;
}
public static IServiceCollection AddSerilogServices(this IServiceCollection services, IConfiguration configuration, IHostEnvironment environment)
{
// Obtenha o workspace do Seq baseado no ambiente
//var workspace = environment.IsDevelopment() ? "Dev" : "Prod";
services.AddSingleton<DiagnosticContext>();
var workspace = configuration["Serilog:Properties:Workspace"];
// Crie o logger usando a configuração
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.Enrich.WithEnvironmentName()
//.Enrich.WithProperty("Workspace", workspace) // Adiciona explicitamente o workspace
.CreateLogger();
// Registra o logger no container de DI
services.AddSingleton(Log.Logger);
return services;
}
// Método opcional para configuração direta sem usar appsettings.json
public static IServiceCollection AddSerilogServicesWithCode(
this IServiceCollection services,
IHostEnvironment environment)
{
services.AddSingleton<DiagnosticContext>();
// Defina as configurações do Seq baseado no ambiente
var (workspace, apiKey) = environment.IsDevelopment()
? ("Dev", "sua-api-key-dev")
: ("Prod", "sua-api-key-prod");
// Configuração básica para ambos ambientes
var loggerConfig = new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.Enrich.WithEnvironmentUserName()
.Enrich.WithThreadId()
.Enrich.WithProperty("Application", "SumaTube")
.Enrich.WithProperty("Environment", environment.EnvironmentName)
.Enrich.WithProperty("Workspace", workspace);
// Adicione destinos específicos por ambiente
if (environment.IsDevelopment())
{
loggerConfig
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.WriteTo.Console()
.WriteTo.File("logs/dev-app-.log", rollingInterval: RollingInterval.Day);
}
else // Produção ou outros ambientes
{
loggerConfig
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("System", LogEventLevel.Error)
.WriteTo.File("logs/prod-app-.log", rollingInterval: RollingInterval.Day);
}
// Adicione o Seq para ambos ambientes, mas com configurações diferentes
//loggerConfig.WriteTo.Seq(
// "http://logs-ingest.carneiro.ddnsfree.com",
// apiKey: apiKey);
loggerConfig.WriteTo.Seq(
"http://logs.carneiro.ddnsfree.com:5341");
Log.Logger = loggerConfig.CreateLogger();
// Registra o logger no container de DI
services.AddSingleton(Log.Logger);
return services;
}
}
}

View File

@ -0,0 +1,28 @@
using Microsoft.Extensions.Logging;
namespace SumaTube.Crosscutting.Logging.Extensions
{
public static class LoggerExtensions
{
public static void LogMethodEntry<T>(this ILogger<T> logger, string methodName, params object[] parameters)
{
logger.LogInformation("Entering method {MethodName} with parameters {@Parameters}", methodName, parameters);
}
public static void LogMethodExit<T>(this ILogger<T> logger, string methodName, object result = null)
{
logger.LogInformation("Exiting method {MethodName} with result {@Result}", methodName, result);
}
public static void LogException<T>(this ILogger<T> logger, Exception exception, string message = null)
{
logger.LogError(exception, message ?? "An error occurred: {ErrorMessage}", exception.Message);
}
public static void LogPerformance<T>(this ILogger<T> logger, string operation, long elapsedMilliseconds)
{
logger.LogInformation("Performance: {Operation} took {ElapsedMilliseconds} ms", operation, elapsedMilliseconds);
}
}
}

View File

@ -0,0 +1,254 @@
namespace SumaTube.Crosscutting.Mappers
{
using System;
using System.Linq;
using System.Reflection;
public static class GenericMapper
{
public static TDestination MapTo<TSource, TDestination>(this TSource source)
where TDestination : class
{
if (source == null)
return default;
var destType = typeof(TDestination);
// Verifica se o tipo de destino tem um construtor público
var constructors = destType.GetConstructors(BindingFlags.Public | BindingFlags.Instance)
.OrderByDescending(c => c.GetParameters().Length)
.ToList();
// Se o tipo de destino tem um construtor com parâmetros, tenta mapear para ele
if (constructors.Any() && constructors[0].GetParameters().Length > 0)
{
return MapToImmutableObject<TSource, TDestination>(source, constructors);
}
// Caso contrário, usa a abordagem de mapeamento de propriedades para objetos mutáveis
else
{
return MapToMutableObject<TSource, TDestination>(source);
}
}
private static TDestination MapToImmutableObject<TSource, TDestination>(TSource source, List<ConstructorInfo> constructors)
where TDestination : class
{
var sourceType = typeof(TSource);
var sourceProps = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
// Tenta cada construtor, começando pelo que tem mais parâmetros
foreach (var constructor in constructors)
{
var parameters = constructor.GetParameters();
if (parameters.Length == 0)
{
// Construtor sem parâmetros, cria instância diretamente
var instance = constructor.Invoke(null);
return (TDestination)instance;
}
var parameterValues = new object[parameters.Length];
bool canUseConstructor = true;
// Tenta mapear os parâmetros do construtor
for (int i = 0; i < parameters.Length; i++)
{
var param = parameters[i];
// Procura propriedade com o mesmo nome (case insensitive)
var matchingProp = sourceProps.FirstOrDefault(p =>
string.Equals(p.Name, param.Name, StringComparison.OrdinalIgnoreCase));
if (matchingProp != null)
{
var value = matchingProp.GetValue(source);
// Se os tipos são compatíveis, usa o valor diretamente
if (param.ParameterType.IsAssignableFrom(matchingProp.PropertyType))
{
parameterValues[i] = value;
}
// Verifica se existe uma conversão implícita
else if (value != null && TryImplicitConversion(value, param.ParameterType, out var convertedValue))
{
parameterValues[i] = convertedValue;
}
// Se o valor é um tipo complexo, tenta mapear recursivamente
else if (value != null && !matchingProp.PropertyType.IsPrimitive &&
!matchingProp.PropertyType.Namespace.StartsWith("System"))
{
try
{
var method = typeof(GenericMapper).GetMethod(nameof(MapTo));
var genericMethod = method.MakeGenericMethod(matchingProp.PropertyType, param.ParameterType);
parameterValues[i] = genericMethod.Invoke(null, new[] { value });
}
catch
{
canUseConstructor = false;
break;
}
}
else
{
canUseConstructor = false;
break;
}
}
else
{
// Se não encontrou uma propriedade correspondente, verifica se o parâmetro é opcional
if (param.IsOptional)
{
parameterValues[i] = param.DefaultValue;
}
else
{
canUseConstructor = false;
break;
}
}
}
if (canUseConstructor)
{
try
{
var instance = constructor.Invoke(parameterValues);
return (TDestination)instance;
}
catch
{
// Se falhou ao criar a instância, tenta o próximo construtor
continue;
}
}
}
// Se não conseguiu usar nenhum construtor, lança exceção
throw new InvalidOperationException(
$"Não foi possível mapear {sourceType.Name} para {typeof(TDestination).Name} " +
$"usando os construtores disponíveis. Verifique se os nomes das propriedades " +
$"correspondem aos nomes dos parâmetros do construtor (case insensitive).");
}
private static TDestination MapToMutableObject<TSource, TDestination>(TSource source)
where TDestination : class
{
var destType = typeof(TDestination);
// Tenta criar uma instância usando o construtor sem parâmetros
TDestination destination;
try
{
destination = Activator.CreateInstance<TDestination>();
}
catch (Exception ex)
{
throw new InvalidOperationException(
$"Não foi possível criar uma instância de {destType.Name}. " +
$"Certifique-se de que a classe tenha um construtor sem parâmetros acessível.", ex);
}
var sourceType = typeof(TSource);
var sourceProps = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
var destProps = destType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty);
foreach (var destProp in destProps)
{
if (!destProp.CanWrite)
continue;
// Procura propriedade com o mesmo nome (case insensitive)
var sourceProp = sourceProps.FirstOrDefault(p =>
string.Equals(p.Name, destProp.Name, StringComparison.OrdinalIgnoreCase));
if (sourceProp != null)
{
var value = sourceProp.GetValue(source);
if (value != null)
{
// Se os tipos são compatíveis, atribui diretamente
if (destProp.PropertyType.IsAssignableFrom(sourceProp.PropertyType))
{
destProp.SetValue(destination, value);
}
// Verifica se existe uma conversão implícita
else if (TryImplicitConversion(value, destProp.PropertyType, out var convertedValue))
{
destProp.SetValue(destination, convertedValue);
}
// Se o valor é um tipo complexo, tenta mapear recursivamente
else if (!sourceProp.PropertyType.IsPrimitive &&
!sourceProp.PropertyType.Namespace.StartsWith("System"))
{
try
{
var method = typeof(GenericMapper).GetMethod(nameof(MapTo));
var genericMethod = method.MakeGenericMethod(sourceProp.PropertyType, destProp.PropertyType);
var mappedValue = genericMethod.Invoke(null, new[] { value });
destProp.SetValue(destination, mappedValue);
}
catch
{
// Ignora se não conseguir mapear
}
}
}
}
}
return destination;
}
private static bool TryImplicitConversion(object source, Type destinationType, out object result)
{
result = null;
if (source == null) return false;
var sourceType = source.GetType();
// Verifica operador de conversão implícita no tipo de origem
var methodSource = sourceType.GetMethods(BindingFlags.Public | BindingFlags.Static)
.FirstOrDefault(m =>
m.Name == "op_Implicit" &&
m.ReturnType == destinationType &&
m.GetParameters().Length == 1 &&
m.GetParameters()[0].ParameterType == sourceType);
if (methodSource != null)
{
result = methodSource.Invoke(null, new[] { source });
return true;
}
// Verifica operador de conversão implícita no tipo de destino
var methodDest = destinationType.GetMethods(BindingFlags.Public | BindingFlags.Static)
.FirstOrDefault(m =>
m.Name == "op_Implicit" &&
m.ReturnType == destinationType &&
m.GetParameters().Length == 1 &&
m.GetParameters()[0].ParameterType == sourceType);
if (methodDest != null)
{
result = methodDest.Invoke(null, new[] { source });
return true;
}
// Tenta converter usando Convert.ChangeType
try
{
if (destinationType.IsValueType || destinationType == typeof(string))
{
result = Convert.ChangeType(source, destinationType);
return true;
}
}
catch { }
return false;
}
}
}

View File

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="4.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0" />
</ItemGroup>
</Project>

View File

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Blinks.Domain.Entities
{
public class BusinessAreas
{
public BusinessAreas() { }
public string Name { get; set; }
}
}

View File

@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Blinks.Domain.Entities
{
internal class BusinessAres
{
}
}

View File

@ -1,36 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Blinks.Domain.Entities
{
public class LinkBio
{
/// <summary>
/// Ordem de exibição
/// </summary>
public int OrderNum { get; set; }
/// <summary>
/// Parte customizada do link
/// </summary>
public string UrlData { get; set; }
/// <summary>
/// Parte fixa do link (obter do service links quando cadastrar)
/// </summary>
public string ServiceUrl { get; set; }
/// <summary>
/// Url/caminho do PNG do link
/// </summary>
public string ServiceIcon { get; set; }
/// <summary>
/// Exibir/nao exibir
/// </summary>
public bool IsVisible { get; set; }
}
}

View File

@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Blinks.Domain.Entities
{
public class PageBio
{
public int Id { get; set; }
public string UrlParte1 { get; set; }
public string UrlParte2 { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<LinkBio>? Links { get; set; }
}
}

View File

@ -1,27 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Blinks.Domain.ValueObjects;
namespace Blinks.Domain.Entities
{
public class PersonUser
{
public Id id { get; private set; }
public Username Username { get; private set; }
public Name Name { get; private set; }
public string FirstName => Name.FirstName;
public string LastName => Name.LastName;
public Email Email { get; private set; }
public DateChanged DateChanged { get; private set; }
public bool IsProfileCompleted { get; private set; }
public int CountryId { get; private set; }
public int BusinessAreaId { get; private set; }
public string DesiredName { get; private set; }
public DateTime CreatedAt { get; private set; }
public UserPlan? Plano { get; private set; }
public List<UserPlan>? PastPlans { get; private set; }
}
}

View File

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SumaTube.Domain.ValueObjects;
namespace SumaTube.Domain.Entities.UserPlan
{
public class PersonUser
{
public PersonUser(string id, Username username, Name name, Email email,
DateChanged dateChanged, bool isProfileCompleted, int countryId,
int businessAreaId, string desiredName, DateTime createdAt,
UserPayment plano = null, List<UserPayment> pastPlans = null)
{
Id = id ?? Guid.NewGuid().ToString("N");
Username = username;
Name = name;
Email = email;
DateChanged = dateChanged;
IsProfileCompleted = isProfileCompleted;
CountryId = countryId;
BusinessAreaId = businessAreaId;
DesiredName = desiredName;
CreatedAt = createdAt;
Plano = plano;
PastPlans = pastPlans ?? new List<UserPayment>();
}
public Id Id { get; private set; }
public Username Username { get; private set; }
public Name Name { get; private set; }
public string FirstName => Name.FirstName;
public string LastName => Name.LastName;
public Email Email { get; private set; }
public DateChanged DateChanged { get; private set; }
public bool IsProfileCompleted { get; private set; }
public int CountryId { get; private set; }
public int BusinessAreaId { get; private set; }
public string DesiredName { get; private set; }
public DateTime CreatedAt { get; private set; }
public UserPayment? Plano { get; private set; }
public List<UserPayment>? PastPlans { get; private set; }
public PersonUser AddPlano(UserPayment plano)
{
if (plano == null) throw new ArgumentNullException(nameof(plano));
PastPlans.Add(plano);
return this;
}
}
}

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Blinks.Domain.Entities
namespace SumaTube.Domain.Entities.UserPlan.UserPlan
{
public class ServiceLinkPart
{

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Blinks.Domain.Entities
namespace SumaTube.Domain.Entities.UserPlan.UserPlan
{
/// <summary>
/// Vai ler uma lista estatica do BD com os links dos serviços

View File

@ -4,9 +4,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Blinks.Domain.Entities
namespace SumaTube.Domain.Entities.UserPlan
{
public class UserPlan
public class UserPayment
{
public int Id { get; set; }
public string Name { get; set; }

View File

@ -0,0 +1,48 @@
using BaseDomain.Results;
using SumaTube.Domain.ValueObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SumaTube.Domain.Entities.Videos
{
public class UserVideo
{
public Id Id { get; private set; }
public string Name { get; private set; }
public List<VideoGroup> VideoGroups { get; private set; } = new List<VideoGroup>();
public UserVideo(int userId, string name)
{
this.Id = Guid.NewGuid();
this.Name = name;
}
public Result<bool> AddVideoGroup(string name, string description)
{
if (!VideoGroups.Any(v => v.Name == name))
{
this.VideoGroups.Add(new VideoGroup(name, description));
return true;
}
return false;
}
public Result<bool> AddVideo(string collectionName, string url)
{
var videoCollectionItem = VideoGroups.Find(v => v.Name == collectionName);
if (videoCollectionItem != null)
{
if (videoCollectionItem.Videos.Any(v => v.Url == url)) return false;
videoCollectionItem.AddVideo(this.Id.Value, url);
return true;
}
return false;
}
public static UserVideo Create(int userId, string name) => new UserVideo(userId, name);
}
}

View File

@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SumaTube.Domain.Entities.Videos
{
public enum VideoSiteEnum
{
Youtube
}
public class VideoData
{
public string SessionId { get; private set; }
public string Title { get; private set; }
public string Image { get; private set; }
public string Url { get; private set; }
public VideoSiteEnum Site { get; private set; }
public VideoResult VideoResult { get; private set; }
public VideoData(string sessionId, string url)
{
SessionId = sessionId;
Url = url;
}
public void SetVideoResult(VideoResult videoResult)
{
VideoResult = videoResult;
}
public void UpdateData(string title, string iamge)
{
Title = title;
Image = iamge;
}
public void ChangeStatus(VideoStatusEnum videoStatus)
{
this.VideoResult.ChangeStatus(videoStatus);
}
}
}

View File

@ -0,0 +1,45 @@
using SumaTube.Domain.ValueObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SumaTube.Domain.Entities.Videos
{
public class VideoGroup
{
public Id Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTime CreatedAt { get; set; }
public List<VideoData> Videos { get; private set; }
public VideoGroup(string name, string description)
{
Id = Guid.NewGuid();
Name = name;
Description = description;
CreatedAt = DateTime.Now;
Videos = new List<VideoData>();
}
public VideoGroup(string id, string name, string description, DateTime createdAt, List<VideoData> videos)
{
Id = id;
Name = name;
Description = description;
CreatedAt = createdAt;
Videos = videos;
}
public void AddVideo(string sessionId, string url)
{
Videos.Add(new VideoData(sessionId, url));
}
}
}

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SumaTube.Domain.Entities.Videos
{
public enum VideoStatusEnum
{
Requested,
Processed,
Error
}
public class VideoResult
{
public string VideoUrl { get; private set; }
public string Summary { get; private set; }
public string ErrorMessage { get; private set; }
public VideoStatusEnum VideoStatus { get; private set; }
public DateTime LastStatusDate { get; private set; }
public void ChangeStatus(VideoStatusEnum status)
{
LastStatusDate = DateTime.Now;
VideoStatus = status;
}
}
}

View File

@ -18,4 +18,9 @@
<ProjectReference Include="..\BaseDomain\BaseDomain.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Contracts\UserPlan\" />
<Folder Include="DomainServices\" />
</ItemGroup>
</Project>

View File

@ -4,7 +4,7 @@ using System.Diagnostics.Metrics;
using System.IO;
using System.Reflection.Emit;
namespace Blinks.Domain
namespace SumaTube.Domain
{
public class DateBirth : AValueObject
{

View File

@ -2,7 +2,7 @@
using BaseDomain;
using System.Globalization;
namespace Blinks.Domain
namespace SumaTube.Domain
{
public class DateChanged : AValueObject
{

View File

@ -1,7 +1,7 @@
using BaseDomain;
using System.Net.Mail;
namespace Blinks.Domain
namespace SumaTube.Domain
{
public class Email : AValueObject
{

View File

@ -1,22 +1,66 @@
using BaseDomain;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Blinks.Domain.ValueObjects
namespace SumaTube.Domain.ValueObjects
{
public class Id : AValueObject
{
private string _value;
public string Value => _value;
public override bool GetValidationExpression()
{
throw new NotImplementedException();
return string.IsNullOrWhiteSpace(_value);
}
protected override IEnumerable<object> GetEqualityComponents()
{
throw new NotImplementedException();
}
public Id(string valor, Guid id)
{
if (string.IsNullOrWhiteSpace(valor))
throw new ArgumentException("O valor não pode ser nulo ou vazio", nameof(valor));
_value = valor;
}
public Id(Guid id)
{
_value = id.ToString("N");
}
private Id(string valor) : this(valor, Guid.NewGuid())
{
}
public static implicit operator Id(string valor)
{
return new Id(valor);
}
public static implicit operator Id(Guid id)
{
return new Id(id);
}
public static explicit operator string(Id vo)
{
return vo.Value.ToString();
}
public static explicit operator Guid(Id vo)
{
return Guid.Parse(vo.Value);
}
}
}

View File

@ -1,6 +1,6 @@
using BaseDomain;
namespace Blinks.Domain
namespace SumaTube.Domain
{
public class Name : AValueObject
{
@ -15,9 +15,15 @@ namespace Blinks.Domain
}
}
public string FullName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Name(string firstName, string lastName)
{
this.FirstName = firstName;
this.LastName = lastName;
}
public string FullName { get; private set; }
public string FirstName { get; private set; }
public string LastName { get; private set; }
public override bool GetValidationExpression()
{

View File

@ -1,7 +1,7 @@
using BaseDomain;
using System.Text.RegularExpressions;
namespace Blinks.Domain
namespace SumaTube.Domain
{
public class Phone : AValueObject
{

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Blinks.Domain.ValueObjects
namespace SumaTube.Domain.ValueObjects
{
public class Username
{

View File

@ -11,6 +11,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SumaTube", "SumaTube\SumaTu
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BaseDomain", "BaseDomain\BaseDomain.csproj", "{8DEA200D-FF43-0D75-15A2-7DA8831449C9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SumaTube.Crosscutting", "SumaTube.Crosscutting\SumaTube.Crosscutting.csproj", "{46EE417D-A974-4011-9799-646F31C9C146}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SumaTube.Application", "..\SumaTube.Application\SumaTube.Application.csproj", "{C598FDC6-26F5-44B2-AB7C-A5471DBE4168}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -33,6 +37,14 @@ Global
{8DEA200D-FF43-0D75-15A2-7DA8831449C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8DEA200D-FF43-0D75-15A2-7DA8831449C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8DEA200D-FF43-0D75-15A2-7DA8831449C9}.Release|Any CPU.Build.0 = Release|Any CPU
{46EE417D-A974-4011-9799-646F31C9C146}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{46EE417D-A974-4011-9799-646F31C9C146}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46EE417D-A974-4011-9799-646F31C9C146}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46EE417D-A974-4011-9799-646F31C9C146}.Release|Any CPU.Build.0 = Release|Any CPU
{C598FDC6-26F5-44B2-AB7C-A5471DBE4168}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C598FDC6-26F5-44B2-AB7C-A5471DBE4168}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C598FDC6-26F5-44B2-AB7C-A5471DBE4168}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C598FDC6-26F5-44B2-AB7C-A5471DBE4168}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

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

View File

@ -1,21 +1,23 @@
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using Blinks.Models;
using SumaTube.Crosscutting.Logging.Extensions;
using SumaTube.Models;
namespace Blinks.Controllers
namespace SumaTube.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> logger;
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
this.logger = logger;
this._logger = logger;
}
public IActionResult Index()
{
this.logger.LogInformation("Home carregada!");
_logger.LogInformation("Home carregada!");
_logger.LogMethodEntry(nameof(Index));
return View();
}

View File

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

View File

@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication;
using Stripe;
namespace Blinks.Controllers
namespace SumaTube.Controllers
{
public class LoginController : Controller
{

View File

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

View File

@ -2,9 +2,9 @@
using Newtonsoft.Json;
using Stripe;
using Stripe.Checkout;
using Blinks.Models;
using SumaTube.Models;
namespace Blinks.Controllers
namespace SumaTube.Controllers
{
public class PlansController : Controller
{

View File

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

View File

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

View File

@ -7,16 +7,16 @@ EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["Blinks.csproj", "."]
RUN dotnet restore "./Blinks.csproj"
COPY ["SumaTube.csproj", "."]
RUN dotnet restore "./SumaTube.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "Blinks.csproj" -c Release -o /app/build
RUN dotnet build "SumaTube.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Blinks.csproj" -c Release -o /app/publish /p:UseAppHost=false
RUN dotnet publish "SumaTube.csproj" -c Release -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Blinks.dll"]
ENTRYPOINT ["dotnet", "SumaTube.dll"]

View File

@ -1,6 +1,6 @@
//using Serilog.Sinks.Loki;
//namespace Blinks.LogConfig
//namespace SumaTube.LogConfig
//{
// public class LogCredentials : LokiCredentials
// {

View File

@ -1,6 +1,6 @@
//using Serilog.Sinks.Loki.Labels;
namespace Blinks.LogConfig
namespace SumaTube.LogConfig
{
//public class LogLabelProvider : ILogLabelProvider
//{
@ -8,7 +8,7 @@ namespace Blinks.LogConfig
// {
// return new List<LokiLabel>
// {
// new LokiLabel("app", "blinks"),
// new LokiLabel("app", "SumaTube"),
// new LokiLabel("namespace", "test")
// };
// }

View File

@ -1,4 +1,4 @@
namespace Blinks.Middle
namespace SumaTube.Middle
{
using Microsoft.AspNetCore.Http;
using System.Globalization;

View File

@ -1,4 +1,4 @@
namespace Blinks.Models
namespace SumaTube.Models
{
public class ChangeViewModel
{

View File

@ -1,4 +1,4 @@
namespace Blinks.Models
namespace SumaTube.Models
{
public class ErrorViewModel
{

View File

@ -1,4 +1,4 @@
namespace Blinks.Models
namespace SumaTube.Models
{
public class Payment
{

View File

@ -32,7 +32,7 @@
},
"projects": [
{
"path": "Blinks.csproj",
"path": "SumaTube.csproj",
"startingProject": true,
"issues": 1,
"storyPoints": 1,
@ -40,7 +40,7 @@
{
"incidentId": "1161414d-b2e4-4447-9d34-e811b563e1c5",
"ruleId": "NuGet.0001",
"projectPath": "Blinks.csproj",
"projectPath": "SumaTube.csproj",
"state": "Active",
"location": {
"snippetModel": {
@ -48,7 +48,7 @@
"protected": "Microsoft.VisualStudio.Azure.Containers.Tools.Targets, 1.19.4\n\nRecommendation:\n\nNo supported version found"
},
"kind": "File",
"path": "Blinks.csproj",
"path": "SumaTube.csproj",
"snippet": "Microsoft.VisualStudio.Azure.Containers.Tools.Targets, 1.19.4\n\nRecommendation:\n\nNo supported version found",
"protectedSnippet": "Microsoft.VisualStudio.Azure.Containers.Tools.Targets, 1.19.4\n\nRecommendation:\n\nNo supported version found",
"label": "Microsoft.VisualStudio.Azure.Containers.Tools.Targets 1.19.4"
@ -57,7 +57,7 @@
]
},
{
"path": "C:\\vscode\\Blinks.me.mvc\\Blinks.Domain\\Blinks.Domain.csproj",
"path": "C:\\vscode\\SumaTube.me.mvc\\SumaTube.Domain\\SumaTube.Domain.csproj",
"startingProject": true,
"issues": 1,
"storyPoints": 1,
@ -65,7 +65,7 @@
{
"incidentId": "2fdd89a6-9f8d-4428-8845-41d048dcaf73",
"ruleId": "Project.0002",
"projectPath": "C:\\vscode\\Blinks.me.mvc\\Blinks.Domain\\Blinks.Domain.csproj",
"projectPath": "C:\\vscode\\SumaTube.me.mvc\\SumaTube.Domain\\SumaTube.Domain.csproj",
"state": "Active",
"location": {
"snippetModel": {
@ -73,7 +73,7 @@
"protected": "Current: net7.0\nNew: net8.0"
},
"kind": "File",
"path": "C:\\vscode\\Blinks.me.mvc\\Blinks.Domain\\Blinks.Domain.csproj",
"path": "C:\\vscode\\SumaTube.me.mvc\\SumaTube.Domain\\SumaTube.Domain.csproj",
"snippet": "Current: net7.0\nNew: net8.0",
"protectedSnippet": "Current: net7.0\nNew: net8.0"
}

View File

@ -1,4 +1,4 @@
using Blinks.LogConfig;
using SumaTube.LogConfig;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.Google;
using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
@ -11,26 +11,14 @@ using Stripe;
using Stripe.Forwarding;
using System.Globalization;
using System.Security.Policy;
using SumaTube.Crosscutting.Logging.Configuration;
var builder = WebApplication.CreateBuilder(args);
//var credentials = new BasicAuthCredentials("http://192.168.0.82:3100");
//var credentials = new LogCredentials("http://192.168.0.82:3100");
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.Enrich.FromLogContext()
.Enrich.WithProperty("app", "blinks")
.WriteTo.Console()
.WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day)
.WriteTo.GrafanaLoki(
uri: "http://192.168.0.82:3100",
propertiesAsLabels: new List<string> { "app", "blinks" },
restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Debug
)
.CreateLogger();
builder.Host.UseSerilog();
builder.Host.UseSerilog((context, services, configuration) =>
{
builder.SetLoggerConfiguration(configuration, services, context.Configuration);
});
// Add services to the container.
builder.Services.AddControllersWithViews();
@ -86,21 +74,29 @@ builder.Services.Configure<RequestLocalizationOptions>(options =>
StripeConfiguration.ApiKey = builder.Configuration["Stripe:SecretKey"];
builder.Services.AddControllersWithViews();
builder.Services.AddHttpClient();
builder.Services.AddSerilog();
var app = builder.Build();
app.UseSerilogRequestLogging(options =>
{
options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
{
diagnosticContext.Set("UserAgent", httpContext.Request.Headers["User-Agent"]);
diagnosticContext.Set("ClientIP", httpContext.Connection.RemoteIpAddress);
diagnosticContext.Set("UserName", httpContext.User?.Identity?.Name ?? "Anonymous");
};
});
var locOptions = app.Services.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(locOptions.Value);
app.UseMiddleware<RequestLocalizationMiddleware>();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
@ -116,8 +112,11 @@ app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.UseSerilogRequestLogging();
app.UseRequestLocalization();
Log.Information("Aplicação iniciando");
Log.Warning("Este é um aviso de teste");
Log.Error("Este é um erro de teste para verificar o Seq");
app.Run();

View File

@ -8,7 +8,7 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace Blinks {
namespace SumaTube {
using System;
@ -39,7 +39,7 @@ namespace Blinks {
public static global::System.Resources.ResourceManager ResourceManager {
get {
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("SumaTube.Resource", typeof(Resource).Assembly);
resourceMan = temp;
}
return resourceMan;

View File

@ -8,7 +8,7 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace Blinks {
namespace SumaTube {
using System;

View File

@ -12,11 +12,16 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="8.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="8.0.7" />
<PackageReference Include="Serilog" Version="4.0.2" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
<PackageReference Include="Serilog" Version="4.2.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Enrichers.Context" Version="4.6.5" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="4.0.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.Grafana.Loki" Version="8.3.0" />
<PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0" />
<PackageReference Include="Stripe.net" Version="45.13.0" />
</ItemGroup>
@ -25,6 +30,10 @@
<Folder Include="wwwroot\img\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SumaTube.Crosscutting\SumaTube.Crosscutting.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Resource.Designer.cs">
<DesignTime>True</DesignTime>

View File

@ -5,7 +5,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Blinks</title>
<title>@ViewData["Title"] - SumaTube</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="~/css/site.css" asp-append-version="true" />
@ -80,7 +80,7 @@
<footer class="border-top footer text-muted">
<div class="container">
&copy; 2024 - Blinks - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
&copy; 2024 - SumaTube - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</div>
</footer>
</div>

View File

@ -11,7 +11,7 @@
<html>
<head>
<title>Blinks</title>
<title>SumaTube</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" integrity="sha384-gfdkjb5BdAXd+lj+gudLWI+BXq4IuLW5IT+brZEZsLFm++aCMlF1V92rMkPaX4PP" crossorigin="anonymous">

View File

@ -1,4 +1,4 @@
@using Blinks
@using SumaTube
@*
For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

View File

@ -1,3 +1,3 @@
@using Blinks
@using Blinks.Models
@using SumaTube
@using SumaTube.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

View File

@ -1,8 +1,28 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
"Serilog": {
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "logs/dev-app-.log",
"rollingInterval": "Day"
}
},
{
"Name": "Seq",
"Args": {
"serverUrl": "http://192.168.0.76:5341",
"compact": true,
"batchPostingLimit": 100
}
}
],
"Properties": {
"Environment": "Development",
"Workspace": "Dev",
"Application": "SumaTube"
}
}
}

View File

@ -0,0 +1,33 @@
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Error" // Note que em produção aumentamos o nível de logs do sistema
}
},
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "logs/prod-app-.log",
"rollingInterval": "Day"
}
},
{
"Name": "Seq",
"Args": {
"serverUrl": "http://logs-ingest.carneiro.ddnsfree.com",
"compact": true,
"batchPostingLimit": 100
}
}
],
"Properties": {
"Environment": "Production",
"Workspace": "Prod",
"Application": "SumaTube"
}
}
}

View File

@ -1,8 +1,20 @@
{
"Logging": {
"LogLevel": {
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId",
"WithEnvironmentUserName"
],
"Properties": {
"Application": "SumaTube"
}
},
"AllowedHosts": "*",