Exemplo n.º 1
0
        public ApiCostsFilterTests()
        {
            actionContext =
                new ActionExecutingContext(
                    new ActionContext(httpContext, new RouteData(),
                                      new ActionDescriptor()),
                    new List <IFilterMetadata>(), new Dictionary <string, object>(), null);

            A.CallTo(() => appPlansProvider.GetPlan(null))
            .Returns(appPlan);

            A.CallTo(() => appPlansProvider.GetPlanForApp(appEntity))
            .Returns((appPlan, "free"));

            A.CallTo(() => appPlan.BlockingApiCalls)
            .ReturnsLazily(x => apiCallsBlocking);

            A.CallTo(() => usageTracker.GetMonthCostsAsync(A <string> ._, DateTime.Today))
            .ReturnsLazily(x => Task.FromResult(apiCallsCurrent));

            next = () =>
            {
                isNextCalled = true;

                return(Task.FromResult <ActionExecutedContext?>(null));
            };

            sut = new ApiCostsFilter(appPlansProvider, usageTracker);
        }
Exemplo n.º 2
0
        public async Task CheckUsagesAsync()
        {
            var today = DateTime.Today;

            foreach (var(key, target) in state.Value.Targets)
            {
                var from = GetFromDate(today, target.NumDays);

                if (!target.Triggered.HasValue || target.Triggered < from)
                {
                    var costs = await usageTracker.GetMonthCostsAsync(target.AppId.Id.ToString(), today);

                    var limit = target.Limits;

                    if (costs > limit)
                    {
                        target.Triggered = today;

                        var @event = new AppUsageExceeded
                        {
                            AppId        = target.AppId,
                            CallsCurrent = costs,
                            CallsLimit   = limit,
                            RuleId       = key
                        };

                        await state.WriteEventAsync(Envelope.Create <IEvent>(@event));
                    }
                }
            }

            await state.WriteAsync();
        }
Exemplo n.º 3
0
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            context.HttpContext.Features.Set <IApiCostsFeature>(FilterDefinition);

            var app = context.HttpContext.Context().App;

            if (app != null)
            {
                var appId = app.Id.ToString();

                if (FilterDefinition.Costs > 0)
                {
                    using (Profiler.Trace("CheckUsage"))
                    {
                        var(plan, _) = appPlansProvider.GetPlanForApp(app);

                        var usage = await usageTracker.GetMonthCostsAsync(appId, DateTime.Today);

                        if (plan.BlockingApiCalls >= 0 && usage > plan.BlockingApiCalls)
                        {
                            context.Result = new StatusCodeResult(429);
                            return;
                        }
                    }
                }

                context.HttpContext.Response.Headers.Add("X-Costs", FilterDefinition.Costs.ToString());
            }

            await next();
        }
Exemplo n.º 4
0
        public virtual async Task <bool> IsBlockedAsync(IAppEntity app, DateTime today)
        {
            Guard.NotNull(app, nameof(app));

            var isLocked = false;

            var(plan, _) = appPlansProvider.GetPlanForApp(app);

            if (plan.MaxApiCalls > 0 || plan.BlockingApiCalls > 0)
            {
                var appId = app.Id;

                var usage = await apiUsageTracker.GetMonthCostsAsync(appId.ToString(), today);

                if (IsAboutToBeLocked(today, plan.MaxApiCalls, usage) && !HasNotifiedBefore(app.Id))
                {
                    var users = app.Contributors.Where(x => x.Value == Role.Owner).Select(x => x.Key).ToArray();

                    var notification = new UsageNotification
                    {
                        AppId      = appId,
                        AppName    = app.Name,
                        Usage      = usage,
                        UsageLimit = plan.MaxApiCalls,
                        Users      = users
                    };

                    usageLimitNotifier.NotifyAsync(notification).Forget();

                    TrackNotified(appId);
                }

                isLocked = plan.BlockingApiCalls > 0 && usage > plan.BlockingApiCalls;
            }

            return(isLocked);
        }
Exemplo n.º 5
0
        public UsageGateTests()
        {
            appEntity = Mocks.App(appId);

            A.CallTo(() => grainFactory.GetGrain <IUsageNotifierGrain>(SingleGrain.Id, null))
            .Returns(usageNotifierGrain);

            A.CallTo(() => appPlansProvider.GetPlan(null))
            .Returns(appPlan);

            A.CallTo(() => appPlansProvider.GetPlanForApp(appEntity))
            .Returns((appPlan, "free"));

            A.CallTo(() => appPlan.MaxApiCalls)
            .ReturnsLazily(x => apiCallsMax);

            A.CallTo(() => appPlan.BlockingApiCalls)
            .ReturnsLazily(x => apiCallsBlocking);

            A.CallTo(() => usageTracker.GetMonthCostsAsync(appId.Id.ToString(), today))
            .ReturnsLazily(x => Task.FromResult(apiCallsCurrent));

            sut = new UsageGate(appPlansProvider, usageTracker, grainFactory);
        }