/// <summary>
        /// Add authorization
        /// </summary>
        /// <param name="services">service collection</param>
        /// <param name="cofigure">authorization options configuration action</param>
        /// <returns>service collection</returns>
        public static IServiceCollection AddAuthZyinAuthorization(this IServiceCollection services, Action <AuthZyinAuthorizationOptions> configure)
        {
            if (configure == null)
            {
                throw new ArgumentNullException(nameof(configure));
            }

            // Add current assembly as an ApplicationPart for the controller to work
            services.AddControllers().AddApplicationPart(typeof(AuthorizationExtensions).Assembly);

            // Add http context accessor - needed by AuthZyinContext registration
            services.AddHttpContextAccessor();

            // Configure authorization options. Use our own AuthZyinAuthorizationOptions to:
            // 1. Expose the list of policies
            // 2. Generate a new configue action to use against AuthorizationOptions.
            var authZyinOptions = new AuthZyinAuthorizationOptions();

            configure(authZyinOptions);

            // Register IAuthorizationPolicyList and enable authoriztion
            services.AddSingleton <IAuthorizationPolicyList>(authZyinOptions);
            services.AddAuthorization(authZyinOptions.CapturedConfigureAction);

            // Add authorization handler - must be registered as scoped
            services.AddScoped <IAuthorizationHandler, AuthZyinHandler>();

            return(services);
        }
        private bool AreOptionsEqual(AuthZyinAuthorizationOptions left, AuthorizationOptions right)
        {
            var propertiesAreTheSame =
                left != null && right != null &&
                left.DefaultPolicy == right.DefaultPolicy &&
                left.FallbackPolicy == right.FallbackPolicy &&
                left.InvokeHandlersAfterFailure == right.InvokeHandlersAfterFailure;

            var policiesAreTheSame = left.Policies.All(x => x.policy == right.GetPolicy(x.name));

            return(propertiesAreTheSame && policiesAreTheSame);
        }
        public void AddPolicyThrowsOnInvalidArg()
        {
            var options = new AuthZyinAuthorizationOptions();

            Assert.Throws <ArgumentNullException>(() => options.AddPolicy(null, (AuthorizationPolicy)null));
            Assert.Throws <ArgumentNullException>(() => options.AddPolicy(null, (Action <AuthorizationPolicyBuilder>)null));
            Assert.Throws <ArgumentNullException>(() => options.AddPolicy(nameof(rolePolicy), (AuthorizationPolicy)null));
            Assert.Throws <ArgumentNullException>(() => options.AddPolicy(nameof(claimPolicyConfigure), (Action <AuthorizationPolicyBuilder>)null));

            // Throws on duplicate policies
            options.AddPolicy(nameof(rolePolicy), rolePolicy);
            Assert.Throws <ArgumentException>(() => options.AddPolicy(nameof(rolePolicy), rolePolicy));
        }
        public void OptionsAreConfiguredCorrectly()
        {
            var ourOptions = new AuthZyinAuthorizationOptions();

            ourOptions.DefaultPolicy              = rolePolicy;
            ourOptions.FallbackPolicy             = ourOptions.DefaultPolicy;
            ourOptions.InvokeHandlersAfterFailure = false;
            testPolicies.ToList().ForEach(kvp => ourOptions.AddPolicy(kvp.Key, kvp.Value));
            testPolicyBuilders.ToList().ForEach(kvp => ourOptions.AddPolicy(kvp.Key, kvp.Value));

            // Compare with base
            Assert.True(this.AreOptionsEqual(ourOptions, ourOptions as AuthorizationOptions));

            // Compare to a new AuthorizationOptions object using the "captured" actions
            var newOptions = new AuthorizationOptions();

            ourOptions.CapturedConfigureAction(newOptions);
            Assert.True(this.AreOptionsEqual(ourOptions, newOptions));
        }