Skip to content

Commit

Permalink
Iniciado modulo 6
Browse files Browse the repository at this point in the history
  • Loading branch information
andrebaltieri committed Nov 9, 2021
1 parent 525d9de commit f4e349a
Show file tree
Hide file tree
Showing 34 changed files with 1,787 additions and 0 deletions.
35 changes: 35 additions & 0 deletions Modulo 6/Blog/Attributes/ApiKeyAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace Blog.Attributes;

[AttributeUsage(validOn: AttributeTargets.Class | AttributeTargets.Method)]
public class ApiKeyAttribute : Attribute, IAsyncActionFilter
{
public async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
if (!context.HttpContext.Request.Query.TryGetValue(Configuration.ApiKeyName, out var extractedApiKey))
{
context.Result = new ContentResult()
{
StatusCode = 401,
Content = "ApiKey não encontrada"
};
return;
}

if (!Configuration.ApiKey.Equals(extractedApiKey))
{
context.Result = new ContentResult()
{
StatusCode = 403,
Content = "Acesso não autorizado"
};
return;
}

await next();
}
}
24 changes: 24 additions & 0 deletions Modulo 6/Blog/Blog.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.11">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.11" />
<PackageReference Include="SecureIdentity" Version="1.0.2" />
</ItemGroup>

<ItemGroup>
<Folder Include="wwwroot\images" />
</ItemGroup>

</Project>
25 changes: 25 additions & 0 deletions Modulo 6/Blog/Blog.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31815.197
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blog", "Blog.csproj", "{5AF32844-E01D-4B13-BF2E-359F82C5CC00}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5AF32844-E01D-4B13-BF2E-359F82C5CC00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5AF32844-E01D-4B13-BF2E-359F82C5CC00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5AF32844-E01D-4B13-BF2E-359F82C5CC00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5AF32844-E01D-4B13-BF2E-359F82C5CC00}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0A38ABAF-B508-44E9-ABD0-ECE25A043CE0}
EndGlobalSection
EndGlobal
17 changes: 17 additions & 0 deletions Modulo 6/Blog/Configuration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Blog;

public static class Configuration
{
public static string JwtKey = "ZmVkYWY3ZDg4NjNiNDhlMTk3YjkyODdkNDkyYjcwOGU=";
public static string ApiKeyName = "api_key";
public static string ApiKey = "curso_api_IlTevUM/z0ey3NwCV/unWg==";
public static SmtpConfiguration Smtp = new();

public class SmtpConfiguration
{
public string Host { get; set; }
public int Port { get; set; } = 25;
public string UserName { get; set; }
public string Password { get; set; }
}
}
129 changes: 129 additions & 0 deletions Modulo 6/Blog/Controllers/AccountController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
using System.Text.RegularExpressions;
using Blog.Data;
using Blog.Extensions;
using Blog.Models;
using Blog.Services;
using Blog.ViewModels;
using Blog.ViewModels.Accounts;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using SecureIdentity.Password;

namespace Blog.Controllers;

[ApiController]
public class AccountController : ControllerBase
{
[HttpPost("v1/accounts/")]
public async Task<IActionResult> Post(
[FromBody] RegisterViewModel model,
[FromServices] BlogDataContext context,
[FromServices] EmailService emailService)
{
if (!ModelState.IsValid)
return BadRequest(new ResultViewModel<string>(ModelState.GetErrors()));

var user = new User
{
Name = model.Name,
Email = model.Email,
Slug = model.Email.Replace("@", "-").Replace(".", "-")
};

var password = PasswordGenerator.Generate(25);
user.PasswordHash = PasswordHasher.Hash(password);

try
{
await context.Users.AddAsync(user);
await context.SaveChangesAsync();

emailService.Send(user.Name, user.Email, "Bem vindo ao blog!", $"Sua senha é {password}");
return Ok(new ResultViewModel<dynamic>(new
{
user = user.Email, password
}));
}
catch (DbUpdateException)
{
return StatusCode(400, new ResultViewModel<string>("05X99 - Este E-mail já está cadastrado"));
}
catch
{
return StatusCode(500, new ResultViewModel<string>("05X04 - Falha interna no servidor"));
}
}

[HttpPost("v1/accounts/login")]
public async Task<IActionResult> Login(
[FromBody] LoginViewModel model,
[FromServices] BlogDataContext context,
[FromServices] TokenService tokenService)
{
if (!ModelState.IsValid)
return BadRequest(new ResultViewModel<string>(ModelState.GetErrors()));

var user = await context
.Users
.AsNoTracking()
.Include(x => x.Roles)
.FirstOrDefaultAsync(x => x.Email == model.Email);

if (user == null)
return StatusCode(401, new ResultViewModel<string>("Usuário ou senha inválidos"));

if (!PasswordHasher.Verify(user.PasswordHash, model.Password))
return StatusCode(401, new ResultViewModel<string>("Usuário ou senha inválidos"));

try
{
var token = tokenService.GenerateToken(user);
return Ok(new ResultViewModel<string>(token, null));
}
catch
{
return StatusCode(500, new ResultViewModel<string>("05X04 - Falha interna no servidor"));
}
}

[Authorize]
[HttpPost("v1/accounts/upload-image")]
public async Task<IActionResult> UploadImage(
[FromBody] UploadImageViewModel model,
[FromServices] BlogDataContext context)
{
var fileName = $"{Guid.NewGuid().ToString()}.jpg";
var data = new Regex(@"^data:image\/[a-z]+;base64,").Replace(model.Base64Image, "");
var bytes = Convert.FromBase64String(data);

try
{
await System.IO.File.WriteAllBytesAsync($"wwwroot/images/{fileName}", bytes);
}
catch (Exception ex)
{
return StatusCode(500, new ResultViewModel<string>("05X04 - Falha interna no servidor"));
}

var user = await context
.Users
.FirstOrDefaultAsync(x => x.Email == User.Identity.Name);

if (user == null)
return NotFound(new ResultViewModel<Category>("Usuário não encontrado"));

user.Image = $"https://localhost:0000/images/{fileName}";
try
{
context.Users.Update(user);
await context.SaveChangesAsync();
}
catch (Exception ex)
{
return StatusCode(500, new ResultViewModel<string>("05X04 - Falha interna no servidor"));
}

return Ok(new ResultViewModel<string>("Imagem alterada com sucesso!", null));
}
}
144 changes: 144 additions & 0 deletions Modulo 6/Blog/Controllers/CategoryController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
using Blog.Data;
using Blog.Extensions;
using Blog.Models;
using Blog.ViewModels;
using Blog.ViewModels.Categories;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace Blog.Controllers
{
[ApiController]
public class CategoryController : ControllerBase
{
[HttpGet("v1/categories")]
public async Task<IActionResult> GetAsync(
[FromServices] BlogDataContext context)
{
try
{
var categories = await context.Categories.ToListAsync();
return Ok(new ResultViewModel<List<Category>>(categories));
}
catch
{
return StatusCode(500, new ResultViewModel<List<Category>>("05X04 - Falha interna no servidor"));
}
}

[HttpGet("v1/categories/{id:int}")]
public async Task<IActionResult> GetByIdAsync(
[FromRoute] int id,
[FromServices] BlogDataContext context)
{
try
{
var category = await context
.Categories
.FirstOrDefaultAsync(x => x.Id == id);

if (category == null)
return NotFound(new ResultViewModel<Category>("Conteúdo não encontrado"));

return Ok(new ResultViewModel<Category>(category));
}
catch
{
return StatusCode(500, new ResultViewModel<Category>("Falha interna no servidor"));
}
}

[HttpPost("v1/categories")]
public async Task<IActionResult> PostAsync(
[FromBody] EditorCategoryViewModel model,
[FromServices] BlogDataContext context)
{
if (!ModelState.IsValid)
return BadRequest(new ResultViewModel<Category>(ModelState.GetErrors()));

try
{
var category = new Category
{
Id = 0,
Name = model.Name,
Slug = model.Slug.ToLower(),
};
await context.Categories.AddAsync(category);
await context.SaveChangesAsync();

return Created($"v1/categories/{category.Id}", new ResultViewModel<Category>(category));
}
catch (DbUpdateException ex)
{
return StatusCode(500, new ResultViewModel<Category>("05XE9 - Não foi possível incluir a categoria"));
}
catch
{
return StatusCode(500, new ResultViewModel<Category>("05X10 - Falha interna no servidor"));
}
}

[HttpPut("v1/categories/{id:int}")]
public async Task<IActionResult> PutAsync(
[FromRoute] int id,
[FromBody] EditorCategoryViewModel model,
[FromServices] BlogDataContext context)
{
try
{
var category = await context
.Categories
.FirstOrDefaultAsync(x => x.Id == id);

if (category == null)
return NotFound(new ResultViewModel<Category>("Conteúdo não encontrado"));

category.Name = model.Name;
category.Slug = model.Slug;

context.Categories.Update(category);
await context.SaveChangesAsync();

return Ok(new ResultViewModel<Category>(category));
}
catch (DbUpdateException ex)
{
return StatusCode(500, new ResultViewModel<Category>("05XE8 - Não foi possível alterar a categoria"));
}
catch (Exception ex)
{
return StatusCode(500, new ResultViewModel<Category>("05X11 - Falha interna no servidor"));
}
}

[HttpDelete("v1/categories/{id:int}")]
public async Task<IActionResult> DeleteAsync(
[FromRoute] int id,
[FromServices] BlogDataContext context)
{
try
{
var category = await context
.Categories
.FirstOrDefaultAsync(x => x.Id == id);

if (category == null)
return NotFound(new ResultViewModel<Category>("Conteúdo não encontrado"));

context.Categories.Remove(category);
await context.SaveChangesAsync();

return Ok(new ResultViewModel<Category>(category));
}
catch (DbUpdateException ex)
{
return StatusCode(500, new ResultViewModel<Category>("05XE7 - Não foi possível excluir a categoria"));
}
catch (Exception ex)
{
return StatusCode(500, new ResultViewModel<Category>("05X12 - Falha interna no servidor"));
}
}
}
}
15 changes: 15 additions & 0 deletions Modulo 6/Blog/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Microsoft.AspNetCore.Mvc;

namespace Blog.Controllers
{
[ApiController]
[Route("")]
public class HomeController : ControllerBase
{
[HttpGet("")]
public IActionResult Get()
{
return Ok();
}
}
}
Loading

0 comments on commit f4e349a

Please sign in to comment.