public async Task OrgHookWithErrorIsSkipped()
        {
            using (var context = new ShipHubContext()) {
                var user = TestUtil.MakeTestUser(context);
                var org  = TestUtil.MakeTestOrg(context);
                context.OrganizationAccounts.Add(new OrganizationAccount()
                {
                    UserId         = user.Id,
                    OrganizationId = org.Id,
                });
                var hook = context.Hooks.Add(new Hook()
                {
                    Id             = 1001,
                    Events         = "event1,event2",
                    GitHubId       = null, // Empty GitHub Id
                    OrganizationId = org.Id,
                    Secret         = Guid.NewGuid(),
                    LastError      = DateTimeOffset.UtcNow,
                });
                await context.SaveChangesAsync();

                var orgActor = CreateOrgActor(org.Id, org.Login);
                var changes  = await orgActor.AddOrUpdateOrganizationWebhooks(context, null);

                var beforeError = hook.LastError;
                await context.Entry(hook).ReloadAsync();

                Assert.IsTrue(hook.LastError == beforeError, "Recent LastError should be skipped.");
                Assert.IsEmpty(changes.Repositories, "skipped hook should not send changes.");
            }
        }
Esempio n. 2
0
        public async Task <HttpResponseMessage> Resync(string owner, string repo)
        {
            // first, validate that the secret is presented
            Request.Headers.TryGetValues("X-Admin-Secret", out var presentedSecrets);
            var presentedSecret = presentedSecrets?.FirstOrDefault();
            var secret          = _configuration.AdminSecret;

            if (secret.IsNullOrWhiteSpace() || presentedSecret != secret)
            {
                return(new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden));
            }

            long?repoId = null;

            using (var context = new ShipHubContext()) {
                var repoFullName = $"{owner}/{repo}";
                repoId = (await context.Repositories.SingleOrDefaultAsync(r => r.FullName == repoFullName))?.Id;
            }

            if (repoId == null)
            {
                return(new HttpResponseMessage(System.Net.HttpStatusCode.NotFound));
            }

            var repoActor = await _grainFactory.GetGrain <IRepositoryActor>(repoId.Value);

            repoActor.ForceResyncRepositoryIssues().LogFailure();

            return(new HttpResponseMessage(System.Net.HttpStatusCode.OK));
        }
Esempio n. 3
0
 private ShipHubContext _ephemeralContext; // this is for WithContext only. If you're not WithContext, don't use it.
 private async Task WithContext(Func <ShipHubContext, Task> dbWork)
 {
     if (_borrowedContext != null)
     {
         // legacy path
         await dbWork(_borrowedContext);
     }
     else if (_ephemeralContext != null)
     {
         // re-entrant path
         await dbWork(_ephemeralContext);
     }
     else
     {
         try {
             _ephemeralContext = _contextFactory.CreateInstance();
             await dbWork(_ephemeralContext);
         } finally {
             if (_ephemeralContext != null)
             {
                 _ephemeralContext.Dispose();
                 _ephemeralContext = null;
             }
         }
     }
 }
        private async Task <string> GitHubUserNameFromWebhookPayload(ChargeBeeWebhookPayload payload)
        {
            // Most events include the customer portion which gives us the GitHub username.
            if (payload.Content.Customer?.GitHubUserName != null)
            {
                return(payload.Content.Customer.GitHubUserName);
            }
            else
            {
                // Invoice events (and maybe others, TBD) don't include the Customer portion so
                // we have to find the customer id in another section.
                var candidates = new[] {
                    payload.Content.Invoice?.CustomerId,
                    payload.Content.CreditNote?.CustomerId,
                };
                var customerId = candidates.SkipWhile(string.IsNullOrEmpty).FirstOrDefault();
                if (customerId != null)
                {
                    var accountId = ChargeBeeUtilities.AccountIdFromCustomerId(customerId);
                    using (var context = new ShipHubContext()) {
                        var login = await context.Accounts
                                    .AsNoTracking()
                                    .Where(x => x.Id == accountId)
                                    .Select(x => x.Login)
                                    .FirstOrDefaultAsync();

                        return(login);
                    }
                }
                else
                {
                    return(null);
                }
            }
        }
        public async Task RepoHookSetLastErrorIfGitHubAddRequestFails()
        {
            using (var context = new ShipHubContext()) {
                var user = TestUtil.MakeTestUser(context);
                var repo = TestUtil.MakeTestRepo(context, user.Id);
                await context.SaveChangesAsync();

                var mock = new Mock <IGitHubActor>();

                mock
                .Setup(x => x.RepositoryWebhooks(repo.FullName, null, It.IsAny <RequestPriority>()))
                .ReturnsAsync(new GitHubResponse <IEnumerable <Webhook> >(null)
                {
                    Result = new List <Webhook>(),
                    Status = HttpStatusCode.OK,
                });
                mock
                .Setup(x => x.AddRepositoryWebhook(repo.FullName, It.IsAny <Webhook>(), It.IsAny <RequestPriority>()))
                .ThrowsAsync(new Exception("some exception!"));

                var repoActor = CreateRepoActor(repo.Id, repo.FullName);
                var changes   = await repoActor.AddOrUpdateWebhooks(mock.Object);

                Assert.IsEmpty(changes.Repositories, "Failed hook creation should not send notifications.");

                var hook = context.Hooks.SingleOrDefault(x => x.RepositoryId == repo.Id);
                Assert.IsNotNull(hook.LastError, "hook should have been marked as errored when we noticed the AddRepoHook failed");
            }
        }
        public async Task OrgHookSetLastErrorIfGitHubAddRequestFails()
        {
            using (var context = new ShipHubContext()) {
                var user = TestUtil.MakeTestUser(context);
                var org  = TestUtil.MakeTestOrg(context);
                context.OrganizationAccounts.Add(new OrganizationAccount()
                {
                    UserId         = user.Id,
                    OrganizationId = org.Id,
                });
                await context.SaveChangesAsync();

                var mock = new Mock <IGitHubActor>();

                mock
                .Setup(x => x.OrganizationWebhooks(org.Login, null, It.IsAny <RequestPriority>()))
                .ReturnsAsync(new GitHubResponse <IEnumerable <Webhook> >(null)
                {
                    Result = new List <Webhook>(),
                    Status = HttpStatusCode.OK,
                });
                mock
                .Setup(x => x.AddOrganizationWebhook(org.Login, It.IsAny <Webhook>(), It.IsAny <RequestPriority>()))
                .ThrowsAsync(new Exception("some exception!"));

                var orgActor = CreateOrgActor(org.Id, org.Login);
                var changes  = await orgActor.AddOrUpdateOrganizationWebhooks(context, mock.Object);

                Assert.IsEmpty(changes.Repositories, "Failed hook creation should not send notifications.");

                var hook = context.Hooks.SingleOrDefault(x => x.OrganizationId == org.Id);
                Assert.IsNotNull(hook.LastError, "hook should have been marked as errored when we noticed the AddRepoHook failed");
            }
        }
Esempio n. 7
0
        public async Task <IHttpActionResult> SaveQuery(string queryId, [FromBody] QueryBody query)
        {
            var id = Guid.Parse(queryId);

            using (var context = new ShipHubContext()) {
                var updater = new DataUpdater(context, _mapper);
                await updater.UpdateQuery(id, ShipHubUser.UserId, query.Title, query.Predicate);

                // If there are no changes, then the author ID didn't match
                if (updater.Changes.IsEmpty)
                {
                    return(StatusCode(System.Net.HttpStatusCode.Conflict));
                }
                _queueClient.NotifyChanges(updater.Changes).LogFailure(ShipHubUser.DebugIdentifier);
            }

            var ret = new ShortQueryResponse()
            {
                Identifier = queryId,
                Title      = query.Title,
                Predicate  = query.Predicate,
                Author     = ShipHubUser.UserId
            };

            return(Ok(ret));
        }
Esempio n. 8
0
        private async Task <QueryEntry> LookupQuery(ShipHubContext context, Guid id)
        {
            var q = await context.Queries
                    .AsNoTracking()
                    .Include(x => x.Author)
                    .Where(x => x.Id == id)
                    .SingleOrDefaultAsync();

            if (q != null)
            {
                return(new QueryEntry()
                {
                    Id = q.Id,
                    Title = q.Title,
                    Predicate = q.Predicate,
                    Author = new AccountEntry()
                    {
                        Identifier = q.Author.Id,
                        Login = q.Author.Login,
                        Name = q.Author.Name
                    }
                });
            }
            return(null);
        }
        public async Task SendPurchasePersonalMessage(ChargeBeeWebhookPayload payload)
        {
            ChargeBeeUtilities.ParseCustomerId(payload.Content.Customer.Id, out var accountType, out var accountId);

            if (accountType != "user")
            {
                // "activated" only happens on transition from trial -> active, and we only do trials
                // for personal subscriptions.
                throw new Exception("subscription_activated should only happen on personal/user subscriptions");
            }

            var belongsToOrganization = false;

            using (var context = new ShipHubContext()) {
                belongsToOrganization = (await context.OrganizationAccounts.CountAsync(x => x.UserId == accountId)) > 0;
            }

            var wasGivenTrialCredit = payload.Content.Invoice.Discounts?
                                      .Count(x => x.EntityType == "document_level_coupon" && x.EntityId.StartsWith("trial_days_left")) > 0;

            var pdf = await PdfInfo(payload);

            await _mailer.PurchasePersonal(
                new Mail.Models.PurchasePersonalMailMessage()
            {
                GitHubUserName        = payload.Content.Customer.GitHubUserName,
                ToAddress             = payload.Content.Customer.Email,
                CustomerName          = payload.Content.Customer.FirstName + " " + payload.Content.Customer.LastName,
                BelongsToOrganization = belongsToOrganization,
                WasGivenTrialCredit   = wasGivenTrialCredit,
                InvoicePdfUrl         = pdf.SignedUrl,
                AttachmentName        = pdf.FileName,
                AttachmentUrl         = pdf.DirectUrl,
            });
        }
Esempio n. 10
0
        private async Task <bool> RepoShipNeedsWebhookHelpHelper(bool hasHook, bool isAdmin)
        {
            using (var context = new ShipHubContext()) {
                var userAccount = TestUtil.MakeTestUser(context);
                var orgAccount  = new AccountTableType()
                {
                    Id    = 4001,
                    Login = "******",
                    Type  = "org",
                };
                var repo = new RepositoryTableType()
                {
                    Id        = 5001,
                    AccountId = 4001,
                    Name      = "unicorns",
                    FullName  = "pureimaginary/unicorns",
                    Private   = true,
                    HasIssues = true,
                };

                await context.BulkUpdateAccounts(DateTimeOffset.UtcNow, new[] { orgAccount });

                var user = context.Users.Single(x => x.Id == userAccount.Id);
                await context.SaveChangesAsync();

                await context.BulkUpdateRepositories(DateTimeOffset.UtcNow, new[] { repo });

                await context.SetUserOrganizations(user.Id, new[] { orgAccount.Id });

                await context.SetAccountLinkedRepositories(
                    userAccount.Id,
                    new[] { (repo.Id, isAdmin) });
Esempio n. 11
0
        public async Task <IHttpActionResult> WatchQuery(Guid queryId)
        {
            QueryEntry entry = null;

            using (var context = new ShipHubContext()) {
                entry = await LookupQuery(context, queryId);

                if (entry != null)
                {
                    var updater = new DataUpdater(context, _mapper);
                    await updater.ToggleWatchQuery(queryId, ShipHubUser.UserId, true);

                    _queueClient.NotifyChanges(updater.Changes).LogFailure(ShipHubUser.DebugIdentifier);
                }
            }

            if (entry != null)
            {
                return(Ok(entry));
            }
            else
            {
                return(NotFound());
            }
        }
        public async Task RepoHookWithErrorIsSkipped()
        {
            using (var context = new ShipHubContext()) {
                var user = TestUtil.MakeTestUser(context);
                var repo = TestUtil.MakeTestRepo(context, user.Id);
                var hook = context.Hooks.Add(new Hook()
                {
                    Id           = 1001,
                    Events       = "event1,event2",
                    GitHubId     = null, // Empty GitHubId
                    RepositoryId = repo.Id,
                    Secret       = Guid.NewGuid(),
                    LastError    = DateTimeOffset.UtcNow,
                });
                await context.SaveChangesAsync();

                var repoActor = CreateRepoActor(repo.Id, repo.FullName);
                var changes   = await repoActor.AddOrUpdateWebhooks(null);

                var beforeError = hook.LastError;
                await context.Entry(hook).ReloadAsync();

                Assert.IsTrue(hook.LastError == beforeError, "Recent LastError should be skipped.");
                Assert.IsEmpty(changes.Repositories, "skipped hook should not send changes.");
            }
        }
        public async Task SendPaymentSucceededOrganizationMessage(ChargeBeeWebhookPayload payload)
        {
            var accountId = ChargeBeeUtilities.AccountIdFromCustomerId(payload.Content.Customer.Id);

            var planLineItem = payload.Content.Invoice.LineItems.Single(x => x.EntityType == "plan");

            var newInvoiceStartDate = DateTimeOffset.FromUnixTimeSeconds(planLineItem.DateFrom);
            var previousMonthStart  = DateTimeOffsetFloor(newInvoiceStartDate.AddMonths(-1));
            var previousMonthEnd    = DateTimeOffsetFloor(newInvoiceStartDate.AddDays(-1));

            int activeUsersCount;

            string[] activeUsersSample;
            using (var context = new ShipHubContext()) {
                activeUsersCount = await context.Usage
                                   .Where(x => (
                                              x.Date >= previousMonthStart &&
                                              x.Date <= previousMonthEnd &&
                                              context.OrganizationAccounts
                                              .Where(y => y.OrganizationId == accountId)
                                              .Select(y => y.UserId)
                                              .Contains(x.AccountId)))
                                   .Select(x => x.AccountId)
                                   .Distinct()
                                   .CountAsync();

                activeUsersSample = await context.Usage
                                    .Where(x => (
                                               x.Date >= previousMonthStart &&
                                               x.Date <= previousMonthEnd &&
                                               context.OrganizationAccounts
                                               .Where(y => y.OrganizationId == accountId)
                                               .Select(y => y.UserId)
                                               .Contains(x.AccountId)))
                                    .Select(x => x.Account.Login)
                                    .OrderBy(x => x)
                                    .Distinct()
                                    .Take(20)
                                    .ToArrayAsync();
            }

            var pdf = await PdfInfo(payload);

            await _mailer.PaymentSucceededOrganization(
                new Mail.Models.PaymentSucceededOrganizationMailMessage()
            {
                GitHubUserName                 = payload.Content.Customer.GitHubUserName,
                ToAddress                      = payload.Content.Customer.Email,
                CustomerName                   = payload.Content.Customer.FirstName + " " + payload.Content.Customer.LastName,
                InvoicePdfUrl                  = pdf.SignedUrl,
                AttachmentName                 = pdf.FileName,
                AttachmentUrl                  = pdf.DirectUrl,
                ServiceThroughDate             = DateTimeOffset.FromUnixTimeSeconds(planLineItem.DateTo),
                PreviousMonthActiveUsersCount  = activeUsersCount,
                PreviousMonthActiveUsersSample = activeUsersSample,
                PreviousMonthStart             = previousMonthStart,
                AmountPaid                     = payload.Content.Invoice.AmountPaid / 100.0,
                PaymentMethodSummary           = PaymentMethodSummary(payload.Content.Transaction),
            });
        }
Esempio n. 14
0
        private async Task <SyncSpiderProgress> SpiderProgress(ShipHubContext context)
        {
            var dsp = context.SyncSpiderProgress(_user.UserId, _selectiveSyncEnabled);

            using (var reader = await dsp.ExecuteReaderAsync()) {
                return(ReadSpiderProgress(reader));
            }
        }
Esempio n. 15
0
        public async Task <IHttpActionResult> BuyFinish(string id, string state)
        {
            var hostedPage = (await _chargeBee.HostedPage.Retrieve(id).Request()).HostedPage;

            if (hostedPage.State != cbm.HostedPage.StateEnum.Succeeded)
            {
                // We should only get here if the signup was completed.
                throw new InvalidOperationException("Asked to complete signup for subscription when checkout did not complete.");
            }

            var passThruContent = JsonConvert.DeserializeObject <BuyPassThruContent>(hostedPage.PassThruContent);

            ChargeBeeUtilities.ParseCustomerId(hostedPage.Content.Subscription.CustomerId, out var accountType, out var accountId);

            ChangeSummary changes;

            using (var context = new ShipHubContext()) {
                changes = await context.BulkUpdateSubscriptions(new[] {
                    new SubscriptionTableType()
                    {
                        AccountId    = accountId,
                        State        = SubscriptionState.Subscribed.ToString(),
                        TrialEndDate = null,
                        Version      = hostedPage.Content.Subscription.ResourceVersion.Value,
                    },
                });
            }

            if (!changes.IsEmpty)
            {
                await _queueClient.NotifyChanges(changes);
            }

            if (passThruContent.AnalyticsId != null)
            {
                await _mixpanelClient.TrackAsync(
                    "Purchased",
                    passThruContent.AnalyticsId,
                    new {
                    plan        = hostedPage.Content.Subscription.PlanId,
                    customer_id = hostedPage.Content.Subscription.CustomerId,
                    // These refer to the account performing the action, which in the case of
                    // an org subscription, is different than the account being purchased.
                    _github_id    = passThruContent.ActorId,
                    _github_login = passThruContent.ActorLogin,
                });
            }

            var hashParams = new ThankYouPageHashParameters()
            {
                Value  = hostedPage.Content.Subscription.PlanUnitPrice.Value / 100,
                PlanId = hostedPage.Content.Subscription.PlanId,
            };
            var hashParamBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(
                                                             JsonConvert.SerializeObject(hashParams, GitHubSerialization.JsonSerializerSettings)));

            return(Redirect($"https://{_configuration.WebsiteHostName}/signup-thankyou.html#{WebUtility.UrlEncode(hashParamBase64)}"));
        }
Esempio n. 16
0
        public async Task <IHttpActionResult> Accounts()
        {
            var combined = new List <Account>();

            using (var context = new ShipHubContext()) {
                var user = await context.Users
                           .Include(x => x.Subscription)
                           .Where(x => x.Subscription != null)
                           .SingleOrDefaultAsync(x => x.Id == ShipHubUser.UserId);

                if (user != null)
                {
                    combined.Add(user);
                }

                var orgs = await context.AccountRepositories
                           .Where(x => (
                                      x.AccountId == ShipHubUser.UserId &&
                                      x.Repository.Account is Organization &&
                                      x.Repository.Account.Subscription != null))
                           .Select(x => x.Repository.Account)
                           .GroupBy(x => x.Id)
                           .Select(x => x.FirstOrDefault())
                           .Include(x => x.Subscription)
                           .ToArrayAsync();

                combined.AddRange(orgs);
            }

            var result = combined
                         .Select(x => {
                var hasSubscription = x.Subscription.State == SubscriptionState.Subscribed;
                var signature       = CreateSignature(ShipHubUser.UserId, x.Id);
                var apiHostName     = _configuration.ApiHostName;
                var actionUrl       = $"https://{apiHostName}/billing/{(hasSubscription ? "manage" : "buy")}/{ShipHubUser.UserId}/{x.Id}/{signature}";

                return(new BillingAccountRow()
                {
                    Account = new BillingAccount()
                    {
                        Identifier = x.Id,
                        Login = x.Login,
                        // TODO: Sync avatars and return real values here.
                        AvatarUrl = "https://avatars.githubusercontent.com/u/335107?v=3",
                        Type = (x is User) ? "user" : "organization",
                    },
                    Subscribed = hasSubscription,
                    // TODO: Only allow edits for purchaser or admins.
                    CanEdit = hasSubscription,
                    ActionUrl = actionUrl,
                    PricingLines = new[] { "Free" },
                });
            }).ToList();

            return(Ok(result));
        }
Esempio n. 17
0
        public async Task <IHttpActionResult> UnwatchQuery(Guid queryId)
        {
            using (var context = new ShipHubContext()) {
                var updater = new DataUpdater(context, _mapper);
                await updater.ToggleWatchQuery(queryId, ShipHubUser.UserId, false);

                _queueClient.NotifyChanges(updater.Changes).LogFailure(ShipHubUser.DebugIdentifier);
            }

            return(StatusCode(System.Net.HttpStatusCode.OK));
        }
        public async Task ModeDefaultsToPaid()
        {
            using (var context = new ShipHubContext()) {
                var env = await MakeEnvironment(context);

                var response = await GetSubscriptionResponse(env.user1);

                Assert.AreEqual(SubscriptionMode.Paid, response.Mode,
                                "If we haven't been able to fetch the data from ChargeBee yet, act as if paid.");
            }
        }
Esempio n. 19
0
        public async Task CanGetAccounts()
        {
            using (var context = new ShipHubContext()) {
                var user     = TestUtil.MakeTestUser(context);
                var org1     = TestUtil.MakeTestOrg(context, 6001, "myorg1");
                var org2     = TestUtil.MakeTestOrg(context, 6002, "myorg2");
                var org3     = TestUtil.MakeTestOrg(context, 6003, "myorg3");
                var org1Repo = TestUtil.MakeTestRepo(context, org1.Id, 2001, "org1repo");
                var org2Repo = TestUtil.MakeTestRepo(context, org2.Id, 2002, "org2repo");
                var org3Repo = TestUtil.MakeTestRepo(context, org3.Id, 2003, "org3repo");

                await context.SetAccountLinkedRepositories(user.Id, new[] {
Esempio n. 20
0
        private async Task RecordUsage()
        {
            var utcNow = DateTimeOffset.UtcNow;

            // We only have to record usage once per calendar day.
            if (_lastRecordedUsage == null || _lastRecordedUsage?.DayOfYear != utcNow.DayOfYear)
            {
                using (var context = new ShipHubContext()) {
                    await context.RecordUsage(_user.UserId, utcNow);
                }
                _lastRecordedUsage = utcNow;
            }
        }
Esempio n. 21
0
        public async Task SendHelloResponse(Guid purgeIdentifier)
        {
            using (var context = new ShipHubContext()) {
                var spiderProgress = await SpiderProgress(context);

                await _connection.SendJsonAsync(
                    new HelloResponse()
                {
                    PurgeIdentifier = purgeIdentifier,
                    SpiderProgress  = spiderProgress
                }
                    );
            }
        }
        private static async Task <Environment> MakeEnvironment(ShipHubContext context)
        {
            var env = new Environment()
            {
                user1 = TestUtil.MakeTestUser(context, 3001, "alok"),
                user2 = TestUtil.MakeTestUser(context, 3002, "aroon"),
                org   = TestUtil.MakeTestOrg(context, 6001, "pureimaginary")
            };
            await context.SetUserOrganizations(env.user1.Id, new[] { env.org.Id });

            await context.SaveChangesAsync();

            return(env);
        }
        public async Task OrgHookWithOldErrorIsRetried()
        {
            using (var context = new ShipHubContext()) {
                var user = TestUtil.MakeTestUser(context);
                var org  = TestUtil.MakeTestOrg(context);
                var hook = context.Hooks.Add(new Hook()
                {
                    Id             = 1001,
                    Events         = "event1,event2",
                    GitHubId       = null, // Empty GitHub Id
                    OrganizationId = org.Id,
                    Secret         = Guid.NewGuid(),
                    LastError      = DateTimeOffset.UtcNow.Subtract(OrganizationActor.HookErrorDelay),
                });
                await context.SaveChangesAsync();

                await context.SetUserOrganizations(user.Id, new[] { org.Id });

                var mock = new Mock <IGitHubActor>();

                mock
                .Setup(x => x.OrganizationWebhooks(org.Login, null, It.IsAny <RequestPriority>()))
                .ReturnsAsync(new GitHubResponse <IEnumerable <Webhook> >(null)
                {
                    Result = new List <Webhook>()
                    {
                    },
                    Status = HttpStatusCode.OK,
                });
                mock
                .Setup(x => x.AddOrganizationWebhook(org.Login, It.IsAny <Webhook>(), It.IsAny <RequestPriority>()))
                .ReturnsAsync(new GitHubResponse <Webhook>(null)
                {
                    Result = new Webhook()
                    {
                        Id = 9999,
                    },
                    Status = HttpStatusCode.OK,
                });

                var orgActor = CreateOrgActor(org.Id, org.Login);
                var changes  = await orgActor.AddOrUpdateOrganizationWebhooks(context, mock.Object);

                await context.Entry(hook).ReloadAsync();

                Assert.AreEqual(9999, hook.GitHubId);
                Assert.IsNull(hook.LastError);
                Assert.IsTrue(changes.Organizations?.First() == org.Id, "New hook should send notifications.");
            }
        }
        public async Task UsersCanBecomeOrgs()
        {
            using (var context = new ShipHubContext()) {
                var user1 = TestUtil.MakeTestUser(context, 3001, "user1");
                var user2 = TestUtil.MakeTestUser(context, 3002, "user2");
                var user3 = TestUtil.MakeTestUser(context, 3003, "user3");
                var repo1 = TestUtil.MakeTestRepo(context, user1.Id, 2001, "unicorns1");
                var repo2 = TestUtil.MakeTestRepo(context, user1.Id, 2002, "unicorns2");
                var repo3 = TestUtil.MakeTestRepo(context, user2.Id, 2003, "unicorns3");
                var repo4 = TestUtil.MakeTestRepo(context, user3.Id, 2004, "unicorns4");
                var org1  = TestUtil.MakeTestOrg(context, 6001, "org1");
                var org2  = TestUtil.MakeTestOrg(context, 6002, "org2");
                await context.SaveChangesAsync();

                await context.SetAccountLinkedRepositories(user1.Id, new[] {
Esempio n. 25
0
        public async Task Run(IAsyncCollector <ChangeMessage> notifyChanges)
        {
            using (var context = new ShipHubContext()) {
                // Get all the tokens
                var tokens = await context.Tokens
                             .AsNoTracking()
                             .Where(x => x.Version < TokenVersion)
                             .ToArrayAsync();

                if (tokens.Any())
                {
                    Log.Info($"{tokens.Length} tokens need to be rolled.");

                    foreach (var token in tokens)
                    {
                        var speedLimit = Task.Delay(1000);
                        try {
                            var newToken = await ResetToken(token.Token);

                            if (newToken == null)
                            {
                                // Delete the single token
                                await context.DeleteUserAccessToken(token.UserId, token.Token);

                                Log.Info("Deleted expired token.");
                            }
                            else
                            {
                                // Replace the token
                                await context.RollUserAccessToken(token.UserId, token.Token, newToken, TokenVersion);

                                Log.Info("Updated valid token.");
                            }

                            var cs = new ChangeSummary();
                            cs.Add(userId: token.UserId);
                            await notifyChanges.AddAsync(new ChangeMessage(cs));
                        } catch (Exception e) {
                            Log.Exception(e, $"Error rolling token for {token.UserId}:{token.Version}");
                        }

                        await speedLimit;
                    }

                    Log.Info($"Done processing tokens.");
                }
            }
        }
Esempio n. 26
0
        public async Task <IHttpActionResult> QueryInfo(Guid queryId)
        {
            QueryEntry entry = null;

            using (var context = new ShipHubContext()) {
                entry = await LookupQuery(context, queryId);
            }

            if (entry != null)
            {
                return(Ok(entry));
            }
            else
            {
                return(NotFound());
            }
        }
        public async Task RepoHookWithOldErrorIsRetried()
        {
            using (var context = new ShipHubContext()) {
                var user = TestUtil.MakeTestUser(context);
                var repo = TestUtil.MakeTestRepo(context, user.Id);
                var hook = context.Hooks.Add(new Hook()
                {
                    Id           = 1001,
                    Events       = "event1,event2",
                    GitHubId     = null, // Empty GitHubId
                    RepositoryId = repo.Id,
                    Secret       = Guid.NewGuid(),
                    LastError    = DateTimeOffset.UtcNow.Subtract(RepositoryActor.HookErrorDelay),
                });
                await context.SaveChangesAsync();

                var mock = new Mock <IGitHubActor>();
                mock
                .Setup(x => x.RepositoryWebhooks(repo.FullName, It.IsAny <GitHubCacheDetails>(), It.IsAny <RequestPriority>()))
                .ReturnsAsync(new GitHubResponse <IEnumerable <Webhook> >(null)
                {
                    Result = new List <Webhook>(),
                    Status = HttpStatusCode.OK,
                });
                mock
                .Setup(x => x.AddRepositoryWebhook(repo.FullName, It.IsAny <Webhook>(), It.IsAny <RequestPriority>()))
                .ReturnsAsync(new GitHubResponse <Webhook>(null)
                {
                    Result = new Webhook()
                    {
                        Id = 9999,
                    },
                    Status = HttpStatusCode.OK,
                });

                var repoActor = CreateRepoActor(repo.Id, repo.FullName);
                var changes   = await repoActor.AddOrUpdateWebhooks(mock.Object);

                await context.Entry(hook).ReloadAsync();

                Assert.AreEqual(9999, hook.GitHubId);
                Assert.IsNull(hook.LastError);
                Assert.IsTrue(changes.Repositories.First() == repo.Id, "New hook should send notifications.");
            }
        }
        public static async Task <ShipHubPrincipal> ValidateToken(string token)
        {
            using (var s = new ShipHubContext()) {
                var user = await s.Tokens
                           .AsNoTracking()
                           .Where(x => x.Token == token)
                           .Select(x => new { Id = x.UserId, Login = x.User.Login })
                           .SingleOrDefaultAsync()
                           .ConfigureAwait(false);

                if (user == null)
                {
                    return(null);
                }

                return(new ShipHubPrincipal(user.Id, user.Login));
            }
        }
        public async Task ModeIsPaidWithPersonalSubscription()
        {
            using (var context = new ShipHubContext()) {
                var env = await MakeEnvironment(context);

                context.Subscriptions.Add(new Subscription()
                {
                    AccountId = env.user1.Id,
                    State     = SubscriptionState.Subscribed,
                });
                await context.SaveChangesAsync();

                var entry = await GetSubscriptionResponse(env.user1);

                Assert.AreEqual(SubscriptionMode.Paid, entry.Mode,
                                "Mode is paid with a personal subscription.");
            }
        }
        public async Task HandlePendingInvoiceCreated(ChargeBeeWebhookPayload payload)
        {
            var accountId    = ChargeBeeUtilities.AccountIdFromCustomerId(payload.Content.Invoice.CustomerId);
            var planLineItem = payload.Content.Invoice.LineItems.Single(x => x.EntityType == "plan");

            if (planLineItem.EntityId == "organization")
            {
                // Calculate the number of active users during the previous month, and then
                // attach extra charges to this month's invoice.  So, for organizations, the
                // base charge on every invoice is for the coming month, but the metered
                // component is always for the trailing month.
                var newInvoiceStartDate = DateTimeOffset.FromUnixTimeSeconds(planLineItem.DateFrom);
                var previousMonthStart  = DateTimeOffsetFloor(newInvoiceStartDate.AddMonths(-1));
                var previousMonthEnd    = DateTimeOffsetFloor(newInvoiceStartDate.AddDays(-1));

                int activeUsers;
                using (var context = new ShipHubContext()) {
                    activeUsers = await context.Usage
                                  .AsNoTracking()
                                  .Where(x => (
                                             x.Date >= previousMonthStart &&
                                             x.Date <= previousMonthEnd &&
                                             context.OrganizationAccounts
                                             .Where(y => y.OrganizationId == accountId)
                                             .Select(y => y.UserId)
                                             .Contains(x.AccountId)))
                                  .Select(x => x.AccountId)
                                  .Distinct()
                                  .CountAsync();
                }

                if (activeUsers > 1)
                {
                    await _chargeBee.Invoice.AddAddonCharge(payload.Content.Invoice.Id)
                    .AddonId("additional-seats")
                    .AddonQuantity(Math.Max(activeUsers - 1, 0))
                    .Request();
                }
            }

            await _chargeBee.Invoice.Close(payload.Content.Invoice.Id).Request();
        }