using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Kreta.BusinessLogic.Classes.MobileApi.Common.Co;
using Kreta.BusinessLogic.Classes.MobileApi.Common.Enum;
using Kreta.Web.Configuration;
namespace Kreta.Web.Areas.MobileApi.Attributes
{
//
/// Authorization filter attribute
///
///
class MobileApiAuthorizationAttribute : AuthorizationFilterAttribute, IOverrideFilter
{
///
/// Institute code
///
const string InstituteCode = nameof(InstituteCode);
///
/// Gets the API key.
///
const string ApiKey = nameof(ApiKey);
///
/// User Id
///
const string UserId = nameof(UserId);
///
/// Tutelary Id
///
const string TutelaryId = nameof(TutelaryId);
///
/// User roles
///
const string UserRoles = nameof(UserRoles);
const string SchoolYearId = nameof(SchoolYearId);
///
/// Gets the filters to override.
///
public Type FiltersToOverride
{
get
{
return typeof(IAuthorizationFilter);
}
}
///
/// Validating api key
///
/// Header item, contains api key
/// true, if api key is valid (access granted)
private bool AccessGratnedByApiKey(KeyValuePair> apiKeyHeader)
{
if (apiKeyHeader.Value != null)
{
string targetApiKey = apiKeyHeader.Value.SingleOrDefault();
if (!string.IsNullOrWhiteSpace(targetApiKey) && targetApiKey == MobileApiConfigurationSection.Instance.ApiKey)
{
return true;
}
}
return false;
}
///
/// Get mobile user
///
/// Http headers
/// Mobile user
private MobileUser GetMobileUser(HttpRequestHeaders headers)
{
var instituteCodeHeaderValue = headers.SingleOrDefault(x => x.Key.Equals(InstituteCode, StringComparison.InvariantCultureIgnoreCase)).Value?.SingleOrDefault();
var schoolYearIdHeaderValue = headers.SingleOrDefault(x => x.Key.Equals(SchoolYearId, StringComparison.InvariantCultureIgnoreCase)).Value?.SingleOrDefault();
int schoolYearId;
int userId;
var userIdHeaderValue = headers.SingleOrDefault(x => x.Key.Equals(UserId, StringComparison.InvariantCultureIgnoreCase)).Value?.SingleOrDefault();
if (userIdHeaderValue == null)
{
throw new InvalidOperationException($"\"{UserId}\" header value was not found");
}
if (!int.TryParse(userIdHeaderValue, out userId))
{
throw new InvalidOperationException($"Cannot parse \"{UserId}\" header value: \"{userIdHeaderValue}\"");
}
if (schoolYearIdHeaderValue == null)
{
throw new InvalidOperationException($"\"{SchoolYearId}\" header value was not found");
}
if (!int.TryParse(schoolYearIdHeaderValue, out schoolYearId))
{
throw new InvalidOperationException($"Cannot parse \"{SchoolYearId}\" header value: \"{schoolYearIdHeaderValue}\"");
}
int? tutelaryId = null;
var tutelaryIdHeaderValue = headers.SingleOrDefault(x => x.Key.Equals(TutelaryId, StringComparison.InvariantCultureIgnoreCase)).Value?.SingleOrDefault() ?? string.Empty;
if (tutelaryIdHeaderValue == null)
{
throw new InvalidOperationException($"\"{TutelaryId}\" header value was not found");
}
if (!string.IsNullOrWhiteSpace(tutelaryIdHeaderValue.Trim()))
{
int tutelaryId1;
if (!int.TryParse(tutelaryIdHeaderValue, out tutelaryId1))
{
throw new InvalidOperationException($"Cannot parse \"{TutelaryId}\" header value: \"{tutelaryIdHeaderValue}\"");
}
tutelaryId = tutelaryId1;
}
var userRolesHeaderValue = headers.SingleOrDefault(x => x.Key.Equals(UserRoles, StringComparison.InvariantCultureIgnoreCase)).Value?.SingleOrDefault();
if (userRolesHeaderValue == null)
{
throw new InvalidOperationException($"\"{UserRoles}\" header value was not found");
}
List userRoles = new List();
foreach (string userRoleHeaderValue in userRolesHeaderValue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
MobileUserRole userRole;
if (!Enum.TryParse(userRoleHeaderValue, out userRole))
{
throw new InvalidOperationException($"\"{userRoleHeaderValue}\" is not a valid user role");
}
userRoles.Add(userRole);
}
return new MobileUser(instituteCodeHeaderValue, userId, tutelaryId, userRoles, schoolYearId);
}
///
/// Authorization event
///
/// Context of the current action
/// Cancellation token
public override Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
var headers = actionContext.Request.Headers;
var apiKeyHeader = headers.SingleOrDefault(x => x.Key.Equals(ApiKey, StringComparison.InvariantCultureIgnoreCase));
if (!AccessGratnedByApiKey(apiKeyHeader))
{
actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
HttpContext.Current?.Items?.Add(nameof(MobileUser), GetMobileUser(headers));
return Task.FromResult(0);
}
}
}