﻿// MIT License. Copyright (c) 2016 Maxim Kuzmin. Contacts: https://github.com/maxim-kuzmin

// Author: Maxim Kuzmin

using Makc2016.Core.Web.App;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;

namespace Makc2016.Core.Web.Authorize
{
    /// <summary>
    /// Ядро. Веб. Авторизация. HTTP-атрибут.
    /// </summary>
    public class CoreWebAuthorizeHttpAttribute : AuthorizeAttribute
    {
        #region Properties

        /// <summary>
        /// Приложение.
        /// </summary>
        private static ICoreWebAppContext App
        {
            get
            {
                return CoreWebAppContext.Current;
            }
        }

        /// <summary>
        /// Список ролей, которым доступ к операции разрешен (через запятую).
        /// </summary>
        public new string Roles { get; set; }

        #endregion Properties

        #region Public methods

        /// <summary>
        /// Вызывается в процессе авторизации действия.
        /// </summary>
        /// <param name="actionContext">Контекст действия.</param>
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            if (!HasAccess(actionContext))
            {
                HandleUnauthorizedRequest(actionContext);
            }
        }

        #endregion Public methods

        #region Protected methods

        /// <summary>
        /// Обработка неавторизованного запроса - ответ с кодом 403.
        /// </summary>
        /// <param name="actionContext">Контекст действия.</param>
        protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
        {
            HttpContext.Current.Response.AddHeader("AuthenticationStatus", "NotAuthorized");

            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden);
        }

        #endregion Protected methods

        #region Private methods

        /// <summary>
        /// Проверка наличия доступа.
        /// </summary>
        /// <param name="actionContext">Контекст действия.</param>
        /// <returns>True - доступ разрешён, False - доступ не разрешен.</returns>
        private bool HasAccess(HttpActionContext actionContext)
        {            
            var principal = App.GetPrincipal();

            if (!string.IsNullOrEmpty(Roles))
            {
                var roles = Roles.Split(',');

                foreach (var role in roles)
                {
                    if (principal.IsInRole(role.Trim())) return true;
                }

                return false;
            }

            return true;
        }

        #endregion Private methods
    }
}
