using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using BH.API.Identity.Client.NetCore; using Microsoft.Extensions.Options; using BH.Signup.Core.Models; using BH.Signup.Core.Services; using BH.Signup.Core.Domain; using BH.Signup.Core; using Microsoft.AspNetCore.Diagnostics; using System.Reflection; namespace Signup.Billhighway.Com.Controllers { /// /// /// /// public class HomeController : Controller { #region Constructors & Initialization /// /// Initializes a new instance of the class. /// /// The identity proxy settings. /// The subscription proxy settings. /// The cookie service. /// The template client map service. /// The client mapping service. public HomeController(IOptions identityProxySettings, IFormTemplateClientMapService templateClientMapService, IClientMappingsService clientMappingService, ITokenService tokenService, ILogService logService) { IdentitySettings = identityProxySettings.Value; TemplateClientMapService = templateClientMapService; ClientMappingService = clientMappingService; TokenService = tokenService; LogService = logService; } #endregion #region Public Properties /// Gets the identity settings. /// The identity settings. public IdentityProxySettings IdentitySettings { get; private set; } /// Gets the template client map service. /// The template client map service. public IFormTemplateClientMapService TemplateClientMapService { get; private set; } /// Gets the client mapping service. /// The client mapping service. public IClientMappingsService ClientMappingService { get; private set; } /// Gets the token service. /// The token service. public ITokenService TokenService { get; private set; } /// Gets the log service. /// The log service. public ILogService LogService { get; private set; } #endregion #region Helper Methods /// Validates the user request. /// The model. /// private ErrorModel ValidateUserRequest(SubscriptionInitModel model) { if (!string.IsNullOrWhiteSpace(model.UserID) && !string.IsNullOrWhiteSpace(model.UserType)) { if (string.IsNullOrWhiteSpace(model.Jwt)) { return new ErrorModel { ErrorCode = "401.01", ErrorMessage = "Invalid request, token not found.", LogError = true }; } } return null; } /// Validates the token claims with route values. /// The model. /// The token. /// private ErrorModel ValidateTokenClaimsWithRouteValues(SubscriptionInitModel model, int natID, int groupID, string jwtToken, out long expires) { var token = TokenService.DecodeJwtToken(jwtToken); expires = token.Expires.ToUnixTime(); var chapid = token?.Claims.FirstOrDefault(c => c.Key == "chapid").Value ?? string.Empty; var natid = token?.Claims.FirstOrDefault(c => c.Key == "natid").Value ?? string.Empty; var userid = token?.Claims.FirstOrDefault(c => c.Key == "userid").Value ?? string.Empty; var usertype = token?.Claims.FirstOrDefault(c => c.Key == "usertype").Value ?? string.Empty; if( natID.ToString() != natid) { return new ErrorModel { ErrorCode = "403.01", ErrorMessage = "Invalid request, national mismatch." }; } if( groupID.ToString() != chapid) { return new ErrorModel { ErrorCode = "403.02", ErrorMessage = "Invalid request, group mismatch." }; } if ((model.UserID ?? "0") != userid) { return new ErrorModel { ErrorCode = "403.03", ErrorMessage = "Invalid request, user mismatch." }; } if ((model.UserType ?? "bh") != (string.IsNullOrWhiteSpace(usertype) ? "bh" : usertype)) { return new ErrorModel { ErrorCode = "403.04", ErrorMessage = "Invalid request, user type mismatch." }; } return null; } /// Validates the client mappings. /// The nat identifier. /// The group identifier. /// private ErrorModel ValidateClientMappings(int natID, int groupID) { if( natID <= 0 ) { return new ErrorModel { ErrorCode = "400.01", ErrorMessage = "Invalid client mapping url values." }; } else if (groupID <= 0) { return new ErrorModel { ErrorCode = "400.02", ErrorMessage = "Invalid client mapping url values." }; } return null; } #endregion /// Indexes the specified model. /// The model. /// [HttpGet] public async Task Index(SubscriptionInitModel model) { int natId = model.NatID ?? 0; int groupId = model.GroupID ?? 0; ErrorModel errorModel = null; string jwtTokenValue = string.Empty; long jwtTokenExpiresOn = 0; if (string.IsNullOrWhiteSpace(model.Jwt)) { errorModel = new ErrorModel { ErrorCode = "401.03", ErrorMessage = "Invalid token, your request is not valid." }; } if (errorModel == null) { if (!string.IsNullOrWhiteSpace(model.UserID) && !string.IsNullOrWhiteSpace(model.UserType)) { errorModel = ValidateUserRequest(model); if (errorModel == null) { errorModel = ValidateClientMappings(natId, groupId); if (errorModel == null) { errorModel = ValidateTokenClaimsWithRouteValues(model, natId, groupId, model.Jwt, out jwtTokenExpiresOn); jwtTokenValue = (errorModel == null) ? model.Jwt : string.Empty; } } } else { errorModel = ValidateClientMappings(natId, groupId); if (errorModel == null) { errorModel = ValidateTokenClaimsWithRouteValues(model, natId, groupId, model.Jwt, out jwtTokenExpiresOn); jwtTokenValue = (errorModel == null) ? model.Jwt : string.Empty; } } } if (errorModel == null) { if (jwtTokenExpiresOn <= DateTime.UtcNow.ToUnixTime()) { errorModel = new ErrorModel { ErrorCode = "401.02", ErrorMessage = "Authentication token has expired, your request is no longer valid." }; } } if (errorModel == null) { return View(); } else { if (errorModel.LogError == true) { await LogService.Log(new LogRequest { Comment = errorModel.ErrorMessage, Exception = null, Method = this.GetType().GetMethod(nameof(Router)), Path = HttpContext.Request.Path, UserID = 0 }); } return RedirectToAction("Error", "Errors", errorModel); } } /// Routers the specified model. /// The model. /// [HttpGet] public async Task Router(SubscriptionInitModel model) { ErrorModel errorModel = null; Dictionary mappings = null; string jwtTokenValue = string.Empty; long jwtTokenExpiresOn = 0; if (!string.IsNullOrWhiteSpace(model.UserID) && !string.IsNullOrWhiteSpace(model.UserType)) { errorModel = ValidateUserRequest(model); if (errorModel == null) { mappings = (await ClientMappingService.GetUrlMappingValues(model.NatMap, model.GroupMap)); model.NatID = (mappings.ContainsKey(model.NatMap.ToLower())) ? mappings.First(m => m.Key == model.NatMap.ToLower()).Value : 0; model.GroupID = (mappings.ContainsKey(model.GroupMap.ToLower())) ? mappings.First(m => m.Key == model.GroupMap.ToLower()).Value : 0; errorModel = ValidateClientMappings(model.NatID ?? 0, model.GroupID ?? 0); if (errorModel == null) { errorModel = ValidateTokenClaimsWithRouteValues(model, model.NatID ?? 0, model.GroupID ?? 0, model.Jwt, out jwtTokenExpiresOn); jwtTokenValue = (errorModel == null) ? model.Jwt : string.Empty; } } } else { mappings = (await ClientMappingService.GetUrlMappingValues(model.NatMap, model.GroupMap)); model.NatID = (mappings.ContainsKey(model.NatMap.ToLower())) ? mappings.First(m => m.Key == model.NatMap.ToLower()).Value : 0; model.GroupID = (mappings.ContainsKey(model.GroupMap.ToLower())) ? mappings.First(m => m.Key == model.GroupMap.ToLower()).Value : 0; errorModel = ValidateClientMappings(model.NatID ?? 0, model.GroupID ?? 0); if (errorModel == null) { if (!string.IsNullOrWhiteSpace(model.Jwt)) { errorModel = ValidateTokenClaimsWithRouteValues(model, model.NatID ?? 0, model.GroupID ?? 0, model.Jwt, out jwtTokenExpiresOn); jwtTokenValue = (errorModel == null) ? model.Jwt : string.Empty; } else { var tokenResponse = await TokenService.GetSignupToken(new SignupTokenCreateRq { NationalId = model.NatID ?? 0, GroupId = model.GroupID ?? 0, UserId = "0", UserType = string.Empty, AdminId = 0 }); if (tokenResponse.Data != null && tokenResponse.Data.Token != null && !string.IsNullOrWhiteSpace(tokenResponse.Data.Token.Value)) { jwtTokenValue = tokenResponse.Data.Token.Value; jwtTokenExpiresOn = tokenResponse.Data.Token.Expires; } } } } model.Jwt = jwtTokenValue; if (mappings == null) { mappings = (await ClientMappingService.GetUrlMappingValues(model.NatMap, model.GroupMap)); model.NatID = (mappings.ContainsKey(model.NatMap.ToLower())) ? mappings.First(m => m.Key == model.NatMap.ToLower()).Value : 0; model.GroupID = (mappings.ContainsKey(model.GroupMap.ToLower())) ? mappings.First(m => m.Key == model.GroupMap.ToLower()).Value : 0; } model.FormTemplateID = await TemplateClientMapService.GetFormTemplateIDForNationalID(model.NatID ?? 0); return (string.IsNullOrWhiteSpace(model.UserID)) ? RedirectToRoute("index-nat-and-group", model) : RedirectToRoute("index-nat-and-group-and-user", model); } } }