Skip to content

Commit

Permalink
Add project file to repository
Browse files Browse the repository at this point in the history
  • Loading branch information
uness126 committed Oct 6, 2022
0 parents commit 96244a9
Show file tree
Hide file tree
Showing 33 changed files with 14,118 additions and 0 deletions.
42 changes: 42 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Logs
logs
*.log
npm-debug.log*

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules
jspm_packages
typings

# Optional npm cache directory
.npm

# Optional REPL history
.node_repl_history

# .NET compiled files
bin
obj
45 changes: 45 additions & 0 deletions Controllers/WeatherController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Microsoft.AspNetCore.Mvc;
using Weather.Helpers;
using Weather.Models;
using Weather.Services;

namespace Weather.Controllers;

[ApiController]
[Route("[controller]")]
public class WeatherController : ControllerBase
{
private readonly ILogger<WeatherController> _logger;
private readonly IUserService _userService;
private readonly IWeatherForecast _weatherForecast;

public WeatherController(ILogger<WeatherController> logger, IUserService userService, IWeatherForecast weatherForecast)
{
_logger = logger;
_userService = userService;
_weatherForecast = weatherForecast;
}

[HttpPost("authenticate")]
public IActionResult Authenticate(AuthenticateRequest model)
{
var response = _userService.Authenticate(model);

if (response == null)
return BadRequest(new { message = "Username or password is incorrect" });

return Ok(response);
}

[Authorize]
[HttpGet("[action]/{city}")]
public IActionResult Get(string city)
{
var weather = _weatherForecast.GetForecast(city);

_logger.LogInformation(weather == null ? "Not found!" :
$"City: {city} TemperatureC: {weather.TemperatureC} Summary: {weather.Summary}");

return Ok(weather);
}
}
20 changes: 20 additions & 0 deletions DependencyContainer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Weather.Helpers;
using Weather.OpenWeatherMaps;
using Weather.Services;

namespace Weather;

public static class DependencyContainer
{
public static void RegisterServices(WebApplicationBuilder builder)
{
builder.Services.AddScoped<IWeatherForecast, OpenWeatherMap>();
builder.Services.AddScoped<IUserService, UserService>();

builder.Services.Configure<OpenWeatherMapViewModel>(
builder.Configuration.GetSection(OpenWeatherMapViewModel.OpenWeatherMap));

builder.Services.Configure<AppSettings>(
builder.Configuration.GetSection(AppSettings.AppSetting));
}
}
37 changes: 37 additions & 0 deletions Extensions/ExceptionMiddlewareExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http.Features;
using System.Net;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

namespace Weather.Extensions;

public static class ExceptionMiddlewareExtensions
{
public static void ConfigureBuildInExceptionHandler(this IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseExceptionHandler(error =>
{
error.Run(async context =>
{
var _logger = loggerFactory.CreateLogger("exceptionhandlermiddleware");

context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.ContentType = "application/json";

var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
var contextRequest = context.Features.Get<IHttpRequestFeature>();

if (contextFeature != null)
{
string _error = $"[{context.Response.StatusCode}] - {contextFeature.Error.Message}: {contextRequest.Path}";

_logger.LogError(_error);

await context.Response.WriteAsync(_error);
}
});
});
}
}
7 changes: 7 additions & 0 deletions Helpers/AppSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Weather.Helpers;

public class AppSettings
{
public const string AppSetting = "AppSettings";
public string Secret { get; set; }
}
19 changes: 19 additions & 0 deletions Helpers/AuthorizeAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Weather.Helpers;

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Weather.Models;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeAttribute : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var user = (User)context.HttpContext.Items["User"];
if (user == null)
{
// not logged in
context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
}
}
}
58 changes: 58 additions & 0 deletions Helpers/JwtMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
namespace Weather.Helpers;

using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using Weather.Services;

public class JwtMiddleware
{
private readonly RequestDelegate _next;
private readonly AppSettings _appSettings;

public JwtMiddleware(RequestDelegate next, IOptions<AppSettings> appSettings)
{
_next = next;
_appSettings = appSettings.Value;
}

public async Task Invoke(HttpContext context, IUserService userService)
{
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();

if (token != null)
attachUserToContext(context, userService, token);

await _next(context);
}

private void attachUserToContext(HttpContext context, IUserService userService, string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
// set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);

var jwtToken = (JwtSecurityToken)validatedToken;
var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value);

// attach user to context on successful jwt validation
context.Items["User"] = userService.GetById(userId);
}
catch
{
// do nothing if jwt validation fails
// user is not attached to context so request won't have access to secure routes
}
}
}
12 changes: 12 additions & 0 deletions Models/AuthenticateRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;

namespace Weather.Models;

public class AuthenticateRequest
{
[Required]
public string Username { get; set; }

[Required]
public string Password { get; set; }
}
20 changes: 20 additions & 0 deletions Models/AuthenticateResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Weather.Models;

public class AuthenticateResponse
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Username { get; set; }
public string Token { get; set; }


public AuthenticateResponse(User user, string token)
{
Id = user.Id;
FirstName = user.FirstName;
LastName = user.LastName;
Username = user.Username;
Token = token;
}
}
12 changes: 12 additions & 0 deletions Models/Dto/WeatherForecastDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;

namespace Weather.Models.Dto
{
public class WeatherForecastDto
{
public int Id { get; set; }
public DateTime Date { get; set; }
public float TemperatureC { get; set; }
public string? Summary { get; set; }
}
}
14 changes: 14 additions & 0 deletions Models/User.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Text.Json.Serialization;

namespace Weather.Models;

public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Username { get; set; }

[JsonIgnore]
public string Password { get; set; }
}
8 changes: 8 additions & 0 deletions OpenWeatherMaps/Clouds.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Weather.OpenWeatherMaps
{
public class Clouds
{
public int All { get; set; }
}
}

8 changes: 8 additions & 0 deletions OpenWeatherMaps/Coord.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Weather.OpenWeatherMaps
{
public class Coord
{
public float Lon { get; set; }
public float Lat { get; set; }
}
}
12 changes: 12 additions & 0 deletions OpenWeatherMaps/Main.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Weather.OpenWeatherMaps
{
public class Main
{
public float Temp { get; set; }
public int Pressure { get; set; }
public int Humidity { get; set; }
public float Temp_Min { get; set; }
public float Temp_Max { get; set; }

}
}
7 changes: 7 additions & 0 deletions OpenWeatherMaps/OpenWeatherMapViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Weather.OpenWeatherMaps;

public class OpenWeatherMapViewModel
{
public const string OpenWeatherMap = "OpenWeatherMap";
public string Api { get; set; } = String.Empty;
}
13 changes: 13 additions & 0 deletions OpenWeatherMaps/Sys.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Weather.OpenWeatherMaps
{
public class Sys
{
public int Type { get; set; }
public int Id { get; set; }
public float Message { get; set; }
public string Country { get; set; }
public int Sunrise { get; set; }
public int Sunshine { get; set; }

}
}
11 changes: 11 additions & 0 deletions OpenWeatherMaps/Weather.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Weather.OpenWeatherMaps
{
public class Weather
{
public int Id { get; set; }
public string Main { get; set; }
public string Description { get; set; }
public string Icon { get; set; }

}
}
20 changes: 20 additions & 0 deletions OpenWeatherMaps/WeatherResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Weather.OpenWeatherMaps
{
public class WeatherResponse
{
public Coord Coord { get; set; }
public List<Weather> Weather { get; set; }
public string Base { get; set; }
public Main Main { get; set; }
public int Visibility { get; set; }
public Wind Wind { get; set; }
public Clouds Clouds { get; set; }
public int Dt { get; set; }
public Sys Sys { get; set; }
public int Timezone { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public int Cod { get; set; }

}
}
9 changes: 9 additions & 0 deletions OpenWeatherMaps/Wind.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Weather.OpenWeatherMaps
{
public class Wind
{
public float Speed { get; set; }
public int Deg { get; set; }

}
}
Loading

0 comments on commit 96244a9

Please sign in to comment.