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