kreta/KretaWeb/Areas/MobileApi/Attributes/MobileApiAuthorizationAttribute.cs
2024-03-13 00:33:46 +01:00

175 lines
6.5 KiB
C#

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
{
// <summary>
/// Authorization filter attribute
/// </summary>
/// <seealso cref="System.Web.Http.Filters.AuthorizationFilterAttribute" />
class MobileApiAuthorizationAttribute : AuthorizationFilterAttribute, IOverrideFilter
{
/// <summary>
/// Institute code
/// </summary>
const string InstituteCode = nameof(InstituteCode);
/// <summary>
/// Gets the API key.
/// </summary>
const string ApiKey = nameof(ApiKey);
/// <summary>
/// User Id
/// </summary>
const string UserId = nameof(UserId);
/// <summary>
/// Tutelary Id
/// </summary>
const string TutelaryId = nameof(TutelaryId);
/// <summary>
/// User roles
/// </summary>
const string UserRoles = nameof(UserRoles);
const string SchoolYearId = nameof(SchoolYearId);
/// <summary>
/// Gets the filters to override.
/// </summary>
public Type FiltersToOverride
{
get
{
return typeof(IAuthorizationFilter);
}
}
/// <summary>
/// Validating api key
/// </summary>
/// <param name="apiKeyHeader">Header item, contains api key</param>
/// <returns>true, if api key is valid (access granted)</returns>
private bool AccessGratnedByApiKey(KeyValuePair<string, IEnumerable<string>> apiKeyHeader)
{
if (apiKeyHeader.Value != null)
{
string targetApiKey = apiKeyHeader.Value.SingleOrDefault();
if (!string.IsNullOrWhiteSpace(targetApiKey) && targetApiKey == MobileApiConfigurationSection.Instance.ApiKey)
{
return true;
}
}
return false;
}
/// <summary>
/// Get mobile user
/// </summary>
/// <param name="headers">Http headers</param>
/// <returns>Mobile user</returns>
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<MobileUserRole> userRoles = new List<MobileUserRole>();
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);
}
/// <summary>
/// Authorization event
/// </summary>
/// <param name="actionContext">Context of the current action</param>
/// <param name="cancellationToken">Cancellation token</param>
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);
}
}
}