public bool CanDownGrade(Organization organization, BillingPlan plan, User user, out string message) { if (organization == null || String.IsNullOrWhiteSpace(organization.Id)) { message = "Invalid Organization"; return false; } int currentNumberOfUsers = _userRepository.GetByOrganizationId(organization.Id).Count() + organization.Invites.Count; int maxUsers = plan.MaxUsers != -1 ? plan.MaxUsers : int.MaxValue; if (currentNumberOfUsers > maxUsers) { message = String.Format("Please remove {0} user{1} and try again.", currentNumberOfUsers - maxUsers, (currentNumberOfUsers - maxUsers) > 0 ? "s" : String.Empty); return false; } int maxProjects = plan.MaxProjects != -1 ? plan.MaxProjects : int.MaxValue; long projectCount = _projectRepository.GetCountByOrganizationId(organization.Id); if (projectCount > maxProjects) { message = String.Format("Please remove {0} project{1} and try again.", projectCount - maxProjects, (projectCount - maxProjects) > 0 ? "s" : String.Empty); return false; } // Ensure the user can't be apart of more than one free plan. if (String.Equals(plan.Id, FreePlan.Id) && user != null && _organizationRepository.GetByIds(user.OrganizationIds).Any(o => String.Equals(o.PlanId, FreePlan.Id))) { message = "You already have one free account. You are not allowed to create more than one free account."; return false; } message = String.Empty; return true; }
public bool CanDownGrade(Organization organization, BillingPlan plan, User user, out string message) { if (organization == null || String.IsNullOrWhiteSpace(organization.Id)) { message = "Invalid Organization"; return false; } int currentNumberOfUsers = _userRepository.GetByOrganizationId(organization.Id).Count() + organization.Invites.Count; int maxUsers = plan.MaxUsers != -1 ? plan.MaxUsers : int.MaxValue; if (currentNumberOfUsers > maxUsers) { message = String.Format("Please remove {0} user{1} and try again.", currentNumberOfUsers - maxUsers, (currentNumberOfUsers - maxUsers) > 0 ? "s" : String.Empty); return false; } int maxProjects = plan.MaxProjects != -1 ? plan.MaxProjects : int.MaxValue; if (organization.ProjectCount > maxProjects) { message = String.Format("Please remove {0} project{1} and try again.", organization.ProjectCount - maxProjects, (organization.ProjectCount - maxProjects) > 0 ? "s" : String.Empty); return false; } // TODO: We need to make this smarter. if (organization.OverageDays != null && organization.OverageDays.Count(d => d.Day > DateTime.Now.AddDays(-30)) > 0 && plan.MaxErrorsPerDay < GetBillingPlan(organization.PlanId).MaxErrorsPerDay) { message = "You would exceed the maximum errors per day plan limit."; return false; } // Ensure the user can't be apart of more than one free plan. if (String.Equals(plan.Id, FreePlan.Id) && user != null && _organizationRepository.GetByIds(user.OrganizationIds).Any(o => String.Equals(o.PlanId, FreePlan.Id))) { message = "You already have one free account. You are not allowed to create more than one free account."; return false; } message = String.Empty; return true; }
public bool CanAddUser(Organization organization) { if (organization == null || String.IsNullOrWhiteSpace(organization.Id)) return false; List<User> users = _userRepository.GetByOrganizationId(organization.Id).ToList(); return organization.MaxUsers <= -1 || users.Count < organization.MaxUsers; }
public bool CanAddUser(Organization organization) { if (organization == null || String.IsNullOrWhiteSpace(organization.Id)) return false; int numberOfUsers = _userRepository.GetByOrganizationId(organization.Id).Count + organization.Invites.Count; return organization.MaxUsers <= -1 || numberOfUsers < organization.MaxUsers; }
public async Task SendPaymentFailedAsync(User owner, Organization organization) { MailMessage msg = _emailGenerator.GenerateMessage(new PaymentModel { Owner = owner, Organization = organization, BaseUrl = Settings.Current.BaseURL }, "PaymentFailed"); msg.To.Add(owner.EmailAddress); await QueueMessage(msg); }
public async Task SendInviteAsync(User sender, Organization organization, Invite invite) { MailMessage msg = _emailGenerator.GenerateMessage(new InviteModel { Sender = sender, Organization = organization, Invite = invite, BaseUrl = Settings.Current.BaseURL }, "Invite"); msg.To.Add(invite.EmailAddress); await QueueMessage(msg); }
public async Task SendAddedToOrganizationAsync(User sender, Organization organization, User user) { MailMessage msg = _emailGenerator.GenerateMessage(new AddedToOrganizationModel { Sender = sender, Organization = organization, User = user, BaseUrl = Settings.Current.BaseURL }, "AddedToOrganization"); msg.To.Add(user.EmailAddress); await QueueMessage(msg); }
public WebHookDataContext(Version version, Stack stack, Organization organization = null, Project project = null, bool isNew = false, bool isRegression = false) { if (version == null) throw new ArgumentException("Version cannot be null.", "version"); if (stack == null) throw new ArgumentException("Stack cannot be null.", "stack"); Version = version; Organization = organization; Project = project; Stack = stack; IsNew = isNew; IsRegression = isRegression; }
public static Organization GenerateOrganization(bool generateId = false, string name = null, string id = null, string inviteEmail = null, bool isSuspended = false) { var organization = new Organization { Id = id.IsNullOrEmpty() ? generateId ? ObjectId.GenerateNewId().ToString() : TestConstants.OrganizationId : id, Name = name ?? String.Format("Organization{0}", id), IsSuspended = isSuspended }; if (!String.IsNullOrEmpty(inviteEmail)) { organization.Invites.Add(new Invite { EmailAddress = inviteEmail, Token = Guid.NewGuid().ToString() }); } return organization; }
public WebHookDataContext(Version version, PersistentEvent ev, Organization organization = null, Project project = null, Stack stack = null, bool isNew = false, bool isRegression = false) { if (version == null) throw new ArgumentException("Version cannot be null.", "version"); if (ev == null) throw new ArgumentException("Event cannot be null.", "ev"); Version = version; Organization = organization; Project = project; Stack = stack; Event = ev; IsNew = isNew; IsRegression = isRegression; }
public void CanCreateUpdateRemove() { _repository.RemoveAll(); Assert.Equal(0, _repository.Count()); var organization = new Organization(); Assert.Null(organization.Id); _repository.Add(organization); Assert.NotNull(organization.Id); organization = _repository.GetById(organization.Id); Assert.NotNull(organization); organization.Name = "New organization"; _repository.Save(organization); _repository.Remove(organization.Id); }
public void CanCreateUpdateRemove() { _repository.RemoveAll(); Assert.Equal(0, _repository.Count()); var organization = new Organization { Name = "Test Organization", PlanId = BillingManager.FreePlan.Id }; Assert.Null(organization.Id); _repository.Add(organization); Assert.NotNull(organization.Id); organization = _repository.GetById(organization.Id); Assert.NotNull(organization); organization.Name = "New organization"; _repository.Save(organization); _repository.Remove(organization.Id); }
private void TryDeleteOrganization(Organization organization) { try { Log.Info().Message("Removing existing empty projects for the organization '{0}' with Id: '{1}'.", organization.Name, organization.Id).Write(); List<Project> projects = _projectRepository.GetByOrganizationId(organization.Id).ToList(); if (projects.Any(project => project.TotalEventCount > 0)) { Log.Info().Message("Organization '{0}' with Id: '{1}' has a project with existing data. This organization will not be deleted.", organization.Name, organization.Id).Write(); return; } foreach (Project project in projects) { Log.Info().Message("Resetting all project data for project '{0}' with Id: '{1}'.", project.Name, project.Id).Write(); _stackRepository.RemoveAllByProjectIdAsync(project.Id).Wait(); _eventRepository.RemoveAllByProjectIdAsync(project.Id).Wait(); _dayStackStats.RemoveAllByProjectIdAsync(project.Id).Wait(); _monthStackStats.RemoveAllByProjectIdAsync(project.Id).Wait(); _dayProjectStats.RemoveAllByProjectIdAsync(project.Id).Wait(); _monthProjectStats.RemoveAllByProjectIdAsync(project.Id).Wait(); } Log.Info().Message("Deleting all projects for organization '{0}' with Id: '{1}'.", organization.Name, organization.Id).Write(); _projectRepository.Remove(projects); Log.Info().Message("Removing users from organization '{0}' with Id: '{1}'.", organization.Name, organization.Id).Write(); List<User> users = _userRepository.GetByOrganizationId(organization.Id).ToList(); foreach (User user in users) { if (user.OrganizationIds.All(oid => String.Equals(oid, organization.Id))) { Log.Info().Message("Removing user '{0}' as they do not belong to any other organizations.", user.Id, organization.Name, organization.Id).Write(); _userRepository.Remove(user.Id); } else { Log.Info().Message("Removing user '{0}' from organization '{1}' with Id: '{2}'", user.Id, organization.Name, organization.Id).Write(); user.OrganizationIds.Remove(organization.Id); _userRepository.Save(user); } } Log.Info().Message("Deleting organization '{0}' with Id: '{1}'.", organization.Name, organization.Id).Write(); _organizationRepository.Remove(organization); // TODO: Send notifications that the organization and projects have been updated. } catch (Exception ex) { ex.ToExceptionless().MarkAsCritical().AddTags("Remove Stale Accounts").AddObject(organization).Submit(); } }
private void EnforceEventCountLimits(Organization organization) { Log.Info().Message("Enforcing event count limits for organization '{0}' with Id: '{1}'", organization.Name, organization.Id).Write(); try { // use the next higher plans retention days to enable us to upsell them BillingPlan nextPlan = BillingManager.Plans .Where(p => p.RetentionDays > organization.RetentionDays) .OrderByDescending(p => p.RetentionDays) .FirstOrDefault(); int retentionDays = organization.RetentionDays; if (nextPlan != null) retentionDays = nextPlan.RetentionDays; DateTime cutoff = DateTime.UtcNow.Date.AddDays(-retentionDays); _eventRepository.RemoveAllByDate(organization.Id, cutoff); } catch (Exception ex) { ex.ToExceptionless().MarkAsCritical().AddTags("Enforce Limits").AddObject(organization).Submit(); } }
public void CanAddAndGetByCached() { var cache = IoC.GetInstance<ICacheClient>() as InMemoryCacheClient; Assert.NotNull(cache); cache.FlushAll(); var organization = new Organization { Name = "Test Organization", PlanId = BillingManager.FreePlan.Id }; Assert.Null(organization.Id); Assert.Equal(0, cache.Count); _repository.Add(organization, true); Assert.NotNull(organization.Id); Assert.Equal(1, cache.Count); cache.FlushAll(); Assert.Equal(0, cache.Count); _repository.GetById(organization.Id, true); Assert.NotNull(organization.Id); Assert.Equal(1, cache.Count); _repository.RemoveAll(); Assert.Equal(0, cache.Count); }
public void CanAddAndGetByCached() { var cache = IoC.GetInstance<ICacheClient>() as InMemoryCacheClient; Assert.NotNull(cache); cache.FlushAll(); var organization = new Organization(); Assert.Null(organization.Id); Assert.Equal(0, cache.Count); _repository.Add(organization, true); Assert.NotNull(organization.Id); Assert.Equal(1, cache.Count); cache.FlushAll(); Assert.Equal(0, cache.Count); _repository.GetById(organization.Id, true); Assert.NotNull(organization.Id); Assert.Equal(1, cache.Count); _repository.RemoveAll(); Assert.Equal(0, cache.Count); }
public void SendAddedToOrganization(User sender, Organization organization, User user) {}
public void SendPaymentFailed(User owner, Organization organization) {}
public void SendInvite(User sender, Organization organization, Invite invite) {}
public Task SendInviteAsync(User sender, Organization organization, Invite invite) { return Task.FromResult(0); }
public Task SendAddedToOrganizationAsync(User sender, Organization organization, User user) { return Task.FromResult(0); }
public Task SendAddedToOrganizationAsync(User sender, Organization organization, User user) { return Task.Delay(0); }
public void CreateSampleOrganizationAndProject(string userId) { if (_projectRepository.GetByApiKey(SAMPLE_API_KEY) != null) return; User user = _userRepository.GetByIdCached(userId); var organization = new Organization { Name = "Acme" }; _billingManager.ApplyBillingPlan(organization, BillingManager.UnlimitedPlan, user); organization = _organizationRepository.Add(organization); var project = new Project { Name = "Disintegrating Pistol", TimeZone = TimeZone.CurrentTimeZone.StandardName, OrganizationId = organization.Id }; project.NextSummaryEndOfDayTicks = TimeZoneInfo.ConvertTime(DateTime.Today.AddDays(1), project.DefaultTimeZone()).ToUniversalTime().Ticks; project.ApiKeys.Add(SAMPLE_API_KEY); project.Configuration.Settings.Add("IncludeConditionalData", "true"); project.AddDefaultOwnerNotificationSettings(userId); project = _projectRepository.Add(project); _organizationRepository.IncrementStats(project.OrganizationId, projectCount: 1); user.OrganizationIds.Add(organization.Id); _userRepository.Update(user); }
public void CreateSampleOrganizationAndProject(string userId) { if (_tokenRepository.GetById(SAMPLE_API_KEY) != null) return; User user = _userRepository.GetById(userId, true); var organization = new Organization { Id = "537650f3b77efe23a47914f3", Name = "Acme" }; _billingManager.ApplyBillingPlan(organization, BillingManager.UnlimitedPlan, user); organization = _organizationRepository.Add(organization); var project = new Project { Id = "537650f3b77efe23a47914f4", Name = "Disintegrating Pistol", TimeZone = TimeZone.CurrentTimeZone.StandardName, OrganizationId = organization.Id }; project.NextSummaryEndOfDayTicks = TimeZoneInfo.ConvertTime(DateTime.Today.AddDays(1), project.DefaultTimeZone()).ToUniversalTime().Ticks; project.Configuration.Settings.Add("IncludeConditionalData", "true"); project.AddDefaultOwnerNotificationSettings(userId); project = _projectRepository.Add(project); _tokenRepository.Add(new Token { Id = SAMPLE_API_KEY, OrganizationId = organization.Id, ProjectId = project.Id, ExpiresUtc = DateTime.UtcNow.AddYears(100), CreatedUtc = DateTime.UtcNow, ModifiedUtc = DateTime.UtcNow, Type = TokenType.Access }); _tokenRepository.Add(new Token { Id = SAMPLE_USER_API_KEY, OrganizationId = organization.Id, UserId = user.Id, ExpiresUtc = DateTime.UtcNow.AddYears(100), CreatedUtc = DateTime.UtcNow, ModifiedUtc = DateTime.UtcNow, Type = TokenType.Access }); _organizationRepository.IncrementStats(project.OrganizationId, projectCount: 1); user.OrganizationIds.Add(organization.Id); _userRepository.Save(user); }
public void ApplyBillingPlan(Organization organization, BillingPlan plan, User user, bool updateBillingPrice = true) { organization.PlanId = plan.Id; organization.BillingChangeDate = DateTime.Now; if (updateBillingPrice) organization.BillingPrice = plan.Price; organization.BillingChangedByUserId = user.Id; organization.MaxUsers = plan.MaxUsers; organization.MaxProjects = plan.MaxProjects; organization.RetentionDays = plan.RetentionDays; organization.MaxEventsPerMonth = plan.MaxEventsPerMonth; organization.HasPremiumFeatures = plan.HasPremiumFeatures; }
public Task SendPaymentFailedAsync(User owner, Organization organization) { return Task.FromResult(0); }
public Task SendInviteAsync(User sender, Organization organization, Invite invite) { return Task.Delay(0); }
public Task SendAddedToOrganizationAsync(User sender, Organization organization, User user) { return Task.Run(() => SendAddedToOrganization(sender, organization, user)); }
private void TryDeleteOrganization(Organization organization) { try { Log.Info().Message("Checking to see if organization '{0}' with Id: '{1}' can be deleted.", organization.Name, organization.Id).Write(); ObjectId id; if (String.IsNullOrWhiteSpace(organization.Id) || !ObjectId.TryParse(organization.Id, out id)) { Log.Info().Message("Organization '{0}' with Id: '{1}' has an invalid id.", organization.Name, organization.Id).Write(); return; } if (id.CreationTime >= DateTime.Now.SubtractDays(90)) { Log.Info().Message("Organization '{0}' with Id: '{1}' has been created less than 90 days ago.", organization.Name, organization.Id).Write(); return; } if (organization.LastErrorDate >= DateTime.Now.SubtractDays(90)) { Log.Info().Message("Organization '{0}' with Id: '{1}' has had an exception newer than 90 days.", organization.Name, organization.Id).Write(); return; } if (!String.IsNullOrEmpty(organization.StripeCustomerId)) { Log.Info().Message("Organization '{0}' with Id: '{1}' has a stripe customer id and cannot be deleted.", organization.Name, organization.Id).Write(); return; } Log.Info().Message("Removing existing empty projects for the organization '{0}' with Id: '{1}'.", organization.Name, organization.Id).Write(); List<Project> projects = _projectRepository.GetByOrganizationId(organization.Id).ToList(); if (projects.Any(project => project.TotalErrorCount > 0)) { Log.Info().Message("Organization '{0}' with Id: '{1}' has a project with existing data. This organization will not be deleted.", organization.Name, organization.Id).Write(); return; } foreach (Project project in projects) { Log.Info().Message("Resetting all project data for project '{0}' with Id: '{1}'.", project.Name, project.Id).Write(); _errorStackRepository.RemoveAllByProjectId(project.Id); _errorRepository.RemoveAllByProjectId(project.Id); _dayStackStats.RemoveAllByProjectId(project.Id); _monthStackStats.RemoveAllByProjectId(project.Id); _dayProjectStats.RemoveAllByProjectId(project.Id); _monthProjectStats.RemoveAllByProjectId(project.Id); } Log.Info().Message("Deleting all projects for organization '{0}' with Id: '{1}'.", organization.Name, organization.Id).Write(); _projectRepository.Delete(projects); Log.Info().Message("Removing users from organization '{0}' with Id: '{1}'.", organization.Name, organization.Id).Write(); List<User> users = _userRepository.GetByOrganizationId(organization.Id).ToList(); foreach (User user in users) { if (user.OrganizationIds.All(oid => String.Equals(oid, organization.Id))) { Log.Info().Message("Removing user '{0}' as they do not belong to any other organizations.", user.Id, organization.Name, organization.Id).Write(); _userRepository.Delete(user.Id); } else { Log.Info().Message("Removing user '{0}' from organization '{1}' with Id: '{2}'", user.Id, organization.Name, organization.Id).Write(); user.OrganizationIds.Remove(organization.Id); _userRepository.Update(user); } } Log.Info().Message("Deleting organization '{0}' with Id: '{1}'.", organization.Name, organization.Id).Write(); _organizationRepository.Delete(organization); // TODO: Send notifications that the organization and projects have been updated. } catch (Exception ex) { ex.ToExceptionless().MarkAsCritical().AddTags("Remove Stale Accounts").AddObject(organization).Submit(); } }
public Task SendPaymentFailedAsync(User owner, Organization organization) { return Task.Delay(0); }