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);
}
}
}